salix/front/core/components/dialog/dialog.js

131 lines
3.5 KiB
JavaScript

import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
/**
* Dialog component.
*
* @property {HTMLElement} body The dialog HTML body
* @property {HTMLElement} buttons The dialog HTML buttons
*/
export default class Dialog extends Component {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.shown = false;
this.$element.addClass('vn-dialog');
this.element.addEventListener('mousedown',
e => this.onBackgroundMouseDown(e));
if ($transclude) {
$transclude($scope.$parent, tClone => {
this.body = tClone[0];
}, null, 'body');
$transclude($scope.$parent, tClone => {
this.buttons = tClone[0];
}, null, 'buttons');
}
}
set body(value) {
this.element.querySelector('.body').appendChild(value);
}
set buttons(value) {
this.element.querySelector('.buttons').appendChild(value);
}
/**
* Displays the dialog to the user.
*/
show() {
if (this.shown) return;
this.shown = true;
this.keyDownHandler = e => this.onkeyDown(e);
this.document.addEventListener('keydown', this.keyDownHandler);
this.element.style.display = 'flex';
this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
if (this.onOpen)
this.onOpen();
let firstFocusable = this.element.querySelector('input, textarea');
if (firstFocusable) firstFocusable.focus();
}
/**
* Hides the dialog calling the response handler.
*/
hide() {
this.fireResponse();
this.realHide();
}
/**
* Calls the response handler.
*
* @param {String} response The response code
* @return {Boolean} %true if response was canceled, %false otherwise
*/
fireResponse(response) {
let cancel = false;
if (this.onResponse)
cancel = this.onResponse({response: response});
return cancel;
}
realHide() {
if (!this.shown) return;
this.element.style.display = 'none';
this.document.removeEventListener('keydown', this.keyDownHandler);
this.lastEvent = null;
this.shown = false;
this.transitionTimeout = setTimeout(() => this.$element.removeClass('shown'), 30);
}
onButtonClick(event) {
let buttons = this.element.querySelector('.buttons');
let tplButtons = buttons.querySelector('tpl-buttons');
let node = event.target;
while (node.parentNode != tplButtons) {
if (node == buttons) return;
node = node.parentNode;
}
let response = node.getAttribute('response');
let cancel = this.fireResponse(response);
if (cancel !== false) this.realHide();
}
onDialogMouseDown(event) {
this.lastEvent = event;
}
onBackgroundMouseDown(event) {
if (event != this.lastEvent)
this.hide();
}
onkeyDown(event) {
if (event.keyCode == 27) // Esc
this.hide();
}
$onDestroy() {
clearTimeout(this.transitionTimeout);
}
}
Dialog.$inject = ['$element', '$scope', '$transclude'];
ngModule.component('vnDialog', {
template: require('./dialog.html'),
transclude: {
body: 'tplBody',
buttons: '?tplButtons'
},
bindings: {
onOpen: '&?',
onResponse: '&?'
},
controller: Dialog
});