326 lines
8.9 KiB
JavaScript

import { Webcomponent } from "./webcomponent.js";
const config = {
item: ".tab-item",
content: ".tab-content"
};
class UiPopup extends Webcomponent {
constructor() {
super();
this.fetch_template();
this.message = this.querySelector('.message');
this.title = this.querySelector('.title');
this.replaceVarsPlaceholder().attach().render();
this.init();
this.handleOptions();
}
handleOptions() {
if ( this.options ) {
if ( ! this.options['skip-keys'] ) {
document.addEventListener('keyup', function(e) {
if ( this.visible() ) {
let trigger, ev;
e.preventDefault();
// There's no real value in checking if the popup is shown or not.
switch ( e.keyCode ) {
// RETURN
case 13:
trigger = this.querySelector('[action="confirm"]');
ev = new CustomEvent('click', { trigger: trigger } );
trigger.dispatchEvent(ev);
break;
// ESC
case 27:
trigger = this.querySelector('[action="close"]');
ev = new CustomEvent('click', { trigger: trigger } );
trigger.dispatchEvent(ev);
break;
}
}
}.bind(this));
}
}
}
init() {
document.addEventListener('keyup', function(e) {
if ( this.visible() ) {
let trigger, ev;
e.preventDefault();
// There's no real value in checking if the popup is shown or not.
switch ( e.keyCode ) {
case 13: // RETURN
trigger = this.querySelector('[action="confirm"]');
ev = new CustomEvent('click', { trigger: trigger } );
trigger.dispatchEvent(ev);
break;
case 8: // BACKSPACE
case 27: // ESC
trigger = this.querySelector('[action="close"]');
ev = new CustomEvent('click', { trigger: trigger } );
trigger.dispatchEvent(ev);
break;
}
}
}.bind(this));
}
attach() {
let triggers = document.querySelectorAll('[ui-popup]');
if ( triggers.length ) {
triggers.forEach(function(item) {
let trigger_args = this._parseTriggerArguments(item);
if ( trigger_args.name === this.getAttribute('name') ) {
item.addEventListener('click', this.triggerAction.bind(this, item, trigger_args));
}
this.options = trigger_args.options;
}.bind(this));
}
return this;
}
render() {
this.querySelectorAll('[action]').forEach(function(element) {
element.addEventListener("click", this.action.bind(this, element), false);
}.bind(this));
this.hide();
}
action(element, e) {
if ( ! element.attributes.action ) {
throw "A button was clicked onto which no action was bound.";
}
switch(element.attributes.action.value) {
case "confirm":
case "yes":
case "ok":
this.actionFollowLink(element) ||
this.actionClickButton(element) ||
this.actionSendForm(element) ||
this.actionSendForm(this.trigger);
case "cancel":
case "no":
case "close":
this.hide();
break;
}
this.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
this.trigger.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
if ( element.getAttribute("action") ) {
e.preventDefault();
}
return true;
}
hide() {
this.classList.remove('visible');
}
show() {
this.classList.add('visible');
}
visible() {
return this.classList.contains('visible');
}
actionFollowLink(element) {
//if ( element.getAttribute('follow-link') !== null ) {
// Automatically redirect to given location if it exists.
if ( this.trigger.tagName === "A" ) {
let href = this.trigger.getAttribute('href');
if ( href ) {
window.location = href;
return true;
}
}
//}
return false;
}
actionClickButton(element) {
//if ( element.getAttribute('button-click') !== null ) {
let tag = this.trigger.tagName.toLowerCase();
// Automatically redirect to given location if it exists.
if ( tag === "button" || ( ( tag === "input" ) && ( this.trigger.getAttribute("type").toLowerCase() === "submit") ) ) {
this.pause = true;
this.trigger.click();
this.pause = false;
return true;
}
//}
return false;
}
actionSendForm(element) {
//if ( element.getAttribute('send-form') !== null ) {
//let form = this.trigger.tagName === "FORM" ? this.trigger : this.trigger.closest('FORM');
let form = element.tagName === "FORM" ? element : element.closest('FORM');
if ( form ) {
form.submit();
return true;
}
else {
throw "A send-form action was set on a popup where the trigger as no parent form.";
}
//}
}
triggerAction(item, args, e) {
if (this.pause) {
return false;
}
e.preventDefault();
this.trigger = item;
args.vars && Object.keys(args.vars).map(function(objectKey, index) {
// let element = this.message.querySelectorAll(`.${objectKey}`);
let element = Array.prototype.slice.call( this.message.querySelectorAll(`.${objectKey}`) ).concat(Array.prototype.slice.call(this.title.querySelectorAll(`.${objectKey}`)));
element.length ? element.forEach(function(item) {
item.innerHTML = args.vars[objectKey];
}) : ( function() {
console.warn(`Variable '${objectKey}' could not be found within popup's message`);
} )();
}.bind(this));
if ( args.options ) {
args.options['input'] && Object.keys(args.options['input']).forEach(
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) {
if (f.tagName === "TEXTAREA") {
f.value = args.options['input'][key];
}
else {
f.setAttribute("value", args.options['input'][key]);
}
f.dispatchEvent(new Event("change"));
})
);
}
this.show();
return true;
}
replaceVarsPlaceholder() {
let setVar = function(match, varname) {
let element = document.createElement('span');
element.classList.add('variable', varname);
return element.outerHTML;
};
this.message.innerHTML = this.message.innerHTML.replace(/{\$(.*?)}/g, setVar);
this.title.innerHTML = this.title.innerHTML.replace(/{\$(.*?)}/g, setVar);
return this;
}
get trigger() {
return this._trigger;
}
set trigger(value) {
return this._trigger = value;
}
get pause() {
return this._pause;
}
set pause(value) {
return this._pause = value;
}
get message() {
return this._message;
}
set message(value) {
return this._message = value;
}
get title() {
return this._title;
}
set title(value) {
return this._title = value;
}
get action_func() {
return this._action_func;
}
set action_func(value) {
return this._action_func = value;
}
_parseTriggerArguments(item) {
let attr = item.getAttribute('ui-popup').trim();
if ( attr.charAt(0) === '{' ) {
try {
return JSON.parse(attr);
}
catch(error) {
console.error("Popup trigger failed on JSON parsing of " + attr + " from object:", item);
}
}
else if ( typeof attr === "string" && attr.length ) {
return {
name: attr
};
}
else {
throw "A popup name must be given to attach this object.";
}
}
}
export { UiPopup }