diff --git a/dist/powerbuttons.compress.js b/dist/powerbuttons.compress.js index 6327019..08f8a55 100644 --- a/dist/powerbuttons.compress.js +++ b/dist/powerbuttons.compress.js @@ -1,2 +1,2 @@ /* Copyright 2021 Carlos A. (https://github.com/dealfonso); License: http://www.apache.org/licenses/LICENSE-2.0 */ -!function(exports){var exports;function pascalToSnake(t){return t.replace(/[A-Z]/g,t=>"_"+t.toLowerCase()).replace(/^_*/,"")}function pascalToKebab(t){return t.replace(/[A-Z]/g,t=>"-"+t.toLowerCase()).replace(/^-*/,"")}function snakeCaseToCamel(t){t.replace(/-([a-z])/g,t=>t[1].toUpperCase())}function pascalToCamel(t){return t.charAt(0).toLowerCase()+t.slice(1)}function CamelToCamel(t){return t.charAt(0).toUpperCase()+t.slice(1)}function isElement(t){t instanceof Element||0 instanceof HTMLDocument}function parseBoolean(t){return"boolean"==typeof t?t:"string"==typeof t?"true"===(t=t.toLowerCase())||"yes"===t||"1"===t:!!t}function createTag(t,e={},n=null){var o=t.split("#");let s=null;var i,o=(t=1==o.length?o[0]:(o[1]=o[1].split("."),s=o[1][0],[o[0],...o[1].slice(1)].join("."))).split("."),l=(""===(t=o[0])&&(t="div"),"string"==typeof e&&(n=e,e={}),null!==n&&(e.innerHTML=n),null!==s&&(e.id=s),e.className=[e.className,...o.slice(1)].filter(function(t){return""!==(""+t).trim()}).join(" "),document.createElement(t));for(i in e)void 0!==l[i]?l[i]=e[i]:l.setAttribute(i,e[i]);return l}function appendToElement(t,...e){e=e.filter(t=>null!=t);return t.append(...e),t}function searchForm(t){let e=null;return null!==t&&void 0===(e=document.forms[t])&&null===(e=document.querySelector(t))&&console.warn(`form ${t} not found`),null!==e&&"form"!==e.tagName.toLowerCase()&&console.warn(`form ${t} is not a form`),e}function getValueWithJavascriptSupport(value,context=null){if("function"==typeof value)return value.bind(context);if("string"==typeof value){let internalValue=value.trim();if(internalValue.startsWith("javascript:"))try{let f=internalValue.substring(11);value=function(){return eval(f)}.bind(context)}catch(e){console.error(`Error executing javascript code ${internalValue.substring(11)}, error: `+e),value=null}}return value}function promiseForEvent(e,n){let o=null;var t=new Promise(t=>{o=t});return e.addEventListener(n,function t(){e.removeEventListener(n,t),o()}),t}function isEmpty(t){return null==t||(t instanceof Array?0===t.length:t instanceof Object?0===Object.keys(t).length:"string"==typeof t&&""===t.trim())}void 0===exports&&(exports=window),exports.powerButtons=function(t,e=[],n={}){let o=e,s=("string"==typeof o?o=document.querySelectorAll(o):void 0===o.length&&(o=[o]),null);for(var i in PowerButtons.actionsRegistered)if(t.toLocaleLowerCase()===i.toLocaleLowerCase()){s=PowerButtons.actionsRegistered[i];break}if(void 0===s)console.error(`The action ${t} is not registered`);else for(var l of o)s.initialize(l,n);return e},exports.powerButtons.version="2.0.1",exports.powerButtons.plugins=function(){return Object.keys(PowerButtons.actionsRegistered)},void 0!==exports.$&&(exports.$.fn.powerButtons=function(t,e={}){return exports.powerButtons(t,this,e),this},exports.$.fn.powerButtons.version=exports.powerButtons.version,exports.$.fn.powerButtons.plugins=exports.powerButtons.plugins);class DialogLegacy{DEFAULTS={message:"Main message",buttonCount:2};constructor(t={},e=null,n=null){this.options={...this.DEFAULTS,...t},this.buttonCount=this.options.buttons.length,this.options.buttons=["Accept","Cancel"],this.result=null,this.onButton=e,this.onHidden=n}dispose(){}show(t=null,e=null){switch(null!==t&&(this.onButton=t),null!==e&&(this.onHidden=e),this.buttonCount){case 0:case 1:alert(this.message),this.result=0;break;case 2:this.result=confirm(this.options.message)?0:1;break;default:throw"Unsupported button count "+this.buttonCount}null!==this.onButton&&this.onButton(this.result,{button:this.result,text:this.options.buttons[this.result]},null),null!==this.onHidden&&this.onHidden(this.result,{button:this.result,text:this.options.buttons[this.result]},null)}}class Dialog{static create(t={},e=null,n=null){if(void 0===exports.bootstrap||void 0===exports.bootstrap.Modal)return new DialogLegacy(t,e,n);if(void 0!==t.selector&&null!==t.selector||void 0!==t.dialogFunction&&null!==t.dialogFunction)throw new Error("not implemented, yet");return new Dialog(t,e,n)}DEFAULTS={title:"Title",message:"Main message",customContent:null,buttons:["Accept"],buttonClasses:["btn-primary","btn-secondary"],buttonPanelClasses:["text-end"],escapeKeyCancels:!0,header:!0,footer:!0,body:!0,close:!0};dialog=null;options=null;modal=null;onButton=null;result=null;onHidden=null;onButton=null;constructor(t={},e=null,n=null){if(void 0===exports.bootstrap||void 0===exports.bootstrap.Modal)throw new Error("Bootstrap is required to use this class");this.options={...this.DEFAULTS,...t};var o=[];for(let e=0;ethis._handleButton(-1,null,e)),parseBoolean(s.header)&&(t=createTag(".modal-header"),null!==s.title&&t.append(appendToElement(createTag(".modal-title"),appendToElement(createTag("h5",s.title)))),parseBoolean(s.close))&&t.append(e);var i=[];if(null!==s.buttons)for(let o=0;ot.trim()).filter(t=>""!==t).join("."),n=(!1===s.footer&&(e+=".mx-1"),createTag("button.btn"+(e=""!==e?"."+e:e)+".button"+o,{type:"button"},t.text));n.addEventListener("click",function(){this._handleButton(o,t,n),void 0!==t.handler&&null!==t.handler&&t.handler(o,t,n)}.bind(this)),i.push(n)}let n=null,o=(parseBoolean(s.footer)&&(n=appendToElement(createTag(".modal-footer"),...i)),null);if(parseBoolean(s.body)&&(o=createTag(".modal-body"),null===t&&parseBoolean(s.close)&&o.append(appendToElement(createTag(".text-end"),e)),null!==s.message&&o.append(createTag("p.message.text-center",s.message)),null!==s.customContent&&o.append(createTag(".custom-content.mx-auto",s.customContent)),null===n)){let t=s.buttonPanelClasses.map(t=>t.trim()).filter(t=>""!==t).join(".");""!==t&&(t="."+t),appendToElement(o,appendToElement(createTag(".buttons"+t),...i))}return appendToElement(createTag(".modal.fade",{tabindex:"-1",role:"dialog","aria-hidden":"true","data-keyboard":"false"}),appendToElement(createTag(".modal-dialog.modal-dialog-centered",{role:"document"}),appendToElement(createTag(".modal-content"),t,o,n)))}}function confirmDialog(t,e="this action needs confirmation",n=null,o=null,s=!0){e=new Dialog({title:e,message:t,buttons:[{text:"Cancel",class:"btn-secondary",handler:o},{text:"Confirm",class:"btn-primary",handler:n}],escapeKeyCancels:s});return e.show(),e}function alertDialog(t,e="Alert",n=null){e=new Dialog({title:e,message:t,buttons:[{text:"Accept",class:"btn-primary",handler:n}],escapeKeyCancels:!0});return e.show(),e}function loadingDialog(t,e=null,n=null){"function"==typeof e&&(n=e,e=null);t=new Dialog({title:null,message:t,buttons:[{text:"Cancel",class:"btn-primary"}],customContent:e,escapeKeyCancels:!1,close:!1,header:!1,footer:!1},n);return t.show(),t}void 0===exports.powerButtons.utils&&(exports.powerButtons.utils={}),Object.assign(exports.powerButtons.utils,{confirmDialog:confirmDialog,alertDialog:alertDialog,loadingDialog:loadingDialog});class PowerButtons{static actionsRegistered={};static registerAction(t){this.actionsRegistered[t.NAME.toLowerCase()]=t,void 0===exports.powerButtons&&(exports.powerButtons={}),void 0===exports.powerButtons.defaults&&(exports.powerButtons.defaults={}),exports.powerButtons.defaults[t.NAME.toLowerCase()]=Object.assign({},t.DEFAULTS)}static getActionSettings(t,e){if(void 0===this.actionsRegistered[t.NAME.toLowerCase()])return console.error(`The action ${t.NAME} is not registered`),{};let n={};return void 0!==exports.powerButtons&&void 0!==exports.powerButtons.defaults&&void 0!==exports.powerButtons.defaults[t.NAME.toLowerCase()]&&(n=exports.powerButtons.defaults[t.NAME.toLowerCase()]),Object.assign({},t.DEFAULTS,n,e)}static addAction(t,e={}){PowerButtons.addActionSupport(t).appendAction(e)}static addActionSupport(t){return void 0===t._powerButtons?t._powerButtons=new PowerButtons(t):t._powerButtons.reset(),t._powerButtons}el=null;current_action=0;actions=[];back_onclick=null;constructor(t){(t._powerButtons=this).el=t,this.current_action=0,this.actions=[],this.back_onclick=null,void 0!==t.onclick&&null!==t.onclick&&(this.back_onclick=t.onclick,t.onclick=null),t.addEventListener("click",this.handlerClick.bind(this))}appendAction(t={}){if(void 0===t.type)throw"The type of the action is mandatory";this.actions.push(t)}handlerClick(t){if(this.current_action>=this.actions.length)this.current_action=0,"function"!=typeof this.back_onclick||this.back_onclick()||t.preventDefault();else{var e=this.actions[this.current_action],n=(t.preventDefault(),t.stopImmediatePropagation(),function(){this.current_action++,this.current_action>=this.actions.length&&void 0!==this.el.click?this.el.click():this.el.dispatchEvent(new Event(t.type,t))}.bind(this)),o=this.constructor.actionsRegistered[e.type];if(void 0===o)throw`The action ${e.type} is not registered`;o.execute(this.el,e,n,()=>this.reset())}}reset(){this.current_action=0}static initializeAll(){Object.entries(this.actionsRegistered).forEach(([,t])=>{t.initializeAll()})}}function init(){PowerButtons.initializeAll()}void 0!==document.addEventListener&&document.addEventListener("DOMContentLoaded",function(t){init()});class Action{static NAME=null;static register(){PowerButtons.registerAction(this)}static DEFAULTS={};static extractOptions(t,e=null,n=null){null===e&&(e=this.NAME.toLowerCase()),null===n&&((n={})[e]=e);var o,s={};for(o in this.DEFAULTS){var i=void 0!==n[i=o]?n[i]:e+CamelToCamel(i);void 0!==t.dataset[i]&&(s[o]=t.dataset[i])}return s}static initialize(t,e={}){PowerButtons.addAction(t,Object.assign({type:this.NAME.toLowerCase()},e))}static initializeAll(t=null){var e,n=this.NAME.toLowerCase();for(e of document.querySelectorAll("[data-"+n)){var o=null===t?this.extractOptions(e,n):Object.assign({},t);this.initialize(e,o)}}static execute(t,e,n,o){throw new Error("The execute method must be implemented by the derived class")}}class ActionVerify extends Action{static NAME="Verify";static DEFAULTS={verify:null,form:null,verified:null,notVerified:"The condition for this action is not met",customContentVerified:null,customContentNotVerified:null,titleNotVerified:"The action requires verification",titleVerified:null,buttonAccept:"Accept",buttonClose:!1,escapeKey:!0,header:!0,footer:!0};static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options),result=null,bindObject=searchForm(settings.form);null===bindObject&&(bindObject=document);try{result="function"==typeof settings.verify?settings.verify.bind(bindObject)():"string"==typeof settings.verify?function(){return eval(settings.verify)}.bind(bindObject)():parseBoolean(settings.verify)}catch(e){console.error("Error executing verification function",e),result=!1}let dialog=null,onVerificationSuccess=onNextAction,onVerificationFailure=onCancelActions;result?null===settings.verified&&null===settings.customContentVerified&&null===settings.titleVerified||(dialog=Dialog.create({title:settings.titleVerified,message:settings.verified,customContent:settings.customContentVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){null!==onVerificationSuccess&&onVerificationSuccess()})):null===settings.notVerified&&null===settings.customContentNotVerified&&null===settings.titleNotVerified||(dialog=Dialog.create({title:settings.titleNotVerified,message:settings.notVerified,customContent:settings.customContentNotVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){null!==onVerificationFailure&&onVerificationFailure()})),null!==dialog?dialog.show():result?null!==onVerificationSuccess&&onVerificationSuccess():null!==onVerificationFailure&&onVerificationFailure()}}ActionVerify.register();class ActionConfirm extends Action{static NAME="Confirm";static DEFAULTS={confirm:"Please confirm this action",customContent:null,title:"The action requires confirmation",buttonConfirm:"Confirm",buttonCancel:"Cancel",buttonClose:!0,escapeKey:!0};static extractOptions(t,e=null,n=null){t=super.extractOptions(t,e,n);return""==t.confirm.trim()&&delete t.confirm,t}static execute(t,e,n,o){e=PowerButtons.getActionSettings(this,e);Dialog.create({title:e.title,message:e.confirm,customContent:e.customContent,buttons:[e.buttonConfirm,e.buttonCancel],escapeKeyCancels:e.escapeKey,close:e.buttonClose},null,function(t){0===t?null!==n&&n():null!==o&&o()}).show()}}ActionConfirm.register();class ActionAsyncTask extends Action{static NAME="AsyncTask";static DEFAULTS={task:null,message:"Please wait...",customContent:null,title:null,buttonCancel:"Cancel",cancel:null,header:!0,footer:!0};static extractOptions(t,e=null,n){return super.extractOptions(t,e,{task:"asynctask"})}static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);if(null===settings.task)console.error("The task to execute cannot be null");else{let task=null;if("string"==typeof settings.task)task=async function(){return eval(settings.task)};else{if("function"!=typeof settings.task)return void console.error("The task to execute must be either a string or a function");task=settings.task}let buttons=[],cancelHandler=null,dialog=(null!==settings.cancel&&(buttons=[settings.buttonCancel],"string"==typeof settings.cancel?cancelHandler=function(){eval(settings.cancel)}:"function"==typeof settings.cancel?cancelHandler=settings.cancel:console.error("The cancel handler must be either a string or a function")),Dialog.create({title:settings.title,message:settings.message,customContent:settings.customContent,buttons:buttons,escapeKeyCancels:!1,close:!1,header:void 0!==options.header?settings.header:null!==settings.title&&""!=settings.title,footer:void 0!==options.footer?settings.footer:null!==cancelHandler},function(){cancelHandler(),onCancelActions()},function(t){null!==onNextAction&&onNextAction()}));dialog.show().then(function(){task().finally(function(){dialog.hide()})})}}}ActionAsyncTask.register();class ActionShowMessage extends Action{static NAME="ShowMessage";static DEFAULTS={showmessage:"This is a message",customContent:null,title:null,buttonAccept:"Accept",escapeKey:!0,buttonClose:!0,header:!0,footer:!0};static execute(t,e,n,o){var s=PowerButtons.getActionSettings(this,e);Dialog.create({title:s.title,message:s.showmessage,customContent:s.customContent,buttons:[s.buttonAccept],escapeKeyCancels:s.escapeKey,close:s.buttonClose,header:void 0!==e.header?s.header:null!==s.title&&""!=s.title,footer:void 0!==e.footer?s.footer:null!==s.buttonAccept&&""!=s.buttonAccept},null,function(t){null!==n&&n()}).show()}}ActionShowMessage.register();class ActionFormset extends Action{static NAME="Formset";static DEFAULTS={form:null,fields:{}};static extractOptions(e,n=null,t){var o,s=super.extractOptions(e,n,{form:"formset"}),i={};for(o in e.dataset)if(o.startsWith(n)){let t=o.substring(n.length);""!==t&&t[0]===t[0].toUpperCase()&&(i[t=t.toLocaleLowerCase()]=e.dataset[o])}return void 0===s.fields&&(s.fields={}),Object.assign(s.fields,i),s}static execute(t,e,n,o){var s,i=PowerButtons.getActionSettings(this,e);let l=null,r=[],a=[];if(""==i.form)null!==t.form?l=t.form:a=Array.from(document.querySelectorAll("input")).filter(t=>null===t.form);else if(null===(l=searchForm(i.form)))return void console.error("Form not found "+i.form);for(s in(a=null!==l?Array.from(l.elements):a).forEach(t=>{""!==t.name&&(r[t.name.toLocaleLowerCase()]=t),""!==t.id&&(r[t.id.toLocaleLowerCase()]=t)}),i.fields)if(void 0!==r[s]){var c=i.fields[s];let t=getValueWithJavascriptSupport(c,null!==l?l:r);if("function"==typeof t)try{t=t()}catch(t){console.error("Error executing "+c,t);continue}r[s].value=t}n()}}ActionFormset.register();class ActionFormButton extends Action{static NAME="FormButton";static DEFAULTS={formbutton:null,method:"post",formClass:"formbutton",convertCase:"none",formId:null,fields:{}};static extractOptions(e,n=null,t=null){var o,s=super.extractOptions(e,n,t),i={};for(o in n+="Field",e.dataset)if(o.startsWith(n)){let t=o.substring(n.length);if(""!==t&&t[0]===t[0].toUpperCase()){switch(s.convertCase){case"kebab":t=pascalToKebab(t);break;case"snake":t=pascalToSnake(t);break;case"camel":t=pascalToCamel(t)}i[t]=e.dataset[o]}}return void 0===s.fields&&(s.fields={}),Object.assign(s.fields,i),s}static initialize(t,e={}){for(var n=PowerButtons.getActionSettings(this,e),o=document.createElement("form"),s=(o.method=n.method,isEmpty(n.formbutton)||(o.action=n.formbutton),null!==n.formId&&(o.id=n.formId),n.formClass.split(" ")),i=0;i"_"+t.toLowerCase()).replace(/^_*/,"")}function pascalToKebab(t){return t.replace(/[A-Z]/g,t=>"-"+t.toLowerCase()).replace(/^-*/,"")}function snakeCaseToCamel(t){t.replace(/-([a-z])/g,t=>t[1].toUpperCase())}function pascalToCamel(t){return t.charAt(0).toLowerCase()+t.slice(1)}function CamelToCamel(t){return t.charAt(0).toUpperCase()+t.slice(1)}function isElement(t){t instanceof Element||0 instanceof HTMLDocument}function parseBoolean(t){return"boolean"==typeof t?t:"string"==typeof t?"true"===(t=t.toLowerCase())||"yes"===t||"1"===t:!!t}function createTag(t,e={},n=null){var o=t.split("#");let s=null;var i,o=(t=1==o.length?o[0]:(o[1]=o[1].split("."),s=o[1][0],[o[0],...o[1].slice(1)].join("."))).split("."),l=(""===(t=o[0])&&(t="div"),"string"==typeof e&&(n=e,e={}),null!==n&&(e.innerHTML=n),null!==s&&(e.id=s),e.className=[e.className,...o.slice(1)].filter(function(t){return""!==(""+t).trim()}).join(" "),document.createElement(t));for(i in e)void 0!==l[i]?l[i]=e[i]:l.setAttribute(i,e[i]);return l}function appendToElement(t,...e){e=e.filter(t=>null!=t);return t.append(...e),t}function searchForm(t){let e=null;return null!==t&&void 0===(e=document.forms[t])&&null===(e=document.querySelector(t))&&console.warn(`form ${t} not found`),null!==e&&"form"!==e.tagName.toLowerCase()&&console.warn(`form ${t} is not a form`),e}function getValueWithJavascriptSupport(value,context=null){if("function"==typeof value)return value.bind(context);if("string"==typeof value){let internalValue=value.trim();if(internalValue.startsWith("javascript:"))try{let f=internalValue.substring(11);value=function(){return eval(f)}.bind(context)}catch(e){console.error(`Error executing javascript code ${internalValue.substring(11)}, error: `+e),value=null}}return value}function promiseForEvent(e,n){let o=null;var t=new Promise(t=>{o=t});return e.addEventListener(n,function t(){e.removeEventListener(n,t),o()}),t}function isEmpty(t){return null==t||(t instanceof Array?0===t.length:t instanceof Object?0===Object.keys(t).length:"string"==typeof t&&""===t.trim())}void 0===exports&&(exports=window),exports.powerButtons=function(t,e=null,n=null){let o=null,s=[],i={};if("string"==typeof t)if(null===(o=function(t){for(var e in PowerButtons.actionsRegistered)if(t.toLocaleLowerCase()===e.toLocaleLowerCase())return e;return null}(t))){if(0===(s=document.querySelectorAll(t)).length)return void console.error(`Parameter ${t} is neither the name of a registered plugin nor a valid selector`);2this._handleButton(-1,null,e)),parseBoolean(s.header)&&(t=createTag(".modal-header"),null!==s.title&&t.append(appendToElement(createTag(".modal-title"),appendToElement(createTag("h5",s.title)))),parseBoolean(s.close))&&t.append(e);var i=[];if(null!==s.buttons)for(let o=0;ot.trim()).filter(t=>""!==t).join("."),n=(!1===s.footer&&(e+=".mx-1"),createTag("button.btn"+(e=""!==e?"."+e:e)+".button"+o,{type:"button"},t.text));n.addEventListener("click",function(){this._handleButton(o,t,n),void 0!==t.handler&&null!==t.handler&&t.handler(o,t,n)}.bind(this)),i.push(n)}let n=null,o=(parseBoolean(s.footer)&&(n=appendToElement(createTag(".modal-footer"),...i)),null);if(parseBoolean(s.body)&&(o=createTag(".modal-body"),null===t&&parseBoolean(s.close)&&o.append(appendToElement(createTag(".text-end"),e)),null!==s.message&&o.append(createTag("p.message.text-center",s.message)),null!==s.customContent&&o.append(createTag(".custom-content.mx-auto",s.customContent)),null===n)){let t=s.buttonPanelClasses.map(t=>t.trim()).filter(t=>""!==t).join(".");""!==t&&(t="."+t),appendToElement(o,appendToElement(createTag(".buttons"+t),...i))}return appendToElement(createTag(".modal.fade",{tabindex:"-1",role:"dialog","aria-hidden":"true","data-keyboard":"false"}),appendToElement(createTag(".modal-dialog.modal-dialog-centered",{role:"document"}),appendToElement(createTag(".modal-content"),t,o,n)))}}function confirmDialog(t,e="this action needs confirmation",n=null,o=null,s=!0){e=new Dialog({title:e,message:t,buttons:[{text:"Cancel",class:"btn-secondary",handler:o},{text:"Confirm",class:"btn-primary",handler:n}],escapeKeyCancels:s});return e.show(),e}function alertDialog(t,e="Alert",n=null){e=new Dialog({title:e,message:t,buttons:[{text:"Accept",class:"btn-primary",handler:n}],escapeKeyCancels:!0});return e.show(),e}function loadingDialog(t,e=null,n=null){"function"==typeof e&&(n=e,e=null);t=new Dialog({title:null,message:t,buttons:[{text:"Cancel",class:"btn-primary"}],customContent:e,escapeKeyCancels:!1,close:!1,header:!1,footer:!1},n);return t.show(),t}void 0===exports.powerButtons.utils&&(exports.powerButtons.utils={}),Object.assign(exports.powerButtons.utils,{confirmDialog:confirmDialog,alertDialog:alertDialog,loadingDialog:loadingDialog});class PowerButtons{static actionsRegistered={};static registerAction(t){this.actionsRegistered[t.NAME.toLowerCase()]=t,void 0===exports.powerButtons&&(exports.powerButtons={}),void 0===exports.powerButtons.defaults&&(exports.powerButtons.defaults={}),exports.powerButtons.defaults[t.NAME.toLowerCase()]=Object.assign({},t.DEFAULTS)}static getActionSettings(t,e){if(void 0===this.actionsRegistered[t.NAME.toLowerCase()])return console.error(`The action ${t.NAME} is not registered`),{};let n={};return void 0!==exports.powerButtons&&void 0!==exports.powerButtons.defaults&&void 0!==exports.powerButtons.defaults[t.NAME.toLowerCase()]&&(n=exports.powerButtons.defaults[t.NAME.toLowerCase()]),Object.assign({},t.DEFAULTS,n,e)}static addAction(t,e={}){PowerButtons.addActionSupport(t).appendAction(e)}static addActionSupport(t){return void 0===t._powerButtons?t._powerButtons=new PowerButtons(t):t._powerButtons.reset(),t._powerButtons}el=null;current_action=0;actions=[];back_onclick=null;constructor(t){(t._powerButtons=this).el=t,this.current_action=0,this.actions=[],this.back_onclick=null,void 0!==t.onclick&&null!==t.onclick&&(this.back_onclick=t.onclick,t.onclick=null),t.addEventListener("click",this.handlerClick.bind(this))}appendAction(t={}){if(void 0===t.type)throw"The type of the action is mandatory";this.actions.push(t)}handlerClick(t){if(this.current_action>=this.actions.length)this.current_action=0,"function"!=typeof this.back_onclick||this.back_onclick()||t.preventDefault();else{var e=this.actions[this.current_action],n=(t.preventDefault(),t.stopImmediatePropagation(),function(){this.current_action++,this.current_action>=this.actions.length&&void 0!==this.el.click?this.el.click():this.el.dispatchEvent(new Event(t.type,t))}.bind(this)),o=this.constructor.actionsRegistered[e.type];if(void 0===o)throw`The action ${e.type} is not registered`;o.execute(this.el,e,n,()=>this.reset())}}reset(){this.current_action=0}static discoverAll(){Object.entries(this.actionsRegistered).forEach(([,t])=>{t.discoverAll()})}static discover(e,n={}){Object.entries(this.actionsRegistered).forEach(([,t])=>{t.discover(e,n)})}}class Action{static NAME=null;static register(){PowerButtons.registerAction(this)}static DEFAULTS={};static extractOptions(t,e=null,n=null){null===e&&(e=this.NAME.toLowerCase()),null===n&&((n={})[e]=e);var o,s={};for(o in this.DEFAULTS){var i=void 0!==n[i=o]?n[i]:e+CamelToCamel(i);void 0!==t.dataset[i]&&(s[o]=t.dataset[i])}return s}static initialize(t,e={}){PowerButtons.addAction(t,Object.assign({type:this.NAME.toLowerCase()},e))}static discoverAll(){var t=this.NAME.toLowerCase();this.discover(document.querySelectorAll(`[data-${t}]`))}static discover(t,e={},n=!0){void 0===t.length&&(t=[t]);var o,s,i=this.NAME.toLowerCase();for(o of t)n&&void 0!==o._powerButtons&&void 0!==o._powerButtons._discover&&-1!==o._powerButtons._discover.indexOf(i)||void 0!==o.dataset[i]&&(s=Object.assign(this.extractOptions(o,i),e),this.initialize(o,s),void 0!==o._powerButtons)&&(void 0===o._powerButtons._discover&&(o._powerButtons._discover=[]),o._powerButtons._discover.includes(i)||o._powerButtons._discover.push(i))}static execute(t,e,n,o){throw new Error("The execute method must be implemented by the derived class")}}class ActionVerify extends Action{static NAME="Verify";static DEFAULTS={verify:null,form:null,verified:null,notVerified:"The condition for this action is not met",customContentVerified:null,customContentNotVerified:null,titleNotVerified:"The action requires verification",titleVerified:null,buttonAccept:"Accept",buttonClose:!1,escapeKey:!0,header:!0,footer:!0};static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options),result=null,bindObject=searchForm(settings.form);null===bindObject&&(bindObject=document);try{result="function"==typeof settings.verify?settings.verify.bind(bindObject)():"string"==typeof settings.verify?function(){return eval(settings.verify)}.bind(bindObject)():parseBoolean(settings.verify)}catch(e){console.error("Error executing verification function",e),result=!1}let dialog=null,onVerificationSuccess=onNextAction,onVerificationFailure=onCancelActions;result?null===settings.verified&&null===settings.customContentVerified&&null===settings.titleVerified||(dialog=Dialog.create({title:settings.titleVerified,message:settings.verified,customContent:settings.customContentVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){null!==onVerificationSuccess&&onVerificationSuccess()})):null===settings.notVerified&&null===settings.customContentNotVerified&&null===settings.titleNotVerified||(dialog=Dialog.create({title:settings.titleNotVerified,message:settings.notVerified,customContent:settings.customContentNotVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){null!==onVerificationFailure&&onVerificationFailure()})),null!==dialog?dialog.show():result?null!==onVerificationSuccess&&onVerificationSuccess():null!==onVerificationFailure&&onVerificationFailure()}}ActionVerify.register();class ActionConfirm extends Action{static NAME="Confirm";static DEFAULTS={confirm:"Please confirm this action",customContent:null,title:"The action requires confirmation",buttonConfirm:"Confirm",buttonCancel:"Cancel",buttonClose:!0,escapeKey:!0};static extractOptions(t,e=null,n=null){t=super.extractOptions(t,e,n);return""==t.confirm.trim()&&delete t.confirm,t}static execute(t,e,n,o){e=PowerButtons.getActionSettings(this,e);Dialog.create({title:e.title,message:e.confirm,customContent:e.customContent,buttons:[e.buttonConfirm,e.buttonCancel],escapeKeyCancels:e.escapeKey,close:e.buttonClose},null,function(t){0===t?null!==n&&n():null!==o&&o()}).show()}}ActionConfirm.register();class ActionAsyncTask extends Action{static NAME="AsyncTask";static DEFAULTS={task:null,message:"Please wait...",customContent:null,title:null,buttonCancel:"Cancel",cancel:null,header:!0,footer:!0};static extractOptions(t,e=null,n){return super.extractOptions(t,e,{task:"asynctask"})}static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);if(null===settings.task)console.error("The task to execute cannot be null");else{let task=null;if("string"==typeof settings.task)task=async function(){return eval(settings.task)};else{if("function"!=typeof settings.task)return void console.error("The task to execute must be either a string or a function");task=settings.task}let buttons=[],cancelHandler=null,dialog=(null!==settings.cancel&&(buttons=[settings.buttonCancel],"string"==typeof settings.cancel?cancelHandler=function(){eval(settings.cancel)}:"function"==typeof settings.cancel?cancelHandler=settings.cancel:console.error("The cancel handler must be either a string or a function")),Dialog.create({title:settings.title,message:settings.message,customContent:settings.customContent,buttons:buttons,escapeKeyCancels:!1,close:!1,header:void 0!==options.header?settings.header:null!==settings.title&&""!=settings.title,footer:void 0!==options.footer?settings.footer:null!==cancelHandler},function(){cancelHandler(),onCancelActions()},function(t){null!==onNextAction&&onNextAction()}));dialog.show().then(function(){task().finally(function(){dialog.hide()})})}}}ActionAsyncTask.register();class ActionShowMessage extends Action{static NAME="ShowMessage";static DEFAULTS={showmessage:"This is a message",customContent:null,title:null,buttonAccept:"Accept",escapeKey:!0,buttonClose:!0,header:!0,footer:!0};static execute(t,e,n,o){var s=PowerButtons.getActionSettings(this,e);Dialog.create({title:s.title,message:s.showmessage,customContent:s.customContent,buttons:[s.buttonAccept],escapeKeyCancels:s.escapeKey,close:s.buttonClose,header:void 0!==e.header?s.header:null!==s.title&&""!=s.title,footer:void 0!==e.footer?s.footer:null!==s.buttonAccept&&""!=s.buttonAccept},null,function(t){null!==n&&n()}).show()}}ActionShowMessage.register();class ActionFormset extends Action{static NAME="Formset";static DEFAULTS={form:null,fields:{}};static extractOptions(e,n=null,t){var o,s=super.extractOptions(e,n,{form:"formset"}),i={};for(o in e.dataset)if(o.startsWith(n)){let t=o.substring(n.length);""!==t&&t[0]===t[0].toUpperCase()&&(i[t=t.toLocaleLowerCase()]=e.dataset[o])}return void 0===s.fields&&(s.fields={}),Object.assign(s.fields,i),s}static execute(t,e,n,o){var s,i=PowerButtons.getActionSettings(this,e);let l=null,r=[],a=[];if(""==i.form)null!==t.form?l=t.form:a=Array.from(document.querySelectorAll("input")).filter(t=>null===t.form);else if(null===(l=searchForm(i.form)))return void console.error("Form not found "+i.form);for(s in(a=null!==l?Array.from(l.elements):a).forEach(t=>{""!==t.name&&(r[t.name.toLocaleLowerCase()]=t),""!==t.id&&(r[t.id.toLocaleLowerCase()]=t)}),i.fields)if(void 0!==r[s]){var c=i.fields[s];let t=getValueWithJavascriptSupport(c,null!==l?l:r);if("function"==typeof t)try{t=t()}catch(t){console.error("Error executing "+c,t);continue}r[s].value=t}n()}}ActionFormset.register();class ActionFormButton extends Action{static NAME="FormButton";static DEFAULTS={formbutton:null,method:"post",formClass:"formbutton",convertCase:"none",formId:null,fields:{}};static extractOptions(e,n=null,t=null){var o,s=super.extractOptions(e,n,t),i={};for(o in n+="Field",e.dataset)if(o.startsWith(n)){let t=o.substring(n.length);if(""!==t&&t[0]===t[0].toUpperCase()){switch(s.convertCase){case"kebab":t=pascalToKebab(t);break;case"snake":t=pascalToSnake(t);break;case"camel":t=pascalToCamel(t)}i[t]=e.dataset[o]}}return void 0===s.fields&&(s.fields={}),Object.assign(s.fields,i),s}static initialize(t,e={}){for(var n=PowerButtons.getActionSettings(this,e),o=document.createElement("form"),s=(o.method=n.method,isEmpty(n.formbutton)||(o.action=n.formbutton),null!==n.formId&&(o.id=n.formId),n.formClass.split(" ")),i=0;i 2) { + console.warn(`Ignoring extra parameters`) + } + options = param2 + } else { + let valid = false; + if (typeof param2 === "string") { + els = document.querySelectorAll(param2); + valid = true + } else if (param2 instanceof HTMLElement) { + els = [param2]; + valid = true + } else if (param2.length !== undefined) { + valid = true; + for (let e in param2) { + if (!(param2[e] instanceof HTMLElement)) { + valid = false; + break + } + } + if (valid) { + els = param2 + } + } + if (!valid) { + console.error(`Parameter ${param2} is neither a valid selector, a list of elements or an HTMLElement`); + return + } + options = param3 + } + } else if (param1 instanceof HTMLElement) { + els = [param1] + } else if (param1.length !== undefined) { + for (let e in param1) { + if (!(param1[e] instanceof HTMLElement)) { + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return + } } - } - if (pluginToApply === undefined) { - console.error(`The action ${pluginName} is not registered`) + els = param1 } else { - for (let el of elements) { - pluginToApply.initialize(el, options) + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return + } + if (options === null) { + options = {} + } + if (typeof options !== "object") { + console.error(`Options parameter must be an object`); + return + } + if (pluginName !== null) { + let plugin = PowerButtons.actionsRegistered[pluginName]; + for (let el of els) { + plugin.initialize(el, options) } + } else { + PowerButtons.discover(els, options) } - return els }; - exports.powerButtons.version = "2.0.1"; + exports.powerButtons.version = "2.1.0"; exports.powerButtons.plugins = function () { return Object.keys(PowerButtons.actionsRegistered) }; + exports.powerButtons.discoverAll = function () { + PowerButtons.discoverAll() + }; + exports.powerButtons.discover = function (els, options) { + PowerButtons.discover(els, options) + }; + if (document.addEventListener !== undefined) { + document.addEventListener("DOMContentLoaded", function (e) { + PowerButtons.discoverAll() + }) + } if (exports.$ !== undefined) { exports.$.fn.powerButtons = function (pluginName, options = {}) { exports.powerButtons(pluginName, this, options); @@ -611,20 +678,16 @@ reset() { this.current_action = 0 } - static initializeAll() { + static discoverAll() { Object.entries(this.actionsRegistered).forEach(([key, action]) => { - action.initializeAll() + action.discoverAll() + }) + } + static discover(els, options = {}) { + Object.entries(this.actionsRegistered).forEach(([key, action]) => { + action.discover(els, options) }) } - } - - function init() { - PowerButtons.initializeAll() - } - if (document.addEventListener !== undefined) { - document.addEventListener("DOMContentLoaded", function (e) { - init() - }) } class Action { static NAME = null; @@ -659,16 +722,32 @@ type: this.NAME.toLowerCase() }, values)) } - static initializeAll(values = null) { + static discoverAll() { let prefix = this.NAME.toLowerCase(); - for (let el of document.querySelectorAll(`[data-${prefix}`)) { - let options = null; - if (values === null) { - options = this.extractOptions(el, prefix) - } else { - options = Object.assign({}, values) + this.discover(document.querySelectorAll(`[data-${prefix}]`)) + } + static discover(els, options = {}, skipInitialized = true) { + if (els.length === undefined) { + els = [els] + } + let prefix = this.NAME.toLowerCase(); + for (let el of els) { + if (skipInitialized && el._powerButtons !== undefined && el._powerButtons._discover !== undefined && el._powerButtons._discover.indexOf(prefix) !== -1) { + continue + } + if (el.dataset[prefix] === undefined) { + continue + } + let currentOptions = Object.assign(this.extractOptions(el, prefix), options); + this.initialize(el, currentOptions); + if (el._powerButtons !== undefined) { + if (el._powerButtons._discover === undefined) { + el._powerButtons._discover = [] + } + if (!el._powerButtons._discover.includes(prefix)) { + el._powerButtons._discover.push(prefix) + } } - this.initialize(el, options) } } static execute(el, options, onNextAction, onCancelActions) { diff --git a/dist/powerbuttons.js b/dist/powerbuttons.js index e2f49b9..e918c3b 100644 --- a/dist/powerbuttons.js +++ b/dist/powerbuttons.js @@ -19,35 +19,102 @@ if (typeof exports === "undefined") { var exports = window; } - exports.powerButtons = function (pluginName, els = [], options = {}) { - let elements = els; - if (typeof elements === "string") { - elements = document.querySelectorAll(elements); - } else { - if (elements.length === undefined) { - elements = [elements]; + exports.powerButtons = function (param1, param2 = null, param3 = null) { + let pluginName = null; + let els = []; + let options = {}; + + function registeredPlugin(pluginName) { + for (let actionName in PowerButtons.actionsRegistered) { + if (pluginName.toLocaleLowerCase() === actionName.toLocaleLowerCase()) { + return actionName; + } } + return null; } - let pluginToApply = null; - for (let actionName in PowerButtons.actionsRegistered) { - if (pluginName.toLocaleLowerCase() === actionName.toLocaleLowerCase()) { - pluginToApply = PowerButtons.actionsRegistered[actionName]; - break; + if (typeof param1 === "string") { + pluginName = registeredPlugin(param1); + if (pluginName === null) { + els = document.querySelectorAll(param1); + if (els.length === 0) { + console.error(`Parameter ${param1} is neither the name of a registered plugin nor a valid selector`); + return; + } + if (arguments.length > 2) { + console.warn(`Ignoring extra parameters`); + } + options = param2; + } else { + let valid = false; + if (typeof param2 === "string") { + els = document.querySelectorAll(param2); + valid = true; + } else if (param2 instanceof HTMLElement) { + els = [param2]; + valid = true; + } else if (param2.length !== undefined) { + valid = true; + for (let e in param2) { + if (!(param2[e] instanceof HTMLElement)) { + valid = false; + break; + } + } + if (valid) { + els = param2; + } + } + if (!valid) { + console.error(`Parameter ${param2} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } + options = param3; + } + } else if (param1 instanceof HTMLElement) { + els = [param1]; + } else if (param1.length !== undefined) { + for (let e in param1) { + if (!(param1[e] instanceof HTMLElement)) { + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } } - } - if (pluginToApply === undefined) { - console.error(`The action ${pluginName} is not registered`); + els = param1; } else { - for (let el of elements) { - pluginToApply.initialize(el, options); + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } + if (options === null) { + options = {}; + } + if (typeof options !== "object") { + console.error(`Options parameter must be an object`); + return; + } + if (pluginName !== null) { + let plugin = PowerButtons.actionsRegistered[pluginName]; + for (let el of els) { + plugin.initialize(el, options); } + } else { + PowerButtons.discover(els, options); } - return els; }; - exports.powerButtons.version = "2.0.1"; + exports.powerButtons.version = "2.1.0"; exports.powerButtons.plugins = function () { return Object.keys(PowerButtons.actionsRegistered); }; + exports.powerButtons.discoverAll = function () { + PowerButtons.discoverAll(); + }; + exports.powerButtons.discover = function (els, options) { + PowerButtons.discover(els, options); + }; + if (document.addEventListener !== undefined) { + document.addEventListener("DOMContentLoaded", function (e) { + PowerButtons.discoverAll(); + }); + } if (exports.$ !== undefined) { exports.$.fn.powerButtons = function (pluginName, options = {}) { exports.powerButtons(pluginName, this, options); @@ -611,20 +678,16 @@ reset() { this.current_action = 0; } - static initializeAll() { + static discoverAll() { Object.entries(this.actionsRegistered).forEach(([key, action]) => { - action.initializeAll(); + action.discoverAll(); + }); + } + static discover(els, options = {}) { + Object.entries(this.actionsRegistered).forEach(([key, action]) => { + action.discover(els, options); }); } - } - - function init() { - PowerButtons.initializeAll(); - } - if (document.addEventListener !== undefined) { - document.addEventListener("DOMContentLoaded", function (e) { - init(); - }); } class Action { static NAME = null; @@ -659,16 +722,32 @@ type: this.NAME.toLowerCase() }, values)); } - static initializeAll(values = null) { + static discoverAll() { let prefix = this.NAME.toLowerCase(); - for (let el of document.querySelectorAll(`[data-${prefix}`)) { - let options = null; - if (values === null) { - options = this.extractOptions(el, prefix); - } else { - options = Object.assign({}, values); + this.discover(document.querySelectorAll(`[data-${prefix}]`)); + } + static discover(els, options = {}, skipInitialized = true) { + if (els.length === undefined) { + els = [els]; + } + let prefix = this.NAME.toLowerCase(); + for (let el of els) { + if (skipInitialized && el._powerButtons !== undefined && el._powerButtons._discover !== undefined && el._powerButtons._discover.indexOf(prefix) !== -1) { + continue; + } + if (el.dataset[prefix] === undefined) { + continue; + } + let currentOptions = Object.assign(this.extractOptions(el, prefix), options); + this.initialize(el, currentOptions); + if (el._powerButtons !== undefined) { + if (el._powerButtons._discover === undefined) { + el._powerButtons._discover = []; + } + if (!el._powerButtons._discover.includes(prefix)) { + el._powerButtons._discover.push(prefix); + } } - this.initialize(el, options); } } static execute(el, options, onNextAction, onCancelActions) { diff --git a/dist/powerbuttons.min.js b/dist/powerbuttons.min.js index 7f99a72..292152c 100644 --- a/dist/powerbuttons.min.js +++ b/dist/powerbuttons.min.js @@ -1,2 +1,2 @@ /* Copyright 2021 Carlos A. (https://github.com/dealfonso); License: http://www.apache.org/licenses/LICENSE-2.0 */ -(function(exports){"use strict";if(typeof exports==="undefined"){var exports=window}exports.powerButtons=function(e,t=[],n={}){let i=t;if(typeof i==="string"){i=document.querySelectorAll(i)}else{if(i.length===undefined){i=[i]}}let o=null;for(let t in PowerButtons.actionsRegistered){if(e.toLocaleLowerCase()===t.toLocaleLowerCase()){o=PowerButtons.actionsRegistered[t];break}}if(o===undefined){console.error(`The action ${e} is not registered`)}else{for(let t of i){o.initialize(t,n)}}return t};exports.powerButtons.version="2.0.1";exports.powerButtons.plugins=function(){return Object.keys(PowerButtons.actionsRegistered)};if(exports.$!==undefined){exports.$.fn.powerButtons=function(t,e={}){exports.powerButtons(t,this,e);return this};exports.$.fn.powerButtons.version=exports.powerButtons.version;exports.$.fn.powerButtons.plugins=exports.powerButtons.plugins}function pascalToSnake(t){return t.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`).replace(/^_*/,"")}function pascalToKebab(t){return t.replace(/[A-Z]/g,t=>`-${t.toLowerCase()}`).replace(/^-*/,"")}function snakeCaseToCamel(t){return t.replace(/-([a-z])/g,t=>t[1].toUpperCase())}function pascalToCamel(t){return t.charAt(0).toLowerCase()+t.slice(1)}function CamelToCamel(t){return t.charAt(0).toUpperCase()+t.slice(1)}function isElement(t){return t instanceof Element||t instanceof HTMLDocument}function parseBoolean(t){if(typeof t==="boolean"){return t}if(typeof t==="string"){t=t.toLowerCase();if(t==="true"||t==="yes"||t==="1"){return true}return false}return!!t}function createTag(t,e={},n=null){let i=t.split("#");let o=null;if(i.length==1){t=i[0]}else{i[1]=i[1].split(".");o=i[1][0];t=[i[0],...i[1].slice(1)].join(".")}let s=t.split(".");t=s[0];if(t===""){t="div"}if(typeof e==="string"){n=e;e={}}if(n!==null){e.innerHTML=n}if(o!==null){e.id=o}e.className=[e.className,...s.slice(1)].filter(function(t){return`${t}`.trim()!==""}).join(" ");let l=document.createElement(t);for(let t in e){if(l[t]!==undefined){l[t]=e[t]}else{l.setAttribute(t,e[t])}}return l}function appendToElement(t,...e){let n=e.filter(t=>t!==null&&t!==undefined);t.append(...n);return t}function searchForm(t){let e=null;if(t!==null){e=document.forms[t];if(e===undefined){e=document.querySelector(t);if(e===null){console.warn(`form ${t} not found`)}}}if(e!==null){if(e.tagName.toLowerCase()!=="form"){console.warn(`form ${t} is not a form`)}}return e}function getValueWithJavascriptSupport(value,context=null){if(typeof value==="function"){return value.bind(context)}if(typeof value==="string"){let internalValue=value.trim();if(internalValue.startsWith("javascript:")){try{let f=internalValue.substring(11);value=function(){return eval(f)}.bind(context)}catch(e){console.error(`Error executing javascript code ${internalValue.substring(11)}, error: ${e}`);value=null}}}return value}function promiseForEvent(t,e){let n=null;let i=new Promise(t=>{n=t});let o=function(){t.removeEventListener(e,o);n()};t.addEventListener(e,o);return i}function isEmpty(t){if(t===null||t===undefined){return true}if(t instanceof Array){return t.length===0}if(t instanceof Object){return Object.keys(t).length===0}if(typeof t==="string"){return t.trim()===""}return false}class DialogLegacy{DEFAULTS={message:"Main message",buttonCount:2};constructor(t={},e=null,n=null){this.options={...this.DEFAULTS,...t};this.buttonCount=this.options.buttons.length;this.options.buttons=["Accept","Cancel"];this.result=null;this.onButton=e;this.onHidden=n}dispose(){}show(t=null,e=null){if(t!==null){this.onButton=t}if(e!==null){this.onHidden=e}switch(this.buttonCount){case 0:case 1:alert(this.message);this.result=0;break;case 2:this.result=confirm(this.options.message)?0:1;break;default:throw`Unsupported button count ${this.buttonCount}`}if(this.onButton!==null){this.onButton(this.result,{button:this.result,text:this.options.buttons[this.result]},null)}if(this.onHidden!==null){this.onHidden(this.result,{button:this.result,text:this.options.buttons[this.result]},null)}}}class Dialog{static create(t={},e=null,n=null){if(exports.bootstrap===undefined||exports.bootstrap.Modal===undefined){return new DialogLegacy(t,e,n)}if(t.selector!==undefined&&t.selector!==null||t.dialogFunction!==undefined&&t.dialogFunction!==null){throw new Error("not implemented, yet")}return new Dialog(t,e,n)}DEFAULTS={title:"Title",message:"Main message",customContent:null,buttons:["Accept"],buttonClasses:["btn-primary","btn-secondary"],buttonPanelClasses:["text-end"],escapeKeyCancels:true,header:true,footer:true,body:true,close:true};dialog=null;options=null;modal=null;onButton=null;result=null;onHidden=null;onButton=null;constructor(t={},e=null,n=null){if(exports.bootstrap===undefined||exports.bootstrap.Modal===undefined){throw new Error("Bootstrap is required to use this class")}this.options={...this.DEFAULTS,...t};let i=[];for(let e=0;e=0){this.onHidden(this.result,{button:this.result,text:this.options.buttons[this.result]})}else{this.onHidden(this.result,null)}}}dispose(){if(this.modal!==null){this.modal.dispose();this.modal=null}this.dialog.remove();this.dialog=null}show(t=null,e=null){if(this.dialog===null){this.dialog=this._build_dialog(this.options)}if(this.modal===null){this.modal=new bootstrap.Modal(this.dialog,{backdrop:this.options.escapeKeyCancels?true:"static",keyboard:this.options.escapeKeyCancels})}this.dialog.addEventListener("hidden.bs.modal",this._hiddenHandler);this.result=null;if(t!==null){this.onButton=t}if(e!==null){this.onHidden=e}this.modal.show();return promiseForEvent(this.dialog,"shown.bs.modal")}hide(){this.modal.hide();return promiseForEvent(this.dialog,"hidden.bs.modal")}_handleButton(t,e,n){this.result=t;let i=true;if(this.onButton!==null){i=!(this.onButton(t,e,n)===false)}if(i){this.hide()}}_build_dialog(o={}){let t=null;let e=null;if(parseBoolean(o.close)){e=createTag("button.close.btn-close",{type:"button","aria-label":"Close"});e.addEventListener("click",()=>this._handleButton(-1,null,e))}if(parseBoolean(o.header)){t=createTag(".modal-header");if(o.title!==null){t.append(appendToElement(createTag(".modal-title"),appendToElement(createTag("h5",o.title))))}if(parseBoolean(o.close)){t.append(e)}}let s=[];if(o.buttons!==null){for(let i=0;it.trim()).filter(t=>t!=="").join(".");if(o.footer===false){e+=".mx-1"}if(e!==""){e="."+e}let n=createTag("button.btn"+e+".button"+i,{type:"button"},t.text);n.addEventListener("click",function(){this._handleButton(i,t,n);if(t.handler!==undefined&&t.handler!==null){t.handler(i,t,n)}}.bind(this));s.push(n)}}let n=null;if(parseBoolean(o.footer)){n=appendToElement(createTag(".modal-footer"),...s)}let i=null;if(parseBoolean(o.body)){i=createTag(".modal-body");if(t===null){if(parseBoolean(o.close)){i.append(appendToElement(createTag(".text-end"),e))}}if(o.message!==null){i.append(createTag("p.message.text-center",o.message))}if(o.customContent!==null){i.append(createTag(".custom-content.mx-auto",o.customContent))}if(n===null){let t=o.buttonPanelClasses.map(t=>t.trim()).filter(t=>t!=="").join(".");if(t!==""){t="."+t}appendToElement(i,appendToElement(createTag(".buttons"+t),...s))}}let l=appendToElement(createTag(".modal.fade",{tabindex:"-1",role:"dialog","aria-hidden":"true","data-keyboard":"false"}),appendToElement(createTag(".modal-dialog.modal-dialog-centered",{role:"document"}),appendToElement(createTag(".modal-content"),t,i,n)));return l}}function confirmDialog(t,e="this action needs confirmation",n=null,i=null,o=true){let s=new Dialog({title:e,message:t,buttons:[{text:"Cancel",class:"btn-secondary",handler:i},{text:"Confirm",class:"btn-primary",handler:n}],escapeKeyCancels:o});s.show();return s}function alertDialog(t,e="Alert",n=null){let i=new Dialog({title:e,message:t,buttons:[{text:"Accept",class:"btn-primary",handler:n}],escapeKeyCancels:true});i.show();return i}function loadingDialog(t,e=null,n=null){if(typeof e==="function"){n=e;e=null}let i=new Dialog({title:null,message:t,buttons:[{text:"Cancel",class:"btn-primary"}],customContent:e,escapeKeyCancels:false,close:false,header:false,footer:false},n);i.show();return i}if(exports.powerButtons.utils===undefined){exports.powerButtons.utils={}}Object.assign(exports.powerButtons.utils,{confirmDialog:confirmDialog,alertDialog:alertDialog,loadingDialog:loadingDialog});class PowerButtons{static actionsRegistered={};static registerAction(t){this.actionsRegistered[t.NAME.toLowerCase()]=t;if(exports.powerButtons===undefined){exports.powerButtons={}}if(exports.powerButtons.defaults===undefined){exports.powerButtons.defaults={}}exports.powerButtons.defaults[t.NAME.toLowerCase()]=Object.assign({},t.DEFAULTS)}static getActionSettings(t,e){if(this.actionsRegistered[t.NAME.toLowerCase()]===undefined){console.error(`The action ${t.NAME} is not registered`);return{}}let n={};if(exports.powerButtons!==undefined&&exports.powerButtons.defaults!==undefined&&exports.powerButtons.defaults[t.NAME.toLowerCase()]!==undefined){n=exports.powerButtons.defaults[t.NAME.toLowerCase()]}return Object.assign({},t.DEFAULTS,n,e)}static addAction(t,e={}){let n=PowerButtons.addActionSupport(t);n.appendAction(e)}static addActionSupport(t){if(t._powerButtons===undefined){t._powerButtons=new PowerButtons(t)}else{t._powerButtons.reset()}return t._powerButtons}el=null;current_action=0;actions=[];back_onclick=null;constructor(t){t._powerButtons=this;this.el=t;this.current_action=0;this.actions=[];this.back_onclick=null;if(t.onclick!==undefined&&t.onclick!==null){this.back_onclick=t.onclick;t.onclick=null}t.addEventListener("click",this.handlerClick.bind(this))}appendAction(t={}){if(t.type===undefined){throw"The type of the action is mandatory"}this.actions.push(t)}handlerClick(t){if(this.current_action>=this.actions.length){this.current_action=0;if(typeof this.back_onclick==="function"){if(!this.back_onclick()){t.preventDefault()}}return}let e=this.actions[this.current_action];t.preventDefault();t.stopImmediatePropagation();let n=function(){this.current_action++;if(this.current_action>=this.actions.length){if(this.el.click!==undefined){this.el.click()}else{this.el.dispatchEvent(new Event(t.type,t))}}else{this.el.dispatchEvent(new Event(t.type,t))}}.bind(this);let i=this.constructor.actionsRegistered[e.type];if(i===undefined){throw`The action ${e.type} is not registered`}i.execute(this.el,e,n,()=>this.reset())}reset(){this.current_action=0}static initializeAll(){Object.entries(this.actionsRegistered).forEach(([t,e])=>{e.initializeAll()})}}function init(){PowerButtons.initializeAll()}if(document.addEventListener!==undefined){document.addEventListener("DOMContentLoaded",function(t){init()})}class Action{static NAME=null;static register(){PowerButtons.registerAction(this)}static DEFAULTS={};static extractOptions(n,i=null,o=null){if(i===null){i=this.NAME.toLowerCase()}if(o===null){o={};o[i]=i}let s={};for(let e in this.DEFAULTS){let t=e;if(o[t]!==undefined){t=o[t]}else{t=i+CamelToCamel(t)}if(n.dataset[t]!==undefined){s[e]=n.dataset[t]}}return s}static initialize(t,e={}){PowerButtons.addAction(t,Object.assign({type:this.NAME.toLowerCase()},e))}static initializeAll(n=null){let i=this.NAME.toLowerCase();for(let e of document.querySelectorAll(`[data-${i}`)){let t=null;if(n===null){t=this.extractOptions(e,i)}else{t=Object.assign({},n)}this.initialize(e,t)}}static execute(t,e,n,i){throw new Error("The execute method must be implemented by the derived class")}}class ActionVerify extends Action{static NAME="Verify";static DEFAULTS={verify:null,form:null,verified:null,notVerified:"The condition for this action is not met",customContentVerified:null,customContentNotVerified:null,titleNotVerified:"The action requires verification",titleVerified:null,buttonAccept:"Accept",buttonClose:false,escapeKey:true,header:true,footer:true};static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);let result=null;let bindObject=searchForm(settings.form);if(bindObject===null){bindObject=document}try{if(typeof settings.verify==="function"){result=settings.verify.bind(bindObject)()}else if(typeof settings.verify==="string"){result=function(){return eval(settings.verify)}.bind(bindObject)()}else{result=parseBoolean(settings.verify)}}catch(e){console.error("Error executing verification function",e);result=false}let dialog=null;let onVerificationSuccess=onNextAction;let onVerificationFailure=onCancelActions;if(result){if(settings.verified!==null||settings.customContentVerified!==null||settings.titleVerified!==null){dialog=Dialog.create({title:settings.titleVerified,message:settings.verified,customContent:settings.customContentVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){if(onVerificationSuccess!==null){onVerificationSuccess()}})}}else{if(settings.notVerified!==null||settings.customContentNotVerified!==null||settings.titleNotVerified!==null){dialog=Dialog.create({title:settings.titleNotVerified,message:settings.notVerified,customContent:settings.customContentNotVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(t){if(onVerificationFailure!==null){onVerificationFailure()}})}}if(dialog!==null){dialog.show()}else{if(result){if(onVerificationSuccess!==null){onVerificationSuccess()}}else{if(onVerificationFailure!==null){onVerificationFailure()}}}}}ActionVerify.register();class ActionConfirm extends Action{static NAME="Confirm";static DEFAULTS={confirm:"Please confirm this action",customContent:null,title:"The action requires confirmation",buttonConfirm:"Confirm",buttonCancel:"Cancel",buttonClose:true,escapeKey:true};static extractOptions(t,e=null,n=null){let i=super.extractOptions(t,e,n);if(i.confirm.trim()==""){delete i.confirm}return i}static execute(t,e,n,i){let o=PowerButtons.getActionSettings(this,e);let s=Dialog.create({title:o.title,message:o.confirm,customContent:o.customContent,buttons:[o.buttonConfirm,o.buttonCancel],escapeKeyCancels:o.escapeKey,close:o.buttonClose},null,function(t){if(t===0){if(n!==null){n()}}else{if(i!==null){i()}}});s.show()}}ActionConfirm.register();class ActionAsyncTask extends Action{static NAME="AsyncTask";static DEFAULTS={task:null,message:"Please wait...",customContent:null,title:null,buttonCancel:"Cancel",cancel:null,header:true,footer:true};static extractOptions(t,e=null,n=null){return super.extractOptions(t,e,{task:"asynctask"})}static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);if(settings.task===null){console.error("The task to execute cannot be null");return}let task=null;if(typeof settings.task==="string"){task=async function(){return await eval(settings.task)}}else if(typeof settings.task==="function"){task=settings.task}else{console.error("The task to execute must be either a string or a function");return}let buttons=[];let cancelHandler=null;if(settings.cancel!==null){buttons=[settings.buttonCancel];if(typeof settings.cancel==="string"){cancelHandler=function(){eval(settings.cancel)}}else if(typeof settings.cancel==="function"){cancelHandler=settings.cancel}else{console.error("The cancel handler must be either a string or a function")}}let dialog=Dialog.create({title:settings.title,message:settings.message,customContent:settings.customContent,buttons:buttons,escapeKeyCancels:false,close:false,header:options.header!==undefined?settings.header:settings.title!==null&&settings.title!="",footer:options.footer!==undefined?settings.footer:cancelHandler!==null},function(){cancelHandler();onCancelActions()},function(t){if(onNextAction!==null){onNextAction()}});dialog.show().then(function(){task().finally(function(){dialog.hide()})})}}ActionAsyncTask.register();class ActionShowMessage extends Action{static NAME="ShowMessage";static DEFAULTS={showmessage:"This is a message",customContent:null,title:null,buttonAccept:"Accept",escapeKey:true,buttonClose:true,header:true,footer:true};static execute(t,e,n,i){let o=PowerButtons.getActionSettings(this,e);let s=Dialog.create({title:o.title,message:o.showmessage,customContent:o.customContent,buttons:[o.buttonAccept],escapeKeyCancels:o.escapeKey,close:o.buttonClose,header:e.header!==undefined?o.header:o.title!==null&&o.title!="",footer:e.footer!==undefined?o.footer:o.buttonAccept!==null&&o.buttonAccept!=""},null,function(t){if(n!==null){n()}});s.show()}}ActionShowMessage.register();class ActionFormset extends Action{static NAME="Formset";static DEFAULTS={form:null,fields:{}};static extractOptions(n,i=null,t=null){let e=super.extractOptions(n,i,{form:"formset"});let o={};for(let e in n.dataset){if(e.startsWith(i)){let t=e.substring(i.length);if(t===""){continue}if(t[0]!==t[0].toUpperCase()){continue}t=t.toLocaleLowerCase();o[t]=n.dataset[e]}}if(e.fields===undefined){e.fields={}}Object.assign(e.fields,o);return e}static execute(t,e,n,i){let o=PowerButtons.getActionSettings(this,e);let s=null;let l=[];let r=[];if(o.form==""){if(t.form!==null){s=t.form}else{r=Array.from(document.querySelectorAll("input")).filter(t=>t.form===null)}}else{s=searchForm(o.form);if(s===null){console.error(`Form not found ${o.form}`);return}}if(s!==null){r=Array.from(s.elements)}r.forEach(t=>{if(t.name!==""){l[t.name.toLocaleLowerCase()]=t}if(t.id!==""){l[t.id.toLocaleLowerCase()]=t}});for(let n in o.fields){if(l[n]!==undefined){let e=o.fields[n];let t=getValueWithJavascriptSupport(e,s!==null?s:l);if(typeof t==="function"){try{t=t()}catch(t){console.error(`Error executing ${e}`,t);continue}}l[n].value=t}}n()}}ActionFormset.register();class ActionFormButton extends Action{static NAME="FormButton";static DEFAULTS={formbutton:null,method:"post",formClass:"formbutton",convertCase:"none",formId:null,fields:{}};static extractOptions(n,i=null,t=null){let o=super.extractOptions(n,i,t);let s={};i=i+"Field";for(let e in n.dataset){if(e.startsWith(i)){let t=e.substring(i.length);if(t===""){continue}if(t[0]!==t[0].toUpperCase()){continue}switch(o.convertCase){case"kebab":t=pascalToKebab(t);break;case"snake":t=pascalToSnake(t);break;case"camel":t=pascalToCamel(t);break;case"pascal":break}s[t]=n.dataset[e]}}if(o.fields===undefined){o.fields={}}Object.assign(o.fields,s);return o}static initialize(t,e={}){let n=PowerButtons.getActionSettings(this,e);let i=document.createElement("form");i.method=n.method;if(!isEmpty(n.formbutton)){i.action=n.formbutton}if(n.formId!==null){i.id=n.formId}let o=n.formClass.split(" ");for(var s=0;s0){n.fields=r;n._formObject=i;super.initialize(t,n)}}static execute(t,e,n,i){let o=PowerButtons.getActionSettings(this,e);let s=false;for(let e in o.fields){try{let t=o.fields[e]();o._formObject[e].value=t}catch(t){console.error(`Error obtaining value for field ${e}: ${t}`);s=true}}if(s){i()}else{n()}}}ActionFormButton.register()})(window); +(function(exports){"use strict";if(typeof exports==="undefined"){var exports=window}exports.powerButtons=function(t,n=null,e=null){let i=null;let o=[];let s={};function l(t){for(let e in PowerButtons.actionsRegistered){if(t.toLocaleLowerCase()===e.toLocaleLowerCase()){return e}}return null}if(typeof t==="string"){i=l(t);if(i===null){o=document.querySelectorAll(t);if(o.length===0){console.error(`Parameter ${t} is neither the name of a registered plugin nor a valid selector`);return}if(arguments.length>2){console.warn(`Ignoring extra parameters`)}s=n}else{let t=false;if(typeof n==="string"){o=document.querySelectorAll(n);t=true}else if(n instanceof HTMLElement){o=[n];t=true}else if(n.length!==undefined){t=true;for(let e in n){if(!(n[e]instanceof HTMLElement)){t=false;break}}if(t){o=n}}if(!t){console.error(`Parameter ${n} is neither a valid selector, a list of elements or an HTMLElement`);return}s=e}}else if(t instanceof HTMLElement){o=[t]}else if(t.length!==undefined){for(let e in t){if(!(t[e]instanceof HTMLElement)){console.error(`Parameter ${t} is neither a valid selector, a list of elements or an HTMLElement`);return}}o=t}else{console.error(`Parameter ${t} is neither a valid selector, a list of elements or an HTMLElement`);return}if(s===null){s={}}if(typeof s!=="object"){console.error(`Options parameter must be an object`);return}if(i!==null){let t=PowerButtons.actionsRegistered[i];for(let e of o){t.initialize(e,s)}}else{PowerButtons.discover(o,s)}};exports.powerButtons.version="2.1.0";exports.powerButtons.plugins=function(){return Object.keys(PowerButtons.actionsRegistered)};exports.powerButtons.discoverAll=function(){PowerButtons.discoverAll()};exports.powerButtons.discover=function(e,t){PowerButtons.discover(e,t)};if(document.addEventListener!==undefined){document.addEventListener("DOMContentLoaded",function(e){PowerButtons.discoverAll()})}if(exports.$!==undefined){exports.$.fn.powerButtons=function(e,t={}){exports.powerButtons(e,this,t);return this};exports.$.fn.powerButtons.version=exports.powerButtons.version;exports.$.fn.powerButtons.plugins=exports.powerButtons.plugins}function pascalToSnake(e){return e.replace(/[A-Z]/g,e=>`_${e.toLowerCase()}`).replace(/^_*/,"")}function pascalToKebab(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`).replace(/^-*/,"")}function snakeCaseToCamel(e){return e.replace(/-([a-z])/g,e=>e[1].toUpperCase())}function pascalToCamel(e){return e.charAt(0).toLowerCase()+e.slice(1)}function CamelToCamel(e){return e.charAt(0).toUpperCase()+e.slice(1)}function isElement(e){return e instanceof Element||e instanceof HTMLDocument}function parseBoolean(e){if(typeof e==="boolean"){return e}if(typeof e==="string"){e=e.toLowerCase();if(e==="true"||e==="yes"||e==="1"){return true}return false}return!!e}function createTag(e,t={},n=null){let i=e.split("#");let o=null;if(i.length==1){e=i[0]}else{i[1]=i[1].split(".");o=i[1][0];e=[i[0],...i[1].slice(1)].join(".")}let s=e.split(".");e=s[0];if(e===""){e="div"}if(typeof t==="string"){n=t;t={}}if(n!==null){t.innerHTML=n}if(o!==null){t.id=o}t.className=[t.className,...s.slice(1)].filter(function(e){return`${e}`.trim()!==""}).join(" ");let l=document.createElement(e);for(let e in t){if(l[e]!==undefined){l[e]=t[e]}else{l.setAttribute(e,t[e])}}return l}function appendToElement(e,...t){let n=t.filter(e=>e!==null&&e!==undefined);e.append(...n);return e}function searchForm(e){let t=null;if(e!==null){t=document.forms[e];if(t===undefined){t=document.querySelector(e);if(t===null){console.warn(`form ${e} not found`)}}}if(t!==null){if(t.tagName.toLowerCase()!=="form"){console.warn(`form ${e} is not a form`)}}return t}function getValueWithJavascriptSupport(value,context=null){if(typeof value==="function"){return value.bind(context)}if(typeof value==="string"){let internalValue=value.trim();if(internalValue.startsWith("javascript:")){try{let f=internalValue.substring(11);value=function(){return eval(f)}.bind(context)}catch(e){console.error(`Error executing javascript code ${internalValue.substring(11)}, error: ${e}`);value=null}}}return value}function promiseForEvent(e,t){let n=null;let i=new Promise(e=>{n=e});let o=function(){e.removeEventListener(t,o);n()};e.addEventListener(t,o);return i}function isEmpty(e){if(e===null||e===undefined){return true}if(e instanceof Array){return e.length===0}if(e instanceof Object){return Object.keys(e).length===0}if(typeof e==="string"){return e.trim()===""}return false}class DialogLegacy{DEFAULTS={message:"Main message",buttonCount:2};constructor(e={},t=null,n=null){this.options={...this.DEFAULTS,...e};this.buttonCount=this.options.buttons.length;this.options.buttons=["Accept","Cancel"];this.result=null;this.onButton=t;this.onHidden=n}dispose(){}show(e=null,t=null){if(e!==null){this.onButton=e}if(t!==null){this.onHidden=t}switch(this.buttonCount){case 0:case 1:alert(this.message);this.result=0;break;case 2:this.result=confirm(this.options.message)?0:1;break;default:throw`Unsupported button count ${this.buttonCount}`}if(this.onButton!==null){this.onButton(this.result,{button:this.result,text:this.options.buttons[this.result]},null)}if(this.onHidden!==null){this.onHidden(this.result,{button:this.result,text:this.options.buttons[this.result]},null)}}}class Dialog{static create(e={},t=null,n=null){if(exports.bootstrap===undefined||exports.bootstrap.Modal===undefined){return new DialogLegacy(e,t,n)}if(e.selector!==undefined&&e.selector!==null||e.dialogFunction!==undefined&&e.dialogFunction!==null){throw new Error("not implemented, yet")}return new Dialog(e,t,n)}DEFAULTS={title:"Title",message:"Main message",customContent:null,buttons:["Accept"],buttonClasses:["btn-primary","btn-secondary"],buttonPanelClasses:["text-end"],escapeKeyCancels:true,header:true,footer:true,body:true,close:true};dialog=null;options=null;modal=null;onButton=null;result=null;onHidden=null;onButton=null;constructor(e={},t=null,n=null){if(exports.bootstrap===undefined||exports.bootstrap.Modal===undefined){throw new Error("Bootstrap is required to use this class")}this.options={...this.DEFAULTS,...e};let i=[];for(let t=0;t=0){this.onHidden(this.result,{button:this.result,text:this.options.buttons[this.result]})}else{this.onHidden(this.result,null)}}}dispose(){if(this.modal!==null){this.modal.dispose();this.modal=null}this.dialog.remove();this.dialog=null}show(e=null,t=null){if(this.dialog===null){this.dialog=this._build_dialog(this.options)}if(this.modal===null){this.modal=new bootstrap.Modal(this.dialog,{backdrop:this.options.escapeKeyCancels?true:"static",keyboard:this.options.escapeKeyCancels})}this.dialog.addEventListener("hidden.bs.modal",this._hiddenHandler);this.result=null;if(e!==null){this.onButton=e}if(t!==null){this.onHidden=t}this.modal.show();return promiseForEvent(this.dialog,"shown.bs.modal")}hide(){this.modal.hide();return promiseForEvent(this.dialog,"hidden.bs.modal")}_handleButton(e,t,n){this.result=e;let i=true;if(this.onButton!==null){i=!(this.onButton(e,t,n)===false)}if(i){this.hide()}}_build_dialog(o={}){let e=null;let t=null;if(parseBoolean(o.close)){t=createTag("button.close.btn-close",{type:"button","aria-label":"Close"});t.addEventListener("click",()=>this._handleButton(-1,null,t))}if(parseBoolean(o.header)){e=createTag(".modal-header");if(o.title!==null){e.append(appendToElement(createTag(".modal-title"),appendToElement(createTag("h5",o.title))))}if(parseBoolean(o.close)){e.append(t)}}let s=[];if(o.buttons!==null){for(let i=0;ie.trim()).filter(e=>e!=="").join(".");if(o.footer===false){t+=".mx-1"}if(t!==""){t="."+t}let n=createTag("button.btn"+t+".button"+i,{type:"button"},e.text);n.addEventListener("click",function(){this._handleButton(i,e,n);if(e.handler!==undefined&&e.handler!==null){e.handler(i,e,n)}}.bind(this));s.push(n)}}let n=null;if(parseBoolean(o.footer)){n=appendToElement(createTag(".modal-footer"),...s)}let i=null;if(parseBoolean(o.body)){i=createTag(".modal-body");if(e===null){if(parseBoolean(o.close)){i.append(appendToElement(createTag(".text-end"),t))}}if(o.message!==null){i.append(createTag("p.message.text-center",o.message))}if(o.customContent!==null){i.append(createTag(".custom-content.mx-auto",o.customContent))}if(n===null){let e=o.buttonPanelClasses.map(e=>e.trim()).filter(e=>e!=="").join(".");if(e!==""){e="."+e}appendToElement(i,appendToElement(createTag(".buttons"+e),...s))}}let l=appendToElement(createTag(".modal.fade",{tabindex:"-1",role:"dialog","aria-hidden":"true","data-keyboard":"false"}),appendToElement(createTag(".modal-dialog.modal-dialog-centered",{role:"document"}),appendToElement(createTag(".modal-content"),e,i,n)));return l}}function confirmDialog(e,t="this action needs confirmation",n=null,i=null,o=true){let s=new Dialog({title:t,message:e,buttons:[{text:"Cancel",class:"btn-secondary",handler:i},{text:"Confirm",class:"btn-primary",handler:n}],escapeKeyCancels:o});s.show();return s}function alertDialog(e,t="Alert",n=null){let i=new Dialog({title:t,message:e,buttons:[{text:"Accept",class:"btn-primary",handler:n}],escapeKeyCancels:true});i.show();return i}function loadingDialog(e,t=null,n=null){if(typeof t==="function"){n=t;t=null}let i=new Dialog({title:null,message:e,buttons:[{text:"Cancel",class:"btn-primary"}],customContent:t,escapeKeyCancels:false,close:false,header:false,footer:false},n);i.show();return i}if(exports.powerButtons.utils===undefined){exports.powerButtons.utils={}}Object.assign(exports.powerButtons.utils,{confirmDialog:confirmDialog,alertDialog:alertDialog,loadingDialog:loadingDialog});class PowerButtons{static actionsRegistered={};static registerAction(e){this.actionsRegistered[e.NAME.toLowerCase()]=e;if(exports.powerButtons===undefined){exports.powerButtons={}}if(exports.powerButtons.defaults===undefined){exports.powerButtons.defaults={}}exports.powerButtons.defaults[e.NAME.toLowerCase()]=Object.assign({},e.DEFAULTS)}static getActionSettings(e,t){if(this.actionsRegistered[e.NAME.toLowerCase()]===undefined){console.error(`The action ${e.NAME} is not registered`);return{}}let n={};if(exports.powerButtons!==undefined&&exports.powerButtons.defaults!==undefined&&exports.powerButtons.defaults[e.NAME.toLowerCase()]!==undefined){n=exports.powerButtons.defaults[e.NAME.toLowerCase()]}return Object.assign({},e.DEFAULTS,n,t)}static addAction(e,t={}){let n=PowerButtons.addActionSupport(e);n.appendAction(t)}static addActionSupport(e){if(e._powerButtons===undefined){e._powerButtons=new PowerButtons(e)}else{e._powerButtons.reset()}return e._powerButtons}el=null;current_action=0;actions=[];back_onclick=null;constructor(e){e._powerButtons=this;this.el=e;this.current_action=0;this.actions=[];this.back_onclick=null;if(e.onclick!==undefined&&e.onclick!==null){this.back_onclick=e.onclick;e.onclick=null}e.addEventListener("click",this.handlerClick.bind(this))}appendAction(e={}){if(e.type===undefined){throw"The type of the action is mandatory"}this.actions.push(e)}handlerClick(e){if(this.current_action>=this.actions.length){this.current_action=0;if(typeof this.back_onclick==="function"){if(!this.back_onclick()){e.preventDefault()}}return}let t=this.actions[this.current_action];e.preventDefault();e.stopImmediatePropagation();let n=function(){this.current_action++;if(this.current_action>=this.actions.length){if(this.el.click!==undefined){this.el.click()}else{this.el.dispatchEvent(new Event(e.type,e))}}else{this.el.dispatchEvent(new Event(e.type,e))}}.bind(this);let i=this.constructor.actionsRegistered[t.type];if(i===undefined){throw`The action ${t.type} is not registered`}i.execute(this.el,t,n,()=>this.reset())}reset(){this.current_action=0}static discoverAll(){Object.entries(this.actionsRegistered).forEach(([e,t])=>{t.discoverAll()})}static discover(n,i={}){Object.entries(this.actionsRegistered).forEach(([e,t])=>{t.discover(n,i)})}}class Action{static NAME=null;static register(){PowerButtons.registerAction(this)}static DEFAULTS={};static extractOptions(n,i=null,o=null){if(i===null){i=this.NAME.toLowerCase()}if(o===null){o={};o[i]=i}let s={};for(let t in this.DEFAULTS){let e=t;if(o[e]!==undefined){e=o[e]}else{e=i+CamelToCamel(e)}if(n.dataset[e]!==undefined){s[t]=n.dataset[e]}}return s}static initialize(e,t={}){PowerButtons.addAction(e,Object.assign({type:this.NAME.toLowerCase()},t))}static discoverAll(){let e=this.NAME.toLowerCase();this.discover(document.querySelectorAll(`[data-${e}]`))}static discover(e,n={},i=true){if(e.length===undefined){e=[e]}let o=this.NAME.toLowerCase();for(let t of e){if(i&&t._powerButtons!==undefined&&t._powerButtons._discover!==undefined&&t._powerButtons._discover.indexOf(o)!==-1){continue}if(t.dataset[o]===undefined){continue}let e=Object.assign(this.extractOptions(t,o),n);this.initialize(t,e);if(t._powerButtons!==undefined){if(t._powerButtons._discover===undefined){t._powerButtons._discover=[]}if(!t._powerButtons._discover.includes(o)){t._powerButtons._discover.push(o)}}}}static execute(e,t,n,i){throw new Error("The execute method must be implemented by the derived class")}}class ActionVerify extends Action{static NAME="Verify";static DEFAULTS={verify:null,form:null,verified:null,notVerified:"The condition for this action is not met",customContentVerified:null,customContentNotVerified:null,titleNotVerified:"The action requires verification",titleVerified:null,buttonAccept:"Accept",buttonClose:false,escapeKey:true,header:true,footer:true};static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);let result=null;let bindObject=searchForm(settings.form);if(bindObject===null){bindObject=document}try{if(typeof settings.verify==="function"){result=settings.verify.bind(bindObject)()}else if(typeof settings.verify==="string"){result=function(){return eval(settings.verify)}.bind(bindObject)()}else{result=parseBoolean(settings.verify)}}catch(e){console.error("Error executing verification function",e);result=false}let dialog=null;let onVerificationSuccess=onNextAction;let onVerificationFailure=onCancelActions;if(result){if(settings.verified!==null||settings.customContentVerified!==null||settings.titleVerified!==null){dialog=Dialog.create({title:settings.titleVerified,message:settings.verified,customContent:settings.customContentVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(e){if(onVerificationSuccess!==null){onVerificationSuccess()}})}}else{if(settings.notVerified!==null||settings.customContentNotVerified!==null||settings.titleNotVerified!==null){dialog=Dialog.create({title:settings.titleNotVerified,message:settings.notVerified,customContent:settings.customContentNotVerified,buttons:[settings.buttonAccept],escapeKeyCancels:settings.escapeKey,close:settings.buttonClose},null,function(e){if(onVerificationFailure!==null){onVerificationFailure()}})}}if(dialog!==null){dialog.show()}else{if(result){if(onVerificationSuccess!==null){onVerificationSuccess()}}else{if(onVerificationFailure!==null){onVerificationFailure()}}}}}ActionVerify.register();class ActionConfirm extends Action{static NAME="Confirm";static DEFAULTS={confirm:"Please confirm this action",customContent:null,title:"The action requires confirmation",buttonConfirm:"Confirm",buttonCancel:"Cancel",buttonClose:true,escapeKey:true};static extractOptions(e,t=null,n=null){let i=super.extractOptions(e,t,n);if(i.confirm.trim()==""){delete i.confirm}return i}static execute(e,t,n,i){let o=PowerButtons.getActionSettings(this,t);let s=Dialog.create({title:o.title,message:o.confirm,customContent:o.customContent,buttons:[o.buttonConfirm,o.buttonCancel],escapeKeyCancels:o.escapeKey,close:o.buttonClose},null,function(e){if(e===0){if(n!==null){n()}}else{if(i!==null){i()}}});s.show()}}ActionConfirm.register();class ActionAsyncTask extends Action{static NAME="AsyncTask";static DEFAULTS={task:null,message:"Please wait...",customContent:null,title:null,buttonCancel:"Cancel",cancel:null,header:true,footer:true};static extractOptions(e,t=null,n=null){return super.extractOptions(e,t,{task:"asynctask"})}static execute(el,options,onNextAction,onCancelActions){let settings=PowerButtons.getActionSettings(this,options);if(settings.task===null){console.error("The task to execute cannot be null");return}let task=null;if(typeof settings.task==="string"){task=async function(){return await eval(settings.task)}}else if(typeof settings.task==="function"){task=settings.task}else{console.error("The task to execute must be either a string or a function");return}let buttons=[];let cancelHandler=null;if(settings.cancel!==null){buttons=[settings.buttonCancel];if(typeof settings.cancel==="string"){cancelHandler=function(){eval(settings.cancel)}}else if(typeof settings.cancel==="function"){cancelHandler=settings.cancel}else{console.error("The cancel handler must be either a string or a function")}}let dialog=Dialog.create({title:settings.title,message:settings.message,customContent:settings.customContent,buttons:buttons,escapeKeyCancels:false,close:false,header:options.header!==undefined?settings.header:settings.title!==null&&settings.title!="",footer:options.footer!==undefined?settings.footer:cancelHandler!==null},function(){cancelHandler();onCancelActions()},function(e){if(onNextAction!==null){onNextAction()}});dialog.show().then(function(){task().finally(function(){dialog.hide()})})}}ActionAsyncTask.register();class ActionShowMessage extends Action{static NAME="ShowMessage";static DEFAULTS={showmessage:"This is a message",customContent:null,title:null,buttonAccept:"Accept",escapeKey:true,buttonClose:true,header:true,footer:true};static execute(e,t,n,i){let o=PowerButtons.getActionSettings(this,t);let s=Dialog.create({title:o.title,message:o.showmessage,customContent:o.customContent,buttons:[o.buttonAccept],escapeKeyCancels:o.escapeKey,close:o.buttonClose,header:t.header!==undefined?o.header:o.title!==null&&o.title!="",footer:t.footer!==undefined?o.footer:o.buttonAccept!==null&&o.buttonAccept!=""},null,function(e){if(n!==null){n()}});s.show()}}ActionShowMessage.register();class ActionFormset extends Action{static NAME="Formset";static DEFAULTS={form:null,fields:{}};static extractOptions(n,i=null,e=null){let t=super.extractOptions(n,i,{form:"formset"});let o={};for(let t in n.dataset){if(t.startsWith(i)){let e=t.substring(i.length);if(e===""){continue}if(e[0]!==e[0].toUpperCase()){continue}e=e.toLocaleLowerCase();o[e]=n.dataset[t]}}if(t.fields===undefined){t.fields={}}Object.assign(t.fields,o);return t}static execute(e,t,n,i){let o=PowerButtons.getActionSettings(this,t);let s=null;let l=[];let r=[];if(o.form==""){if(e.form!==null){s=e.form}else{r=Array.from(document.querySelectorAll("input")).filter(e=>e.form===null)}}else{s=searchForm(o.form);if(s===null){console.error(`Form not found ${o.form}`);return}}if(s!==null){r=Array.from(s.elements)}r.forEach(e=>{if(e.name!==""){l[e.name.toLocaleLowerCase()]=e}if(e.id!==""){l[e.id.toLocaleLowerCase()]=e}});for(let n in o.fields){if(l[n]!==undefined){let t=o.fields[n];let e=getValueWithJavascriptSupport(t,s!==null?s:l);if(typeof e==="function"){try{e=e()}catch(e){console.error(`Error executing ${t}`,e);continue}}l[n].value=e}}n()}}ActionFormset.register();class ActionFormButton extends Action{static NAME="FormButton";static DEFAULTS={formbutton:null,method:"post",formClass:"formbutton",convertCase:"none",formId:null,fields:{}};static extractOptions(n,i=null,e=null){let o=super.extractOptions(n,i,e);let s={};i=i+"Field";for(let t in n.dataset){if(t.startsWith(i)){let e=t.substring(i.length);if(e===""){continue}if(e[0]!==e[0].toUpperCase()){continue}switch(o.convertCase){case"kebab":e=pascalToKebab(e);break;case"snake":e=pascalToSnake(e);break;case"camel":e=pascalToCamel(e);break;case"pascal":break}s[e]=n.dataset[t]}}if(o.fields===undefined){o.fields={}}Object.assign(o.fields,s);return o}static initialize(e,t={}){let n=PowerButtons.getActionSettings(this,t);let i=document.createElement("form");i.method=n.method;if(!isEmpty(n.formbutton)){i.action=n.formbutton}if(n.formId!==null){i.id=n.formId}let o=n.formClass.split(" ");for(var s=0;s0){n.fields=r;n._formObject=i;super.initialize(e,n)}}static execute(e,t,n,i){let o=PowerButtons.getActionSettings(this,t);let s=false;for(let t in o.fields){try{let e=o.fields[t]();o._formObject[t].value=e}catch(e){console.error(`Error obtaining value for field ${t}: ${e}`);s=true}}if(s){i()}else{n()}}}ActionFormButton.register()})(window); diff --git a/dist/powerbuttons.raw.js b/dist/powerbuttons.raw.js index 3f85004..3a888ef 100644 --- a/dist/powerbuttons.raw.js +++ b/dist/powerbuttons.raw.js @@ -5,38 +5,124 @@ if (typeof exports === 'undefined') { } // We'll create a namespace for the plugin, that will contain the plugin itself -exports.powerButtons = function(pluginName, els = [], options = {}) { - let elements = els; +exports.powerButtons = function(param1, param2 = null, param3 = null) { - if (typeof(elements) === "string") { - elements = document.querySelectorAll(elements); - } else { - if (elements.length === undefined) { - elements = [ elements ]; + // We are going to support three different ways of calling the plugin: + // - powerButtons(pluginName, els, options) + // - powerButtons(selector, options) + // - powerButtons(el, options) + // - powerButtons(els, options) + + let pluginName = null; + let els = []; + let options = {}; + + function registeredPlugin(pluginName) { + for (let actionName in PowerButtons.actionsRegistered) { + if (pluginName.toLocaleLowerCase() === actionName.toLocaleLowerCase()) { + return actionName; + } } + return null; } - let pluginToApply = null; - for (let actionName in PowerButtons.actionsRegistered) { - if (pluginName.toLocaleLowerCase() === actionName.toLocaleLowerCase()) { - pluginToApply = PowerButtons.actionsRegistered[actionName]; - break; + + if (typeof(param1) === "string") { + // Let's check if the plugin is registered + pluginName = registeredPlugin(param1); + if (pluginName === null) { + // If the plugin is not registered, we'll assume that it is a selector and this is powerButtons(selector, options) + els = document.querySelectorAll(param1); + if (els.length === 0) { + console.error(`Parameter ${param1} is neither the name of a registered plugin nor a valid selector`); + return; + } + + // If the second parameter is not an object or there are three parameters, we'll raise an error + if (arguments.length > 2) { + console.warn(`Ignoring extra parameters`); + } + options = param2; + } else { + // If the plugin is registered, this is powerButtons(pluginName, els, options) + let valid = false; + if (typeof(param2) === "string") { + els = document.querySelectorAll(param2); + valid = true; + } else if (param2 instanceof HTMLElement) { + els = [ param2 ]; + valid = true; + } else if (param2.length !== undefined) { + valid = true; + for (let e in param2) { + if (! (param2[e] instanceof HTMLElement)) { + valid = false; + break; + } + } + if (valid) { + els = param2; + } + } + if (! valid) { + console.error(`Parameter ${param2} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } + options = param3; + } + } else if (param1 instanceof HTMLElement) { + els = [ param1 ]; + } else if (param1.length !== undefined) { + for (let e in param1) { + if (! (param1[e] instanceof HTMLElement)) { + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } } - } - if (pluginToApply === undefined) { - console.error(`The action ${pluginName} is not registered`); + els = param1; } else { - for (let el of elements) { - pluginToApply.initialize(el, options); + console.error(`Parameter ${param1} is neither a valid selector, a list of elements or an HTMLElement`); + return; + } + + if (options === null) { + options = {}; + } + if (typeof(options) !== "object") { + console.error(`Options parameter must be an object`); + return; + } + + // Retrieve the keys of the registered plugins + if (pluginName !== null) { + let plugin = PowerButtons.actionsRegistered[pluginName]; + for (let el of els) { + plugin.initialize(el, options); } + } else { + // We are discovering the plugins and parameters from the tag + PowerButtons.discover(els, options); } - return els; }; -exports.powerButtons.version = '2.0.1'; +exports.powerButtons.version = '2.1.0'; exports.powerButtons.plugins = function() { return Object.keys(PowerButtons.actionsRegistered); } +exports.powerButtons.discoverAll = function() { + PowerButtons.discoverAll(); +} + +exports.powerButtons.discover = function(els, options) { + PowerButtons.discover(els, options); +} + +if (document.addEventListener !== undefined) { + document.addEventListener('DOMContentLoaded', function(e) { + PowerButtons.discoverAll(); + }); +} + // Now we add the plugin to jQuery, if it has been loaded if (exports.$ !== undefined) { exports.$.fn.powerButtons = function(pluginName, options = {}) { @@ -811,27 +897,22 @@ Object.assign(exports.powerButtons.utils, { } /** - * Function that initializes the actions of this library, by calling the `initializeAll` method of each action. The idea - * is that the `initializeAll` searches for the elements that have the data attributes for the action and initializes + * Function that initializes the actions of this library, by calling the `discoverAll` method of each action. The idea + * is that the `discoverAll` searches for the elements that have the data attributes for the action and initializes * them. */ - static initializeAll() { + static discoverAll() { Object.entries(this.actionsRegistered).forEach(([key, action]) => { - action.initializeAll(); + action.discoverAll(); }); } -} - -function init() { - PowerButtons.initializeAll(); -} -if (document.addEventListener !== undefined) { - document.addEventListener('DOMContentLoaded', function(e) { - init(); - }); -} -class Action { + static discover(els, options = {}) { + Object.entries(this.actionsRegistered).forEach(([key, action]) => { + action.discover(els, options); + }); + } +}class Action { static NAME = null; static register() { @@ -918,23 +999,47 @@ class Action { /** * Searches for any element with a data-{name} attribute, extract the values from the dataset (if any) and initializes - * it using the `initialize` method. (see `initialize` for more info). + * it using the `discover` method. (see `discover` for more info). + */ + static discoverAll() { + let prefix = this.NAME.toLowerCase(); + this.discover(document.querySelectorAll(`[data-${prefix}]`)); + } + + /** + * Extract the values from the dataset (if any) and initializes it using the `initialize` method. (see `initialize` for more info). * - * @param {object} values, the specific values to use for the initialization appart from the default ones; if not provided, - * the values will be extracted from the data attributes + * @param {HTMLElement | Array(HTMLElement)} els, the element(s) to discover the action for + * @param {object} options, the options to override for the initialization of the action from those extracted from the data attributes and the user-provided ones. + * @param {boolean} skipInitialized, if true, it will skip the element if it has already been initialized (i.e. if it has the _powerButtons._discover property contains the name + * of this action as a value in the array) */ - static initializeAll(values = null) { + static discover(els, options = {}, skipInitialized = true) { + if (els.length === undefined) { + els = [ els ]; + } + let prefix = this.NAME.toLowerCase(); - for (let el of document.querySelectorAll(`[data-${prefix}`)) { - let options = null; - if (values === null) { - options = this.extractOptions(el, prefix); - } else { - options = Object.assign({}, values); + for (let el of els) { + if ((skipInitialized) && (el._powerButtons !== undefined) && (el._powerButtons._discover !== undefined) && (el._powerButtons._discover.indexOf(prefix) !== -1)) { + continue; + } + if (el.dataset[prefix] === undefined) { + continue; } - this.initialize(el, options); - } + + let currentOptions = Object.assign(this.extractOptions(el, prefix), options); + this.initialize(el, currentOptions); + if (el._powerButtons !== undefined) { + if (el._powerButtons._discover === undefined) { + el._powerButtons._discover = []; + } + if (! el._powerButtons._discover.includes(prefix)) { + el._powerButtons._discover.push(prefix); + } + } + } } /**