Skip to content

Instantly share code, notes, and snippets.

@dhilst
Last active August 20, 2023 02:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhilst/b642e8ad6a24d243de91e708d9b9991a to your computer and use it in GitHub Desktop.
Save dhilst/b642e8ad6a24d243de91e708d9b9991a to your computer and use it in GitHub Desktop.
html from js
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
</head>
<body>
<script>
function html(text, ...values) {
const html = text.flatMap((text, i) => {
return [text, values[i]?.outerHTML || values[i]]
}).filter(Boolean).join("");
const elm = document.createElement("div");
elm.innerHTML = html;
values.forEach(val => {
if (val.id)
elm.querySelector(`#${val.id}`)?.replaceWith(val);
});
const node = elm.children[0];
return ((obj) => {
Object.assign(node, obj);
// Save properties in the data-* attributes
Object.entries(obj).forEach(([dskey, dsval]) => {
if (!["onclick"].includes(dskey)) {
node.dataset[dskey] = dsval;
}
});
return node;
});
}
function freshid() {
return `ID_${crypto.randomUUID()}`;
}
// works like counter below but with
// immutability
function counterimut({ id, value }) {
id ||= freshid();
return html`<button>${value}</button>`(
{
...arguments[0],
id,
onclick() {
// Update happens by rerendering a new
// node and replaceing old with new
document.querySelector(`#${id}`).replaceWith(
counterimut({ id, value: value + 1}));
},
})
}
function trace(x) {
console.log("trace", x);
return x;
}
function counter({ id, value }) {
const x = (html`<button>${value}</button>`(
{
...arguments[0],
id: id || freshid(),
onclick(e) {
e.target.textContent = +e.target.textContent + 1
},
}));
console.log("counter", x);
return x;
}
function card() {
const id = freshid();
const link = onclick =>
html`<a href="# class="card-link">Link</a>`(
{
id: freshid(),
onclick,
});
const onclick = () => {
document
.querySelector(`#${id}`)
.querySelector(".card-title").textContent = "FOOOOOO";
};
return html`<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
${link(onclick)}
<a href="#" class="card-link">Another link</a>
${counter({ value: 1 })}
</div>
</div>
`(
{
id,
});
}
document.body.appendChild(counterimut({ value: 1, foo: 1}));
const x = counter({ value: 1 });
console.log("x",x);
console.log(html`<h1>Hello</h1`({id: "hello"}));
document.body.appendChild(x);
const c = card();
console.log("card", c);
document.body.appendChild(c);
/* document.body.appendChild(card()); */
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment