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

141 lines
3.3 KiB
JavaScript

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'));
}]);