From 7aa203150fc1a2ec79c681c13f0d486d531746eb Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Sun, 12 Mar 2023 23:57:48 +0200 Subject: error pages; js system to support back/front-end --- html/assets/js/utils/domHelper.js | 375 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 html/assets/js/utils/domHelper.js (limited to 'html/assets/js/utils/domHelper.js') diff --git a/html/assets/js/utils/domHelper.js b/html/assets/js/utils/domHelper.js new file mode 100644 index 0000000..f36ab1a --- /dev/null +++ b/html/assets/js/utils/domHelper.js @@ -0,0 +1,375 @@ +define(function () { + + function isElement(obj) { + //instanceof fails for elements that have been created by another document (iframe case) + //in that case we check other properties existing in all element nodes + return obj instanceof HTMLElement || ((typeof obj === "object") && + (obj.nodeType === 1) && (typeof obj.style === "object") && + (typeof obj.ownerDocument === "object")); + } + + let slideUp = (target, duration = 500, callback = null) => { + target.style.transitionProperty = 'height, margin, padding'; + target.style.transitionDuration = duration + 'ms'; + target.style.boxSizing = 'border-box'; + target.style.height = target.offsetHeight + 'px'; + target.offsetHeight; + target.style.overflow = 'hidden'; + target.style.height = 0; + target.style.paddingTop = 0; + target.style.paddingBottom = 0; + target.style.marginTop = 0; + target.style.marginBottom = 0; + window.setTimeout(() => { + target.style.display = 'none'; + target.style.removeProperty('height'); + target.style.removeProperty('padding-top'); + target.style.removeProperty('padding-bottom'); + target.style.removeProperty('margin-top'); + target.style.removeProperty('margin-bottom'); + target.style.removeProperty('overflow'); + target.style.removeProperty('transition-duration'); + target.style.removeProperty('transition-property'); + if (callback) { + callback(); + } + }, duration); + } + + let slideDown = (target, duration = 500, callback = null) => { + target.style.removeProperty('display'); + let display = window.getComputedStyle(target).display; + + if (display === 'none') + display = 'block'; + + target.style.display = display; + let height = target.offsetHeight; + target.style.overflow = 'hidden'; + target.style.height = 0; + target.style.paddingTop = 0; + target.style.paddingBottom = 0; + target.style.marginTop = 0; + target.style.marginBottom = 0; + target.offsetHeight; + target.style.boxSizing = 'border-box'; + target.style.transitionProperty = "height, margin, padding"; + target.style.transitionDuration = duration + 'ms'; + target.style.height = height + 'px'; + target.style.removeProperty('padding-top'); + target.style.removeProperty('padding-bottom'); + target.style.removeProperty('margin-top'); + target.style.removeProperty('margin-bottom'); + window.setTimeout(() => { + target.style.removeProperty('height'); + target.style.removeProperty('overflow'); + target.style.removeProperty('transition-duration'); + target.style.removeProperty('transition-property'); + if (callback) { + callback(); + } + }, duration); + } + + var slideToggle = (target, duration = 500, callback = null) => { + if (window.getComputedStyle(target).display === 'none') { + return slideDown(target, duration, callback); + } else { + return slideUp(target, duration, callback); + } + } + + function resolveSelector(selector, context) { + if (typeof (selector) !== "string") { + if (context) { + throw 'Context is allowed only when selector is a string.'; + } + if (Array.isArray(selector)) { + return selector; + } + if (isElement(selector)) { + return [selector]; + } + + throw 'Selector can either be a string or an array'; + } + if (!context) { + return document.querySelectorAll(selector); + } + if (typeof (context) == "string") { + return resolveSelector(selector).filter(element => element.matches(selector)); + } + else if (Array.isArray(context)) { + return context.filter(element => element.matches(selector)); + } + else if (isElement(context)) { + return context.querySelectorAll(selector); + } + else { + throw 'Unknown context type: ' + typeof (context) + ". Not a string, array or HTMLElement."; + } + } + + var factory = (target, context) => new domHelper(target, context); + function domHelper(target, context) { + this.elements = Array.from(resolveSelector(target, context)); + this.on = function (event, callback) { + for (let i = 0; i < this.elements.length; i++) { + this.elements[i].addEventListener(event, function (e) { + callback.apply(e.target, arguments); + }); + } + return this; + } + this.parent = function (selector) { + if (!selector) { + return factory( + this.elements.map(e => e.parentElement).filter(e => e) + ); + } + return factory( + this.elements.map(element => { + do { + if (element.parentElement.matches(selector)) { + return element.parentElement; + } + element = element.parentElement; + + } while (element.parentElement); + return null; + }).filter(e => e) + ); + } + this.parents = function (selector) { + var parents = this.elements.map(e => { + var r = []; + while (e.parentElement) { + r.push(e.parentElement); + e = e.parentElement; + } + return r; + }).reduce((acc, curVal) => { + return acc.concat(curVal) + }).filter(e => e); + + if (!selector) { + return factory(parents); + } + return factory(selector, parents); + } + this.find = function (selector) { + return factory(this.elements.map(e => { + return factory(selector, e).elements; + }).reduce((acc, curVal) => { + return acc.concat(curVal) + })); + } + this.show = function () { + this.each(e => e.style.display = "block"); + } + this.hide = function () { + this.each(e => e.style.display = "none"); + } + this.innerWidth = function () { + var element = this.elements[0]; + return parseInt(window.getComputedStyle(element).width); + } + this.toggle = function () { + this.each(e => { + if ((e.offsetParent === null)) // hidden + { + e.style.display = "block"; + } + else { + e.style.display = "none"; + } + }); + } + this.each = function (callback) { + this.elements.forEach(callback); + return this; + } + this.scroll = function () { + this.each(element => element.scroll.apply(element, arguments)); + return this; + } + this.addClass = function (cssClass) { + if (!cssClass) { + return; + } + var classes = cssClass.split(' '); + this.elements.forEach(element => { + classes.forEach(cssClass => { + element.classList.add(cssClass); + }); + }); + return this; + } + this.removeClass = function (cssClass) { + if (!cssClass) { + return; + } + var classes = cssClass.split(' '); + this.elements.forEach(element => { + classes.forEach(cssClass => { + element.classList.remove(cssClass); + }); + }); + return this; + } + this.toggleClass = function (cssClass) { + if (!cssClass) { + return; + } + var classes = cssClass.split(' '); + this.elements.forEach(element => { + classes.forEach(cssClass => { + element.classList.toggle(cssClass); + }); + }); + return this; + } + this.is = function (selector) { + return factory(selector, this.elements).elements.length > 0; + } + this.not = function (exclude) { + if (typeof (exclude) == "string") { + return factory(this.elements.filter(e => !e.matches(exclude))); + } + else if (Array.isArray(exclude)) { + return factory(this.elements.filter(e => exclude.indexOf(e) == -1)); + } + else if (isElement(exclude)) { + return factory(this.elements.filter(e => e != exclude)); + } + else if (exclude instanceof domHelper) { + return factory(this.elements.filter(e => exclude.elements.indexOf(e) == -1)); + } + else { + throw 'Unknown exclude type: ' + typeof (exclude) + ". Not a string, array or HTMLElement or domHelper."; + } + } + this.get = (index) => this.elements[index]; + this.length = this.elements.length; + this.siblings = function (selector) { + var next = this.next(selector); + var prev = this.prev(selector); + return factory(prev.elements.concat(next.elements)); + } + this.next = function (selector) { + var siblings = this.elements.map(e => { + var r = []; + while (e.nextElementSibling) { + r.push(e.nextElementSibling); + e = e.nextElementSibling; + } + return r; + }).reduce((acc, curVal) => { + return acc.concat(curVal) + }).filter(e => e); + + if (!selector) { + return factory(siblings); + } + return factory(selector, siblings); + } + this.prev = function (selector) { + var siblings = this.elements.map(e => { + var r = []; + while (e.previousElementSibling) { + r.push(e.previousElementSibling); + e = e.previousElementSibling; + } + return r; + }).reduce((acc, curVal) => { + return acc.concat(curVal) + }).filter(e => e); + + if (!selector) { + return factory(siblings); + } + return factory(selector, siblings); + } + this.index = function () { + var items = []; + this.prev().each(function (e) { + items.push(e); + }); + items.push(this.get(0)); + this.next().each(function (e) { + items.push(e); + }); + return items.indexOf(this.get(0)); + } + this.slideDown = function (duration, callback) { + return this.each(function (e) { + slideDown(e, duration, callback); + }); + } + this.slideUp = function (duration, callback) { + return this.each(function (e) { + slideUp(e, duration, callback); + }); + } + this.slideToggle = function (duration, callback) { + return this.each(function (e) { + slideToggle(e, duration, callback); + }); + } + this.removeAttr = function (attribute) { + this.each(e => e.removeAttribute(attribute)); + } + this.hasClass = function (cssClass) { + if (!cssClass) { + return; + } + return new RegExp('(\\s|^)' + cssClass + '(\\s|$)').test(this.get(0).className); + } + this.val = function (inputValue) { + if (typeof (inputValue) === 'undefined') { + return this.elements[0].value; + } + return this.each(function (e) { + e.value = inputValue; + }); + } + this.data = function (attribute, inputValue) { + if (typeof (inputValue) === 'undefined') { + return this.elements[0].dataset[attribute]; + } + return this.each(function (e) { + e.dataset[attribute] = inputValue; + }); + } + this.text = function (inputValue) { + if (typeof (inputValue) === 'undefined') { + return this.elements[0].innerText; + } + return this.each(function (e) { + e.innerText = inputValue; + }); + } + this.contains = function (element) { + return this.elements.indexOf(element) >= 0; + } + + this.trigger = function (eventName) { + + if ("createEvent" in document) { + var evt = document.createEvent("HTMLEvents"); + evt.initEvent(eventName, false, true); + return this.each(function (e) { + e.dispatchEvent(evt); + }); + } + else { + return this.each(function (e) { + e.fireEvent("on" + eventName); + }); + + } + } + } + + return factory; +}); \ No newline at end of file -- cgit v1.2.3