Skip to content
Snippets Groups Projects
Select Git revision
  • ac97ce5ab2a49171baf844b97b6ddb193d552b8e
  • master default protected
  • 1.31
  • 4.38.3
  • 4.38.2
  • 4.38.1
  • 4.38.0
  • 4.37.2
  • 4.37.1
  • 4.37.0
  • 4.36.0
  • 4.35.0
  • 4.34.1
  • 4.34.0
  • 4.33.1
  • 4.33.0
  • 4.32.2
  • 4.32.1
  • 4.32.0
  • 4.31.0
  • 4.30.1
  • 4.30.0
  • 4.29.1
23 results

template.js

Blame
  • Volker Schukai's avatar
    ac97ce5a
    History
    template.js 5.96 KiB
    'use strict';
    
    /**
     * @author schukai GmbH
     */
    
    import {Base} from '../types/base.js';
    import {getGlobalFunction, getGlobalObject} from '../types/global.js';
    import {validateInstance, validateString} from "../types/validate.js";
    import {ATTRIBUTE_TEMPLATE_PREFIX} from "./constants.js";
    import {getDocumentTheme} from "./theme.js";
    
    /**
     * The template class provides methods for creating templates.
     * 
     * ```
     * <script type="module">
     * import {Template} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@latest/source/dom/template.js';
     * new Template()
     * </script>
     * ```
     *
     * @since 1.6.0
     * @copyright schukai GmbH
     * @memberOf Monster.DOM
     * @summary A template class
     */
    export class Template extends Base {
        /**
         *
         * @param {HTMLTemplateElement} template
         * @throws {TypeError} value is not an instance of
         * @throws {TypeError} value is not a function
         * @throws {Error} the function is not defined
         */
        constructor(template) {
            super();
            const HTMLTemplateElement = getGlobalFunction('HTMLTemplateElement');
            validateInstance(template, HTMLTemplateElement);
            this.template = template;
        }
    
        /**
         *
         * @returns {HTMLTemplateElement}
         */
        getTemplateElement() {
            return this.template;
        }
    
        /**
         *
         * @return {DocumentFragment}
         * @throws {TypeError} value is not an instance of
         */
        createDocumentFragment() {
            return this.template.content.cloneNode(true);
        }
    
    }
    
    /**
     * This method loads a template with the given ID and returns it.
     *
     * To do this, it first reads the theme of the document and looks for the `data-monster-theme-name` attribute in the HTML tag.
     *
     * ```
     * <html data-monster-theme-name="my-theme">
     * ```
     *
     * If no theme was specified, the default theme is `monster`.
     *
     * Now it is looked if there is a template with the given ID and theme `id-theme` and if yes it is returned.
     * If there is no template a search for a template with the given ID `id` is done. If this is also not found, an error is thrown.
     *
     * You can call the method via the monster namespace `Monster.DOM.findDocumentTemplate()`.
     *
     * ```
     * <script type="module">
     * import {findTemplate} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@latest/source/dom/template.js';
     * findDocumentTemplate()
     * </script>
     * ```
     *
     * @example
     *
     * import { findDocumentTemplate } from "https://cdn.jsdelivr.net/npm/@schukai/monster@latest/source/dom/template.js";
     *
     * const template = document.createElement("template");
     * template.id = "myTemplate";
     * template.innerHTML = "<p>my default template</p>";
     * document.body.appendChild(template);
     *
     * const themedTemplate = document.createElement("template");
     * themedTemplate.id = "myTemplate-myTheme";
     * themedTemplate.innerHTML = "<p>my themed template</p>";
     * document.body.appendChild(themedTemplate);
     *
     * // loads the temple and since no theme is set the default template
     * const template1 = findDocumentTemplate("myTemplate");
     * console.log(template1.createDocumentFragment());
     * // ↦ '<p>my default template</p>'
     *
     * // now we set our own theme
     * document
     * .querySelector("html")
     * .setAttribute("data-monster-theme-name", "myTheme");
     *
     * // now we don't get the default template,
     * // but the template with the theme in the id
     * const template2 = findDocumentTemplate("myTemplate");
     * console.log(template2.createDocumentFragment());
     * // ↦ '<p>my themed template</p>'
     *
     * @param {string} id
     * @param {Node} currentNode
     * @return {Monster.DOM.Template}
     * @since 1.7.0
     * @copyright schukai GmbH
     * @memberOf Monster.DOM
     * @throws {Error} template id not found.
     * @throws {TypeError} value is not a string
     */
    export function findDocumentTemplate(id, currentNode) {
        validateString(id);
    
        const document = getGlobalObject('document');
        const HTMLTemplateElement = getGlobalFunction('HTMLTemplateElement');
        const DocumentFragment = getGlobalFunction('DocumentFragment');
        const Document = getGlobalFunction('Document');
    
    
        let prefixID;
    
        if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
    
            if (currentNode instanceof Node) {
    
                if (currentNode.hasAttribute(ATTRIBUTE_TEMPLATE_PREFIX)) {
                    prefixID = currentNode.getAttribute(ATTRIBUTE_TEMPLATE_PREFIX)
                }
    
                currentNode = currentNode.getRootNode();
    
                if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
                    currentNode = currentNode.ownerDocument;
                }
    
            }
    
            if (!(currentNode instanceof Document || currentNode instanceof DocumentFragment)) {
                currentNode = document;
            }
        }
    
        let template;
        let theme = getDocumentTheme()
    
        if (prefixID) {
            let themedPrefixID = prefixID + '-' + id + '-' + theme.getName();
    
            // current + themedPrefixID
            template = currentNode.getElementById(themedPrefixID);
            if (template instanceof HTMLTemplateElement) {
                return new Template(template);
            }
    
            // document + themedPrefixID
            template = document.getElementById(themedPrefixID);
            if (template instanceof HTMLTemplateElement) {
                return new Template(template);
            }
        }
    
        let themedID = id + '-' + theme.getName();
    
        // current + themedID
        template = currentNode.getElementById(themedID);
        if (template instanceof HTMLTemplateElement) {
            return new Template(template);
        }
    
        // document + themedID
        template = document.getElementById(themedID);
        if (template instanceof HTMLTemplateElement) {
            return new Template(template);
        }
    
        // current + ID
        template = currentNode.getElementById(id);
        if (template instanceof HTMLTemplateElement) {
            return new Template(template);
        }
    
        // document + ID
        template = document.getElementById(id);
        if (template instanceof HTMLTemplateElement) {
            return new Template(template);
        }
    
        throw new Error("template " + id + " not found.")
    }