MOBILE-2327 core: Hide navbar-buttons when change core-tab

main
Dani Palou 2018-02-22 11:58:08 +01:00 committed by Pau Ferrer Ocaña
parent ac6b54322c
commit 3ed3ded3da
5 changed files with 121 additions and 14 deletions

View File

@ -34,6 +34,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
hideMenu: boolean;
ariaLabel: string;
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;
@ -74,7 +75,11 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
if (this.parentContextMenu) {
// All items were moved to the "parent" menu. Add the item in there.
this.parentContextMenu.addItem(item);
} else {
if (this.itemsMovedToParent.indexOf(item) == -1) {
this.itemsMovedToParent.push(item);
}
} else if (this.items.indexOf(item) == -1) {
this.items.push(item);
this.itemsChanged();
}
@ -103,7 +108,9 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
// Add all the items to the other menu.
for (let i = 0; i < this.items.length; i++) {
contextMenu.addItem(this.items[i]);
const item = this.items[i];
contextMenu.addItem(item);
this.itemsMovedToParent.push(item);
}
// Remove all items from the current menu.
@ -120,6 +127,11 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
if (this.parentContextMenu) {
// All items were moved to the "parent" menu. Remove the item from there.
this.parentContextMenu.removeItem(item);
const index = this.itemsMovedToParent.indexOf(item);
if (index >= 0) {
this.itemsMovedToParent.splice(index, 1);
}
} else {
const index = this.items.indexOf(item);
if (index >= 0) {
@ -129,6 +141,28 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
}
}
/**
* Remove the items that were merged to a parent context menu.
*/
removeMergedItems(): void {
if (this.parentContextMenu) {
for (let i = 0; i < this.itemsMovedToParent.length; i++) {
this.parentContextMenu.removeItem(this.itemsMovedToParent[i]);
}
}
}
/**
* Restore the items that were merged to a parent context menu.
*/
restoreMergedItems(): void {
if (this.parentContextMenu) {
for (let i = 0; i < this.itemsMovedToParent.length; i++) {
this.parentContextMenu.addItem(this.itemsMovedToParent[i]);
}
}
}
/**
* Show the context menu.
*
@ -146,5 +180,6 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
*/
ngOnDestroy(): void {
this.domUtils.removeInstanceById(this.instanceId);
this.removeMergedItems();
}
}

View File

@ -16,6 +16,7 @@ import { Component, Input, OnInit, OnDestroy, ContentChildren, ElementRef, Query
import { Button } from 'ionic-angular';
import { CoreLoggerProvider } from '../../providers/logger';
import { CoreDomUtilsProvider } from '../../providers/utils/dom';
import { CoreContextMenuComponent } from '../context-menu/context-menu';
/**
* Component to add buttons to the app's header without having to place them inside the header itself. This is meant for
@ -59,12 +60,16 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
protected element: HTMLElement;
protected _hidden: boolean;
protected forceHidden = false;
protected logger: any;
protected movedChildren: Node[];
protected instanceId: string;
protected mergedContextMenu: CoreContextMenuComponent;
constructor(element: ElementRef, logger: CoreLoggerProvider, private domUtils: CoreDomUtilsProvider) {
this.element = element.nativeElement;
this.logger = logger.getInstance('CoreNavBarButtonsComponent');
this.instanceId = this.domUtils.storeInstanceByElement(this.element, this);
}
/**
@ -100,6 +105,17 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
});
}
/**
* Force or unforce hiding all buttons. If this is true, it will override the "hidden" input.
*
* @param {boolean} value The value to set.
*/
forceHide(value: boolean): void {
this.forceHidden = value;
this.showHideAllElements();
}
/**
* If both button containers have a context menu, merge them into a single one.
*
@ -122,7 +138,9 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
secondaryContextMenuInstance = this.domUtils.getInstanceByElement(secondaryContextMenu);
if (mainContextMenuInstance && secondaryContextMenuInstance) {
secondaryContextMenuInstance.mergeContextMenus(mainContextMenuInstance);
this.mergedContextMenu = secondaryContextMenuInstance;
this.mergedContextMenu.mergeContextMenus(mainContextMenuInstance);
// Remove the empty context menu from the DOM.
secondaryContextMenu.parentElement.removeChild(secondaryContextMenu);
@ -189,11 +207,21 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
* Show or hide all the elements.
*/
protected showHideAllElements(): void {
// Show or hide all moved children.
if (this.movedChildren) {
this.movedChildren.forEach((child: Node) => {
this.showHideElement(child);
});
}
// Show or hide all the context menu items that were merged to another context menu.
if (this.mergedContextMenu) {
if (this.forceHidden || this._hidden) {
this.mergedContextMenu.removeMergedItems();
} else {
this.mergedContextMenu.restoreMergedItems();
}
}
}
/**
@ -204,7 +232,7 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
protected showHideElement(element: Node): void {
// Check if it's an HTML Element
if (element instanceof Element) {
if (this._hidden) {
if (this.forceHidden || this._hidden) {
element.classList.add(this.BUTTON_HIDDEN_CLASS);
} else {
element.classList.remove(this.BUTTON_HIDDEN_CLASS);
@ -216,6 +244,8 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
* Component destroyed.
*/
ngOnDestroy(): void {
this.domUtils.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.
@ -226,5 +256,9 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
}
});
}
if (this.mergedContextMenu) {
this.mergedContextMenu.removeMergedItems();
}
}
}

