355 lines
11 KiB
JavaScript
355 lines
11 KiB
JavaScript
import ol_control_Control from 'ol/control/Control.js'
|
|
import ol_ext_element from '../util/element.js'
|
|
|
|
/**
|
|
* @classdesc
|
|
* Application dialog
|
|
* @extends {ol_control_Control}
|
|
* @constructor
|
|
* @fires show
|
|
* @fires hide
|
|
* @fires cancel
|
|
* @fires button
|
|
* @param {*} options
|
|
* @param {string} options.className
|
|
* @param {ol.Map} options.map the map to place the dialog inside
|
|
* @param {Element} options.target target to place the dialog
|
|
* @param {boolean} options.fullscreen view dialog fullscreen (same as options.target = document.body)
|
|
* @param {boolean} options.zoom add a zoom effect
|
|
* @param {boolean} options.closeBox add a close button
|
|
* @param {number} options.max if not null add a progress bar to the dialog, default null
|
|
* @param {boolean} options.hideOnClick close dialog when click
|
|
* @param {boolean} options.hideOnBack close dialog when click the background
|
|
* @param {boolean} options.closeOnSubmit Prevent closing the dialog on submit
|
|
*/
|
|
var ol_control_Dialog = class olcontrolDialog extends ol_control_Control {
|
|
constructor(options) {
|
|
options = options || {};
|
|
if (options.fullscreen) options.target = document.body;
|
|
var fullscreen = (options.target === document.body);
|
|
|
|
var element = ol_ext_element.create(fullscreen ? 'DIALOG' : 'DIV', {
|
|
className: ((options.className || '') + (options.zoom ? ' ol-zoom' : '') + ' ol-ext-dialog').trim()
|
|
})
|
|
super({
|
|
element: element,
|
|
target: options.target
|
|
});
|
|
|
|
if (fullscreen) {
|
|
// Handle close (DIALOG)
|
|
element.addEventListener('close', function(){
|
|
this.hide();
|
|
}.bind(this));
|
|
// Prevent cancel (DIALOG on escape)
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key !== 'Escape') return;
|
|
if (!this.get('closeBox') && this.isOpen()) {
|
|
e.preventDefault()
|
|
}
|
|
}.bind(this))
|
|
// Cancel event
|
|
element.addEventListener('cancel', function() {
|
|
setTimeout(function() { this.dispatchEvent('cancel'); }.bind(this))
|
|
}.bind(this));
|
|
}
|
|
|
|
// Constructor
|
|
element.addEventListener('click', function (e) {
|
|
if (this.get('hideOnBack') && e.target === element) this.close();
|
|
if (this.get('hideOnClick')) this.close();
|
|
}.bind(this));
|
|
// form
|
|
var form = ol_ext_element.create('FORM', {
|
|
on: {
|
|
submit: this._onButton('submit')
|
|
},
|
|
parent: element
|
|
});
|
|
// Title
|
|
ol_ext_element.create('H2', {
|
|
parent: form
|
|
});
|
|
// Close box
|
|
ol_ext_element.create('DIV', {
|
|
className: 'ol-closebox',
|
|
click: this._onButton('cancel'),
|
|
parent: form
|
|
});
|
|
// Content
|
|
ol_ext_element.create('DIV', {
|
|
className: 'ol-content',
|
|
parent: form
|
|
});
|
|
// Progress
|
|
this._progress = ol_ext_element.create('DIV', {
|
|
style: { display: 'none' },
|
|
parent: form
|
|
});
|
|
var bar = ol_ext_element.create('DIV', {
|
|
className: 'ol-progress-bar',
|
|
parent: this._progress
|
|
});
|
|
this._progressbar = ol_ext_element.create('DIV', {
|
|
parent: bar
|
|
});
|
|
this._progressMessage = ol_ext_element.create('DIV', {
|
|
className: 'ol-progress-message',
|
|
parent: this._progress
|
|
});
|
|
// Buttons
|
|
ol_ext_element.create('DIV', {
|
|
className: 'ol-buttons',
|
|
parent: form
|
|
});
|
|
|
|
this.set('closeBox', options.closeBox !== false);
|
|
this.set('zoom', !!options.zoom);
|
|
this.set('hideOnClick', !!options.hideOnClick);
|
|
this.set('hideOnBack', !!options.hideOnBack);
|
|
this.set('className', element.className);
|
|
this.set('closeOnSubmit', options.closeOnSubmit);
|
|
this.set('buttons', options.buttons);
|
|
this.setContent(options);
|
|
}
|
|
/** Show a new dialog
|
|
* @param { * | Element | string } options options or a content to show
|
|
* @param {Element | String} options.content dialog content
|
|
* @param {string} options.title title of the dialog
|
|
* @param {string} options.className dialog class name
|
|
* @param {number} options.autoclose a delay in ms before auto close
|
|
* @param {boolean} options.hideOnBack close dialog when click the background
|
|
* @param {number} options.max if not null add a progress bar to the dialog
|
|
* @param {number} options.progress set the progress bar value
|
|
* @param {Object} options.buttons a key/value list of button to show
|
|
* @param {function} [options.onButton] a function that takes the button id and a list of input by className
|
|
*/
|
|
show(options) {
|
|
if (options) {
|
|
if (options instanceof Element || typeof (options) === 'string') {
|
|
options = { content: options };
|
|
}
|
|
this.setContent(options);
|
|
}
|
|
if (this.element.showModal) this.element.showModal();
|
|
this.element.classList.add('ol-visible');
|
|
this.element.setAttribute('aria-hidden', false);
|
|
var input = this.element.querySelector('input[type="text"],input[type="search"],input[type="number"]');
|
|
if (input) {
|
|
setTimeout(function() { input.focus(); })
|
|
}
|
|
this.dispatchEvent({ type: 'show' });
|
|
if (options) {
|
|
// Auto close
|
|
if (options.autoclose) {
|
|
var listener = setTimeout(function () { this.hide(); }.bind(this), options.autoclose);
|
|
this.once('hide', function () {
|
|
clearTimeout(listener);
|
|
});
|
|
}
|
|
// hideOnBack
|
|
if (options.hideOnBack) {
|
|
// save value
|
|
var value = this.get('hideOnBack');
|
|
this.set('hideOnBack', true);
|
|
this.once('hide', function () {
|
|
this.set('hideOnBack', value);
|
|
}.bind(this));
|
|
}
|
|
}
|
|
}
|
|
/** Open the dialog
|
|
*/
|
|
open() {
|
|
this.show();
|
|
}
|
|
/** Set the dialog content
|
|
* @param {Element | String} content dialog content
|
|
*/
|
|
setContentMessage(content) {
|
|
if (content !== undefined) {
|
|
var elt = this.getContentElement();
|
|
if (content instanceof Element)
|
|
ol_ext_element.setHTML(elt, '');
|
|
ol_ext_element.setHTML(elt, content || '');
|
|
}
|
|
}
|
|
/** Set the dialog title
|
|
* @param {Element | String} content dialog content
|
|
*/
|
|
setTitle(title) {
|
|
var form = this.element.querySelector('form');
|
|
form.querySelector('h2').innerText = title || '';
|
|
if (title) {
|
|
form.classList.add('ol-title');
|
|
} else {
|
|
form.classList.remove('ol-title');
|
|
}
|
|
}
|
|
/** Set the dialog content
|
|
* @param {*} options
|
|
* @param {Element | String} options.content dialog content
|
|
* @param {string} options.title title of the dialog
|
|
* @param {string} options.className dialog class name
|
|
* @param {number} options.max if not null add a progress bar to the dialog
|
|
* @param {number} options.progress set the progress bar value
|
|
* @param {Object} options.buttons a key/value list of button to show
|
|
* @param {function} [options.onButton] a function that takes the button id and a list of input by className
|
|
*/
|
|
setContent(options) {
|
|
if (!options)
|
|
return;
|
|
this.element.className = this.get('className');
|
|
if (typeof (options) === 'string')
|
|
options = { content: options };
|
|
options = options || {};
|
|
this.setProgress(false);
|
|
if (options.max)
|
|
this.setProgress(0, options.max);
|
|
if (options.progress !== undefined)
|
|
this.setProgress(options.progress);
|
|
//this.element.className = 'ol-ext-dialog' + (this.get('zoom') ? ' ol-zoom' : '');
|
|
if (this.get('zoom'))
|
|
this.element.classList.add('ol-zoom');
|
|
else
|
|
this.element.classList.remove('ol-zoom');
|
|
if (options.className) {
|
|
options.className.split(' ').forEach(function (c) {
|
|
this.element.classList.add(c);
|
|
}.bind(this));
|
|
}
|
|
var form = this.element.querySelector('form');
|
|
// Content
|
|
if (options.content !== undefined) {
|
|
if (options.content instanceof Element)
|
|
ol_ext_element.setHTML(form.querySelector('.ol-content'), '');
|
|
ol_ext_element.setHTML(form.querySelector('.ol-content'), options.content || '');
|
|
}
|
|
// Title
|
|
this.setTitle(options.title);
|
|
// Closebox
|
|
if (options.closeBox || (this.get('closeBox') && options.closeBox !== false)) {
|
|
form.classList.add('ol-closebox');
|
|
} else {
|
|
form.classList.remove('ol-closebox');
|
|
}
|
|
// Buttons
|
|
var buttons = this.element.querySelector('.ol-buttons');
|
|
buttons.innerHTML = '';
|
|
var btn = options.buttons || this.get('buttons');
|
|
if (btn) {
|
|
form.classList.add('ol-button');
|
|
for (var i in btn) {
|
|
ol_ext_element.create('INPUT', {
|
|
type: (i === 'submit' ? 'submit' : 'button'),
|
|
value: btn[i],
|
|
click: this._onButton(i, options.onButton),
|
|
parent: buttons
|
|
});
|
|
}
|
|
} else {
|
|
form.classList.remove('ol-button');
|
|
}
|
|
}
|
|
/** Get dialog content element
|
|
* @returns {Element}
|
|
*/
|
|
getContentElement() {
|
|
return this.element.querySelector('form .ol-content');
|
|
}
|
|
/** Set progress
|
|
* @param {number|boolean} val the progress value or false to hide the progressBar
|
|
* @param {number} max
|
|
* @param {string|element} message
|
|
*/
|
|
setProgress(val, max, message) {
|
|
if (val === false) {
|
|
ol_ext_element.setStyle(this._progress, { display: 'none' });
|
|
return;
|
|
}
|
|
if (max > 0) {
|
|
this.set('max', Number(max));
|
|
} else {
|
|
max = this.get('max');
|
|
}
|
|
if (!max) {
|
|
ol_ext_element.setStyle(this._progress, { display: 'none' });
|
|
} else {
|
|
var p = Math.round(val / max * 100);
|
|
ol_ext_element.setStyle(this._progress, { display: '' });
|
|
this._progressbar.className = p ? '' : 'notransition';
|
|
ol_ext_element.setStyle(this._progressbar, { width: p + '%' });
|
|
}
|
|
this._progressMessage.innerHTML = '';
|
|
ol_ext_element.setHTML(this._progressMessage, message || '');
|
|
}
|
|
/** Returns a function to do something on button click
|
|
* @param {strnig} button button id
|
|
* @param {function} callback
|
|
* @returns {function}
|
|
* @private
|
|
*/
|
|
_onButton(button, callback) {
|
|
// Dispatch a button event
|
|
var fn = function (e) {
|
|
e.preventDefault();
|
|
if (button !== 'submit' || this.get('closeOnSubmit') !== false) this.hide();
|
|
var inputs = this.getInputs();
|
|
setTimeout(function() {
|
|
this.dispatchEvent({ type: 'button', button: button, inputs: inputs });
|
|
if (typeof (callback) === 'function') callback(button, inputs);
|
|
}.bind(this))
|
|
}.bind(this);
|
|
return fn;
|
|
}
|
|
/** Get inputs, textarea an select of the dialog by classname
|
|
* @return {Object} a {key:value} list of Elements by classname
|
|
*/
|
|
getInputs() {
|
|
var inputs = {};
|
|
['input', 'textarea', 'select'].forEach(function (type) {
|
|
this.element.querySelectorAll('form ' + type).forEach(function (input) {
|
|
if (input.className) {
|
|
input.className.split(' ').forEach(function (n) {
|
|
inputs[n] = input;
|
|
});
|
|
}
|
|
});
|
|
}.bind(this));
|
|
return inputs;
|
|
}
|
|
/** Close the dialog
|
|
*/
|
|
hide() {
|
|
// Remove focus on dialog
|
|
if (document.activeElement && document.activeElement !== document.body) {
|
|
document.activeElement.blur();
|
|
}
|
|
// DIALOG element
|
|
if (this.element.close) {
|
|
this.element.close();
|
|
}
|
|
if (this.isOpen()) {
|
|
this.element.classList.remove('ol-visible');
|
|
this.element.setAttribute('aria-hidden', true)
|
|
// Dispatch event when close
|
|
setTimeout(function() {
|
|
this.dispatchEvent({ type: 'hide' });
|
|
}.bind(this))
|
|
}
|
|
}
|
|
/** Close the dialog
|
|
*/
|
|
close() {
|
|
this.hide();
|
|
}
|
|
/** The dialog is shown
|
|
* @return {bool} true if a dialog is open
|
|
*/
|
|
isOpen() {
|
|
return (this.element.classList.contains('ol-visible'));
|
|
}
|
|
}
|
|
|
|
export default ol_control_Dialog
|