DOM tweaks, basic templating

This commit is contained in:
2025-10-09 17:19:12 +02:00
parent 4331ee0ebe
commit 71e6e88694

75
dom.js
View File

@@ -5,6 +5,8 @@
* *
*/ */
import { jsonQuery } from './json.js';
/** /**
* A helper class to create (and manipulate) elements in the DOM. * A helper class to create (and manipulate) elements in the DOM.
* *
@@ -64,7 +66,7 @@ class DomHelper {
tag.appendChild(children); tag.appendChild(children);
return; return;
} }
if (typeof children == 'string') { if (typeof children == 'string' || typeof children == 'number') {
//console.debug(`-> appended string`); //console.debug(`-> appended string`);
let n = document.createTextNode(children); let n = document.createTextNode(children);
tag.appendChild(n); tag.appendChild(n);
@@ -91,6 +93,77 @@ class DomHelper {
}); });
return str; return str;
} }
/**
* Discover parent node matching query
*
*
*/
parent(el, match) {
let m = el; // pointer
while (m.querySelector(match) === null) {
if (!m.parentNode) return false;
m = m.parentNode;
}
return m.querySelector(match);
}
/**
* Apply data to a cloned template element and return it
*
* @param {string|Element} el
* @param {*} data
*/
template(el, data) {
if (!("content" in document.createElement('template'))) {
console.error("Templates not supported on this browser.");
return;
}
const tpl = (el instanceof Element) ? el : document.querySelector(el);
const clone = tpl.content.cloneNode(true);
clone.querySelectorAll('[if]').forEach(el => {
let path = el.getAttribute('if');
let negate = false;
if (path[0] === '!') {
negate = true;
path = path.substring(1);
}
let value = false;
if (path[0] === '.') {
value = jsonQuery(data, path, null);
} else {
value = !!eval('(' + path + ')');
}
if (negate) value = !value;
if (!value) {
el.classList.add('d-none');
} else {
el.classList.remove('d-none');
}
});
clone.querySelectorAll('[template]').forEach(el => {
const path = el.getAttribute('template');
let value = jsonQuery(data, path, null);
if (value !== null) {
if ('value' in el) {
el.value = value;
} else {
el.innerText = value;
}
}
});
clone.querySelectorAll('[templated]').forEach(el => {
let value = eval(el.innerText);
if (value !== null) {
el.innerText = value;
}
});
return clone;
}
}; };
// The DOM helper // The DOM helper