From 97f8c2eed3247b736a6841aea3eba0fdcc434983 Mon Sep 17 00:00:00 2001 From: Jan Andrle Date: Mon, 3 Jun 2024 16:20:42 +0200 Subject: [PATCH] :abc: 3PS --- docs/index.html | 15 +++--- docs/p04-signals.html | 2 +- .../components/examples/introducing/3ps.js | 1 + .../examples/introducing/helloWorld.js | 8 ++-- docs_src/index.html.js | 48 +++++++++++-------- docs_src/p04-signals.html.js | 4 ++ docs_src/p06-customElement.html.js | 30 ++++++------ 7 files changed, 60 insertions(+), 48 deletions(-) diff --git a/docs/index.html b/docs/index.html index 4020e79..450cbf6 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,21 +1,22 @@ -`deka-dom-el` — Introduction

`deka-dom-el` — Introduction

Introducing a library.

The library tries to provide pure JavaScript tool(s) to create reactive interfaces using …

# Event-driven programming (3 parts separation ≡ 3PS)

Let's introduce the basic principle on which the library is built. We'll use the JavaScript listener as a starting point.

const onchage= +`deka-dom-el` — Introduction

`deka-dom-el` — Introduction

Introducing a library.

The library tries to provide pure JavaScript tool(s) to create reactive interfaces using …

# Event-driven programming (3 parts separation ≡ 3PS)

Let's introduce the basic principle on which the library is built. We'll use the JavaScript listener as a starting point.

// pseudo code! +const onchage= event=> console.log("Reacting to the:", event); // A input.addEventListener("change", onchange); // B input.dispatchEvent(new Event("change")); // C -

As we can see, in the code at location “A” we define how to react when the function is called with any event as an argument. At that moment, we don't care who/why/how the function was called. Similarly, at point “B”, we reference to a function to be called on the event without caring what the function will do at that time. Finally, at point “C”, we tell the application that a change has occurred, in the input, and we don't care if/how someone is listening for the event.

We start with creating and modifying a static elements and end up with UI templates. From document.createElement to el.. Then we go through the native events system and the way to include it declaratively in UI templates. From element.addEventListener to on.

Next step is providing interactivity not only for our UI templates. We introduce signals (S) and how them incorporate to UI templates.

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 scopes. We will look at how they work in components represented in JavaScript by functions.

import { el } from "./esm-with-signals.js"; +

As we can see, in the code at location “A” we define how to react when the function is called with any event as an argument. At that moment, we don't care who/why/how the function was called. Similarly, at point “B”, we reference to a function to be called on the event without caring what the function will do at that time. Finally, at point “C”, we tell the application that a change has occurred, in the input, and we don't care if/how someone is listening for the event.

import { el } from "./esm-with-signals.js"; import { S } from "./esm-with-signals.js"; -const clicks= S(0); +const clicks= S(0); // A document.body.append( el().append( el("p", S(()=> - "Hello World "+"🎉".repeat(clicks()) + "Hello World "+"🎉".repeat(clicks()) // B )), el("button", { type: "button", - onclick: ()=> clicks(clicks()+1), - textContent: "Fire" + onclick: ()=> clicks(clicks()+1), // C + textContent: "Fire", }) ) ); -
\ No newline at end of file +

The library introduces a new “type” of variable/constant called signal allowing us to to use introduced 3PS pattern in our applications. As you can see it in the example above.

Also please notice that there is very similar 3PS pattern used for separate creation of UI and business logic.

The 3PS is very simplified definition of the pattern. There are more deep/academic definitions more precisely describe usage in specific situations, see for example MVVM or MVC.

# Organization of the documentation

\ No newline at end of file diff --git a/docs/p04-signals.html b/docs/p04-signals.html index e674cbe..24ced16 100644 --- a/docs/p04-signals.html +++ b/docs/p04-signals.html @@ -4,7 +4,7 @@ S===signal /** @type {ddeSignal} */ /** @type {ddeAction} */ /** @type {ddeActions} */ -

# Introducing signals

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.

import { S } from "./esm-with-signals.js"; +

# Introducing signals

Let’s re-introduce 3PS principle.

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.

