import { NgModule, Component, ElementRef, AfterContentInit, OnDestroy, Input, Output, EventEmitter,
ContentChildren, QueryList, ChangeDetectorRef, Inject, forwardRef} from '@angular/core';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { CommonModule } from '@angular/common';
import { SharedModule, Header } from '../common/shared';
import { BlockableUI } from '../common/blockableui';
import { Subscription } from 'rxjs/Subscription';
let idx: number = 0;
@Component({
selector: 'p-accordionTab',
template: `
`,
animations: [
trigger('tabContent', [
state('hidden', style({
height: '0'
})),
state('visible', style({
height: '*'
})),
transition('visible <=> hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
])
]
})
export class AccordionTab implements OnDestroy {
@Input() header: string;
@Input() selected: boolean;
@Input() disabled: boolean;
@Output() selectedChange: EventEmitter = new EventEmitter();
@ContentChildren(Header) headerFacet: QueryList;
animating: boolean;
id: string = `ui-accordiontab-${idx++}`;
constructor( @Inject(forwardRef(() => Accordion)) public accordion: Accordion) {}
toggle(event) {
if (this.disabled || this.animating) {
return false;
}
this.animating = true;
let index = this.findTabIndex();
if (this.selected) {
this.selected = false;
this.accordion.onClose.emit({ originalEvent: event, index: index });
}
else {
if (!this.accordion.multiple) {
for (var i = 0; i < this.accordion.tabs.length; i++) {
this.accordion.tabs[i].selected = false;
this.accordion.tabs[i].selectedChange.emit(false);
}
}
this.selected = true;
this.accordion.onOpen.emit({ originalEvent: event, index: index });
}
this.selectedChange.emit(this.selected);
event.preventDefault();
}
findTabIndex() {
let index = -1;
for (var i = 0; i < this.accordion.tabs.length; i++) {
if (this.accordion.tabs[i] == this) {
index = i;
break;
}
}
return index;
}
get lazy(): boolean {
return this.accordion.lazy;
}
get hasHeaderFacet(): boolean {
return this.headerFacet && this.headerFacet.length > 0;
}
onToggleDone(event: Event) {
this.animating = false;
}
ngOnDestroy() {
this.accordion.tabs.splice(this.findTabIndex(), 1);
}
}
@Component({
selector: 'p-accordion',
template: `
`
})
export class Accordion implements BlockableUI, AfterContentInit, OnDestroy {
@Input() multiple: boolean;
@Output() onClose: EventEmitter = new EventEmitter();
@Output() onOpen: EventEmitter = new EventEmitter();
@Input() style: any;
@Input() styleClass: string;
@Input() expandIcon: string = 'fa fa-fw fa-caret-right';
@Input() collapseIcon: string = 'fa fa-fw fa-caret-down';
@Input() lazy: boolean;
@ContentChildren(AccordionTab) tabList: QueryList;
tabListSubscription: Subscription;
private _activeIndex: any;
public tabs: AccordionTab[] = [];
constructor(public el: ElementRef, public changeDetector: ChangeDetectorRef) {}
ngAfterContentInit() {
this.initTabs();
this.tabListSubscription = this.tabList.changes.subscribe(_ => {
this.initTabs();
this.changeDetector.markForCheck();
});
}
initTabs(): any {
this.tabs = this.tabList.toArray();
this.updateSelectionState();
}
getBlockableElement(): HTMLElement {
return this.el.nativeElement.children[0];
}
@Input() get activeIndex(): any {
return this._activeIndex;
}
set activeIndex(val: any) {
this._activeIndex = val;
this.updateSelectionState();
}
updateSelectionState() {
if (this.tabs && this.tabs.length && this._activeIndex != null) {
for (let i = 0; i < this.tabs.length; i++) {
let selected = this.multiple ? this._activeIndex.includes(i) : (i === this._activeIndex);
let changed = selected !== this.tabs[i].selected;
if (changed) {
this.tabs[i].animating = true;
}
this.tabs[i].selected = selected;
this.tabs[i].selectedChange.emit(selected);
}
}
}
ngOnDestroy() {
if(this.tabListSubscription) {
this.tabListSubscription.unsubscribe();
}
}
}
@NgModule({
imports: [CommonModule],
exports: [Accordion,AccordionTab,SharedModule],
declarations: [Accordion,AccordionTab]
})
export class AccordionModule { }