| 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>`; |
| // } |