Compare commits
11
Commits
e55292fba7
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d08bd478fe | ||
|
|
c944b8569f | ||
|
|
0bb08584e2 | ||
|
|
45095b221d | ||
|
|
14bccd50a8 | ||
|
|
778fabb51c | ||
|
|
005f631793 | ||
|
|
2bfb4bc7f8 | ||
|
|
cf03c5b542 | ||
|
|
29057fcdfa | ||
|
|
722226d062 |
No files matched your search
@@ -1,14 +1,20 @@
|
|||||||
|
|
||||||
import { ElementObserver } from "./element-observer.js";
|
|
||||||
|
|
||||||
import { UiTabs } from "./module/ui-tabs.js";
|
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";
|
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";
|
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";
|
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.get("ui-notification") || window.customElements.define("ui-notification", UiNotification);
|
||||||
|
|
||||||
|
import './module/input.js';
|
||||||
@@ -89,7 +89,7 @@ class ElementObserver {
|
|||||||
console.log("@todo!", split_selector);
|
console.log("@todo!", split_selector);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( $element.is( this.listeners[action][j].selector ) ) {
|
if ( element.is( this.listeners[action][j].selector ) ) {
|
||||||
this.listeners[action][j].callback.call(element, element);
|
this.listeners[action][j].callback.call(element, element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,39 @@
|
|||||||
/*
|
const defaultConfig = {
|
||||||
* Really simple timer / timeout object
|
|
||||||
*
|
|
||||||
* @author Dave Mc Nicoll
|
|
||||||
* @version 2.0.0
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
timer: 1000,
|
timer: 1000,
|
||||||
start: false,
|
start: false,
|
||||||
loop: true,
|
loop: true,
|
||||||
run: false, // If you need a defined number of code execution, set a number to run and loop to false.
|
occurences: false, // If you need a defined number of code execution, set a number to run and loop to false.
|
||||||
complete: function(){} // This complete callback function is called if the run exec number is reached.
|
complete: function(){} // This complete callback function is called if the run exec number is reached.
|
||||||
};
|
};
|
||||||
|
|
||||||
class Hourglass {
|
class Hourglass {
|
||||||
|
#callback;
|
||||||
|
#config = {};
|
||||||
|
|
||||||
constructor(callback, options) {
|
constructor(callback, options) {
|
||||||
this.object_id = null;
|
this.#config = {...this.#config, ...defaultConfig, ...( options ? options : {} ), };
|
||||||
this.counter = null;
|
|
||||||
this.callback = callback !== undefined ? callback : function() {};
|
|
||||||
|
|
||||||
if ( config.start ) {
|
this.objectId = null;
|
||||||
|
this.counter = null;
|
||||||
|
this.callback = callback ? callback : function() {};
|
||||||
|
|
||||||
|
if ( this.config.start ) {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start(timeout) {
|
start(timeout) {
|
||||||
let time = ( timeout !== undefined ? timeout : config.timer );
|
let time = ( timeout !== undefined ? timeout : this.config.timer );
|
||||||
|
|
||||||
if ( config.loop ) {
|
if ( this.config.loop ) {
|
||||||
if ( this.counter === null ) {
|
if ( this.counter === null ) {
|
||||||
this.counter = config.loop ? 0 : null
|
this.counter = this.config.loop ? 0 : null
|
||||||
}
|
}
|
||||||
|
|
||||||
this.object_id = window.setInterval( this.call_interval.bind(this), time);
|
this.objectId = window.setInterval( this.callInterval.bind(this), time);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.object_id = window.setTimeout( this.call_timeout.bind(this), time);
|
this.objectId = window.setTimeout( this.callTimeout.bind(this), time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,44 +43,45 @@ class Hourglass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
if ( config.loop ) {
|
if ( this.config.loop ) {
|
||||||
this.object_id && window.clearInterval(this.object_id);
|
this.objectId && window.clearInterval(this.objectId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.object_id && window.clearTimeout(this.object_id);
|
this.objectId && window.clearTimeout(this.objectId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.stop();
|
this.stop();
|
||||||
this.counter = null;
|
this.counter = null;
|
||||||
this.object_id = null;
|
this.objectId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_timeout() {
|
callTimeout() {
|
||||||
this.callback();
|
this.callback();
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
call_interval() {
|
callInterval() {
|
||||||
this.callback();
|
this.callback();
|
||||||
|
|
||||||
if ( this.counter !== null && ++this.counter === config.run ) {
|
if ( this.counter !== null && ++this.counter === this.config.occurences ) {
|
||||||
this.clear();
|
this.clear();
|
||||||
config.complete !== undefined && config.complete();
|
|
||||||
|
this.config.complete !== undefined && this.config.complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
running() {
|
running() {
|
||||||
return !! this.object_id;
|
return !! this.objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get callback() {
|
get callback() {
|
||||||
return this._callback;
|
return this.#callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
set callback(value) {
|
set callback(value) {
|
||||||
return this._callback = value;
|
return this.#callback = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get counter() {
|
get counter() {
|
||||||
@@ -95,12 +92,20 @@ class Hourglass {
|
|||||||
return this._counter = value;
|
return this._counter = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get object_id() {
|
get objectId() {
|
||||||
return this._object_id;
|
return this._objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
set object_id(value) {
|
set objectId(value) {
|
||||||
return this._object_id = value;
|
return this._objectId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get config() {
|
||||||
|
return this.#config;
|
||||||
|
}
|
||||||
|
|
||||||
|
set config(value) {
|
||||||
|
return this.#config = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* JQuery Mobile Swipe
|
||||||
|
*
|
||||||
|
* This plugin adds some classes to html's DOM which can be used as fallback for action such as :hover which are not
|
||||||
|
* always intuitive on mobile ( and sometimes, unexisting ).
|
||||||
|
|
||||||
|
* Based on jquery.detectSwipe v2.1.1 [http://github.com/marcandre/detect_swipe] which is based on touchwipe by Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
|
||||||
|
*/
|
||||||
|
(function ($) {
|
||||||
|
$.mobileswipe = {
|
||||||
|
attach : register,
|
||||||
|
enabled : 'ontouchstart' in document.documentElement,
|
||||||
|
threshold : 20,
|
||||||
|
reset_timer : null
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.mobileswipe = register;
|
||||||
|
|
||||||
|
$.event.special.swipe = { setup: register };
|
||||||
|
|
||||||
|
$.each(['left', 'up', 'down', 'right'], function () {
|
||||||
|
$.event.special['swipe' + this] = {setup: function () {
|
||||||
|
$(this).on('swipe', $.noop);
|
||||||
|
}};
|
||||||
|
});
|
||||||
|
|
||||||
|
$(function() { $('.swipe').mobileswipe(); });
|
||||||
|
|
||||||
|
var startX, startY,
|
||||||
|
timeout_instance = [],
|
||||||
|
isMoving = false;
|
||||||
|
|
||||||
|
function onTouchEnd() {
|
||||||
|
this.removeEventListener('touchmove', onTouchMove);
|
||||||
|
this.removeEventListener('touchend', onTouchEnd);
|
||||||
|
isMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTouchMove(e) {
|
||||||
|
if (isMoving) {
|
||||||
|
var dir, delta, $this = $(this);
|
||||||
|
|
||||||
|
if (Math.abs(delta = startX - e.touches[0].pageX) >= $.mobileswipe.threshold) {
|
||||||
|
dir = delta > 0 ? 'left' : 'right';
|
||||||
|
$this.removeClass('swipe-left swipe-right');
|
||||||
|
}
|
||||||
|
else if (Math.abs(delta = startY - e.touches[0].pageY) >= $.mobileswipe.threshold) {
|
||||||
|
dir = delta < 0 ? 'down' : 'up';
|
||||||
|
$this.removeClass('swipe-down swipe-up');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dir ) {
|
||||||
|
onTouchEnd.call(this);
|
||||||
|
$this.trigger('swipe', dir).trigger('swipe' + dir).addClass('swipe-' + dir);
|
||||||
|
checkPersistency($this, dir, $this.data('reset-timer'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTouchStart(e) {
|
||||||
|
if (e.touches.length === 1) {
|
||||||
|
startX = e.touches[0].pageX;
|
||||||
|
startY = e.touches[0].pageY;
|
||||||
|
isMoving = true;
|
||||||
|
|
||||||
|
this.addEventListener('touchmove', onTouchMove, false);
|
||||||
|
this.addEventListener('touchend', onTouchEnd, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkPersistency($elem, dir, timer) {
|
||||||
|
timer || ( timer = $.mobileswipe.reset_timer );
|
||||||
|
|
||||||
|
if ( timer ) {
|
||||||
|
(dir in timeout_instance) && clearTimeout(timeout_instance[dir]);
|
||||||
|
|
||||||
|
timeout_instance[dir] = setTimeout(function() {
|
||||||
|
$elem.removeClass('swipe-'+dir);
|
||||||
|
}, timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function register() {
|
||||||
|
$(this).each(function() {
|
||||||
|
this.addEventListener && this.addEventListener('touchstart', onTouchStart, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function unregister() {
|
||||||
|
$(this).each(function() {
|
||||||
|
this.removeEventListener('touchstart', onTouchStart);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})(jQuery);
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { Webcomponent } from "./webcomponent.js";
|
||||||
|
|
||||||
|
class UiNotification extends Webcomponent {
|
||||||
|
|
||||||
|
#intervalId;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
template: {
|
||||||
|
fetch:false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
if ( this.activate() ) {
|
||||||
|
this.start_pooling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
if (window.Notification) {
|
||||||
|
if ( (Notification.permission !== "denied") && (Notification.permission !== 'granted') ) {
|
||||||
|
this.style.visibility = "visible";
|
||||||
|
this.style.cursor = "pointer";
|
||||||
|
|
||||||
|
this.addEventListener('click', e => {
|
||||||
|
Notification.requestPermission().then((permission) => {
|
||||||
|
this.style.visibility = "hidden";
|
||||||
|
this.start_pooling();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Notification.permission === "granted";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pooling() {
|
||||||
|
this.intervalId = setInterval(this.pool.bind(this), this.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_pooling() {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
pool() {
|
||||||
|
if (Notification.permission === "granted") {
|
||||||
|
fetch(this.url_fetch + "?ts=" + this.timestamp)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data =>{
|
||||||
|
if (data.notification) {
|
||||||
|
var notification = new Notification(data.title, {
|
||||||
|
icon: this.url_icon,
|
||||||
|
body: data.body,
|
||||||
|
});
|
||||||
|
|
||||||
|
notification.onclick = function () {
|
||||||
|
let win = window.open(data.url, data.title);
|
||||||
|
|
||||||
|
setTimeout(e => win.focus(), 600);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.timestamp = data.timestamp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get timestamp() {
|
||||||
|
return this.dataset.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
set timestamp(value) {
|
||||||
|
return this.dataset.timestamp = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get url_fetch() {
|
||||||
|
return this.dataset.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
get url_icon() {
|
||||||
|
return this.dataset.icon ? this.dataset.icon : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get interval() {
|
||||||
|
return this.dataset.interval ? this.dataset.interval : Math.floor(Math.random() * (45000 - 15000) + 15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
get intervalId() {
|
||||||
|
return this.#intervalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
set intervalId(value) {
|
||||||
|
return this.#intervalId = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { UiNotification }
|
||||||
@@ -6,79 +6,55 @@ const config = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class UiPopup extends Webcomponent {
|
class UiPopup extends Webcomponent {
|
||||||
|
#scrollPosition;
|
||||||
|
#options = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.fetch_template();
|
|
||||||
this.message = this.querySelector('.message');
|
this.message = this.querySelector('.message');
|
||||||
this.title = this.querySelector('.title');
|
this.title = this.querySelector('.title');
|
||||||
|
|
||||||
this.replaceVarsPlaceholder().attach().render();
|
if (!this.message) {
|
||||||
|
this.message = document.createElement("div");
|
||||||
|
}
|
||||||
|
|
||||||
this.init();
|
if (!this.title) {
|
||||||
|
this.title = document.createElement("div");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.replaceVarsPlaceholder().attach().render();
|
||||||
this.handleOptions();
|
this.handleOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOptions() {
|
handleOptions() {
|
||||||
if ( this.options ) {
|
if ( this.options['skip-keys'] === undefined ) {
|
||||||
if ( ! this.options['skip-keys'] ) {
|
document.addEventListener('keyup', function(e) {
|
||||||
document.addEventListener('keyup', function(e) {
|
if ( this.visible() ) {
|
||||||
if ( this.visible() ) {
|
|
||||||
let trigger, ev;
|
|
||||||
|
|
||||||
e.preventDefault();
|
let trigger, ev;
|
||||||
|
|
||||||
// There's no real value in checking if the popup is shown or not.
|
e.preventDefault();
|
||||||
switch ( e.keyCode ) {
|
|
||||||
// RETURN
|
|
||||||
case 13:
|
|
||||||
trigger = this.querySelector('[action="confirm"]');
|
|
||||||
ev = new CustomEvent('click', { trigger: trigger } );
|
|
||||||
|
|
||||||
trigger.dispatchEvent(ev);
|
switch ( e.keyCode ) {
|
||||||
break;
|
case 13:
|
||||||
|
trigger = this.querySelector('[action="confirm"]');
|
||||||
|
break;
|
||||||
|
|
||||||
// ESC
|
case 27:
|
||||||
case 27:
|
trigger = this.querySelector('[action="close"]');
|
||||||
trigger = this.querySelector('[action="close"]');
|
break;
|
||||||
ev = new CustomEvent('click', { trigger: trigger } );
|
|
||||||
|
|
||||||
trigger.dispatchEvent(ev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
|
||||||
}
|
if (trigger) {
|
||||||
|
ev = new CustomEvent('click', {trigger: trigger});
|
||||||
|
trigger.dispatchEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
|
||||||
document.addEventListener('keyup', function(e) {
|
|
||||||
if ( this.visible() ) {
|
|
||||||
let trigger, ev;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// There's no real value in checking if the popup is shown or not.
|
|
||||||
switch ( e.keyCode ) {
|
|
||||||
case 13: // RETURN
|
|
||||||
trigger = this.querySelector('[action="confirm"]');
|
|
||||||
ev = new CustomEvent('click', { trigger: trigger } );
|
|
||||||
|
|
||||||
trigger.dispatchEvent(ev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case 8: // BACKSPACE
|
|
||||||
case 27: // ESC
|
|
||||||
trigger = this.querySelector('[action="close"]');
|
|
||||||
ev = new CustomEvent('click', { trigger: trigger } );
|
|
||||||
|
|
||||||
trigger.dispatchEvent(ev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
attach() {
|
attach() {
|
||||||
let triggers = document.querySelectorAll('[ui-popup]');
|
let triggers = document.querySelectorAll('[ui-popup]');
|
||||||
@@ -99,14 +75,23 @@ class UiPopup extends Webcomponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.querySelectorAll('[action]').forEach(function(element) {
|
this.querySelectorAll('[action]:not(form)').forEach(function(element) {
|
||||||
element.addEventListener("click", this.action.bind(this, element), false);
|
element.addEventListener("click", this.action.bind(this, element), false);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this.hide();
|
if ( this.classList.contains("show") ) {
|
||||||
|
this.classList.remove("show");
|
||||||
|
|
||||||
|
setTimeout(() => this.show(), 100);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action(element, e) {
|
action(element, e) {
|
||||||
|
let retval;
|
||||||
|
|
||||||
if ( ! element.attributes.action ) {
|
if ( ! element.attributes.action ) {
|
||||||
throw "A button was clicked onto which no action was bound.";
|
throw "A button was clicked onto which no action was bound.";
|
||||||
}
|
}
|
||||||
@@ -115,10 +100,22 @@ class UiPopup extends Webcomponent {
|
|||||||
case "confirm":
|
case "confirm":
|
||||||
case "yes":
|
case "yes":
|
||||||
case "ok":
|
case "ok":
|
||||||
this.actionFollowLink(element) ||
|
retval = this.actionFollowLink(element) ||
|
||||||
this.actionClickButton(element) ||
|
this.actionClickButton(element);
|
||||||
this.actionSendForm(this.trigger) ||
|
|
||||||
this.actionSendForm(element);
|
if (! retval) {
|
||||||
|
retval = this.actionSendForm(element) ||
|
||||||
|
this.actionSendForm(this.trigger) ||
|
||||||
|
this.actionSendForm(this.querySelector('[slot="message"] form')) ||
|
||||||
|
this.actionSendForm(this.querySelector('[slot="title"] form')) ||
|
||||||
|
this.actionSendForm(this.querySelector('[slot="buttons"] form'));
|
||||||
|
|
||||||
|
if ( ! retval ) {
|
||||||
|
throw "No action to trigger automatically on Popup confirmation.";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "cancel":
|
case "cancel":
|
||||||
case "no":
|
case "no":
|
||||||
@@ -127,8 +124,13 @@ class UiPopup extends Webcomponent {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable multiple clicks
|
||||||
|
if (retval !== undefined) {
|
||||||
|
element.setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
this.dispatchEvent(new CustomEvent('action:' + element.attributes.action.value));
|
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") ) {
|
if ( element.getAttribute("action") ) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -139,10 +141,15 @@ class UiPopup extends Webcomponent {
|
|||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
this.classList.remove('visible');
|
this.classList.remove('visible');
|
||||||
|
|
||||||
|
window.scrollTo(window.scrollX, this.scrollPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
|
this.scrollPosition = window.scrollY;
|
||||||
this.classList.add('visible');
|
this.classList.add('visible');
|
||||||
|
|
||||||
|
window.scrollTo(window.scrollX, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
visible() {
|
visible() {
|
||||||
@@ -153,8 +160,8 @@ class UiPopup extends Webcomponent {
|
|||||||
|
|
||||||
//if ( element.getAttribute('follow-link') !== null ) {
|
//if ( element.getAttribute('follow-link') !== null ) {
|
||||||
// Automatically redirect to given location if it exists.
|
// Automatically redirect to given location if it exists.
|
||||||
if ( this.trigger.tagName === "A" ) {
|
if ( this.trigger && this.trigger.tagName === "A" ) {
|
||||||
let href = this.trigger.getAttribute('href');
|
const href = this.trigger.getAttribute('href');
|
||||||
|
|
||||||
if ( href ) {
|
if ( href ) {
|
||||||
window.location = href;
|
window.location = href;
|
||||||
@@ -168,19 +175,19 @@ class UiPopup extends Webcomponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actionClickButton(element) {
|
actionClickButton(element) {
|
||||||
|
if (this.trigger) {
|
||||||
|
const tag = this.trigger.tagName.toLowerCase();
|
||||||
|
|
||||||
//if ( element.getAttribute('button-click') !== null ) {
|
// Automatically redirect to given location if it exists.
|
||||||
let tag = this.trigger.tagName.toLowerCase();
|
if ((tag === "button" || tag === "input") && this.trigger.getAttribute("type").toLowerCase() === "submit") {
|
||||||
|
this.pause = true;
|
||||||
|
|
||||||
// Automatically redirect to given location if it exists.
|
this.trigger.click();
|
||||||
if ( tag === "button" || ( ( tag === "input" ) && ( this.trigger.getAttribute("type").toLowerCase() === "submit") ) ) {
|
|
||||||
this.pause = true;
|
|
||||||
|
|
||||||
this.trigger.click();
|
this.pause = false;
|
||||||
|
|
||||||
this.pause = false;
|
return true;
|
||||||
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -188,18 +195,28 @@ class UiPopup extends Webcomponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actionSendForm(element) {
|
actionSendForm(element) {
|
||||||
//if ( element.getAttribute('send-form') !== null ) {
|
if ( ! element ) {
|
||||||
//let form = this.trigger.tagName === "FORM" ? this.trigger : this.trigger.closest('FORM');
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let form = element.tagName === "FORM" ? element : element.closest('FORM');
|
let form = element.tagName === "FORM" ? element : element.closest('FORM');
|
||||||
|
|
||||||
if ( form ) {
|
if ( form ) {
|
||||||
form.submit();
|
form.addEventListener("submit", e => this.hide, { once: true });
|
||||||
|
|
||||||
|
let submitBtn = form.querySelector("button[type='submit']");
|
||||||
|
|
||||||
|
if (submitBtn) {
|
||||||
|
submitBtn.click();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
form.requestSubmit();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw "A send-form action was set on a popup where the trigger as no parent form.";
|
return false;
|
||||||
}
|
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +230,6 @@ class UiPopup extends Webcomponent {
|
|||||||
this.trigger = item;
|
this.trigger = item;
|
||||||
|
|
||||||
args.vars && Object.keys(args.vars).map(function(objectKey, index) {
|
args.vars && Object.keys(args.vars).map(function(objectKey, index) {
|
||||||
// let element = this.message.querySelectorAll(`.${objectKey}`);
|
|
||||||
let element = Array.prototype.slice.call( this.message.querySelectorAll(`.${objectKey}`) ).concat(Array.prototype.slice.call(this.title.querySelectorAll(`.${objectKey}`)));
|
let element = Array.prototype.slice.call( this.message.querySelectorAll(`.${objectKey}`) ).concat(Array.prototype.slice.call(this.title.querySelectorAll(`.${objectKey}`)));
|
||||||
|
|
||||||
element.length ? element.forEach(function(item) {
|
element.length ? element.forEach(function(item) {
|
||||||
@@ -224,22 +240,42 @@ class UiPopup extends Webcomponent {
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
if ( args.options ) {
|
if ( args.options ) {
|
||||||
|
if (args.options['clear_input']) {
|
||||||
|
let skipInput = args.options['clear_input']['skip'] ? args.options['clear_input']['skip'] : [];
|
||||||
|
|
||||||
|
this.querySelectorAll(`input,textarea`).forEach(function(f) {
|
||||||
|
if (! skipInput.includes(f.name)) {
|
||||||
|
f.value = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
args.options['input'] && Object.keys(args.options['input']).forEach(
|
args.options['input'] && Object.keys(args.options['input']).forEach(
|
||||||
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) {
|
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) {
|
||||||
if (f.tagName === "TEXTAREA") {
|
f.value = args.options['input'][key];
|
||||||
f.value = args.options['input'][key];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
f.setAttribute("value", args.options['input'][key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
f.dispatchEvent(new Event("change"));
|
f.dispatchEvent(new Event("change"));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
args.options['form_url'] && Object.keys(args.options['form_url']).forEach(
|
||||||
|
key => {
|
||||||
|
let form = this.querySelector(`form${key}`);
|
||||||
|
|
||||||
|
form = form ? form : this.closest(`form${key}`);
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
form.setAttribute('action', args.options['form_url'][key]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn(`Form selector '${key}' could not be found within popup.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.show();
|
this.show();
|
||||||
|
|
||||||
|
e.stopPropagation();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,6 +317,22 @@ class UiPopup extends Webcomponent {
|
|||||||
return this._message = value;
|
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() {
|
get title() {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ class UiSelect extends Webcomponent {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.fetch_template();
|
|
||||||
|
|
||||||
this.wrapper = this.shadowRoot.querySelector(config.content.wrapper);
|
this.wrapper = this.shadowRoot.querySelector(config.content.wrapper);
|
||||||
this.list = this.shadowRoot.querySelector(config.content.list);
|
this.list = this.shadowRoot.querySelector(config.content.list);
|
||||||
this.input = this.querySelector('input:not([type="hidden"])');
|
this.input = this.querySelector('input:not([type="hidden"])');
|
||||||
|
|||||||
@@ -5,19 +5,20 @@ const config = {
|
|||||||
item: ".tab-item",
|
item: ".tab-item",
|
||||||
content: ".tab-content",
|
content: ".tab-content",
|
||||||
activeClass: "ui-tab-active",
|
activeClass: "ui-tab-active",
|
||||||
|
template: {
|
||||||
|
fetch : false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class UiTabs extends Webcomponent {
|
class UiTabs extends Webcomponent {
|
||||||
constructor(parameters) {
|
constructor() {
|
||||||
super();
|
super(config);
|
||||||
|
|
||||||
this.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
connectedCallback() {
|
||||||
window.addEventListener("hashchange", this.hashChange.bind(this), false);
|
window.addEventListener("hashchange", this.hashChange.bind(this), false);
|
||||||
|
|
||||||
//this.querySelectorAll(config.item).forEach(ele => ele.addEventListener("click", this.clickTab.bind(this)));
|
//this.querySelectorAll(this.config.item).forEach(ele => ele.addEventListener("click", this.clickTab.bind(this)));
|
||||||
|
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
let eve = new Event("click");
|
let eve = new Event("click");
|
||||||
@@ -29,16 +30,16 @@ class UiTabs extends Webcomponent {
|
|||||||
hashChange(e) {
|
hashChange(e) {
|
||||||
let anchor = e.newURL.split('#')[1];
|
let anchor = e.newURL.split('#')[1];
|
||||||
|
|
||||||
document.querySelectorAll("#" + anchor + config.content).forEach(function(content) {
|
document.querySelectorAll(`[id='${anchor}']${this.config.content}`).forEach(function(content) {
|
||||||
content.parentNode.querySelectorAll(config.content + "." + config.activeClass).forEach(ele => ele.classList.remove(config.activeClass));
|
content.parentNode.querySelectorAll(this.config.content + "." + this.config.activeClass).forEach(ele => ele.classList.remove(this.config.activeClass));
|
||||||
content.classList.add(config.activeClass);
|
content.classList.add(this.config.activeClass);
|
||||||
});
|
}.bind(this));
|
||||||
|
|
||||||
let element = this.querySelector("." + config.activeClass);
|
let element = this.querySelector("." + this.config.activeClass);
|
||||||
element ? element.classList.remove(config.activeClass) : null;
|
element ? element.classList.remove(this.config.activeClass) : null;
|
||||||
|
|
||||||
element = this.querySelector(config.item + `[href="#${anchor}"]`);
|
element = this.querySelector(this.config.item + `[href="#${anchor}"]`);
|
||||||
element ? element.closest('div').classList.add(config.activeClass) : null;
|
element ? element.closest('div').classList.add(this.config.activeClass) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
clickTab(e) {
|
clickTab(e) {
|
||||||
@@ -47,4 +48,4 @@ class UiTabs extends Webcomponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { UiTabs }
|
export { UiTabs };
|
||||||
@@ -24,8 +24,7 @@ class UiTextarea extends Webcomponent {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.fetch_template();
|
|
||||||
this.wrapper = this.shadowRoot.querySelector(domElements.wrapper);
|
this.wrapper = this.shadowRoot.querySelector(domElements.wrapper);
|
||||||
this.content = this.shadowRoot.querySelector(domElements.boilerplate);
|
this.content = this.shadowRoot.querySelector(domElements.boilerplate);
|
||||||
this.toolbar = this.shadowRoot.querySelector(domElements.toolbar);
|
this.toolbar = this.shadowRoot.querySelector(domElements.toolbar);
|
||||||
@@ -41,7 +40,9 @@ class UiTextarea extends Webcomponent {
|
|||||||
render() {
|
render() {
|
||||||
document.execCommand("DefaultParagraphSeparator", false, "p");
|
document.execCommand("DefaultParagraphSeparator", false, "p");
|
||||||
|
|
||||||
this.content.innerHTML = this.textarea.value.trim();
|
this.textarea.addEventListener("change", (e) => this.content.innerHTML = this.textarea.value.trim());
|
||||||
|
|
||||||
|
this.textarea.dispatchEvent(new Event("change"));
|
||||||
|
|
||||||
this.content.addEventListener("input", function(e, d) {
|
this.content.addEventListener("input", function(e, d) {
|
||||||
this.content.querySelectorAll('[style]').forEach(function(element) {
|
this.content.querySelectorAll('[style]').forEach(function(element) {
|
||||||
|
|||||||
@@ -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 }
|
||||||
@@ -1,21 +1,38 @@
|
|||||||
|
|
||||||
class Webcomponent extends HTMLElement {
|
class Webcomponent extends HTMLElement {
|
||||||
|
#config = {
|
||||||
|
template: {
|
||||||
|
fetch : true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fetch_template() {
|
constructor(config) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
this.#config = {...this.#config, ...( config ? config : {} ) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.config.template.fetch) {
|
||||||
|
this.fetchTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchTemplate() {
|
||||||
this.attachShadow({mode: 'open'}).appendChild(
|
this.attachShadow({mode: 'open'}).appendChild(
|
||||||
document.querySelector("template#" + this.tagName.toLowerCase()).content.cloneNode(true)
|
document.querySelector("template#" + this.tagName.toLowerCase()).content.cloneNode(true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_name() {
|
getName() {
|
||||||
return Object.getPrototypeOf(this).constructor.name;
|
return Object.getPrototypeOf(this).constructor.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_slot(name) {
|
getSlot(name) {
|
||||||
return this.querySelector('[slot="' + name + '"]');
|
return this.querySelector('[slot="' + name + '"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
empty_element(element) {
|
emptyElement(element) {
|
||||||
while (element.lastChild) {
|
while (element.lastChild) {
|
||||||
element.removeChild(element.lastChild);
|
element.removeChild(element.lastChild);
|
||||||
}
|
}
|
||||||
@@ -23,11 +40,40 @@ class Webcomponent extends HTMLElement {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_url(url, data) {
|
buildUrl(url, data) {
|
||||||
return url + ( Object.entries(data).length ? "?" + Object.keys(data).map(function(key) {
|
return url + ( Object.entries(data).length ? "?" + Object.keys(data).map(function(key) {
|
||||||
return [key, data[key]].map(encodeURIComponent).join("=");
|
return [key, data[key]].map(encodeURIComponent).join("=");
|
||||||
}).join("&") : "" );
|
}).join("&") : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on(type, listener, options) {
|
||||||
|
this.addEventListener(type, listener, options);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
off(type, listener, options) {
|
||||||
|
this.removeEventListener(type, listener, options);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(name, detail, bubbles, cancelable, composed) {
|
||||||
|
this.dispatchEvent(new CustomEvent(name, {
|
||||||
|
detail: detail ? detail : null,
|
||||||
|
bubbles: !! bubbles,
|
||||||
|
cancelable: !! cancelable,
|
||||||
|
composed: !! composed,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
get config() {
|
||||||
|
return this.#config;
|
||||||
|
}
|
||||||
|
|
||||||
|
set config(value) {
|
||||||
|
return this.#config = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Webcomponent };
|
export { Webcomponent };
|
||||||
@@ -3,6 +3,12 @@
|
|||||||
return [
|
return [
|
||||||
'assets.webcomponent' => [
|
'assets.webcomponent' => [
|
||||||
'picea' => [
|
'picea' => [
|
||||||
|
'view' => [
|
||||||
|
[
|
||||||
|
'path' => implode(DIRECTORY_SEPARATOR, [ dirname(__DIR__), "view", '' ]),
|
||||||
|
'order' => 10
|
||||||
|
]
|
||||||
|
],
|
||||||
'asset' => [
|
'asset' => [
|
||||||
[
|
[
|
||||||
'path' => implode(DIRECTORY_SEPARATOR, [ dirname(__DIR__), "asset", '' ]),
|
'path' => implode(DIRECTORY_SEPARATOR, [ dirname(__DIR__), "asset", '' ]),
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<ui-calendar>
|
||||||
|
<style></style>
|
||||||
|
|
||||||
|
</ui-calendar>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<template id="ui-message">
|
||||||
|
<style type="text/css">
|
||||||
|
.fa, .fas {font-family: "Font Awesome 5 Pro";font-weight: 900;}
|
||||||
|
.fa, .fab, .fal, .far, .fas {-moz-osx-font-smoothing: grayscale;-webkit-font-smoothing: antialiased;font-style: normal;font-variant: normal;text-rendering: auto;line-height: 1;}
|
||||||
|
.fa-check::before { content: "\f00c"; }
|
||||||
|
.fa-exclamation::before { content: "\f12a"; }
|
||||||
|
.fa-question::before { content: "\f128"; }
|
||||||
|
.fa-times::before { content: "\f00d"; }
|
||||||
|
|
||||||
|
.ui-message { cursor:pointer;padding: 1em;margin: 1.5em auto;display: block;background: #aeaeae;border-radius: 2px;max-width: 90%;color: #424040;font-size: 0.9em; }
|
||||||
|
.ui-message.error { background:#ec4f4f;border-bottom: 2px solid #ad4e4e;color:#621f1f }
|
||||||
|
.ui-message.success { background:#67d87c; border-bottom: 2px solid #4ead60;color:#2b362e}
|
||||||
|
.ui-message.info { background:#61b5f3; border-bottom: 2px solid #4c8ebf;color:#113550 }
|
||||||
|
.ui-message.warning { background:#e6da55; border-bottom: 2px solid #c9bf52; color:#5f5708}
|
||||||
|
|
||||||
|
.icon-main {display:none;}
|
||||||
|
.ui-message.success .icon-main.green,
|
||||||
|
.ui-message.error .icon-main.is-error,
|
||||||
|
.ui-message.info .icon-main.is-info,
|
||||||
|
.ui-message.warning .icon-main.yellow {display:inline}
|
||||||
|
|
||||||
|
header {font-family:inherit;display:flex;font-size:1.8em;width:100%;line-height:1em; flex-direction:row;resize: horizontal;}
|
||||||
|
header .icon-main {flex-shrink:1;width:1.75em;text-align: center;}
|
||||||
|
header .is-title {margin-right:auto;flex-grow: 1;}
|
||||||
|
|
||||||
|
.message:not(:empty) { margin-top:0.66em;}
|
||||||
|
|
||||||
|
/* footer:not(:empty) {padding:15px 0 0 0;margin:15px 0 0 0;border-top:1px solid rgba(255,255,255,1)} */
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="ui-message">
|
||||||
|
<header>
|
||||||
|
<i class="icon-main green fas fa-check"></i>
|
||||||
|
<i class="icon-main yellow fas fa-exclamation"></i>
|
||||||
|
<i class="icon-main is-error fas fa-times"></i>
|
||||||
|
<i class="icon-main is-info fas fa-exclamation"></i>
|
||||||
|
|
||||||
|
<slot class="is-title" name="title"></slot>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="message"><slot name="content"></slot></section>
|
||||||
|
<footer><slot name="footer"></slot></footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script defer="defer" src='{% asset "apps/script/component/message.js" %}'></script>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<template id="ui-notification">
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="notification-wrapper">
|
||||||
|
<header>
|
||||||
|
<i class="icon-main green fas fa-check"></i>
|
||||||
|
<i class="icon-main yellow fas fa-exclamation"></i>
|
||||||
|
<i class="icon-main is-error fas fa-times"></i>
|
||||||
|
<i class="icon-main is-info fas fa-exclamation"></i>
|
||||||
|
|
||||||
|
<slot class="is-title" name="title"></slot>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="message"><slot name="content"></slot></section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script defer="defer" src='{% asset "apps/script/component/notification.js" %}'></script>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<style>
|
||||||
|
ui-popup:not(.modal) {box-shadow:0px 0px 0px 9999px rgba(0, 0, 0, 0.5);z-index:9999;transition:all 0.3s ease-out;background:#fff;position:absolute!important;top:0;left: 50%;transform:translate(-50%, 5vh);border: 2px solid #ddd;}
|
||||||
|
ui-popup:not(.visible) {transform: translate(-50%, -100%);transition-timing-function: ease-in;translate(-50%, -100%);box-shadow:none;}
|
||||||
|
ui-popup.modal.visible {display:flex}
|
||||||
|
ui-popup > * {padding:1rem 1.4rem}
|
||||||
|
ui-popup .button-list {text-align:right;}
|
||||||
|
ui-popup .button-list .button {padding: 0px 7%;}
|
||||||
|
ui-popup [slot="title"] {font-size:1.5rem;display:flex;justify-content: space-between;background:rgba(120,120,120,0.12);color:#464646}
|
||||||
|
ui-popup [slot="title"]:empty {display:none}
|
||||||
|
ui-popup [slot="message"] {background: transparent;padding:1.2rem 1.5rem!important}
|
||||||
|
ui-popup [slot="buttons"] {background:rgba(120,120,120,0.07)}
|
||||||
|
ui-popup [slot="buttons"]:empty {display:none}
|
||||||
|
ui-popup::before {left:0;right:0;top:0;bottom:0;background:rgba(0,0,0,0.1);content:" ";pointer-events: none}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<template id="ui-popup">
|
||||||
|
<section class="ui-popup section">
|
||||||
|
<slot name="title"></slot>
|
||||||
|
<slot name="message"></slot>
|
||||||
|
<slot name="buttons"></slot>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
Whitespace-only changes.
@@ -0,0 +1,31 @@
|
|||||||
|
<style>
|
||||||
|
ui-select .input{padding-right:35px;}
|
||||||
|
ui-select .input[readonly]{cursor:pointer}
|
||||||
|
ui-select .input:focus {border-bottom:0;border-bottom-left-radius:0; border-bottom-right-radius:0;}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<template id="ui-select">
|
||||||
|
<style>
|
||||||
|
:root {box-sizing:border-box;}
|
||||||
|
* {box-sizing: border-box;}
|
||||||
|
.hidden {display:none!important}
|
||||||
|
.wrapper {position:relative;}
|
||||||
|
.item-list { max-height:calc(2.25rem * 6); overflow-y:auto; background: #fff;margin:0;list-style:none;padding: 5px;z-index: 15;position: absolute;width: 100%;border:1px solid #3273dc;border-top: transparent;top: calc(100%);border-bottom-left-radius:4px; border-bottom-right-radius:4px; }
|
||||||
|
.is-editing .item-list {box-shadow: 0 2px 0 .125em rgba(50,115,220,.25);}
|
||||||
|
.item-list li {padding-bottom: calc(.375em - 1px);padding-left: calc(.625em - 1px);padding-right: calc(.625em - 1px);padding-top: calc(.375em - 1px);color:#333;cursor:pointer;border-top: 1px solid #efefef;}
|
||||||
|
.item-list li.selected,
|
||||||
|
.item-list li:hover {background:#f7f7f7}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<slot style="display:none" name="input"></slot>
|
||||||
|
<slot name="search-input">
|
||||||
|
<input type="text">
|
||||||
|
</slot>
|
||||||
|
<slot name="create-input">
|
||||||
|
<input type="hidden">
|
||||||
|
</slot>
|
||||||
|
<ul class="item-list">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<template id="ui-textarea">
|
||||||
|
<style>
|
||||||
|
.wrapper {position:relative;max-width:100%;}
|
||||||
|
.wrapper:before {content: " ";display: block;position: absolute;height: 100%;top: 0;transition:all ease-in-out 0.3s;background: #fff;z-index: 0;border: 1px solid #dbdbdb;width: calc(100% - 2px);left: 2px}
|
||||||
|
.wrapper:after {content: " ";display: block;position: absolute;width:auto;height:calc(100% - 40px);left: 25px; right:25px;top: 20px; z-index: 0;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QcLAh4Qvp/CQwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAAQSURBVAjXY2CgF3jx4sV/AAmVA7iKudk/AAAAAElFTkSuQmCC')}
|
||||||
|
|
||||||
|
.content {position:relative;word-wrap: break-word;font-family:Helvetica;white-space: pre-wrap;padding: 20px 30px 20px 30px;max-width:100%;left:0;right:0;top:0;bottom:0;cursor:text;z-index: 3;font:inherit;min-height:7em;line-height:22px;outline:0;font-size:0.9em}
|
||||||
|
.content::-moz-selection {background: rgba(0,0,0,0.10);color:#365766}
|
||||||
|
.content::selection {background: rgba(0,0,0,0.10);color:#365766}
|
||||||
|
.content *::-moz-selection {background: rgba(0,0,0,0.10);color:#365766}
|
||||||
|
.content *::selection {background: rgba(0,0,0,0.10);color:#365766}
|
||||||
|
.content b {font-weight:bold;}
|
||||||
|
.content i {font-style:italic}
|
||||||
|
.content p {margin-bottom: 0;margin-top: 0;}
|
||||||
|
|
||||||
|
.toolbar { position:absolute;color: #000;padding: 4px;transition:all 0.3s ease-in;top:0;right: 10px;opacity:0.0;z-index:0;background:#eee;border:1px solid #ccc;text-align:center;}
|
||||||
|
.toolbar:hover, .content:focus + .toolbar {opacity:1.0;z-index:20;top: -20px;}
|
||||||
|
.toolbar .is-action {display:none;}
|
||||||
|
.toolbar .icon {color:#adadad;cursor:pointer;width:30px;height:30px;line-height:30px;vertical-align:middle;}
|
||||||
|
.toolbar .icon svg {max-width: 50%;max-height: 50%;}
|
||||||
|
.toolbar .icon:hover{color:#555;background:rgba(0,0,0,0.15);}
|
||||||
|
.toolbar .icon:before{color:inherit;}
|
||||||
|
.toolbar .font-color .color-palette { display:none; }
|
||||||
|
.toolbar .font-color:hover .color-palette { display:block; }
|
||||||
|
.toolbar .font-weight {font-weight:bold}
|
||||||
|
.toolbar a {text-decoration:none;}
|
||||||
|
.toolbar-lite .toolbar [data-action="align"],
|
||||||
|
.toolbar-lite .toolbar .font-color {display:none;}
|
||||||
|
|
||||||
|
.toolbar[action~="color"] .font-color,
|
||||||
|
.toolbar[action~="italic"] .font-style,
|
||||||
|
.toolbar[action~="align-left"] .align-left,
|
||||||
|
.toolbar[action~="align-right"] .align-right,
|
||||||
|
.toolbar[action~="align-center"] .align-center,
|
||||||
|
.toolbar[action~="align-justify"] .align-justify,
|
||||||
|
.toolbar[action~="undo"] .undo,
|
||||||
|
.toolbar[action~="redo"] .redo,
|
||||||
|
.toolbar[action~="bold"] .font-weight {display:inline-block}
|
||||||
|
|
||||||
|
.lite .content {min-height:auto;}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
<slot style="display:none" name="input"></slot>
|
||||||
|
|
||||||
|
<div contenteditable="true" class="content"></div>
|
||||||
|
|
||||||
|
<div class="toolbar" action="bold italic color align-left align-right align-center align-justify undo redo">
|
||||||
|
<a href="#" data-action="bold" class="icon font-weight is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="bold" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="svg-inline--fa fa-bold fa-w-12 fa-3x"><path fill="currentColor" d="M304.793 243.891c33.639-18.537 53.657-54.16 53.657-95.693 0-48.236-26.25-87.626-68.626-104.179C265.138 34.01 240.849 32 209.661 32H24c-8.837 0-16 7.163-16 16v33.049c0 8.837 7.163 16 16 16h33.113v318.53H24c-8.837 0-16 7.163-16 16V464c0 8.837 7.163 16 16 16h195.69c24.203 0 44.834-1.289 66.866-7.584C337.52 457.193 376 410.647 376 350.014c0-52.168-26.573-91.684-71.207-106.123zM142.217 100.809h67.444c16.294 0 27.536 2.019 37.525 6.717 15.828 8.479 24.906 26.502 24.906 49.446 0 35.029-20.32 56.79-53.029 56.79h-76.846V100.809zm112.642 305.475c-10.14 4.056-22.677 4.907-31.409 4.907h-81.233V281.943h84.367c39.645 0 63.057 25.38 63.057 63.057.001 28.425-13.66 52.483-34.782 61.284z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="italic" class="icon font-style is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="italic" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" class="svg-inline--fa fa-italic fa-w-10"><path fill="currentColor" d="M204.758 416h-33.849l62.092-320h40.725a16 16 0 0 0 15.704-12.937l6.242-32C297.599 41.184 290.034 32 279.968 32H120.235a16 16 0 0 0-15.704 12.937l-6.242 32C96.362 86.816 103.927 96 113.993 96h33.846l-62.09 320H46.278a16 16 0 0 0-15.704 12.935l-6.245 32C22.402 470.815 29.967 480 40.034 480h158.479a16 16 0 0 0 15.704-12.935l6.245-32c1.927-9.88-5.638-19.065-15.704-19.065z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<label data-action="color" class="icon font-color is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="palette" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-palette fa-w-16 fa-3x"><path fill="currentColor" d="M204.3 5C104.9 24.4 24.8 104.3 5.2 203.4c-37 187 131.7 326.4 258.8 306.7 41.2-6.4 61.4-54.6 42.5-91.7-23.1-45.4 9.9-98.4 60.9-98.4h79.7c35.8 0 64.8-29.6 64.9-65.3C511.5 97.1 368.1-26.9 204.3 5zM96 320c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm32-128c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128-64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm128 64c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z" class=""></path></svg>
|
||||||
|
|
||||||
|
<div class="color-palette">
|
||||||
|
<input style="display:none" name="colorpicker" type="color" value="">
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<a href="#" data-action="align" data-value="left" class="icon align-left is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="align-left" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-align-left fa-w-14 fa-3x"><path fill="currentColor" d="M288 44v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16V44c0-8.837 7.163-16 16-16h256c8.837 0 16 7.163 16 16zM0 172v40c0 8.837 7.163 16 16 16h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16zm16 312h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm256-200H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="align" data-value="center" class="icon align-center is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="align-center" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-align-center fa-w-14 fa-3x"><path fill="currentColor" d="M352 44v40c0 8.837-7.163 16-16 16H112c-8.837 0-16-7.163-16-16V44c0-8.837 7.163-16 16-16h224c8.837 0 16 7.163 16 16zM16 228h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm320-200H112c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16h224c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="align" data-value="right" class="icon align-right is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="align-right" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-align-right fa-w-14 fa-3x"><path fill="currentColor" d="M160 84V44c0-8.837 7.163-16 16-16h256c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H176c-8.837 0-16-7.163-16-16zM16 228h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm160-128h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H176c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="align" data-value="justify" class="icon align-justify is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="align-justify" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-align-justify fa-w-14 fa-3x"><path fill="currentColor" d="M0 84V44c0-8.837 7.163-16 16-16h416c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16zm16 144h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0-128h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="undo" class="icon undo is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="undo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-undo fa-w-16 fa-3x"><path fill="currentColor" d="M212.333 224.333H12c-6.627 0-12-5.373-12-12V12C0 5.373 5.373 0 12 0h48c6.627 0 12 5.373 12 12v78.112C117.773 39.279 184.26 7.47 258.175 8.007c136.906.994 246.448 111.623 246.157 248.532C504.041 393.258 393.12 504 256.333 504c-64.089 0-122.496-24.313-166.51-64.215-5.099-4.622-5.334-12.554-.467-17.42l33.967-33.967c4.474-4.474 11.662-4.717 16.401-.525C170.76 415.336 211.58 432 256.333 432c97.268 0 176-78.716 176-176 0-97.267-78.716-176-176-176-58.496 0-110.28 28.476-142.274 72.333h98.274c6.627 0 12 5.373 12 12v48c0 6.627-5.373 12-12 12z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="#" data-action="redo" class="icon redo is-action">
|
||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="redo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-redo fa-w-16 fa-3x"><path fill="currentColor" d="M500.333 0h-47.411c-6.853 0-12.314 5.729-11.986 12.574l3.966 82.759C399.416 41.899 331.672 8 256.001 8 119.34 8 7.899 119.526 8 256.187 8.101 393.068 119.096 504 256 504c63.926 0 122.202-24.187 166.178-63.908 5.113-4.618 5.354-12.561.482-17.433l-33.971-33.971c-4.466-4.466-11.64-4.717-16.38-.543C341.308 415.448 300.606 432 256 432c-97.267 0-176-78.716-176-176 0-97.267 78.716-176 176-176 60.892 0 114.506 30.858 146.099 77.8l-101.525-4.865c-6.845-.328-12.574 5.133-12.574 11.986v47.411c0 6.627 5.373 12 12 12h200.333c6.627 0 12-5.373 12-12V12c0-6.627-5.373-12-12-12z" class=""></path></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
{# <script defer="defer" src='{% asset "apps/script/component/textarea.js" %}'></script> #}
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<template id="ui-upload">
|
||||||
|
<style>
|
||||||
|
[hidden] {display:none !important}
|
||||||
|
.image-drop {display:flex;border-radius:4px;cursor:pointer;height:30vh;background:#fff;margin:5vh auto;text-align:center;border:1px dashed #909599;font-size:3rem;justify-content:center;align-items:center;}
|
||||||
|
.image-drop:hover {border-color:#676565}
|
||||||
|
.image-drop:hover span {text-decoration: underline;}
|
||||||
|
.image-drop.ui-dragdrop-over {opacity:0.66;}
|
||||||
|
.image-drop .drop-file {display:inline-block;line-height:20vh;color:#888;font-size:1.5em;}
|
||||||
|
.image-drop i {opacity:0.7}
|
||||||
|
.image-drop:hover i {opacity:1.0}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<label class="image-drop">
|
||||||
|
<slot style="display:none" name="input"></slot>
|
||||||
|
<slot name="icon"></slot>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="ui-upload-media">
|
||||||
|
<style>
|
||||||
|
* {box-sizing: border-box}
|
||||||
|
img {max-height: 15vh;max-width:100%}
|
||||||
|
.new-media-wrapper {display:flex;flex-flow:wrap;align-items:center;background: #e3e3e3;border: 1px solid #ccc;}
|
||||||
|
.new-media-item {width:33.33%;padding:2%}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="new-media-item" hidden><div><img></div></div>
|
||||||
|
|
||||||
|
<div class="new-media-wrapper"></div>
|
||||||
|
</template>
|
||||||
Reference in new issue
Block a user