1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-21 15:39:36 +01:00

docs mainly signals

This commit is contained in:
Jan Andrle 2023-11-23 18:36:26 +01:00
parent 0d5033780d
commit 6a293d75a6
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
11 changed files with 154 additions and 101 deletions

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Introducing a&nbsp;library."><title>`deka-dom-el` — Introduction</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a&nbsp;library.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library." class="current">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces.</p><p>We start with creating and modifying a&nbsp;static elements and end up with UI templates. <i>From <code>document.createElement</code> to <code>el</code>.</i> Then we go through the native events system and the way to include it declaratively in UI templates. <i>From <code>element.addEventListener</code> to <code>on</code>.</i></p><p>Next step is providing interactivity not only for our UI templates. We introduce signals (<code>S</code>) and how them incorporate to UI templates.</p><p>Now we will clarify how the signals are incorporated into our templates with regard to application performance. This is not the only reason the library uses <code>scope</code>s. We will look at how they work in components represented in JavaScript by functions.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-exquzbx4inc" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Introducing a&nbsp;library."><title>`deka-dom-el` — Introduction</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Introduction</h1><p>Introducing a&nbsp;library.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library." class="current">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a><a href="p04-signals" title="Handling reactivity in UI via signals.">4. Signals and reactivity</a></nav><main><p>The library tries to provide pure JavaScript tool(s) to create reactive interfaces.</p><p>We start with creating and modifying a&nbsp;static elements and end up with UI templates. <i>From <code>document.createElement</code> to <code>el</code>.</i> Then we go through the native events system and the way to include it declaratively in UI templates. <i>From <code>element.addEventListener</code> to <code>on</code>.</i></p><p>Next step is providing interactivity not only for our UI templates. We introduce signals (<code>S</code>) and how them incorporate to UI templates.</p><p>Now we will clarify how the signals are incorporated into our templates with regard to application performance. This is not the only reason the library uses <code>scope</code>s. We will look at how they work in components represented in JavaScript by functions.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-exquzbx4inc" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
import { S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const clicks= S(0);
document.body.append(

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Basic concepts of elements modifications and creations."><title>`deka-dom-el` — Elements</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Lets go through all patterns we would like to use and what needs to be improved for better experience.</p><h3 id="h-creating-elements-with-custom-attributes"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-creating-elements-with-custom-attributes" tabindex="-1">§</a> Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a&nbsp;some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a> also known as a JavaScript property.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-nkz9lcdhykg" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">document.body.append(
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Basic concepts of elements modifications and creations."><title>`deka-dom-el` — Elements</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Elements</h1><p>Basic concepts of elements modifications and creations.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations." class="current">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a><a href="p04-signals" title="Handling reactivity in UI via signals.">4. Signals and reactivity</a></nav><main><h2>Native JavaScript DOM elements creations</h2><p>Lets go through all patterns we would like to use and what needs to be improved for better experience.</p><h3 id="h-creating-elements-with-custom-attributes"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-creating-elements-with-custom-attributes" tabindex="-1">#</a> Creating element(s) (with custom attributes)</h3><p>You can create a native DOM element by using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement" title="MDN documentation for document.createElement()"><code>document.createElement()</code></a>. It is also possible to provide a&nbsp;some attribute(s) declaratively using <code>Object.assign()</code>. More precisely, this way you can sets some <a href="https://developer.mozilla.org/en-US/docs/Glossary/IDL" title="MDN page about Interface Description Language"><abbr title="Interface Description Language">IDL</abbr></a> also known as a JavaScript property.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-nkz9lcdhykg" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">document.body.append(
document.createElement("div")
);
console.log(
@ -56,7 +56,7 @@ console.log("paragraph.something=", paragraph.something);
document.body.append(
paragraph
);
</code></div><script>Flems(document.getElementById("code-example-1-iro9ncxa4bc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assign, assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\n\\nassignAttribute(paragraph, \\\"style\\\", \\\"color: red; font-weight: bold;\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassign(paragraph, { //textContent and style see above\\n\\tariaLabel: \\\"v1\\\", //data* see above\\n\\tariaset: { role: \\\"none\\\" }, // dataset see above\\n\\t\\\"=onclick\\\": \\\"console.log(event)\\\",\\n\\tonmouseout: console.info,\\n\\t\\\".something\\\": \\\"something\\\",\\n\\tclassList: {} //see below\\n});\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\nconsole.log(\\\"paragraph.something=\\\", paragraph.something);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3 id="h-native-javascript-templating"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-native-javascript-templating" tabindex="-1">§</a> Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-b6a1hbrxh7s" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">document.body.append(
</code></div><script>Flems(document.getElementById("code-example-1-iro9ncxa4bc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { assign, assignAttribute, classListDeclarative } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= document.createElement(\\\"p\\\");\\n\\nassignAttribute(paragraph, \\\"textContent\\\", \\\"Hello, world!\\\");\\n\\nassignAttribute(paragraph, \\\"style\\\", \\\"color: red; font-weight: bold;\\\");\\nassignAttribute(paragraph, \\\"style\\\", { color: \\\"navy\\\" });\\n\\nassignAttribute(paragraph, \\\"dataTest1\\\", \\\"v1\\\");\\nassignAttribute(paragraph, \\\"dataset\\\", { test2: \\\"v2\\\" });\\n\\nassign(paragraph, { //textContent and style see above\\n\\tariaLabel: \\\"v1\\\", //data* see above\\n\\tariaset: { role: \\\"none\\\" }, // dataset see above\\n\\t\\\"=onclick\\\": \\\"console.log(event)\\\",\\n\\tonmouseout: console.info,\\n\\t\\\".something\\\": \\\"something\\\",\\n\\tclassList: {} //see below\\n});\\n\\nclassListDeclarative(paragraph, {\\n\\tclassAdd: true,\\n\\tclassRemove: false,\\n\\tclassAdd1: 1,\\n\\tclassRemove1: 0,\\n\\tclassToggle: -1\\n});\\n\\nconsole.log(paragraph.outerHTML);\\nconsole.log(\\\"paragraph.something=\\\", paragraph.something);\\ndocument.body.append(\\n\\tparagraph\\n);\\n\"}],\"toolbar\":false}"));</script><h3 id="h-native-javascript-templating"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-native-javascript-templating" tabindex="-1">#</a> Native JavaScript templating</h3><p>By default, the native JS has no good way to define HTML template using DOM API:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-b6a1hbrxh7s" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">document.body.append(
document.createElement("div"),
document.createElement("span"),
document.createElement("main")
@ -102,7 +102,7 @@ document.body.append(
)
)
);
</code></div><script>Flems(document.getElementById("code-example-2-iro9ncxa4bc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\\nimport { chainableAppend } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\n/** @param {keyof HTMLElementTagNameMap} tag */\\nconst createElement= tag=> chainableAppend(document.createElement(tag));\\ndocument.body.append(\\n\\tcreateElement(\\\"p\\\").append(\\n\\t\\tcreateElement(\\\"em\\\").append(\\n\\t\\t\\t\\\"You can also use `chainableAppend`!\\\"\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h3 id="h-basic-state-less-components"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-basic-state-less-components" tabindex="-1">§</a> Basic (state-less) components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-320zz4y072o" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-example-2-iro9ncxa4bc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\"tr, td{ border: 1px solid red; padding: 1em; }\\\",\\n\\t\\t\\\"table{ border-collapse: collapse; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Example of a complex template. Using for example nesting lists:\\\"),\\n\\tel(\\\"ul\\\").append(\\n\\t\\tel(\\\"li\\\", \\\"List item 1\\\"),\\n\\t\\tel(\\\"li\\\").append(\\n\\t\\t\\tel(\\\"ul\\\").append(\\n\\t\\t\\t\\tel(\\\"li\\\", \\\"Nested list item 1\\\"),\\n\\t\\t\\t)\\n\\t\\t)\\n\\t),\\n\\tel(\\\"table\\\").append(\\n\\t\\tel(\\\"tr\\\").append(\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 1\\\"),\\n\\t\\t\\tel(\\\"td\\\", \\\"Row 1 Col 2\\\")\\n\\t\\t)\\n\\t)\\n);\\n\\nimport { chainableAppend } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\n/** @param {keyof HTMLElementTagNameMap} tag */\\nconst createElement= tag=> chainableAppend(document.createElement(tag));\\ndocument.body.append(\\n\\tcreateElement(\\\"p\\\").append(\\n\\t\\tcreateElement(\\\"em\\\").append(\\n\\t\\t\\t\\\"You can also use `chainableAppend`!\\\"\\n\\t\\t)\\n\\t)\\n);\\n\"}],\"toolbar\":false}"));</script><h3 id="h-basic-state-less-components"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-basic-state-less-components" tabindex="-1">#</a> Basic (state-less) components</h3><p>You can use functions for encapsulation (repeating) logic. The <code>el</code> accepts function as first argument. In that case, the function should return dom elements and the second argument for <code>el</code> is argument for given element.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-320zz4y072o" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
document.head.append(
el("style").append(
".class1{ font-weight: bold; }",
@ -119,7 +119,7 @@ function component({ className, textContent }){
el("p", textContent)
);
}
</code></div><script>Flems(document.getElementById("code-example-1-320zz4y072o"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>As you can see, in case of state-less/basic components there is no difference between calling component function directly or using <code>el</code> function.</p><p class="notice">It is nice to use similar naming convention as native DOM API. This allows us to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" title="Destructuring assignment | MDN">the destructuring assignment syntax</a> and keep track of the native API (things are best remembered through regular use).</p><h3 id="h-creating-non-html-elements"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-creating-non-html-elements" tabindex="-1">§</a> Creating non-HTML elements</h3><p>Similarly to the native DOM API (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS" title="MDN"><code>document.createElementNS</code></a>) for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use the <code>elNS</code> function:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-bcjydb50gdc" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { elNS, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-example-1-320zz4y072o"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.head.append(\\n\\tel(\\\"style\\\").append(\\n\\t\\t\\\".class1{ font-weight: bold; }\\\",\\n\\t\\t\\\".class2{ color: purple; }\\\"\\n\\t)\\n);\\ndocument.body.append(\\n\\tel(component, { className: \\\"class2\\\", textContent: \\\"Hello World!\\\" }),\\n\\tcomponent({ className: \\\"class2\\\", textContent: \\\"Hello World!\\\" })\\n);\\n\\nfunction component({ className, textContent }){\\n\\treturn el(\\\"div\\\", { className: [ \\\"class1\\\", className ] }).append(\\n\\t\\tel(\\\"p\\\", textContent)\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>As you can see, in case of state-less/basic components there is no difference between calling component function directly or using <code>el</code> function.</p><p class="notice">It is nice to use similar naming convention as native DOM API. This allows us to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" title="Destructuring assignment | MDN">the destructuring assignment syntax</a> and keep track of the native API (things are best remembered through regular use).</p><h3 id="h-creating-non-html-elements"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-creating-non-html-elements" tabindex="-1">#</a> Creating non-HTML elements</h3><p>Similarly to the native DOM API (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS" title="MDN"><code>document.createElementNS</code></a>) for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use the <code>elNS</code> function:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-bcjydb50gdc" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { elNS, assign } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const elSVG= elNS("http://www.w3.org/2000/svg");
const elMath= elNS("http://www.w3.org/1998/Math/MathML");
document.body.append(
@ -130,4 +130,4 @@ document.body.append(
console.log(
document.body.innerHTML.includes("&lt;svg&gt;&lt;/svg&gt;&lt;math&gt;&lt;/math&gt;")
)
</code></div><script>Flems(document.getElementById("code-example-1-bcjydb50gdc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { elNS, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst elSVG= elNS(\\\"http://www.w3.org/2000/svg\\\");\\nconst elMath= elNS(\\\"http://www.w3.org/1998/Math/MathML\\\");\\ndocument.body.append(\\n\\telSVG(\\\"svg\\\"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement\\n\\telMath(\\\"math\\\") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes\\n);\\n\\nconsole.log(\\n\\tdocument.body.innerHTML.includes(\\\"<svg></svg><math></math>\\\")\\n)\\n\"}],\"toolbar\":false}"));</script><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="./" title="Introducing a&nbsp;library."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Introduction (previous)</a><a rel="next" href="p03-events" title="Using not only events in UI declaratively."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->(next) Events and Addons</a></div></main></body></html>
</code></div><script>Flems(document.getElementById("code-example-1-bcjydb50gdc"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { elNS, assign } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst elSVG= elNS(\\\"http://www.w3.org/2000/svg\\\");\\nconst elMath= elNS(\\\"http://www.w3.org/1998/Math/MathML\\\");\\ndocument.body.append(\\n\\telSVG(\\\"svg\\\"), // see https://developer.mozilla.org/en-US/docs/Web/SVG and https://developer.mozilla.org/en-US/docs/Web/API/SVGElement\\n\\telMath(\\\"math\\\") // see https://developer.mozilla.org/en-US/docs/Web/MathML and https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes\\n);\\n\\nconsole.log(\\n\\tdocument.body.innerHTML.includes(\\\"<svg></svg><math></math>\\\")\\n)\\n\"}],\"toolbar\":false}"));</script><div class="notice"><p>Mnemonic</p><ul><li><code>assign(&lt;element&gt;, ...&lt;idl-objects&gt;): &lt;element&gt;</code> — assign properties to the element</li><li><code>el(&lt;tag-name&gt;, &lt;primitive&gt;)[.append(...)]: &lt;element-from-tag-name&gt;</code> — simple element containing only text</li><li><code>el(&lt;tag-name&gt;, &lt;idl-object&gt;)[.append(...)]: &lt;element-from-tag-name&gt;</code> — element with more properties</li><li><code>el(&lt;function&gt;, &lt;function-argument(s)&gt;)[.append(...)]: &lt;element-returned-by-function&gt;</code> — using component represented by function</li><li><code>el(&lt;...&gt;, &lt;...&gt;, ...&lt;addons&gt;)</code> — see following page</li><li><code>elNS(&lt;namespace&gt;)(&lt;as-el-see-above&gt;)[.append(...)]: &lt;element-based-on-arguments&gt;</code> — typically SVG elements</li></ul></div><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="./" title="Introducing a&nbsp;library."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Introduction (previous)</a><a rel="next" href="p03-events" title="Using not only events in UI declaratively."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->(next) Events and Addons</a></div></main></body></html>

View File

@ -1,4 +1,4 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Using not only events in UI declaratively."><title>`deka-dom-el` — Events and Addons</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Events and Addons</h1><p>Using not only events in UI declaratively.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively." class="current">3. Events and Addons</a></nav><main><h2>Listenning to the native DOM events and other Addons</h2><p>We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called <em>Addon</em> to incorporate not only this in UI templates declaratively.</p><h3 id="h-events-and-listenners"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-events-and-listenners" tabindex="-1">§</a> Events and listenners</h3><p>In JavaScript you can listen to the native DOM events of the given element by using <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener" title="addEventListener on MDN"><code>element.addEventListener(type, listener, options)</code></a>. The library provides an alternative (<code>on</code>) accepting the differen order of the arguments:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-1wmddlo83w68" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Using not only events in UI declaratively."><title>`deka-dom-el` — Events and Addons</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Events and Addons</h1><p>Using not only events in UI declaratively.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively." class="current">3. Events and Addons</a><a href="p04-signals" title="Handling reactivity in UI via signals.">4. Signals and reactivity</a></nav><main><h2>Listenning to the native DOM events and other Addons</h2><p>We quickly introduce helper to listening to the native DOM events. And library syntax/pattern so-called <em>Addon</em> to incorporate not only this in UI templates declaratively.</p><h3 id="h-events-and-listenners"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-events-and-listenners" tabindex="-1">#</a> Events and listenners</h3><p>In JavaScript you can listen to the native DOM events of the given element by using <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener" title="addEventListener on MDN"><code>element.addEventListener(type, listener, options)</code></a>. The library provides an alternative (<code>on</code>) accepting the differen order of the arguments:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-1wmddlo83w68" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const log= mark=&gt; console.log.bind(console, mark);
const button= el("button", "Test click");
@ -21,7 +21,7 @@ on("click", log("`on`"), { signal })(button);
document.body.append(
button, " ", el("button", { textContent: "Off", onclick: ()=&gt; abort_controller.abort() })
);
</code></div><script>Flems(document.getElementById("code-example-1-8r8qappf8mo"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst log= mark=> console.log.bind(console, mark);\\n\\nconst abort_controller= new AbortController();\\nconst { signal }= abort_controller;\\n\\nconst button= el(\\\"button\\\", \\\"Test click\\\");\\nbutton.addEventListener(\\\"click\\\", log(\\\"`addEventListener`\\\"), { signal });\\non(\\\"click\\\", log(\\\"`on`\\\"), { signal })(button);\\n\\ndocument.body.append(\\n\\tbutton, \\\" \\\", el(\\\"button\\\", { textContent: \\\"Off\\\", onclick: ()=> abort_controller.abort() })\\n);\\n\"}],\"toolbar\":false}"));</script><div class="notice"><p>So, there are (typically) three ways to handle events. You can use:</p><ul><li><code>el("button", { textContent: "click me", "=onclick": "console.log(event)" })</code></li><li><code>el("button", { textContent: "click me", onclick: console.log })</code></li><li><code>el("button", { textContent: "click me" }, on("click", console.log))</code></li></ul><p>In the first example we force to use HTML attribute (it corresponds to <code>&lt;button onclick="console.log(event)"&gt;click me&lt;/button&gt;</code>). <em>Side note: this can be useful in case of SSR.</em> To study difference, you can read a nice summary here: <a href="https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944">GIST @WebReflection/web_events.md</a>.</p></div><h3 id="h-addons"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-addons" tabindex="-1">§</a> Addons</h3><p>From practical point of view, <em>Addons</em> are just functions that accept any html element as their first parameter. You can see that the <code>on(…)</code> fullfills this requirement.</p><p>You can use Addons as ≥3rd argument of <code>el</code> function. This way is possible to extends you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-6jtsnxfqzm4" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-example-1-8r8qappf8mo"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst log= mark=> console.log.bind(console, mark);\\n\\nconst abort_controller= new AbortController();\\nconst { signal }= abort_controller;\\n\\nconst button= el(\\\"button\\\", \\\"Test click\\\");\\nbutton.addEventListener(\\\"click\\\", log(\\\"`addEventListener`\\\"), { signal });\\non(\\\"click\\\", log(\\\"`on`\\\"), { signal })(button);\\n\\ndocument.body.append(\\n\\tbutton, \\\" \\\", el(\\\"button\\\", { textContent: \\\"Off\\\", onclick: ()=> abort_controller.abort() })\\n);\\n\"}],\"toolbar\":false}"));</script><div class="notice"><p>So, there are (typically) three ways to handle events. You can use:</p><ul><li><code>el("button", { textContent: "click me", "=onclick": "console.log(event)" })</code></li><li><code>el("button", { textContent: "click me", onclick: console.log })</code></li><li><code>el("button", { textContent: "click me" }, on("click", console.log))</code></li></ul><p>In the first example we force to use HTML attribute (it corresponds to <code>&lt;button onclick="console.log(event)"&gt;click me&lt;/button&gt;</code>). <em>Side note: this can be useful in case of SSR.</em> To study difference, you can read a nice summary here: <a href="https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944">GIST @WebReflection/web_events.md</a>.</p></div><h3 id="h-addons"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-addons" tabindex="-1">#</a> Addons</h3><p>From practical point of view, <em>Addons</em> are just functions that accept any html element as their first parameter. You can see that the <code>on(…)</code> fullfills this requirement.</p><p>You can use Addons as ≥3rd argument of <code>el</code> function. This way is possible to extends you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-6jtsnxfqzm4" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const abort_controller= new AbortController();
const { signal }= abort_controller;
/** @type {ddeElementAddon&lt;HTMLButtonElement&gt;} */
@ -45,7 +45,7 @@ function update(event){
"\n"
);
}
</code></div><script>Flems(document.getElementById("code-example-1-6jtsnxfqzm4"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst abort_controller= new AbortController();\\nconst { signal }= abort_controller;\\n/** @type {ddeElementAddon<HTMLButtonElement>} */\\nconst onclickOff= on(\\\"click\\\", ()=> abort_controller.abort(), { signal });\\n/** @type {(ref?: HTMLOutputElement)=> HTMLOutputElement | null} */\\nconst ref= (store=> ref=> ref ? (store= ref) : store)(null);\\n\\ndocument.body.append(\\n\\tel(\\\"button\\\", \\\"Test `on`\\\",\\n\\t\\ton(\\\"click\\\", console.log, { signal }),\\n\\t\\ton(\\\"click\\\", update, { signal }),\\n\\t\\ton(\\\"mouseup\\\", update, { signal })),\\n\\t\\\" \\\",\\n\\tel(\\\"button\\\", \\\"Off\\\", onclickOff),\\n\\tel(\\\"output\\\", { style: { display: \\\"block\\\", whiteSpace: \\\"pre\\\" } }, ref)\\n);\\n/** @param {MouseEvent} event @this {HTMLButtonElement} */\\nfunction update(event){\\n\\tref().append(\\n\\t\\tevent.type,\\n\\t\\t\\\"\\\\n\\\"\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>As the example shows, you can also provide types in JSDoc+TypeScript by using global type <code>ddeElementAddon</code>. Also notice, you can use Addons to get element reference.</p><h3 id="h-life-cycle-events"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-life-cycle-events" tabindex="-1">§</a> Life-cycle events</h3><p>Addons are called immediately when the element is created, even it is not connected to live DOM yet. Therefore, you can understand the Addon to be “oncreate” event.</p><p>The library provide three additional live-cycle events corresponding to how they are named in a case of custom elements: <code>on.connected</code>, <code>on.disconnected</code> and <code>on.attributeChanged</code>.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-35hjjp3e4js" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-example-1-6jtsnxfqzm4"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst abort_controller= new AbortController();\\nconst { signal }= abort_controller;\\n/** @type {ddeElementAddon<HTMLButtonElement>} */\\nconst onclickOff= on(\\\"click\\\", ()=> abort_controller.abort(), { signal });\\n/** @type {(ref?: HTMLOutputElement)=> HTMLOutputElement | null} */\\nconst ref= (store=> ref=> ref ? (store= ref) : store)(null);\\n\\ndocument.body.append(\\n\\tel(\\\"button\\\", \\\"Test `on`\\\",\\n\\t\\ton(\\\"click\\\", console.log, { signal }),\\n\\t\\ton(\\\"click\\\", update, { signal }),\\n\\t\\ton(\\\"mouseup\\\", update, { signal })),\\n\\t\\\" \\\",\\n\\tel(\\\"button\\\", \\\"Off\\\", onclickOff),\\n\\tel(\\\"output\\\", { style: { display: \\\"block\\\", whiteSpace: \\\"pre\\\" } }, ref)\\n);\\n/** @param {MouseEvent} event @this {HTMLButtonElement} */\\nfunction update(event){\\n\\tref().append(\\n\\t\\tevent.type,\\n\\t\\t\\\"\\\\n\\\"\\n\\t);\\n}\\n\"}],\"toolbar\":false}"));</script><p>As the example shows, you can also provide types in JSDoc+TypeScript by using global type <code>ddeElementAddon</code>. Also notice, you can use Addons to get element reference.</p><h3 id="h-life-cycle-events"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-life-cycle-events" tabindex="-1">#</a> Life-cycle events</h3><p>Addons are called immediately when the element is created, even it is not connected to live DOM yet. Therefore, you can understand the Addon to be “oncreate” event.</p><p>The library provide three additional live-cycle events corresponding to how they are named in a case of custom elements: <code>on.connected</code>, <code>on.disconnected</code> and <code>on.attributeChanged</code>.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-35hjjp3e4js" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const paragraph= el("p", "See live-cycle events in console.",
el=&gt; log({ type: "dde:created", detail: el }),
on.connected(log),
@ -63,7 +63,7 @@ document.body.append(
function log({ type, detail }){
console.log({ _this: this, type, detail });
}
</code></div><script>Flems(document.getElementById("code-example-1-35hjjp3e4js"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= el(\\\"p\\\", \\\"See live-cycle events in console.\\\",\\n\\tel=> log({ type: \\\"dde:created\\\", detail: el }),\\n\\ton.connected(log),\\n\\ton.disconnected(log),\\n\\ton.attributeChanged(log));\\n\\ndocument.body.append(\\n\\tparagraph,\\n\\tel(\\\"button\\\", \\\"Update attribute\\\", on(\\\"click\\\", ()=> paragraph.setAttribute(\\\"test\\\", Math.random().toString()))),\\n\\t\\\" \\\",\\n\\tel(\\\"button\\\", \\\"Remove\\\", on(\\\"click\\\", ()=> paragraph.remove()))\\n);\\n\\n/** @param {Partial<CustomEvent>} event */\\nfunction log({ type, detail }){\\n\\tconsole.log({ _this: this, type, detail });\\n}\\n\"}],\"toolbar\":false}"));</script><p>For Custom elements, we will later introduce a way to replace <code>*Callback</code> syntax with <code>dde:*</code> events. The <code>on.*</code> functions then listen to the appropriate Custom Elements events (see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks">Custom element lifecycle callbacks | MDN</a>).</p><p>But, in case of regular elemnets the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"><code>MutationObserver</code> | MDN</a> is internaly used to track these events. Therefore, there are some drawbacks:</p><ul><li>To proper listener registration, you need to use <code>on.*</code> not `on("dde:*", …)`!</li><li>Use sparingly! Internally, library must loop of all registered events and fires event properly. <strong>It is good practice to use the fact that if an element is removed, its children are also removed!</strong> In this spirit, we will introduce later the <strong>host</strong> syntax to register clean up procedures when the component is removed from the app.</li></ul><h3 id="h-final-notes"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-final-notes" tabindex="-1">§</a> Final notes</h3><p>The library also provides a&nbsp;method to dispatch the events.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-2-b6a1hbrxh7s" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on, dispatchEvent } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
</code></div><script>Flems(document.getElementById("code-example-1-35hjjp3e4js"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst paragraph= el(\\\"p\\\", \\\"See live-cycle events in console.\\\",\\n\\tel=> log({ type: \\\"dde:created\\\", detail: el }),\\n\\ton.connected(log),\\n\\ton.disconnected(log),\\n\\ton.attributeChanged(log));\\n\\ndocument.body.append(\\n\\tparagraph,\\n\\tel(\\\"button\\\", \\\"Update attribute\\\", on(\\\"click\\\", ()=> paragraph.setAttribute(\\\"test\\\", Math.random().toString()))),\\n\\t\\\" \\\",\\n\\tel(\\\"button\\\", \\\"Remove\\\", on(\\\"click\\\", ()=> paragraph.remove()))\\n);\\n\\n/** @param {Partial<CustomEvent>} event */\\nfunction log({ type, detail }){\\n\\tconsole.log({ _this: this, type, detail });\\n}\\n\"}],\"toolbar\":false}"));</script><p>For Custom elements, we will later introduce a way to replace <code>*Callback</code> syntax with <code>dde:*</code> events. The <code>on.*</code> functions then listen to the appropriate Custom Elements events (see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks">Custom element lifecycle callbacks | MDN</a>).</p><p>But, in case of regular elemnets the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"><code>MutationObserver</code> | MDN</a> is internaly used to track these events. Therefore, there are some drawbacks:</p><ul><li>To proper listener registration, you need to use <code>on.*</code> not `on("dde:*", …)`!</li><li>Use sparingly! Internally, library must loop of all registered events and fires event properly. <strong>It is good practice to use the fact that if an element is removed, its children are also removed!</strong> In this spirit, we will introduce later the <strong>host</strong> syntax to register clean up procedures when the component is removed from the app.</li></ul><h3 id="h-final-notes"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-final-notes" tabindex="-1">#</a> Final notes</h3><p>The library also provides a&nbsp;method to dispatch the events.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-2-b6a1hbrxh7s" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { el, on, dispatchEvent } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
document.body.append(
el("p", "Listenning to `test` event.", on("test", console.log)).append(
el("br"),
@ -87,4 +87,4 @@ function dde(){
function ddeOptions(){
dispatchEvent("test", { bubbles: true })(this, "hi");
}
</code></div><script>Flems(document.getElementById("code-example-2-b6a1hbrxh7s"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on, dispatchEvent } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Listenning to `test` event.\\\", on(\\\"test\\\", console.log)).append(\\n\\t\\tel(\\\"br\\\"),\\n\\t\\tel(\\\"button\\\", \\\"native\\\", on(\\\"click\\\", native)),\\n\\t\\t\\\" \\\",\\n\\t\\tel(\\\"button\\\", \\\"dde\\\", on(\\\"click\\\", dde)),\\n\\t\\t\\\" \\\",\\n\\t\\tel(\\\"button\\\", \\\"dde with options\\\", on(\\\"click\\\", ddeOptions))\\n\\t)\\n);\\nfunction native(){\\n\\tthis.dispatchEvent(\\n\\t\\tnew CustomEvent(\\\"test\\\",\\n\\t\\t\\t{ bubbles: true, detail: \\\"hi\\\" }\\n\\t\\t)\\n\\t);\\n}\\nfunction dde(){\\n\\tdispatchEvent(\\\"test\\\")(this.parentElement, \\\"hi\\\");\\n}\\nfunction ddeOptions(){\\n\\tdispatchEvent(\\\"test\\\", { bubbles: true })(this, \\\"hi\\\");\\n}\\n\"}],\"toolbar\":false}"));</script><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="p02-elements" title="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Elements (previous)</a><!--<dde:mark type="component" name="pageLink" host="this" ssr/>--></div></main></body></html>
</code></div><script>Flems(document.getElementById("code-example-2-b6a1hbrxh7s"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { el, on, dispatchEvent } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\ndocument.body.append(\\n\\tel(\\\"p\\\", \\\"Listenning to `test` event.\\\", on(\\\"test\\\", console.log)).append(\\n\\t\\tel(\\\"br\\\"),\\n\\t\\tel(\\\"button\\\", \\\"native\\\", on(\\\"click\\\", native)),\\n\\t\\t\\\" \\\",\\n\\t\\tel(\\\"button\\\", \\\"dde\\\", on(\\\"click\\\", dde)),\\n\\t\\t\\\" \\\",\\n\\t\\tel(\\\"button\\\", \\\"dde with options\\\", on(\\\"click\\\", ddeOptions))\\n\\t)\\n);\\nfunction native(){\\n\\tthis.dispatchEvent(\\n\\t\\tnew CustomEvent(\\\"test\\\",\\n\\t\\t\\t{ bubbles: true, detail: \\\"hi\\\" }\\n\\t\\t)\\n\\t);\\n}\\nfunction dde(){\\n\\tdispatchEvent(\\\"test\\\")(this.parentElement, \\\"hi\\\");\\n}\\nfunction ddeOptions(){\\n\\tdispatchEvent(\\\"test\\\", { bubbles: true })(this, \\\"hi\\\");\\n}\\n\"}],\"toolbar\":false}"));</script><div class="notice"><p>Mnemonic</p><ul><li><code>on(&lt;event&gt;, &lt;listener&gt;[, &lt;options&gt;])(&lt;element&gt;)</code> — just <code>&lt;element&gt;.addEventListener(&lt;event&gt;, &lt;listener&gt;[, &lt;options&gt;])</code></li><li><code>on.&lt;live-cycle&gt;(&lt;event&gt;, &lt;listener&gt;[, &lt;options&gt;])(&lt;element&gt;)</code> — corresponds to custom elemnets callbacks <code>&lt;live-cycle&gt;Callback(...){...}</code>. To connect to custom element see following page, else it is simulated by MutationObserver.</li><li><code>dispatchEvent(&lt;event&gt;[, &lt;options&gt;])(element)</code> — just <code>&lt;element&gt;.dispatchEvent(new Event(&lt;event&gt;[, &lt;options&gt;]))</code></li><li><code>dispatchEvent(&lt;event&gt;[, &lt;options&gt;])(element, detail)</code> — just <code>&lt;element&gt;.dispatchEvent(new CustomEvent(&lt;event&gt;, { detail, ...&lt;options&gt; }))</code></li></ul></div><div class="prevNext"><!--<dde:mark type="component" name="prevNext" host="parentElement" ssr/>--><a rel="prev" href="p02-elements" title="Basic concepts of elements modifications and creations."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->Elements (previous)</a><a rel="next" href="p04-signals" title="Handling reactivity in UI via signals."><!--<dde:mark type="component" name="pageLink" host="parentElement" ssr/>-->(next) Signals and reactivity</a></div></main></body></html>

25
docs/p04-signals.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Handling reactivity in UI via signals."><title>`deka-dom-el` — Signals and reactivity</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Signals and reactivity</h1><p>Handling reactivity in UI via signals.</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a><a href="p04-signals" title="Handling reactivity in UI via signals." class="current">4. Signals and reactivity</a></nav><main><h2>Using signals to manage reactivity</h2><p>How a program responds to variable data or user interactions is one of the fundamental problems of programming. If we desire to solve the issue in a declarative manner, signals may be a viable approach.</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-opc0krfvn3k" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
// α — `signal` represents a&nbsp;reactive value
const signal= S(0);
// β — just reacts on signal changes
S.on(signal, console.log);
// γ — just updates the value
signal(signal()+1);
setInterval(()=&gt; signal(signal()+1), 5000);
</code></div><script>Flems(document.getElementById("code-example-1-opc0krfvn3k"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\n// α — `signal` represents a reactive value\\nconst signal= S(0);\\n// β — just reacts on signal changes\\nS.on(signal, console.log);\\n// γ — just updates the value\\nsignal(signal()+1);\\nsetInterval(()=> signal(signal()+1), 5000);\\n\"}],\"toolbar\":false}"));</script><h3 id="h-introducing-signals"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-introducing-signals" tabindex="-1">#</a> Introducing signals</h3><p>Using signals, we split program logic into the three parts. Firstly (α), we create a&nbsp;variable (constant) representing reactive value. Somewhere later, we can register (β) a&nbsp;logic reacting to the signal value changes. Similarly, in a&nbsp;remaining part (γ), we can update the signal value.</p><p>All this is just an&nbsp;example of <a href="https://en.wikipedia.org/wiki/Event-driven_programming" title="Wikipedia: Event-driven programming">Event-driven programming</a> and <a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern" title="Wikipedia: Publishsubscribe pattern">Publishsubscribe pattern</a> (compare for example with <a href="https://www.npmjs.com/package/fpubsub" title="NPM package: fpubsub">fpubsub library</a>). All three parts can be in some manner independent and still connected to the same reactive entity.</p><p>Signals are implemented in the library as functions. To see current value of signal, just call it without any arguments <code>console.log(signal())</code>. To update the signal value, pass any argument <code>signal('a new value')</code>. For listenning the signal value changes, use <code>S.on(signal, console.log)</code>.</p><p>Similarly to the <code>on</code> function to register DOM events listener. You can use <code>AbortController</code>/<code>AbortSignal</code> to <em>off</em>/stop listenning. For representing “live” piece of code computation pattern:</p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-e9cfsaeb64o" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { S } from "https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js";
const signal= S(0);
// computation pattern
const double= S(()=&gt; 2*signal());
const ac= new AbortController();
S.on(signal, v=&gt; console.log("signal", v), { signal: ac.signal });
S.on(double, v=&gt; console.log("double", v), { signal: ac.signal });
signal(signal()+1);
const interval= 5000;
const id= setInterval(()=&gt; signal(signal()+1), interval);
ac.signal.addEventListener("abort",
()=&gt; setTimeout(()=&gt; clearInterval(id), 2*interval));
setTimeout(()=&gt; ac.abort(), 3*interval)
</code></div><script>Flems(document.getElementById("code-example-1-e9cfsaeb64o"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { S } from \\\"https://cdn.jsdelivr.net/gh/jaandrle/deka-dom-el/dist/esm-with-signals.js\\\";\\nconst signal= S(0);\\n// computation pattern\\nconst double= S(()=> 2*signal());\\n\\nconst ac= new AbortController();\\nS.on(signal, v=> console.log(\\\"signal\\\", v), { signal: ac.signal });\\nS.on(double, v=> console.log(\\\"double\\\", v), { signal: ac.signal });\\n\\nsignal(signal()+1);\\nconst interval= 5000;\\nconst id= setInterval(()=> signal(signal()+1), interval);\\nac.signal.addEventListener(\\\"abort\\\",\\n\\t()=> setTimeout(()=> clearInterval(id), 2*interval));\\n\\nsetTimeout(()=> ac.abort(), 3*interval)\\n\"}],\"toolbar\":false}"));</script><div class="notice"><p>Mnemonic</p><ul><li><code>S(&lt;value&gt;)</code> — signal: reactive value</li><li><code>S(()=&gt; &lt;computation&gt;)</code> — signal: reactive value dependent on calculation using other signals</li><li><code>S.on(&lt;signal&gt;, &lt;listener&gt;[, &lt;options&gt;])</code> — listen to the signal value changes</li><li><code>S.clear(...&lt;signals&gt;)</code> — off and clear signals</li><li><code>S(&lt;value&gt;, &lt;actions&gt;)</code> — signal: pattern to create complex reactive objects/arrays</li><li><code>S.action(&lt;signal&gt;, &lt;action-name&gt;, ...&lt;action-arguments&gt;)</code> — invoke an&nbsp;action for given signal</li></ul></div></main></body></html>

View File

@ -0,0 +1,16 @@
import { S } from "deka-dom-el/signals";
const signal= S(0);
// computation pattern
const double= S(()=> 2*signal());
const ac= new AbortController();
S.on(signal, v=> console.log("signal", v), { signal: ac.signal });
S.on(double, v=> console.log("double", v), { signal: ac.signal });
signal(signal()+1);
const interval= 5000;
const id= setInterval(()=> signal(signal()+1), interval);
ac.signal.addEventListener("abort",
()=> setTimeout(()=> clearInterval(id), 2*interval));
setTimeout(()=> ac.abort(), 3*interval)

View File

@ -0,0 +1,8 @@
import { S } from "deka-dom-el/signals";
// α — `signal` represents a reactive value
const signal= S(0);
// β — just reacts on signal changes
S.on(signal, console.log);
// γ — just updates the value
signal(signal()+1);
setInterval(()=> signal(signal()+1), 5000);

View File

@ -24,7 +24,7 @@ import { el } from "../../index.js";
export function h3({ textContent, id }){
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
return el("h3", { id }).append(
el("a", { textContent: "§", href: "#"+id, tabIndex: -1 }),
el("a", { textContent: "#", href: "#"+id, tabIndex: -1 }),
" ", textContent
);
}

View File

@ -116,6 +116,30 @@ export function page({ pkg, info }){
" We can use the ", el("code", "elNS"), " function:"
),
el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }),
el("div", { className: "notice" }).append(
el("p", "Mnemonic"),
el("ul").append(
el("li").append(
el("code", "assign(<element>, ...<idl-objects>): <element>"), " — assign properties to the element",
),
el("li").append(
el("code", "el(<tag-name>, <primitive>)[.append(...)]: <element-from-tag-name>"), " — simple element containing only text",
),
el("li").append(
el("code", "el(<tag-name>, <idl-object>)[.append(...)]: <element-from-tag-name>"), " — element with more properties",
),
el("li").append(
el("code", "el(<function>, <function-argument(s)>)[.append(...)]: <element-returned-by-function>"), " — using component represented by function",
),
el("li").append(
el("code", "el(<...>, <...>, ...<addons>)"), " — see following page"
),
el("li").append(
el("code", "elNS(<namespace>)(<as-el-see-above>)[.append(...)]: <element-based-on-arguments>"), " — typically SVG elements",
)
)
),
el(prevNext, info)
)

View File

@ -113,6 +113,25 @@ export function page({ pkg, info }){
el(h3, "Final notes"),
el("p", "The library also provides a method to dispatch the events."),
el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }),
el("div", { className: "notice" }).append(
el("p", "Mnemonic"),
el("ul").append(
el("li").append(
el("code", "on(<event>, <listener>[, <options>])(<element>)"), " — just ", el("code", "<element>.addEventListener(<event>, <listener>[, <options>])")
),
el("li").append(
el("code", "on.<live-cycle>(<event>, <listener>[, <options>])(<element>)"), " — corresponds to custom elemnets callbacks ", el("code", "<live-cycle>Callback(...){...}"),
". To connect to custom element see following page, else it is simulated by MutationObserver."
),
el("li").append(
el("code", "dispatchEvent(<event>[, <options>])(element)"), " — just ", el("code", "<element>.dispatchEvent(new Event(<event>[, <options>]))")
),
el("li").append(
el("code", "dispatchEvent(<event>[, <options>])(element, detail)"), " — just ", el("code", "<element>.dispatchEvent(new CustomEvent(<event>, { detail, ...<options> }))")
),
)
),
el(prevNext, info)
)

View File

@ -14,107 +14,67 @@ export function page({ pkg, info }){
return el().append(
el(header, { info, pkg }),
el("main").append(
el("h2", "Listenning to the native DOM events and other Addons"),
el("h2", "Using signals to manage reactivity"),
el("p").append(
"We quickly introduce helper to listening to the native DOM events.",
" ",
"And library syntax/pattern so-called ", el("em", "Addon"), " to",
" incorporate not only this in UI templates declaratively."
"How a program responds to variable data or user",
" interactions is one of the fundamental problems of programming.",
" If we desire to solve the issue in a declarative manner,",
" signals may be a viable approach.",
),
el(example, { src: fileURL("./components/examples/signals/intro.js"), page_id }),
el(h3, "Events and listenners"),
el(h3, "Introducing signals"),
el("p").append(
"In JavaScript you can listen to the native DOM events of the given element by using ",
el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener", title: "addEventListener on MDN" }).append(
el("code", "element.addEventListener(type, listener, options)")
), ".",
" ",
"The library provides an alternative (", el("code", "on"), ") accepting the differen order",
" of the arguments:"
"Using signals, we split program logic into the three parts.",
" Firstly (α), we create a variable (constant) representing reactive",
" value. Somewhere later, we can register (β) a logic reacting",
" to the signal value changes. Similarly, in a remaining part (γ), we",
" can update the signal value."
),
el(example, { src: fileURL("./components/examples/events/compare.js"), page_id }),
el("p").append(
"…this is actually one of the two differences. The another one is that ", el("code", "on"),
" accepts only object as the ", el("code", "options"), " (but it is still optional)."
"All this is just an example of ",
el("a", { textContent: "Event-driven programming", href: "https://en.wikipedia.org/wiki/Event-driven_programming", title: "Wikipedia: Event-driven programming" }),
" and ",
el("a", { textContent: "Publishsubscribe pattern", href: "https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern", title: "Wikipedia: Publishsubscribe pattern" }),
" (compare for example with ", el("a", { textContent: "fpubsub library", href: "https://www.npmjs.com/package/fpubsub", title: "NPM package: fpubsub" }), ").",
" All three parts can be in some manner independent and still connected",
" to the same reactive entity."
),
el("p", { className: "notice" }).append(
"The other difference is that there is ", el("strong", "no"), " ", el("code", "off"), " function.",
" ",
"You can remove listener declaratively using ", el("a", { textContent: "AbortSignal", href: "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal", title: "part of addEventListener on MDN" }),
":"
el("p").append(
"Signals are implemented in the library as functions. To see current value",
" of signal, just call it without any arguments ", el("code", "console.log(signal())"), ".",
" To update the signal value, pass any argument ", el("code", "signal('a new value')"), ".",
" For listenning the signal value changes, use ", el("code", "S.on(signal, console.log)"), "."
),
el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }),
el("p").append(
"Similarly to the ", el("code", "on"), " function to register DOM events listener.",
" You can use ", el("code", "AbortController"), "/", el("code", "AbortSignal"), " to",
" ", el("em", "off"), "/stop listenning. For representing “live” piece of code computation pattern:"
),
el(example, { src: fileURL("./components/examples/signals/computations-abort.js"), page_id }),
el("div", { className: "notice" }).append(
el("p", "So, there are (typically) three ways to handle events. You can use:"),
el("p", "Mnemonic"),
el("ul").append(
el("li").append( el("code", `el("button", { textContent: "click me", "=onclick": "console.log(event)" })`)),
el("li").append( el("code", `el("button", { textContent: "click me", onclick: console.log })`)),
el("li").append( el("code", `el("button", { textContent: "click me" }, on("click", console.log))`))
),
el("p").append(
"In the first example we force to use HTML attribute (it corresponds to ", el("code", `<button onclick="console.log(event)">click me</button>`), ").",
" ",
el("em", "Side note: this can be useful in case of SSR."),
" ",
"To study difference, you can read a nice summary here: ", el("a", { href: "https://gist.github.com/WebReflection/b404c36f46371e3b1173bf5492acc944", textContent: "GIST @WebReflection/web_events.md" }), "."
el("li").append(
el("code", "S(<value>)"), " — signal: reactive value",
),
el("li").append(
el("code", "S(()=> <computation>)"), " — signal: reactive value dependent on calculation using other signals",
),
el("li").append(
el("code", "S.on(<signal>, <listener>[, <options>])"), " — listen to the signal value changes",
),
el("li").append(
el("code", "S.clear(...<signals>)"), " — off and clear signals",
),
el("li").append(
el("code", "S(<value>, <actions>)"), " — signal: pattern to create complex reactive objects/arrays",
),
el("li").append(
el("code", "S.action(<signal>, <action-name>, ...<action-arguments>)"), " — invoke an action for given signal"
)
)
),
el(h3, "Addons"),
el("p").append(
"From practical point of view, ", el("em", "Addons"), " are just functions that accept any html element",
" as their first parameter. You can see that the ", el("code", "on(…)"), " fullfills this requirement."
),
el("p").append(
"You can use Addons as ≥3rd argument of ", el("code", "el"), " function. This way is possible to extends",
" you templates by additional (3rd party) functionalities. But for now mainly, you can add events listeners:"
),
el(example, { src: fileURL("./components/examples/events/templateWithListeners.js"), page_id }),
el("p").append(
"As the example shows, you can also provide types in JSDoc+TypeScript by using global type ", el("code", "ddeElementAddon"), ".",
" ",
"Also notice, you can use Addons to get element reference.",
),
el(h3, "Life-cycle events"),
el("p").append(
"Addons are called immediately when the element is created, even it is not connected to live DOM yet.",
" ",
"Therefore, you can understand the Addon to be “oncreate” event."
),
el("p").append(
"The library provide three additional live-cycle events corresponding to how they are named in",
" a case of custom elements: ", el("code", "on.connected"), ", ", el("code", "on.disconnected"),
" and ", el("code", "on.attributeChanged"), "."
),
el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
el("p").append(
"For Custom elements, we will later introduce a way to replace ", el("code", "*Callback"),
" syntax with ", el("code", "dde:*"), " events. The ", el("code", "on.*"), " functions then",
" listen to the appropriate Custom Elements events (see ", el("a", { textContent: "Custom element lifecycle callbacks | MDN", href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks" }), ")."
),
el("p").append(
"But, in case of regular elemnets the ", el("a", { href: "https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" }).append(el("code", "MutationObserver"), " | MDN"),
" is internaly used to track these events. Therefore, there are some drawbacks:",
),
el("ul").append(
el("li").append(
"To proper listener registration, you need to use ", el("code", "on.*"), " not `on(\"dde:*\", …)`!"
),
el("li").append(
"Use sparingly! Internally, library must loop of all registered events and fires event properly.",
" ",
el("strong", "It is good practice to use the fact that if an element is removed, its children are also removed!"),
" ",
"In this spirit, we will introduce later the ", el("strong", "host"), " syntax to register",
" clean up procedures when the component is removed from the app."
),
),
el(h3, "Final notes"),
el("p", "The library also provides a method to dispatch the events."),
el(example, { src: fileURL("./components/examples/events/compareDispatch.js"), page_id }),
el(prevNext, info)
)
);
}

View File

@ -6,6 +6,7 @@ export const pages= [
{ id: "index", href: "./", title: "Introduction", description: "Introducing a library." },
{ id: "p02-elements", href: "p02-elements", title: "Elements", description: "Basic concepts of elements modifications and creations." },
{ id: "p03-events", href: "p03-events", title: "Events and Addons", description: "Using not only events in UI declaratively." },
{ id: "p04-signals", href: "p04-signals", title: "Signals and reactivity", description: "Handling reactivity in UI via signals." },
];
/**
* @typedef registerClientFile