import ngModule from '../../module'; import Component from '../../lib/component'; import './style.scss'; /** * Base class for windows displayed over application content. */ export default class Popup extends Component { constructor(...args) { super(...args); this._shown = false; this.displayMode = 'centered'; } $onDestroy() { this.hide(); } /** * @type {Boolean} Whether to show or hide the popup. */ get shown() { return this._shown; } set shown(value) { if (value) this.show(); else this.hide(); } /** * Displays the popup. */ show() { if (this.shown) return; this._shown = true; if (this.closeTimeout) { this.$timeout.cancel(this.closeTimeout); this.onClose(); } this.$contentScope = this.$.$new(); this.contentLinkFn( this.$contentScope, element => this.popup = element[0], {parentBoundTranscludeFn: this.$transclude} ); this.windowEl = this.popup.querySelector('.window'); this.windowEl.focus(); let classList = this.popup.classList; classList.add(this.displayMode); classList.add(...this.constructor.$classNames); this.document.body.appendChild(this.popup); this.keyDownHandler = e => this.onkeyDown(e); this.document.addEventListener('keydown', this.keyDownHandler); this.deregisterCallback = this.$transitions.onStart({}, () => this.hide()); this.$timeout.cancel(this.showTimeout); this.showTimeout = this.$timeout(() => { this.showTimeout = null; classList.add('shown'); }, 10); this.emit('open'); } /** * Hides the popup. */ hide() { if (!this.shown) return; this._shown = false; this.document.removeEventListener('keydown', this.keyDownHandler); this.keyDownHandler = null; this.deregisterCallback(); this.deregisterCallback = null; this.popup.classList.remove('shown'); this.closeTimeout = this.$timeout( () => this.onClose(), 200); this.lastEvent = null; this.emit('closeStart'); } /** * Called when closing transition ends and popup is not visible, it can * be overriden by child classes (calling the super) to perform additional * actions. */ onClose() { this.closeTimeout = null; this.popup.remove(); this.popup = null; this.$contentScope.$destroy(); this.$contentScope = null; this.windowEl = null; this.emit('close'); } onWindowMouseDown(event) { this.lastEvent = event; } onBgMouseDown(event) { if (!event.defaultPrevented && event != this.lastEvent) this.hide(); } onkeyDown(event) { if (!event.defaultPrevented && event.key == 'Escape') this.hide(); } } Popup.$inject = ['$element', '$scope', '$transclude']; ngModule.vnComponent('vnPopup', { controller: Popup, transclude: true, bindings: { shown: '=?' }, installClasses: false }); ngModule.run(['$compile', function($compile) { Popup.prototype.contentLinkFn = $compile(require('./index.html')); }]);