381 lines
10 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');
if (!this.message) {
this.message = document.createElement("div");
}
if (!this.title) {
this.title = document.createElement("div");
}
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, action;
e.preventDefault();
// There's no real value in checking if the popup is shown or not.
switch ( e.keyCode ) {
case 13: // RETURN
action = "confirm";
break;
case 27: // ESC
action = "close";
break
}
if (action) {
trigger = this.querySelector(`[action="${action}"]`);
if ( trigger ) {
ev = new CustomEvent('click', {trigger: trigger});
trigger.dispatchEvent(ev);
}
else {
this.hide();
}
}
}
}.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]:not(form)').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":
let retval = this.actionFollowLink(element) ||
this.actionClickButton(element);
if (! retval) {
retval = this.actionSendForm(element) ||
this.actionSendForm(this.trigger) ||
this.actionSendForm(this.querySelector('[slot="message"] form')) ||
this.actionSendForm(this.querySelector('[slot="title"] form')) ||
this.actionSendForm(this.querySelector('[slot="buttons"] form'));
if ( ! retval ) {
throw "No action to trigger automatically on Popup confirmation.";
}
break;
}
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 ) {
return false;
}
//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.addEventListener("submit", e => this.hide, { once: true });
let submitBtn = form.querySelector("button[type='submit']");
if (submitBtn) {
submitBtn.click();
}
else {
form.submit();
}
return true;
}
return false;
//}
}
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 = 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 ) {
if (args.options['clear_input']) {
let skipInput = args.options['clear_input']['skip'] ? args.options['clear_input']['skip'] : [];
this.querySelectorAll(`input,textarea`).forEach(function(f) {
if (! skipInput.includes(f.name)) {
f.value = "";
}
});
}
args.options['input'] && Object.keys(args.options['input']).forEach(
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) {
console.log(f);
f.value = args.options['input'][key];
f.dispatchEvent(new Event("change"));
})
);
args.options['form_url'] && Object.keys(args.options['form_url']).forEach(
key => {
let form = this.querySelector(`form${key}`);
if (form) {
form.setAttribute('action', args.options['form_url'][key]);
}
else {
console.warn(`Form selector '${key}' could not be found within popup.`);
}
}
);
}
this.show();
e.stopPropagation();
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 }