dom/customelement.js

'use strict';

/**
 * @author schukai GmbH
 */

import {getGlobalObject} from "../types/global.js";
import {Monster, validateFunction} from "../types/validate.js";


/**
 * To define a new HTML element we need the power of CustomElement
 *
 * you can call the method via the monster namespace `new Monster.DOM.Element()`.
 *
 * important: after defining a `CustomElement`, the `registerCustomElement` method must be called
 * with the new class name. only then will the tag defined via the `getTag` method be made known to the DOM.
 *
 * ```
 * <script type="module">
 * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.7.0/dist/modules/dom/customelement.js';
 * console.log(new Monster.DOM.CustomElement())
 * </script>
 * ```
 *
 * Alternatively, you can also integrate this function individually.
 *
 * ```
 * <script type="module">
 * import {CustomElement} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.7.0/dist/modules/dom/customelement.js';
 * console.log(new CustomElement())
 * </script>
 * ```
 *
 * ## Styling
 *
 * For optimal display of custom-elements the pseudo-class :defined can be used.
 *
 * ```html
 * <style>
 *
 * my-custom-element:not(:defined) {
 *     display: none;
 * }
 *
 * my-custom-element:defined {
 *     display: flex;
 * }
 *
 * </style>
 * ```
 * 
 *  * @example
 * // returns 2
 * globalNS.method1(5, 10);
 * @example
 * // returns 3
 * globalNS.method(5, 15);
 *
 * @see https://github.com/WICG/webcomponents
 * @see https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements
 * @since 1.7.0
 * @copyright schukai GmbH
 * @memberOf Monster/DOM
 */
class CustomElement extends HTMLElement {

    /**
     *
     */
    constructor() {
        super();
    }

    /**
     * Called every time the element is inserted into the DOM. Useful for running setup code, such as
     * fetching resources or rendering. Generally, you should try to delay work until this time.
     *
     * @return {void}
     */
    connectedCallback() {

    }

    /**
     * Called every time the element is removed from the DOM. Useful for running clean up code.
     *
     * @return {void}
     */
    disconnectedCallback() {

    }

    /**
     * The custom element has been moved into a new document (e.g. someone called document.adoptNode(el)).
     *
     * @return {void}
     */
    adoptedCallback() {

    }

    /**
     * Called when an observed attribute has been added, removed, updated, or replaced. Also called for initial
     * values when an element is created by the parser, or upgraded. Note: only attributes listed in the observedAttributes property will receive this callback.
     *
     * @param {string} attrName
     * @param {string} oldVal
     * @param {string} newVal
     * @return {void}
     */
    attributeChangedCallback(attrName, oldVal, newVal) {

    }

    /**
     * there is no check on the name by this class. the developer is responsible for assigning an appropriate tag.
     * if the name is not valid, registerCustomElement() will issue an erro
     *
     * @link https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
     * @return {string}
     * @throws {Error} the method getTag must be overwritten by the derived class.
     */
    static getTag() {
        throw new Error("the method getTag must be overwritten by the derived class.");
    }


}

/**
 * this method registers a new element. the string returned by `CustomElement.getTag()` is used as the tag.
 *
 * @param {CustomElement} element
 * @return {void}
 * @since 1.7.0
 * @copyright schukai GmbH
 * @memberOf Monster/DOM
 * @throws {DOMException} Failed to execute 'define' on 'CustomElementRegistry': is not a valid custom element name
 */
function registerCustomElement(element) {
    validateFunction(element);

    let tag = element.getTag();

    getGlobalObject('customElements').define(element.getTag(), element);
    return;
}

Monster.assignToNamespace('Monster.DOM', CustomElement, registerCustomElement);
export {Monster, registerCustomElement, CustomElement}