Skip to content
Snippets Groups Projects
Select Git revision
  • 395e54bd27c7a6bd911688fb65f9c555bbab6eaf
  • master default protected
  • 1.31
  • 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
  • 4.29.0
23 results

Monster_Constraints.AbstractConstraint.html

Blame
  • template.mjs 5.92 KiB
    /**
     * Copyright schukai GmbH and contributors 2023. All Rights Reserved.
     * Node module: @schukai/monster
     * This file is licensed under the AGPLv3 License.
     * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
     */
    
    import { Base } from "../types/base.mjs";
    import { getGlobalFunction, getGlobalObject } from "../types/global.mjs";
    import { validateInstance, validateString } from "../types/validate.mjs";
    import { ATTRIBUTE_TEMPLATE_PREFIX } from "./constants.mjs";
    import { getDocumentTheme } from "./theme.mjs";
    import { instanceSymbol } from "../constants.mjs";
    export { Template };
    
    /**
     * The template class provides methods for creating templates.
     *
     * @license AGPLv3
     * @since 1.6.0
     * @copyright schukai GmbH
     * @memberOf Monster.DOM
     * @summary A template class
     */
    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;
    	}
    
    	/**
    	 * This method is called by the `instanceof` operator.
    	 * @returns {symbol}
    	 * @since 2.1.0
    	 */
    	static get [instanceSymbol]() {
    		return Symbol.for("@schukai/monster/dom/resource/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 '@schukai/monster/source/dom/template.mjs';
     * findDocumentTemplate()
     * </script>
     * ```
     *
     * @example
     *
     * import { findDocumentTemplate } from "https://cdn.jsdelivr.net/npm/@schukai/monster@latest/source/dom/template.mjs";
     *
     * 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}
     * @license AGPLv3
     * @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;
    	const theme = getDocumentTheme();
    
    	if (prefixID) {
    		const 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);
    		}
    	}
    
    	const 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.`);
    }