diff --git a/asset/webcomponent/app.js b/asset/webcomponent/app.js
index 3515fc5..ac99c47 100644
--- a/asset/webcomponent/app.js
+++ b/asset/webcomponent/app.js
@@ -1,17 +1,20 @@
-
import { UiTabs } from "./module/ui-tabs.js";
-window.customElements.define("ui-tabs", UiTabs);
+window.customElements.get("ui-tabs") || window.customElements.define("ui-tabs", UiTabs);
import { UiPopup } from "./module/ui-popup.js";
-window.customElements.define("ui-popup", UiPopup);
+window.customElements.get("ui-popup") || window.customElements.define("ui-popup", UiPopup);
import { UiTextarea } from "./module/ui-textarea.js";
-window.customElements.define("ui-textarea", UiTextarea);
+window.customElements.get("ui-textarea") || window.customElements.define("ui-textarea", UiTextarea);
import { UiSelect } from "./module/ui-select.js";
-window.customElements.define("ui-select", UiSelect);
+window.customElements.get("ui-select") || window.customElements.define("ui-select", UiSelect);
+
+import { UiUpload, UiUploadMedia } from "./module/ui-upload.js";
+window.customElements.get("ui-upload") || window.customElements.define("ui-upload", UiUpload);
+window.customElements.get("ui-upload-media") || window.customElements.define("ui-upload-media", UiUploadMedia);
import { UiNotification } from "./module/ui-notification.js";
-window.customElements.define("ui-notification", UiNotification);
+window.customElements.get("ui-notification") || window.customElements.define("ui-notification", UiNotification);
import './module/input.js';
\ No newline at end of file
diff --git a/asset/webcomponent/module/ui-popup.js b/asset/webcomponent/module/ui-popup.js
index 36d8206..b2acf9b 100644
--- a/asset/webcomponent/module/ui-popup.js
+++ b/asset/webcomponent/module/ui-popup.js
@@ -6,6 +6,9 @@ const config = {
};
class UiPopup extends Webcomponent {
+ #scrollPosition;
+ #options = {};
+
constructor() {
super();
@@ -25,36 +28,34 @@ class UiPopup extends Webcomponent {
}
handleOptions() {
- if ( this.options ) {
- if ( ! this.options['skip-keys'] ) {
- document.addEventListener('keyup', function(e) {
- if ( this.visible() ) {
+ if ( this.options['skip-keys'] === undefined ) {
+ document.addEventListener('keyup', function(e) {
+ if ( this.visible() ) {
- let trigger, ev;
+ let trigger, ev;
- e.preventDefault();
- console.log(this.visible());
+ e.preventDefault();
- switch ( e.keyCode ) {
- case 13:
- trigger = this.querySelector('[action="confirm"]');
- break;
+ switch ( e.keyCode ) {
+ case 13:
+ trigger = this.querySelector('[action="confirm"]');
+ break;
- case 27:
- trigger = this.querySelector('[action="close"]');
- break;
- }
-
- if (trigger) {
- ev = new CustomEvent('click', {trigger: trigger});
- trigger.dispatchEvent(ev);
- }
+ case 27:
+ trigger = this.querySelector('[action="close"]');
+ break;
}
- }.bind(this));
- }
+
+ if (trigger) {
+ ev = new CustomEvent('click', {trigger: trigger});
+ trigger.dispatchEvent(ev);
+ }
+ }
+ }.bind(this));
}
}
+
attach() {
let triggers = document.querySelectorAll('[ui-popup]');
@@ -78,10 +79,19 @@ class UiPopup extends Webcomponent {
element.addEventListener("click", this.action.bind(this, element), false);
}.bind(this));
- this.hide();
+ if ( this.classList.contains("show") ) {
+ this.classList.remove("show");
+
+ setTimeout(() => this.show(), 100);
+ }
+ else {
+ this.hide();
+ }
}
action(element, e) {
+ let retval;
+
if ( ! element.attributes.action ) {
throw "A button was clicked onto which no action was bound.";
}
@@ -90,7 +100,7 @@ class UiPopup extends Webcomponent {
case "confirm":
case "yes":
case "ok":
- let retval = this.actionFollowLink(element) ||
+ retval = this.actionFollowLink(element) ||
this.actionClickButton(element);
if (! retval) {
@@ -114,8 +124,13 @@ class UiPopup extends Webcomponent {
break;
}
+ // Disable multiple clicks
+ if (retval !== undefined) {
+ element.setAttribute('disabled', 'disabled');
+ }
+
this.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
- this.trigger.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
+ this.trigger && this.trigger.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
if ( element.getAttribute("action") ) {
e.preventDefault();
@@ -126,10 +141,15 @@ class UiPopup extends Webcomponent {
hide() {
this.classList.remove('visible');
+
+ window.scrollTo(window.scrollX, this.scrollPosition);
}
show() {
+ this.scrollPosition = window.scrollY;
this.classList.add('visible');
+
+ window.scrollTo(window.scrollX, 0);
}
visible() {
@@ -140,8 +160,8 @@ class UiPopup extends Webcomponent {
//if ( element.getAttribute('follow-link') !== null ) {
// Automatically redirect to given location if it exists.
- if ( this.trigger.tagName === "A" ) {
- let href = this.trigger.getAttribute('href');
+ if ( this.trigger && this.trigger.tagName === "A" ) {
+ const href = this.trigger.getAttribute('href');
if ( href ) {
window.location = href;
@@ -155,19 +175,19 @@ class UiPopup extends Webcomponent {
}
actionClickButton(element) {
+ if (this.trigger) {
+ const tag = this.trigger.tagName.toLowerCase();
- //if ( element.getAttribute('button-click') !== null ) {
- let tag = this.trigger.tagName.toLowerCase();
+ // Automatically redirect to given location if it exists.
+ if ((tag === "button" || tag === "input") && this.trigger.getAttribute("type").toLowerCase() === "submit") {
+ this.pause = true;
- // Automatically redirect to given location if it exists.
- if ( ( tag === "button" || tag === "input" ) && this.trigger.getAttribute("type").toLowerCase() === "submit") {
- this.pause = true;
+ this.trigger.click();
- this.trigger.click();
+ this.pause = false;
- this.pause = false;
-
- return true;
+ return true;
+ }
}
//}
@@ -179,8 +199,6 @@ class UiPopup extends Webcomponent {
return false;
}
- //if ( element.getAttribute('send-form') !== null ) {
- //let form = this.trigger.tagName === "FORM" ? this.trigger : this.trigger.closest('FORM');
let form = element.tagName === "FORM" ? element : element.closest('FORM');
if ( form ) {
@@ -192,7 +210,7 @@ class UiPopup extends Webcomponent {
submitBtn.click();
}
else {
- form.submit();
+ form.requestSubmit();
}
return true;
@@ -234,7 +252,6 @@ class UiPopup extends Webcomponent {
args.options['input'] && Object.keys(args.options['input']).forEach(
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) {
- console.log(f);
f.value = args.options['input'][key];
f.dispatchEvent(new Event("change"));
})
@@ -244,6 +261,8 @@ class UiPopup extends Webcomponent {
key => {
let form = this.querySelector(`form${key}`);
+ form = form ? form : this.closest(`form${key}`);
+
if (form) {
form.setAttribute('action', args.options['form_url'][key]);
}
@@ -298,6 +317,22 @@ class UiPopup extends Webcomponent {
return this._message = value;
}
+ get options() {
+ return this.#options;
+ }
+
+ set options(value) {
+ return this.#options = value;
+ }
+
+ get scrollPosition() {
+ return this.#scrollPosition;
+ }
+
+ set scrollPosition(value) {
+ return this.#scrollPosition = value;
+ }
+
get title() {
return this._title;
}
diff --git a/asset/webcomponent/module/ui-tabs.js b/asset/webcomponent/module/ui-tabs.js
index b7e643d..35949da 100644
--- a/asset/webcomponent/module/ui-tabs.js
+++ b/asset/webcomponent/module/ui-tabs.js
@@ -13,11 +13,9 @@ const config = {
class UiTabs extends Webcomponent {
constructor() {
super(config);
-
- this.init();
}
- init() {
+ connectedCallback() {
window.addEventListener("hashchange", this.hashChange.bind(this), false);
//this.querySelectorAll(this.config.item).forEach(ele => ele.addEventListener("click", this.clickTab.bind(this)));
@@ -32,7 +30,7 @@ class UiTabs extends Webcomponent {
hashChange(e) {
let anchor = e.newURL.split('#')[1];
- document.querySelectorAll("#" + anchor + this.config.content).forEach(function(content) {
+ document.querySelectorAll(`[id='${anchor}']${this.config.content}`).forEach(function(content) {
content.parentNode.querySelectorAll(this.config.content + "." + this.config.activeClass).forEach(ele => ele.classList.remove(this.config.activeClass));
content.classList.add(this.config.activeClass);
}.bind(this));
diff --git a/asset/webcomponent/module/ui-upload.js b/asset/webcomponent/module/ui-upload.js
new file mode 100644
index 0000000..ce40ff2
--- /dev/null
+++ b/asset/webcomponent/module/ui-upload.js
@@ -0,0 +1,67 @@
+
+import { Webcomponent } from './webcomponent.js';
+
+const config = {
+ content: {
+ wrapper: ".wrapper",
+ list: ".item-list"
+ }
+};
+
+class UiUpload extends Webcomponent {
+ #input;
+ #uploadmedia;
+
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ this.attachInput();
+
+ this.#uploadmedia = document.querySelector(`ui-upload-media[data-name="${this.name}"]`)
+ }
+
+ attachInput() {
+ this.#input = this.querySelector('input:not([type="hidden"])');
+ this.addEventListener('click', () => this.#input.click());
+ this.#input.addEventListener('change', this.changeMedia.bind(this));
+ }
+
+ changeMedia(e) {
+ let inputHtml = this.#input.outerHTML;
+
+ Array.from(this.#input.files).forEach(file => {
+ const base64Res = new FileReader();
+ this.#uploadmedia.addThumbnail(base64Res, this.#input);
+ base64Res.readAsDataURL(file)
+ });
+
+ this.getSlot("input").insertAdjacentHTML('beforeend', inputHtml);
+ this.attachInput();
+ }
+
+ get name() {
+ return this.dataset['name'];
+ }
+}
+
+class UiUploadMedia extends Webcomponent {
+ addThumbnail(media, input) {
+ const wrapper = this.shadowRoot.querySelector(".new-media-wrapper"),
+ mediaItem = this.shadowRoot.querySelector(".new-media-item[hidden]").cloneNode(true);
+
+ mediaItem.removeAttribute('hidden');
+ wrapper.append(mediaItem);
+ this.getSlot("input").append(input);
+
+ media.onload = f => {
+ mediaItem.querySelector('img').setAttribute('src', media.result);
+// mediaItem.querySelector('.name-input').value = file.name;
+ }
+
+ }
+
+}
+
+export { UiUpload, UiUploadMedia }
diff --git a/view/webcomponent/ui-popup.phtml b/view/webcomponent/ui-popup.phtml
index 990b0dc..fc9921e 100644
--- a/view/webcomponent/ui-popup.phtml
+++ b/view/webcomponent/ui-popup.phtml
@@ -1,14 +1,16 @@