'use strict'; /* Copyright 2026 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() }); } /* creates a new Element */ /* parent object: Element */ /* parameter: name (String) the name of the element (required) */ /* parameter: attr (Object) a list of attributes to be added, */ /* parameter: sub (String|HTMLElement|Array of HTMLElement) add as child/content of the element */ /* returns: the newly created HTMLElement */ /* Support: DOM Level 1 (1998) */ HTMLElement.new = function(name, atlist = undefined, sub = undefined) { var e = null; try { // create the element: e = document.createElement(name); // add the attributes: if (atlist) { for (let attr in atlist) { e.setAttribute(attr, atlist[attr]); } } // insert possible sub-elements: if (sub) { if (typeof sub === 'string' || sub instanceof String) { // in case of string e.textContent = sub.toString(); } else if (sub instanceof HTMLElement) { // in case of a single item e.appendChild(sub) } else if (Array.isArray(sub)) { // in case of an array sub.forEach( it => { if (it instanceof HTMLElement) { e.appendChild(it) } }); } } } catch(err) { // error handling: log to console! if ($p && $p.console) $p.console.error(err.toString()); console.error(err); } finally { return e; } } /* Gets attribute value from an element */ /* parameter: name (String) the name of the attribute, */ /* parent object: Element */ /* returns: the value of the attribute (String) */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.getAttr = function(n) { let a = this.getAttribute(n); return ( a ? a : ''); } /* Sets an attribute value for an element */ /* parameter: name (String) the name of the attribute, */ /* parameter: value (String) the value for the attribute */ /* parent object: Element */ /* returns: the parent element (Object) */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.setAttr = function(n, v) { this.setAttribute(n, v); return this; } /* Appends a new text node to the end of the child nodes list of an element */ /* parameter: (required) text to add */ /* parent object: HTMLElement */ /* returns: the (modified) parent object */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.appendText = function(txt) { this.append(document.createTextNode(txt)); return this; } /* Prepends a new text node to the beginning of the child nodes list of an element */ /* parameter: (required) text to add */ /* parent object: HTMLElement */ /* returns: the (modified) parent object */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.prependText = function(txt) { this.prepend(document.createTextNode(txt)); return this; } /* Sets or gets the text content of an element */ /* parent object: Element */ /* returns: the text content as String */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.getText = function() { return this.textContent; } /* Sets the text content of an element */ /* parameter: (required) text to set */ /* parent object: HTMLElement */ /* returns: the (modified) parent object */ /* Support: DOM Level 1 (1998) */ HTMLElement.prototype.setText = function(txt) { this.textContent = txt.toString(); return this; } /* appends a new child HTMLElement to the parent. */ /* parent object: HTMLElement */ /* parameter: name (String) name of the new child element (required) */ /* parameter: att (Object) name of the new child element (optional) */ /* parameter: sub (String|HTMLElement|Array of HTMLElement) add as child/content of the element (optional) */ /* returns: the (modified) parent object */ /* Requires: HTMLElement.new (static) */ HTMLElement.prototype.appendNew = function(n, att = undefined, sub = undefined) { var e = null; try { e = HTMLElement.new(n, att, sub); this.appendChild(e); } catch(err) { if ($p && $p.console) $p.console.error(err.toString()); console.error(err); } return e; } /* prepends a new child HTMLElement to the parent. */ /* parent object: HTMLElement */ /* parameter: name (String, required) name of the new child element */ /* parameter: att (Object, optional) name of the new child element */ /* returns: the (modified) parent object */ /* Requires: HTMLElement.new (static) */ HTMLElement.prototype.prependNew = function(n, att = undefined, sub = undefined) { var e = null; try { e = HTMLElement.new(n, att, sub); this.prepend(e); } catch(e) { console.error(e); } return e; } /* Sets the html content of an element */ /* parameter: xhtml (String) to parse and set */ /* parent object: Element */ /* returns: the (modified) parent object */ HTMLElement.prototype.setHtml = function(xhtml) { let parser = new DOMParser(); let doc = parser.parseFromString('