'use strict'; /* Copyright 2023 Sascha Leib * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the “Software”), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* returns the first element of an array, or null, if none exists */ /* parent object: Array */ /* returns: any type */ Array.prototype.first = function() { if (this.length > 0) { return this[0]; } else { return null; } } /* returns the last element of an array, or null, if none exists */ /* parent object: Array */ /* returns: any type */ Array.prototype.last = function() { if (this.length > 0) { return this[this.length-1]; } else { return null; } } /* Converts an array into a Html structure */ /* parent object: Array */ /* parameters: */ /* - atlist: Attributes list (object), optional /* returns: HtmlElement (including sub-elements) */ Array.prototype.toHtml = function(atlist = undefined) { /* create the table header: */ const thead = HTMLElement.new('thead'); const thr = thead.appendNew('tr'); thr.appendNew('th').setText('#'); thr.appendNew('th').setText('Value'); /* create the body: */ const tbody = HTMLElement.new('tbody'); this.forEach(function (rval, i) { let tr = tbody.appendNew('tr'); tr.appendNew('th').setText(i); tr.appendNew('td', { "class": (typeof rval) }).setText(JSON.stringify(rval)); }); /* combine header and body to table: */ const table = HTMLElement.new('table', atlist); table.appendChild(thead); table.appendChild(tbody); return table; } /* Adds a class to the parent HTMLElement */ /* parameter: (String, required) name of the class */ /* parent object: HTMLElement */ /* returns: HTMLElement */ HTMLElement.prototype.addClass = function(n) { this.classList.add(n); return this; } /* Removes a class from the parent HTMLElement */ /* parameter: (String, required) name of the class */ /* parent object: HTMLElement */ /* returns: HTMLElement */ HTMLElement.prototype.removeClass = function(n) { this.classList.remove(n); return this; } /* Toggles a class on the parent HTMLElement */ /* parameter: (String, required) name of the class */ /* parent object: HTMLElement */ /* returns: HTMLElement */ HTMLElement.prototype.toggleClass = function(n) { this.classList.toggle(n); return this; } /* Returns true, if the parent HTMLElement has a class of the specified name */ /* parameter: (String, required) name of the class */ /* parent object: HTMLElement */ /* returns: Boolean */ HTMLElement.prototype.hasClass = function(n) { return this.classList.contains(n); } /* Loads a JSON file over the network */ /* parent object: JSON */ /* parameter: url (String) the address where to load the file from (required) */ /* parameter: opt (Object) fetch parameters */ /* returns: Promise */ /* Support: Widely supported since ca. 2014 */ JSON.load = async function(url, opt) { console.info('JSON.load("'+url+'",',opt,')'); return fetch(url, opt) .then( rp => { if (!rp.ok) { throw new Error(`HTTP ${rp.status}: ${rp.statusText} – “${url}”.`); }; return rp.json() }); } /* Attaches an event listener to an HTMLElement */ /* parameter: (String, required) name of the event to listen to */ /* parameter: (Function, required) the callback function */ /* parent object: HTMLElement */ HTMLElement.prototype.on = function(n, cb) { this.addEventListener(n, cb); return this; } /* Attaches an event listener that will only be called once to an HTMLElement */ /* parameter: (String, required) name of the event to listen to */ /* parameter: (Function, required) the callback function */ /* parent object: HTMLElement */ /* returns: nothing */ HTMLElement.prototype.once = function(n, cb) { this.addEventListener(n, cb, {once: true}); return this; } /* Attaches an event listener to an HTMLElement */ /* parameter: (String, required) name of the event to listen to */ /* parameter: (Function, required) the callback function */ /* parent object: HTMLElement */ /* returns: nothing */ HTMLElement.prototype.off = function(n, cb) { this.removeEventListener(n, cb); return this; } /* Attaches a listener for the "blur" event to an Element */ /* parameter: (Function, required) the callback function */ /* parent object: Element */ /* returns: Element (passes through the parent element) */ HTMLElement.prototype.onBlur = function(cb) { this.addEventListener('blur', cb); return this; } /* Attaches a listener for the "click" event to an Element */ /* parameter: (Function, required) the callback function */ /* parent object: Element */ /* returns: Element (passes through the parent element) */ HTMLElement.prototype.onClick = function(cb) { this.addEventListener('click', cb); return this; } /* Attaches a listener for the "focus" event to an Element */ /* parameter: (Function, required) the callback function */ /* parent object: Element */ /* returns: Element (passes through the parent element) */ HTMLElement.prototype.onFocus = function(cb) { this.addEventListener('focus', cb); return this; } /* Attaches a listener for the "focus" event to a