app/@overflow/commons/ui/component/primeng/dropdown-panel.component.ts
crusader beaff07758 ing
2018-08-17 19:53:40 +09:00

186 lines
4.3 KiB
TypeScript

import { Component, ElementRef, OnDestroy, Input, Renderer2, ViewChild, ContentChild } from '@angular/core';
import { trigger, state, style, transition, animate, AnimationEvent } from '@angular/animations';
import { Header, Footer, DomHandler } from 'primeng/primeng';
@Component({
selector: 'p-dropdownPanel',
templateUrl: './dropdown-panel.component.html',
styleUrls: ['./dropdown-panel.component.scss'],
animations: [
trigger('overlayAnimation', [
state('void', style({
// transform: 'translateY(5%)',
transform: 'translate3d(0, 0, 0)',
opacity: 0
})),
state('visible', style({
// transform: 'translateY(0)',
transform: 'translate3d(0, 0, 0)',
opacity: 1
})),
transition('void => visible', animate('225ms ease-in-out')),
transition('visible => void', animate('195ms ease-in-out'))
// transition('void => visible', animate('225ms ease-out')),
// transition('visible => void', animate('195ms ease-in'))
// transition('visible => void', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')),
// transition('void => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
])
],
providers: [DomHandler]
})
export class DropdownPanelComponent implements OnDestroy {
@Input() popup = true;
@Input() style: any;
@Input() styleClass: string;
@Input() dropdownStyle: any;
@Input() dropdownStyleClass: string;
@Input() appendTo: any;
@Input() autoZIndex = true;
@Input() baseZIndex = 0;
@ViewChild('container') containerViewChild: ElementRef;
@ContentChild(Header) headerFacet;
@ContentChild(Footer) footerFacet;
container: HTMLDivElement;
documentClickListener: any;
documentResizeListener: any;
preventDocumentDefault: boolean;
target: any;
visible = false;
constructor(
public el: ElementRef,
public domHandler: DomHandler,
public renderer: Renderer2
) {
}
toggle(event) {
if (this.visible) {
this.hide();
} else {
this.show(event);
}
this.preventDocumentDefault = true;
}
show(event) {
this.target = event.currentTarget;
this.visible = true;
this.preventDocumentDefault = true;
}
onOverlayAnimationStart(event: AnimationEvent) {
switch (event.toState) {
case 'visible':
if (this.popup) {
this.container = event.element;
this.moveOnTop();
this.appendOverlay();
this.domHandler.absolutePosition(this.container, this.target);
this.bindDocumentClickListener();
this.bindDocumentResizeListener();
}
break;
case 'void':
this.onOverlayHide();
break;
}
}
appendOverlay() {
if (this.appendTo) {
if (this.appendTo === 'body') {
document.body.appendChild(this.container);
} else {
this.domHandler.appendChild(this.container, this.appendTo);
}
}
}
restoreOverlayAppend() {
if (this.container && this.appendTo) {
this.el.nativeElement.appendChild(this.container);
}
}
moveOnTop() {
if (this.autoZIndex) {
this.container.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
}
}
hide() {
this.visible = false;
}
onWindowResize() {
this.hide();
}
bindDocumentClickListener() {
if (!this.documentClickListener) {
this.documentClickListener = this.renderer.listen('document', 'click', () => {
if (!this.preventDocumentDefault) {
this.hide();
}
this.preventDocumentDefault = false;
});
}
}
unbindDocumentClickListener() {
if (this.documentClickListener) {
this.documentClickListener();
this.documentClickListener = null;
}
}
bindDocumentResizeListener() {
this.documentResizeListener = this.onWindowResize.bind(this);
window.addEventListener('resize', this.documentResizeListener);
}
unbindDocumentResizeListener() {
if (this.documentResizeListener) {
window.removeEventListener('resize', this.documentResizeListener);
this.documentResizeListener = null;
}
}
onOverlayHide() {
this.unbindDocumentClickListener();
this.unbindDocumentResizeListener();
this.preventDocumentDefault = false;
this.target = null;
}
ngOnDestroy() {
if (this.popup) {
this.restoreOverlayAppend();
this.onOverlayHide();
}
}
}