salix/front/core/components/popup/index.js

132 lines
3.2 KiB
JavaScript

import ngModule from '../../module';
import Component from '../../lib/component';
import template from './index.html';
import './style.scss';
/**
* Base class for windows displayed over application content.
*/
export default class Popup extends Component {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.$transclude = $transclude;
this._shown = false;
this.displayMode = 'centered';
this.template = template;
}
$onDestroy() {
this.hide();
}
/**
* @type {Boolean} Wether to show or hide the popup.
*/
get shown() {
return this._shown;
}
set shown(value) {
if (value)
this.show();
else
this.hide();
}
/**
* Displays the dialog to the user.
*/
show() {
if (this.shown) return;
this._shown = true;
let linkFn = this.$compile(this.template);
this.$contentScope = this.$.$new();
this.popup = linkFn(this.$contentScope, null,
{parentBoundTranscludeFn: this.$transclude}
)[0];
this.windowEl = this.popup.querySelector('.window');
let classList = this.popup.classList;
classList.add(this.displayMode);
classList.add(...this.constructor.$classNames);
if (!this.transitionTimeout)
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.transitionTimeout);
this.transitionTimeout = this.$timeout(() => {
this.transitionTimeout = null;
classList.add('shown');
}, 10);
this.emit('open');
}
/**
* Hides the dialog calling the response handler.
*/
hide() {
if (!this.shown) return;
this.document.removeEventListener('keydown', this.keyDownHandler);
this.keyDownHandler = null;
if (this.deregisterCallback) {
this.deregisterCallback();
this.deregisterCallback = null;
}
this.popup.classList.remove('shown');
this.$timeout.cancel(this.transitionTimeout);
this.transitionTimeout = this.$timeout(
() => this.onClose(), 200);
this.lastEvent = null;
this._shown = false;
this.emit('closeStart');
}
onClose() {
this.transitionTimeout = null;
this.document.body.removeChild(this.popup);
this.$contentScope.$destroy();
this.popup.remove();
this.popup = 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: '=?'
}
});