diff --git a/application/source/dom/constants.mjs b/application/source/dom/constants.mjs index 432ae76ebcac8f1363b321b256d159bbab018224..1d8a53b902ca40cc55e20a5fa0442b64277d971b 100644 --- a/application/source/dom/constants.mjs +++ b/application/source/dom/constants.mjs @@ -16,6 +16,7 @@ export { ATTRIBUTE_UPDATER_SELECT_THIS, ATTRIBUTE_UPDATER_REPLACE, ATTRIBUTE_UPDATER_INSERT, + ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID, ATTRIBUTE_UPDATER_INSERT_REFERENCE, ATTRIBUTE_UPDATER_REMOVE, ATTRIBUTE_UPDATER_BIND, @@ -142,6 +143,14 @@ const ATTRIBUTE_UPDATER_REPLACE = `${ATTRIBUTE_PREFIX}replace`; */ const ATTRIBUTE_UPDATER_INSERT = `${ATTRIBUTE_PREFIX}insert`; +/** + * @memberOf Monster.DOM + * @type {string} + * @license AGPLv3 + * @since 3.21.0 + */ +const ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID = `${ATTRIBUTE_UPDATER_INSERT}-template-id`; + /** * @memberOf Monster.DOM * @type {string} diff --git a/application/source/dom/updater.mjs b/application/source/dom/updater.mjs index 4827144513c3db74f3885af3a1936ab21468aae6..8334d1e39ec0d65d370e58aade3d9a0266dc1f90 100644 --- a/application/source/dom/updater.mjs +++ b/application/source/dom/updater.mjs @@ -5,10 +5,10 @@ * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html */ -import { internalSymbol } from "../constants.mjs"; -import { diff } from "../data/diff.mjs"; -import { Pathfinder } from "../data/pathfinder.mjs"; -import { Pipe } from "../data/pipe.mjs"; +import {internalSymbol} from "../constants.mjs"; +import {diff} from "../data/diff.mjs"; +import {Pathfinder} from "../data/pathfinder.mjs"; +import {Pipe} from "../data/pipe.mjs"; import { ATTRIBUTE_ERRORMESSAGE, ATTRIBUTE_UPDATER_ATTRIBUTES, @@ -18,22 +18,21 @@ import { ATTRIBUTE_UPDATER_REMOVE, ATTRIBUTE_UPDATER_REPLACE, ATTRIBUTE_UPDATER_SELECT_THIS, - customElementUpdaterLinkSymbol, + ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID } from "../dom/constants.mjs"; -import { Base } from "../types/base.mjs"; -import { isArray, isInstance, isIterable } from "../types/is.mjs"; -import { Observer } from "../types/observer.mjs"; -import { ProxyObserver } from "../types/proxyobserver.mjs"; -import { validateArray, validateInstance } from "../types/validate.mjs"; -import { clone } from "../util/clone.mjs"; -import { trimSpaces } from "../util/trimspaces.mjs"; -import { addToObjectLink } from "./attributes.mjs"; -import { findTargetElementFromEvent } from "./events.mjs"; -import { findDocumentTemplate } from "./template.mjs"; -import { getDocument } from "./util.mjs"; +import {Base} from "../types/base.mjs"; +import {isArray, isInstance, isIterable} from "../types/is.mjs"; +import {Observer} from "../types/observer.mjs"; +import {ProxyObserver} from "../types/proxyobserver.mjs"; +import {validateArray, validateInstance} from "../types/validate.mjs"; +import {clone} from "../util/clone.mjs"; +import {trimSpaces} from "../util/trimspaces.mjs"; +import {addToObjectLink} from "./attributes.mjs"; +import {findTargetElementFromEvent} from "./events.mjs"; +import {findDocumentTemplate} from "./template.mjs"; -export { Updater, addObjectWithUpdaterToElement }; +export {Updater, addObjectWithUpdaterToElement}; /** * The updater class connects an object with the dom. In this way, structures and contents in the DOM can be programmatically adapted via attributes. @@ -174,7 +173,7 @@ class Updater extends Base { run() { // the key __init__has no further meaning and is only // used to create the diff for empty objects. - this[internalSymbol].last = { __init__: true }; + this[internalSymbol].last = {__init__: true}; return this[internalSymbol].subject.notifyObservers(); } @@ -323,7 +322,7 @@ function retrieveAndSetValue(element) { let options = element?.selectedOptions; if (options === undefined) options = element.querySelectorAll(":scope option:checked"); - value = Array.from(options).map(({ value }) => value); + value = Array.from(options).map(({value}) => value); break; } @@ -400,7 +399,6 @@ function removeElement(change) { function insertElement(change) { const self = this; const subject = self[internalSymbol].subject.getRealSubject(); - const document = getDocument(); let mem = new WeakSet(); let wd = 0; @@ -516,6 +514,30 @@ function insertElement(change) { } } +function findTemplate(container, key, ref, path) { + + let templateID = key; + let template; + + if (container.hasAttribute(ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID)) { + templateID = container.getAttribute(ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID); + template = findDocumentTemplate(templateID, container); + if (template instanceof HTMLTemplateElement) { + return template; + } + } + + if (container.closest(`[${ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID}]`)) { + templateID = container.closest(`[${ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID}]`).getAttribute(ATTRIBUTE_UPDATER_INSERT_TEMPLATE_ID); + template = findDocumentTemplate(templateID, container); + if (template instanceof HTMLTemplateElement) { + return template; + } + } + + return findDocumentTemplate(templateID, container); +} + /** * * @private @@ -528,8 +550,9 @@ function insertElement(change) { * @throws {Error} no template was found with the specified key. */ function appendNewDocumentFragment(container, key, ref, path) { - let template = findDocumentTemplate(key, container); + let template = findTemplate(container, key, ref, path); +console.log(template); let nodes = template.createDocumentFragment(); for (const [, node] of Object.entries(nodes.childNodes)) { if (node instanceof HTMLElement) { diff --git a/development/playground/dom-insert/index.html b/development/playground/dom-insert/index.html new file mode 100644 index 0000000000000000000000000000000000000000..39665b73d1289a710dc92257d6c1ed7c81728e47 --- /dev/null +++ b/development/playground/dom-insert/index.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <script type="module" src="main.mjs"></script> +</head> +<body data-monster-insert-template-id="bla"> +<h1>Updater</h1> + + +<template id="bla"> + <li data-monster-replace="path:current | index:j"></li> +</template> +<div id="test1"> + <ul data-monster-insert="current path:a.b" > + </ul> +</div> + +</body> +</html> diff --git a/development/playground/dom-insert/main.mjs b/development/playground/dom-insert/main.mjs new file mode 100644 index 0000000000000000000000000000000000000000..1d50035a47d6486b2b0b1de7dfcfd493c531b170 --- /dev/null +++ b/development/playground/dom-insert/main.mjs @@ -0,0 +1,22 @@ +import {Updater} from '../../../application/source/dom/updater.mjs'; + +let element = document.getElementById('test1') + + +let d = new Updater( + element, + { + a: { + b: [ + { + i: '0', + j: 'hello' + }, + ] + } + } +); + +d.run().then(() => { + console.log('done'); +}); diff --git a/development/playground/vite.config.js b/development/playground/vite.config.js index e3845a7c43316edad93c3645215e17ed4701d0ae..97534a42bc35564449e018a53e24c7e3340446c7 100644 --- a/development/playground/vite.config.js +++ b/development/playground/vite.config.js @@ -18,7 +18,7 @@ import {directoryPlugin} from "vite-plugin-list-directory-contents"; import mkcert from 'vite-plugin-mkcert' import {ViteMinifyPlugin} from 'vite-plugin-minify' -import glob from 'glob' +import {globSync} from 'glob' import {exec} from "child_process"; @@ -28,7 +28,7 @@ const source = resolve(__dirname, '') const dist = resolve(__dirname, '') -glob.sync(source + '/**/*.html', { +globSync(source + '/**/*.html', { ignore: [ '**/resource/**' ]