/*
* © 2017 Stratio Big Data Inc., Sucursal en España.
*
* This software is licensed under the Apache License, Version 2.0.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the terms of the License for more details.
*
* SPDX-License-Identifier: Apache-2.0.
*/
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { StSidebarItem } from '../st-sidebar-item.interface';
import { StSidebarVisualMode } from '../st-sidebar-visual-mode';
/**
* @description {Component} [SidebarItemList]
*
* The sidebar item list component has been designed to display a list of items in a sidebar.
*
* @model
*
* [Sidebar items] {../st-sidebar-item.interface.ts#StSidebarItem}
*
* @example
*
* {html}
*
* ```
*
*
* ```
*
*/
@Component({
selector: 'st-sidebar-item-list',
templateUrl: './st-sidebar-item-list.component.html',
styleUrls: ['./st-sidebar-item-list.component.scss'],
providers: [],
host: { class: 'st-sidebar-item-list' },
changeDetection: ChangeDetectionStrategy.OnPush
})
export class StSidebarItemListComponent implements OnInit {
/** @Input {boolean} [defaultActive=true] Unset first item as active by default if false */
@Input() defaultActive: boolean = true;
/** @Input {number} [deep=0] Deep of the item list in the sidebar */
@Input() deep: number = 0;
/** @Input {StSidebarVisualMode} [visualMode='StSidebarVisualMode.normal'] Visual mode used to display the item list */
@Input() visualMode: StSidebarVisualMode = StSidebarVisualMode.normal;
/** @Output {StSidebarItem} [change=''] Event emitted when the active item is changed. This emit the active item */
@Output() change: EventEmitter = new EventEmitter();
public displayAsComplexModeValue: boolean = false;
public expanded: boolean[] = [];
private _items: StSidebarItem[] = [];
private _active: StSidebarItem;
/** @Input {StSidebarItem[]} [items=''] List of items displayed on the menu */
@Input() get items(): StSidebarItem[] {
return this._items;
}
set items(items: StSidebarItem[]) {
this._items = items;
this._updateStatus();
}
/** @Input {string} [active=''] The id of the current active item */
@Input() get active(): StSidebarItem {
return this._active;
}
set active(active: StSidebarItem) {
if (!this._isActive(active)) {
this._active = active;
this._updateStatus();
}
}
ngOnInit(): void {
if (this.defaultActive && !this._active && this._items && this._items.length) {
this._active = this._items[0];
}
this.displayAsComplexModeValue = this.displayAsComplexMode();
}
getItemClasses(item: StSidebarItem, index: number): any {
let classes: any = {};
const active: boolean = this._isActive(item);
const activeChild: boolean = this.hasActiveChild(item);
classes[item.class] = item.class;
classes['item--complex'] = item.items && item.items.length;
classes['item--active'] = active;
classes['item--expanded'] = this.expanded[index];
classes['item--has-active'] = activeChild;
classes['item--disabled'] = item.disabled;
return classes;
}
onSelectItem(item: StSidebarItem, position: number): void {
if (!item.disabled) {
if (item.items && item.items.length) {
this.expanded[position] = !this.expanded[position];
} else {
if (!this._active || this._active.id !== item.id) {
this.change.emit(item);
this._closeRestOfItems(item.id);
}
}
}
}
hasActiveChild(item: StSidebarItem): boolean {
let found = false;
let i = 0;
if (item.items && item.items.length) {
while (!found && i < item.items.length) {
if (this._isActive(item.items[i])) {
found = true;
}
++i;
}
if (!found && item.items && item.items.length) {
return this._hasActiveChildInChildren(item.items);
}
}
return found;
}
onChange(item: StSidebarItem): void {
if (!this._isActive(item)) {
this._closeRestOfItems(item.id);
this.change.emit(item);
}
}
displayAsComplexMode(): boolean {
return this.visualMode === StSidebarVisualMode.complex;
}
private _isActive(item: StSidebarItem): boolean {
return item && this._active && this._active.id === item.id;
}
private _updateStatus(): void {
this.expanded = [];
this._items.forEach((item, i) => {
if (this.hasActiveChild(item)) {
this.expanded[i] = true;
}
});
}
private _hasActiveChildInChildren(items: StSidebarItem[]): boolean {
let found = false;
let i = 0;
while (!found && i < items.length) {
if (this.hasActiveChild(items[i])) {
found = true;
}
++i;
}
return found;
}
private _closeRestOfItems(itemId: string): void {
this.expanded.forEach((open, i) => {
if (open && this._items[i].id !== itemId) {
this.expanded[i] = false;
}
});
}
}