- WIP on Swipe module, fixed some bugs within ui-popup

This commit is contained in:
Dave M. 2024-11-21 19:14:32 -05:00
parent 778fabb51c
commit 14bccd50a8
4 changed files with 154 additions and 22 deletions

View File

@ -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);

View File

@ -13,6 +13,14 @@ class UiPopup extends Webcomponent {
this.message = this.querySelector('.message'); this.message = this.querySelector('.message');
this.title = this.querySelector('.title'); this.title = this.querySelector('.title');
if (!this.message) {
this.message = document.createElement("div");
}
if (!this.title) {
this.title = document.createElement("div");
}
this.replaceVarsPlaceholder().attach().render(); this.replaceVarsPlaceholder().attach().render();
this.init(); this.init();
@ -55,25 +63,32 @@ class UiPopup extends Webcomponent {
init() { init() {
document.addEventListener('keyup', function(e) { document.addEventListener('keyup', function(e) {
if ( this.visible() ) { if ( this.visible() ) {
let trigger, ev; let trigger, ev, action;
e.preventDefault(); e.preventDefault();
// There's no real value in checking if the popup is shown or not. // There's no real value in checking if the popup is shown or not.
switch ( e.keyCode ) { switch ( e.keyCode ) {
case 13: // RETURN case 13: // RETURN
trigger = this.querySelector('[action="confirm"]'); action = "confirm";
ev = new CustomEvent('click', { trigger: trigger } );
trigger.dispatchEvent(ev);
break; break;
case 27: // ESC case 27: // ESC
trigger = this.querySelector('[action="close"]'); action = "close";
break
}
if (action) {
trigger = this.querySelector(`[action="${action}"]`);
if ( trigger ) {
ev = new CustomEvent('click', {trigger: trigger}); ev = new CustomEvent('click', {trigger: trigger});
trigger.dispatchEvent(ev); trigger.dispatchEvent(ev);
break; }
else {
this.hide();
}
} }
} }
}.bind(this)); }.bind(this));
@ -98,7 +113,7 @@ 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));
@ -116,10 +131,13 @@ class UiPopup extends Webcomponent {
case "ok": case "ok":
let retval = this.actionFollowLink(element) || let retval = this.actionFollowLink(element) ||
this.actionClickButton(element); this.actionClickButton(element);
if (! retval) { if (! retval) {
retval = this.actionSendForm(element) || retval = this.actionSendForm(element) ||
this.actionSendForm(this.trigger) || this.actionSendForm(this.trigger) ||
this.actionSendForm(element.closest('ui-popup').querySelector('form')); this.actionSendForm(this.querySelector('[slot="message"] form')) ||
this.actionSendForm(this.querySelector('[slot="title"] form')) ||
this.actionSendForm(this.querySelector('[slot="buttons"] form'));
if ( ! retval ) { if ( ! retval ) {
throw "No action to trigger automatically on Popup confirmation."; throw "No action to trigger automatically on Popup confirmation.";
@ -181,7 +199,7 @@ class UiPopup extends Webcomponent {
let tag = this.trigger.tagName.toLowerCase(); let tag = this.trigger.tagName.toLowerCase();
// Automatically redirect to given location if it exists. // Automatically redirect to given location if it exists.
if ( tag === "button" || ( ( tag === "input" ) && ( this.trigger.getAttribute("type").toLowerCase() === "submit") ) ) { if ( ( tag === "button" || tag === "input" ) && this.trigger.getAttribute("type").toLowerCase() === "submit") {
this.pause = true; this.pause = true;
this.trigger.click(); this.trigger.click();
@ -205,7 +223,7 @@ class UiPopup extends Webcomponent {
let form = element.tagName === "FORM" ? element : element.closest('FORM'); let form = element.tagName === "FORM" ? element : element.closest('FORM');
if ( form ) { if ( form ) {
// form.addEventListener("submit", e => this.hide); form.addEventListener("submit", e => this.hide, { once: true });
let submitBtn = form.querySelector("button[type='submit']"); let submitBtn = form.querySelector("button[type='submit']");
@ -233,7 +251,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) {
@ -244,22 +261,41 @@ class UiPopup extends Webcomponent {
}.bind(this)); }.bind(this));
if ( args.options ) { if ( args.options ) {
args.options['input'] && Object.keys(args.options['input']).forEach( if (args.options['clear_input']) {
key => this.querySelectorAll(`[name="${key}"]`).forEach(function(f) { let skipInput = args.options['clear_input']['skip'] ? args.options['clear_input']['skip'] : [];
if (f.tagName === "TEXTAREA") {
f.value = args.options['input'][key]; this.querySelectorAll(`input,textarea`).forEach(function(f) {
if (! skipInput.includes(f.name)) {
f.value = "";
} }
else { });
f.setAttribute("value", args.options['input'][key]);
} }
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")); f.dispatchEvent(new Event("change"));
}) })
); );
args.options['form_url'] && Object.keys(args.options['form_url']).forEach(
key => {
let form = this.querySelector(`form${key}`);
if (form) {
form.setAttribute('action', args.options['form_url'][key]);
}
else {
console.warn(`Form selector '${key}' could not be found within popup.`);
}
}
);
} }
this.show(); this.show();
e.stopPropagation();
return true; return true;
} }

View File

@ -41,7 +41,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) {

View File

@ -5,8 +5,8 @@
ui-popup > * {padding:1.5rem} ui-popup > * {padding:1.5rem}
ui-popup .button-list {text-align:right;} ui-popup .button-list {text-align:right;}
ui-popup .button-list .button {padding: 0px 7%;} 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="message"] {background: transparent;padding:1.2rem 1.5rem!important} ui-popup [slot="message"] {background: transparent;padding:1.2rem 1.5rem!important}
ui-popup [slot="title"] {font-size:1.5rem;display:flex;justify-content: space-between;background:rgba(120,120,120,0.12)}
ui-popup [slot="buttons"] {background:rgba(120,120,120,0.07)} ui-popup [slot="buttons"] {background:rgba(120,120,120,0.07)}
ui-popup::before {left:0;right:0;top:0;bottom:0;background:rgba(0,0,0,0.1);content:" ";} ui-popup::before {left:0;right:0;top:0;bottom:0;background:rgba(0,0,0,0.1);content:" ";}
</style> </style>