Select Git revision
template.js

Volker Schukai authored
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.")
}