import { S } from "./esm-with-signals.js"; // α — `signal` represents a reactive value const signal= S(0); // β — just reacts on signal changes diff --git a/docs_src/components/examples/introducing/3ps.js b/docs_src/components/examples/introducing/3ps.js index e1660b6..75f62d0 100644 --- a/docs_src/components/examples/introducing/3ps.js +++ b/docs_src/components/examples/introducing/3ps.js @@ -1,3 +1,4 @@ +// pseudo code! const onchage= event=> console.log("Reacting to the:", event); // A diff --git a/docs_src/components/examples/introducing/helloWorld.js b/docs_src/components/examples/introducing/helloWorld.js index 37d13b1..47c0fe9 100644 --- a/docs_src/components/examples/introducing/helloWorld.js +++ b/docs_src/components/examples/introducing/helloWorld.js @@ -1,15 +1,15 @@ import { el } from "deka-dom-el"; import { S } from "deka-dom-el/signals"; -const clicks= S(0); +const clicks= S(0); // A document.body.append( el().append( el("p", S(()=> - "Hello World "+"🎉".repeat(clicks()) + "Hello World "+"🎉".repeat(clicks()) // B )), el("button", { type: "button", - onclick: ()=> clicks(clicks()+1), - textContent: "Fire" + onclick: ()=> clicks(clicks()+1), // C + textContent: "Fire", }) ) ); diff --git a/docs_src/index.html.js b/docs_src/index.html.js index 4a0b366..47472c6 100644 --- a/docs_src/index.html.js +++ b/docs_src/index.html.js @@ -13,6 +13,14 @@ import { code } from "./components/code.html.js"; /** @param {string} url */ const fileURL= url=> new URL(url, import.meta.url); const references= { + w_mvv:{ + title: t`Wikipedia: Model–view–viewmodel`, + href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel", + }, + w_mvc: { + title: t`Wikipedia: Model–view–controller`, + href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller", + }, }; /** @param {import("./types.d.ts").PageAttrs} attrs */ export function page({ pkg, info }){ @@ -25,29 +33,27 @@ export function page({ pkg, info }){ a starting point. `), el(code, { src: fileURL("./components/examples/introducing/3ps.js"), page_id }), - el("p").append(t` - As we can see, in the code at location “A” we define how to react when the function is called with - any event as an argument. At that moment, we don't care who/why/how the function was called. Similarly, - at point “B”, we reference to a function to be called on the event without caring what the function will - do at that time. Finally, at point “C”, we tell the application that a change has occurred, in the input, - and we don't care if/how someone is listening for the event. - `), - el("p").append(...T` - We start with creating and modifying a static elements and end up with UI templates. - ${el("em").append(...T`From ${el("code", "document.createElement")} to ${el("code", "el")}.`)}. - Then we go through the native events system and the way to include it declaratively in UI templates. - ${el("em").append(...T`From ${el("code", "element.addEventListener")} to ${el("code", "on")}.`)} - `), - el("p").append(...T` - Next step is providing interactivity not only for our UI templates. - We introduce signals (${el("code", "S")}) and how them incorporate to UI templates. - `), - el("p").append(...T` - 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 ${el("code", "scope")}s. We will look at - how they work in components represented in JavaScript by functions. + As we can see, in the code at location “A” we define ${el("em", t`how to react`)} when the function + is called with any event as an argument. At that moment, we ${el("em", t`don't care who/why/how`)} + the function was called. Similarly, at point “B”, we reference to a function to be called on the event + ${el("em", t`without caring`)} what the function will do at that time. Finally, at point “C”, we tell + the application that a change has occurred, in the input, and we ${el("em", t`don't care if/how someone`)} + is listening for the event. `), el(example, { src: fileURL("./components/examples/introducing/helloWorld.js"), page_id }), + el("p").append(...T` + The library introduces a new “type” of variable/constant called ${el("em", t`signal`)} allowing us to + to use introduced 3PS pattern in our applications. As you can see it in the example above. + `), + el("p").append(...T` + Also please notice that there is very similar 3PS pattern used for separate creation of UI and business logic. + `), + el("p").append(...T` + The 3PS is very simplified definition of the pattern. There are more deep/academic definitions more precisely + describe usage in specific situations, see for example ${el("a", { textContent: t`MVVM`, ...references.w_mvv })} + or ${el("a", { textContent: t`MVC`, ...references.w_mvc })}. + `), + el(h3, t`Organization of the documentation`), ); } diff --git a/docs_src/p04-signals.html.js b/docs_src/p04-signals.html.js index ba909c8..6cfedc8 100644 --- a/docs_src/p04-signals.html.js +++ b/docs_src/p04-signals.html.js @@ -51,6 +51,10 @@ export function page({ pkg, info }){ el(code, { src: fileURL("./components/examples/signals/intro.js"), page_id }), el(h3, t`Introducing signals`), + el("p").append(...T` + Let’s re-introduce + ${el("a", { textContent: t`3PS principle`, href: "./#h-event-driven-programming--parts-separation--ps" })}. + `), el("p").append(...T` 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 diff --git a/docs_src/p06-customElement.html.js b/docs_src/p06-customElement.html.js index 0233522..b10b044 100644 --- a/docs_src/p06-customElement.html.js +++ b/docs_src/p06-customElement.html.js @@ -1,6 +1,7 @@ +import { T, t } from "./utils/index.js"; export const info= { - title: "Custom elements", - description: "Using custom elements in combinantion with DDE", + title: t`Custom elements`, + description: t`Using custom elements in combinantion with DDE`, }; import { el } from "deka-dom-el"; @@ -14,12 +15,12 @@ const fileURL= url=> new URL(url, import.meta.url); const references= { /** Custom Elements on MDN */ custom_elements: { - title: "MDN documentation page for Custom Elements", + title: t`MDN documentation page for Custom Elements`, href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements", }, /** Custom Elements tips from WebReflection */ custom_elements_tips: { - title: "Ideas and tips from WebReflection", + title: t`Ideas and tips from WebReflection`, href: "https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4", } }; @@ -27,20 +28,19 @@ const references= { export function page({ pkg, info }){ const page_id= info.id; return el(simplePage, { info, pkg }).append( - el("h2", "Using custom elements in combinantion with DDE"), - el("p").append( - - ), + el("h2", t`Using custom elements in combinantion with DDE`), + el("p").append(...T` + `), el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }), - el(h3, "Custom Elements Introduction"), - el("p").append( - el("a", { textContent: "Using custom elements", ...references.custom_elements }) - ), + el(h3, t`Custom Elements Introduction`), + el("p").append(...T` + ${el("a", { textContent: t`Using custom elements`, ...references.custom_elements })} + `), el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }), - el("p").append( - el("a", { textContent: "Handy Custom Elements' Patterns", ...references.custom_elements_tips }) - ), + el("p").append(...T` + ${el("a", { textContent: t`Handy Custom Elements' Patterns`, ...references.custom_elements_tips })} + `), el(mnemonic) );