Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Created November 29, 2023 22:57
Show Gist options
  • Save dfkaye/58f871c8b66bd360adb478d589055a56 to your computer and use it in GitHub Desktop.
Save dfkaye/58f871c8b66bd360adb478d589055a56 to your computer and use it in GitHub Desktop.
attaching shadow DOM to a DIV with a SLOT, and driving changes from a Worker
// continued from https://gist.github.com/dfkaye/feab681496ac9fc8bc63e6b3006f796e
// 25 August 2023
// attaching shadow DOM to a built-in element:
// what are the implications?
/*************************** worker-driven version ****************************/
// This example uses a div with a slot and a worker that posts messages with
// data that is then written to the slot element.
// The slot's content changes but is never presented in the browser except by
// the DOM inspector and element traversal in the console.
// That hints at a Custom Element solution with a dedicated receiver template
// that does not present directly in the DOM while allowing the Custom Element
// to update itself using modified data template...
// Maybe.
var body = document.body;
var div = document.createElement('div');
div.style = `
background: gray;
color: blue;
font-family: sans-serif;
outline: 1px solid aqua;
padding: 2em;
`;
div.attachShadow({
mode: 'open',
delegatesFocus: true,
slotAssignment: 'named'
});
body.replaceChildren(div);
var observer = new MutationObserver(function (list, observer) {
console.log("MutationObserver");
for (var item of list) {
var { type, target, attributeName } = item;
console.log({ type, target, attributeName });
if (attributeName == "changes") {
var json = target.getAttribute(attributeName);
var data;
try { data = JSON.parse(json) }
catch (error) { console.warn(`malformed JSON has caused "${error}".`); }
console.log(target.hasAttribute(attributeName));
console.log({json});
console.log({data})
}
}
});
observer.observe(div, {
attributes: true,
childList: true,
subtree: true
});
var slot = document.createElement("slot");
slot.setAttribute("name", "changes");
slot.style = `
background: blue;
padding: 1em;
`;
div.appendChild(slot);
console.log(slot === div.children["changes"]);
var data = {
"profile": {
"field": 30,
"radio": "individual",
"checkbox": "red",
//"checkbox2": "aqua",
"array": [true, false],
"address": {
"street": "1234 5th Street",
"street2": "Suite Sixteen",
"city": null,
"state": NaN,
"postalCode": {}
}
},
"right": { "path" : { "name": "wrong keyname" } }
};
/* inline worker */
// To do this in the console the current URL must have a permissive Content
// Security Policy for worker-src, or no CSP at all.
// This used to work Chrome-based browsers until April or May of 2023.
// I prefer Firefox Private Windows for this reason.
var source = `
self.onmessage = function(request) {
var { action, value = "" } = Object(request.data);
if (action == "test") {
setTimeout(() => self.postMessage(value), 500);
}
}
`;
var blob = new Blob([source], { type: "text/javascript" });
var url = URL.createObjectURL(blob);
var worker = new Worker(url);
worker.onmessage = function (response) {
console.log({ response });
var data = response.data;
// update attribute
div.children["changes"].setAttribute("changes", JSON.stringify(data));
// update slot
div.children["changes"].textContent = JSON.stringify(data);
div.style.outline = "2px solid red";
}
worker.postMessage({ action: "test", value: data })
// // update attribute
// div.children["changes"].setAttribute("changes", JSON.stringify(data));
// // update slot
// div.children["changes"].textContent = JSON.stringify(data);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment