160 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| // (C) Copyright 2015 Moodle Pty Ltd.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| import {
 | |
|     Component,
 | |
|     Input,
 | |
|     AfterViewInit,
 | |
|     ViewChild,
 | |
|     ElementRef,
 | |
| } from '@angular/core';
 | |
| 
 | |
| import { CoreTabsBaseComponent } from '@classes/tabs';
 | |
| import { CoreTabComponent } from './tab';
 | |
| 
 | |
| /**
 | |
|  * This component displays some top scrollable tabs that will autohide on vertical scroll.
 | |
|  * Unlike core-tabs-outlet, this component does NOT use Angular router.
 | |
|  *
 | |
|  * Example usage:
 | |
|  *
 | |
|  * <core-tabs selectedIndex="1">
 | |
|  *     <core-tab [title]="'core.courses.timeline' | translate" (ionSelect)="switchTab('timeline')">
 | |
|  *         <ng-template> <!-- This ng-template is required, @see CoreTabComponent. -->
 | |
|  *             <!-- Tab contents. -->
 | |
|  *         </ng-template>
 | |
|  *     </core-tab>
 | |
|  * </core-tabs>
 | |
|  */
 | |
| @Component({
 | |
|     selector: 'core-tabs',
 | |
|     templateUrl: 'core-tabs.html',
 | |
|     styleUrls: ['tabs.scss'],
 | |
| })
 | |
| export class CoreTabsComponent extends CoreTabsBaseComponent<CoreTabComponent> implements AfterViewInit {
 | |
| 
 | |
|     @Input() parentScrollable = false; // Determine if the scroll should be in the parent content or the tab itself.
 | |
|     @Input() layout: 'icon-top' | 'icon-start' | 'icon-end' | 'icon-bottom' | 'icon-hide' | 'label-hide' = 'icon-hide';
 | |
| 
 | |
|     @ViewChild('originalTabs') originalTabsRef?: ElementRef;
 | |
| 
 | |
|     protected originalTabsContainer?: HTMLElement; // The container of the original tabs. It will include each tab's content.
 | |
| 
 | |
|     constructor(
 | |
|         element: ElementRef,
 | |
|     ) {
 | |
|         super(element);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * View has been initialized.
 | |
|      */
 | |
|     async ngAfterViewInit(): Promise<void> {
 | |
|         super.ngAfterViewInit();
 | |
| 
 | |
|         if (this.isDestroyed) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         this.tabsElement = this.element.nativeElement;
 | |
|         this.originalTabsContainer = this.originalTabsRef?.nativeElement;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initialize the tabs, determining the first tab to be shown.
 | |
|      */
 | |
|     protected async initializeTabs(): Promise<void> {
 | |
|         await super.initializeTabs();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add a new tab if it isn't already in the list of tabs.
 | |
|      *
 | |
|      * @param tab The tab to add.
 | |
|      */
 | |
|     addTab(tab: CoreTabComponent): void {
 | |
|         // Check if tab is already in the list.
 | |
|         if (this.getTabIndex(tab.id!) == -1) {
 | |
|             this.tabs.push(tab);
 | |
|             this.sortTabs();
 | |
| 
 | |
|             setTimeout(() => {
 | |
|                 this.calculateSlides();
 | |
|             });
 | |
| 
 | |
|             if (this.initialized && this.tabs.length > 1 && this.tabBarHeight == 0) {
 | |
|                 // Calculate the tabBarHeight again now that there is more than 1 tab and the bar will be seen.
 | |
|                 // Use timeout to wait for the view to be rendered. 0 ms should be enough, use 50 to be sure.
 | |
|                 setTimeout(() => {
 | |
|                     this.calculateTabBarHeight();
 | |
|                 }, 50);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Remove a tab from the list of tabs.
 | |
|      *
 | |
|      * @param tab The tab to remove.
 | |
|      */
 | |
|     removeTab(tab: CoreTabComponent): void {
 | |
|         const index = this.getTabIndex(tab.id!);
 | |
|         this.tabs.splice(index, 1);
 | |
| 
 | |
|         this.calculateSlides();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Load the tab.
 | |
|      *
 | |
|      * @param tabToSelect Tab to load.
 | |
|      * @return Promise resolved with true if tab is successfully loaded.
 | |
|      */
 | |
|     protected async loadTab(tabToSelect: CoreTabComponent): Promise<boolean> {
 | |
|         const currentTab = this.getSelected();
 | |
|         currentTab?.unselectTab();
 | |
|         tabToSelect.selectTab();
 | |
| 
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sort the tabs, keeping the same order as in the original list.
 | |
|      */
 | |
|     protected sortTabs(): void {
 | |
|         if (!this.originalTabsContainer) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         const newTabs: CoreTabComponent[] = [];
 | |
| 
 | |
|         this.tabs.forEach((tab) => {
 | |
|             const originalIndex = Array.prototype.indexOf.call(this.originalTabsContainer?.children, tab.element);
 | |
|             if (originalIndex != -1) {
 | |
|                 newTabs[originalIndex] = tab;
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         this.tabs = newTabs;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Function to call when the visibility of a tab has changed.
 | |
|      */
 | |
|     tabVisibilityChanged(): void {
 | |
|         this.calculateSlides();
 | |
|     }
 | |
| 
 | |
| }
 |