Index: js/io-element.js |
=================================================================== |
--- a/js/io-element.js |
+++ b/js/io-element.js |
@@ -1,26 +1,94 @@ |
-/* globals module, require */ |
+/* |
+ * This file is part of Adblock Plus <https://adblockplus.org/>, |
+ * Copyright (C) 2006-present eyeo GmbH |
+ * |
+ * Adblock Plus is free software: you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 3 as |
+ * published by the Free Software Foundation. |
+ * |
+ * Adblock Plus is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
+ */ |
"use strict"; |
// Custom Elements ponyfill (a polyfill triggered on demand) |
const customElementsPonyfill = require("document-register-element/pony"); |
if (typeof customElements !== "object") |
customElementsPonyfill(window); |
// external dependencies |
const {default: HyperHTMLElement} = require("hyperhtml-element/cjs"); |
+// common DOM utilities exposed as IOElement.utils |
+const DOMUtils = { |
+ |
+ // boolean related operations/helpers |
+ boolean: { |
+ // utils.boolean.attribute(node, name, setAsTrue):void |
+ // set a generic node attribute name as "true" |
+ // if value is a boolean one or it removes the attribute |
+ attribute(node, name, setAsTrue) |
+ { |
+ // don't use `this.value(value)` with `this` as context |
+ // to make destructuring of helpers always work. |
+ // @example |
+ // const {attribute: setBoolAttr} = IOElement.utils.boolean; |
+ // setBoolAttr(node, 'test', true); |
+ if (DOMUtils.boolean.value(setAsTrue)) |
+ { |
+ node.setAttribute(name, "true"); |
+ } |
+ else |
+ { |
+ node.removeAttribute(name); |
+ } |
+ }, |
+ |
+ // utils.boolean.value(any):boolean |
+ // it returns either true or false |
+ // via truthy or falsy values, but also via strings |
+ // representing "true", "false" as well as "0" or "1" |
+ value(value) |
+ { |
+ if (typeof value === "string" && value.length) |
+ { |
+ try |
+ { |
+ value = JSON.parse(value); |
+ } |
+ catch (error) |
+ { |
+ // Ignore invalid JSON to continue using value as string |
+ } |
+ } |
+ return !!value; |
+ } |
+ } |
+}; |
+ |
// provides a unique-id suffix per each component |
let counter = 0; |
// common Custom Element class to extend |
class IOElement extends HyperHTMLElement |
{ |
+ // exposes DOM helpers as read only utils |
+ static get utils() |
+ { |
+ return DOMUtils; |
+ } |
+ |
// get a unique ID or, if null, set one and returns it |
static getID(element) |
{ |
return element.getAttribute("id") || IOElement.setID(element); |
} |
// set a unique ID to a generic element and returns the ID |
static setID(element) |
@@ -36,16 +104,33 @@ |
return IOElement.getID(this); |
} |
// whenever an element is created, render its content once |
created() { this.render(); } |
// by default, render is a no-op |
render() {} |
+ |
+ // usually a template would contain a main element such |
+ // input, button, div, section, etc. |
+ // having a simple way to retrieve such element can be |
+ // both semantic and handy, as opposite of using |
+ // this.children[0] each time |
+ get child() |
+ { |
+ let element = this.firstElementChild; |
+ // if accessed too early, will render automatically |
+ if (!element) |
+ { |
+ this.render(); |
+ element = this.firstElementChild; |
+ } |
+ return element; |
+ } |
} |
// whenever an interpolation with ${{i18n: 'string-id'}} is found |
// transform such value into the expected content |
// example: |
// render() { |
// return this.html`<div>${{i18n:'about-abp'}}</div>`; |
// } |