diff --git a/asset/webcomponent/app.js b/asset/webcomponent/app.js index 347f67a..154af99 100644 --- a/asset/webcomponent/app.js +++ b/asset/webcomponent/app.js @@ -11,4 +11,6 @@ import { UiTextarea } from "./module/ui-textarea.js"; window.customElements.define("ui-textarea", UiTextarea); import { UiSelect } from "./module/ui-select.js"; -window.customElements.define("ui-select", UiSelect); \ No newline at end of file +window.customElements.define("ui-select", UiSelect); + +import './module/input.js'; \ No newline at end of file diff --git a/asset/webcomponent/module/input.js b/asset/webcomponent/module/input.js new file mode 100644 index 0000000..e9499d9 --- /dev/null +++ b/asset/webcomponent/module/input.js @@ -0,0 +1,22 @@ +(function() { + // Send automatically a form after one of it's input, which bears the data-input attributes, has changed + document.querySelectorAll('[data-input="send-on-change"]').forEach( + (element) => element.addEventListener("change", (e) => element.closest("form").submit()) + ); + + let inputCopyElement = document.querySelector('[data-input="copy"]'); + + if ( inputCopyElement ) { + inputCopyElement.inputCopy = function() { + let clone = this.cloneNode(true); + + this.parentNode.append(clone); + + this.parentNode.dispatchEvent(new CustomEvent("data-input:copied", { + detail: { + obj: clone + } + })); + }; + } +})(); \ No newline at end of file diff --git a/asset/webcomponent/module/swap.js b/asset/webcomponent/module/swap.js new file mode 100644 index 0000000..3705c8d --- /dev/null +++ b/asset/webcomponent/module/swap.js @@ -0,0 +1,152 @@ +class Swap { + constructor(name, callback) { + this.name = name; + + this.thenCallback = []; + + this.attached = []; + + this.parentElement = document.querySelector("[data-swap='" + name + "']"); + + if (! this.parentElement ) { + console.error("You must provide a valid HTMLElement to swap it. Impossible to query `" + name + "` element."); + } + + this.actionCallback = callback; + + this.swap(); + } + + swapHtml(html) { + this.parentElement.innerHTML = ( new DOMParser() ) + .parseFromString(html, "text/html") + .querySelector('[data-swap="' + this.name + '"]') + .innerHTML; + + this.parentElement.classList.remove("swapping"); + + this.swap(); + + this.attached.forEach(swapObj => { + swapObj.swapHtml(html); + }); + } + + swapUrl(url, callback) { + this.parentElement.classList.add("swapping"); + + fetch(url).then( response => response.text() ).then(html => { + this.swapHtml(html); + + if (callback) { + callback.call(this, this); + } + }); + + return this; + } + + swapForm(element) { + if (element instanceof HTMLElement) { + this.swapSingleForm(element); + } + else if (element instanceof HTMLCollection || element instanceof NodeList) { + element.forEach(ele => this.swapSingleForm(ele)); + } + + return this; + } + + swapSingleForm(element) { + element.addEventListener("submit", e => { + e.preventDefault(); + e.stopImmediatePropagation(); + + let body = new FormData(element); + + if (document.activeElement && document.activeElement.hasAttribute('name')) { + body.append(document.activeElement.getAttribute('name'), document.activeElement.value); + } + + let url = element.getAttribute("action") ? element.getAttribute("action") : location.href, + method = element.getAttribute("method") ? element.getAttribute("method") : "get"; + + fetch(url, { + body: body, + method: method + }).then( response => response.text() ).then( + html => { + this.swapHtml(html); + } + ); + }); + + return this; + } + + swap() { + this.actionCallback && this.actionCallback(this); + } + + then(callback) { + this.thenCallback.push[callback]; + + return this; + } + + attach(element) { + (Symbol.iterator in Object(element) ? element : [ element ]).forEach(e => { + this.attached.push(e); + }); + + return this; + } + + get form() { + return this._form; + } + + set form(value) { + return this._form = value; + } + + get actionCallback() { + return this._actionCallback; + } + + set actionCallback(value) { + return this._actionCallback = value; + } + + get parentElement() { + return this._parentElement; + } + + set parentElement(value) { + return this._parentElement = value; + } + + get name() { + return this._name; + } + + set name(value) { + return this._name = value; + } + + get thenCallback() { + return this._thenCallback; + } + + set thenCallback(value) { + return this._thenCallback = value; + } + + get attached() { + return this._attached; + } + + set attached(value) { + return this._attached = value; + } +} \ No newline at end of file diff --git a/view/webcomponent/ui-popup.phtml b/view/webcomponent/ui-popup.phtml index 2d40a98..e66e844 100644 --- a/view/webcomponent/ui-popup.phtml +++ b/view/webcomponent/ui-popup.phtml @@ -1,5 +1,5 @@