ol-ext
Version:
A set of cool extensions for OpenLayers (ol) in node modules structure
355 lines (348 loc) • 12.1 kB
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