forked from CIT/Vmeda.Online
		
	MOBILE-3320 dom: Store instances using a WeakMap
This commit is contained in:
		
							parent
							
								
									345ff293c1
								
							
						
					
					
						commit
						1e82b7796c
					
				@ -40,13 +40,10 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
 | 
			
		||||
    protected items: CoreContextMenuItemComponent[] = [];
 | 
			
		||||
    protected itemsMovedToParent: CoreContextMenuItemComponent[] = [];
 | 
			
		||||
    protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
 | 
			
		||||
    protected instanceId: string;
 | 
			
		||||
    protected parentContextMenu?: CoreContextMenuComponent;
 | 
			
		||||
    protected expanded = false;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        elementRef: ElementRef,
 | 
			
		||||
    ) {
 | 
			
		||||
    constructor(elementRef: ElementRef) {
 | 
			
		||||
        // Create the stream and subscribe to it. We ignore successive changes during 250ms.
 | 
			
		||||
        this.itemsChangedStream = new Subject<void>();
 | 
			
		||||
        this.itemsChangedStream.pipe(auditTime(250));
 | 
			
		||||
@ -61,7 +58,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
 | 
			
		||||
        // Calculate the unique ID.
 | 
			
		||||
        this.uniqueId = 'core-context-menu-' + CoreUtils.getUniqueId('CoreContextMenuComponent');
 | 
			
		||||
 | 
			
		||||
        this.instanceId = CoreDomUtils.storeInstanceByElement(elementRef.nativeElement, this);
 | 
			
		||||
        CoreDomUtils.storeInstanceByElement(elementRef.nativeElement, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -202,7 +199,6 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
 | 
			
		||||
     * Component destroyed.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        CoreDomUtils.removeInstanceById(this.instanceId);
 | 
			
		||||
        this.removeMergedItems();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -62,13 +62,13 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
 | 
			
		||||
    protected forceHidden = false;
 | 
			
		||||
    protected logger: CoreLogger;
 | 
			
		||||
    protected movedChildren?: Node[];
 | 
			
		||||
    protected instanceId: string;
 | 
			
		||||
    protected mergedContextMenu?: CoreContextMenuComponent;
 | 
			
		||||
 | 
			
		||||
    constructor(element: ElementRef) {
 | 
			
		||||
        this.element = element.nativeElement;
 | 
			
		||||
        this.logger = CoreLogger.getInstance('CoreNavBarButtonsComponent');
 | 
			
		||||
        this.instanceId = CoreDomUtils.storeInstanceByElement(this.element, this);
 | 
			
		||||
 | 
			
		||||
        CoreDomUtils.storeInstanceByElement(this.element, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -138,9 +138,8 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Both containers have a context menu. Merge them to prevent having 2 menus at the same time.
 | 
			
		||||
        const mainContextMenuInstance: CoreContextMenuComponent = CoreDomUtils.getInstanceByElement(mainContextMenu);
 | 
			
		||||
        const secondaryContextMenuInstance: CoreContextMenuComponent =
 | 
			
		||||
            CoreDomUtils.getInstanceByElement(secondaryContextMenu);
 | 
			
		||||
        const mainContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(mainContextMenu);
 | 
			
		||||
        const secondaryContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(secondaryContextMenu);
 | 
			
		||||
 | 
			
		||||
        // Check that both context menus belong to the same core-tab. We shouldn't merge menus from different tabs.
 | 
			
		||||
        if (mainContextMenuInstance && secondaryContextMenuInstance) {
 | 
			
		||||
@ -247,8 +246,6 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
 | 
			
		||||
     * Component destroyed.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        CoreDomUtils.removeInstanceById(this.instanceId);
 | 
			
		||||
 | 
			
		||||
        // This component was destroyed, remove all the buttons that were moved.
 | 
			
		||||
        // The buttons can be moved outside of the current page, that's why we need to manually destroy them.
 | 
			
		||||
        // There's no need to destroy context menu items that were merged because they weren't moved from their DOM position.
 | 
			
		||||
 | 
			
		||||
@ -150,7 +150,7 @@ export class CoreTabsOutletComponent extends CoreTabsBaseComponent<CoreTabsOutle
 | 
			
		||||
        const elements = this.ionTabs!.outlet.nativeEl.querySelectorAll('core-navbar-buttons');
 | 
			
		||||
        const domUtils = CoreDomUtils.instance;
 | 
			
		||||
        elements.forEach((element) => {
 | 
			
		||||
            const instance: CoreNavBarButtonsComponent = domUtils.getInstanceByElement(element);
 | 
			
		||||
            const instance = domUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
 | 
			
		||||
 | 
			
		||||
            if (instance) {
 | 
			
		||||
                const pagetagName = element.closest('.ion-page')?.tagName;
 | 
			
		||||
 | 
			
		||||
@ -144,7 +144,7 @@ export class CoreTabComponent implements OnInit, OnDestroy, CoreTabBase {
 | 
			
		||||
    protected showHideNavBarButtons(show: boolean): void {
 | 
			
		||||
        const elements = this.element.querySelectorAll('core-navbar-buttons');
 | 
			
		||||
        elements.forEach((element) => {
 | 
			
		||||
            const instance: CoreNavBarButtonsComponent = CoreDomUtils.getInstanceByElement(element);
 | 
			
		||||
            const instance = CoreDomUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
 | 
			
		||||
 | 
			
		||||
            if (instance) {
 | 
			
		||||
                instance.forceHide(!show);
 | 
			
		||||
 | 
			
		||||
@ -53,9 +53,7 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
    protected template: HTMLTemplateElement = document.createElement('template'); // A template element to convert HTML to element.
 | 
			
		||||
 | 
			
		||||
    protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call.
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
    protected instances: {[id: string]: any} = {}; // Store component/directive instances by id.
 | 
			
		||||
    protected lastInstanceId = 0;
 | 
			
		||||
    protected instances: WeakMap<Element, unknown> = new WeakMap(); // Store component/directive instances indexed by element.
 | 
			
		||||
    protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
 | 
			
		||||
    protected displayedAlerts: Record<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
 | 
			
		||||
    protected activeLoadingModals: CoreIonLoadingElement[] = [];
 | 
			
		||||
@ -706,11 +704,8 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
     * @param element The root element of the component/directive.
 | 
			
		||||
     * @return The instance, undefined if not found.
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
    getInstanceByElement(element: Element): any {
 | 
			
		||||
        const id = element.getAttribute(this.INSTANCE_ID_ATTR_NAME);
 | 
			
		||||
 | 
			
		||||
        return id && this.instances[id];
 | 
			
		||||
    getInstanceByElement<T = unknown>(element: Element): T | undefined {
 | 
			
		||||
        return this.instances.get(element) as T;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -1629,16 +1624,9 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
     *
 | 
			
		||||
     * @param element The root element of the component/directive.
 | 
			
		||||
     * @param instance The instance to store.
 | 
			
		||||
     * @return ID to identify the instance.
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
    storeInstanceByElement(element: Element, instance: any): string {
 | 
			
		||||
        const id = String(this.lastInstanceId++);
 | 
			
		||||
 | 
			
		||||
        element.setAttribute(this.INSTANCE_ID_ATTR_NAME, id);
 | 
			
		||||
        this.instances[id] = instance;
 | 
			
		||||
 | 
			
		||||
        return id;
 | 
			
		||||
    storeInstanceByElement(element: Element, instance: unknown): void {
 | 
			
		||||
        this.instances.set(element, instance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user