View File

@ -15,6 +15,8 @@
import { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter, ContentChild, TemplateRef } from '@angular/core';
import { CoreTabsComponent } from './tabs';
import { Content } from 'ionic-angular';
import { CoreDomUtilsProvider } from '../../providers/utils/dom';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
/**
* A tab to use inside core-tabs. The content of this tab will be displayed when the tab is selected.
@ -55,7 +57,7 @@ export class CoreTabComponent implements OnInit, OnDestroy {
element: HTMLElement; // The core-tab element.
loaded = false;
constructor(private tabs: CoreTabsComponent, element: ElementRef) {
constructor(protected tabs: CoreTabsComponent, element: ElementRef, protected domUtils: CoreDomUtilsProvider) {
this.element = element.nativeElement;
}
@ -81,6 +83,7 @@ export class CoreTabComponent implements OnInit, OnDestroy {
this.loaded = true;
this.ionSelect.emit(this);
this.showHideNavBarButtons(true);
// Setup tab scrolling.
setTimeout(() => {
@ -97,5 +100,39 @@ export class CoreTabComponent implements OnInit, OnDestroy {
*/
unselectTab(): void {
this.element.classList.remove('selected');
this.showHideNavBarButtons(false);
}
/**
* Get all child core-navbar-buttons. We need to use querySelectorAll because ContentChildren doesn't work with ng-template.
* https://github.com/angular/angular/issues/14842
*
* @return {CoreNavBarButtonsComponent[]} List of component instances.
*/
protected getChildrenNavBarButtons(): CoreNavBarButtonsComponent[] {
const elements = this.element.querySelectorAll('core-navbar-buttons'),
instances: CoreNavBarButtonsComponent[] = [];
for (let i = 0; i < elements.length; i++) {
const instance = this.domUtils.getInstanceByElement(elements[i]);
if (instance) {
instances.push(instance);
}
}
return instances;
}
/**
* Show all hide all children navbar buttons.
*
* @param {boolean} show Whether to show or hide the buttons.
*/
protected showHideNavBarButtons(show: boolean): void {
const instances = this.getChildrenNavBarButtons();
for (const i in instances) {
instances[i].forceHide(!show);
}
}
}

View File

@ -2,12 +2,7 @@
<ion-navbar>
<ion-title><core-format-text [text]="title"></core-format-text></ion-title>
<ion-buttons end>
<core-context-menu>
<core-context-menu-item *ngIf="displayEnableDownload" [priority]="2000" [content]="'core.settings.enabledownloadsection' | translate" (action)="toggleDownload()" [iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item [priority]="1900" [content]="'core.course.downloadcourse' | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
</core-context-menu>
</ion-buttons>
<ion-buttons end></ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
@ -15,6 +10,12 @@
<!-- Course contents tab. -->
<core-tab [title]="'core.course.contents' | translate">
<ng-template>
<core-navbar-buttons>
<core-context-menu>
<core-context-menu-item *ngIf="displayEnableDownload" [priority]="2000" [content]="'core.settings.enabledownloadsection' | translate" (action)="toggleDownload()" [iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item [priority]="1900" [content]="'core.course.downloadcourse' | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
</core-context-menu>
</core-navbar-buttons>
<ion-content>
<ion-refresher [enabled]="dataLoaded" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>

View File

@ -152,7 +152,7 @@ export class CoreDomUtilsProvider {
this.element.innerHTML = html;
elements = this.element.querySelectorAll('a, img, audio, video, source, track');
for (const i in elements) {
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
let url = element.tagName === 'A' ? element.href : element.src;
@ -525,7 +525,7 @@ export class CoreDomUtilsProvider {
if (removeAll) {
selected = this.element.querySelectorAll(selector);
for (const i in selected) {
for (let i = 0; i < selected.length; i++) {
selected[i].remove();
}
} else {
@ -568,7 +568,7 @@ export class CoreDomUtilsProvider {
for (const key in map) {
const foundElements = element.querySelectorAll('.' + key);
for (const i in foundElements) {
for (let i = 0; i < foundElements.length; i++) {
const foundElement = foundElements[i];
foundElement.className = foundElement.className.replace(key, map[key]);
}