mirror of
https://github.com/jaandrle/deka-dom-el
synced 2024-11-25 17:49:37 +01:00
156 lines
7.4 KiB
JavaScript
156 lines
7.4 KiB
JavaScript
import { T, t } from "./utils/index.js";
|
||
export const info= {
|
||
title: t`Elements`,
|
||
description: t`Basic concepts of elements modifications and creations.`,
|
||
};
|
||
|
||
import { el } from "deka-dom-el";
|
||
import { simplePage } from "./layout/simplePage.html.js";
|
||
import { example } from "./components/example.html.js";
|
||
import { h3 } from "./components/pageUtils.html.js";
|
||
import { mnemonic } from "./components/mnemonic/elements-init.js";
|
||
import { code } from "./components/code.html.js";
|
||
/** @param {string} url */
|
||
const fileURL= url=> new URL(url, import.meta.url);
|
||
const references= {
|
||
/** document.createElement() */
|
||
mdn_create: {
|
||
title: t`MDN documentation page for document.createElement()`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement",
|
||
},
|
||
/** Interface Description Language (`el.textContent`) */
|
||
mdn_idl: {
|
||
title: t`MDN page about Interface Description Language`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Glossary/IDL",
|
||
},
|
||
/** HTMLElement */
|
||
mdn_el: {
|
||
title: t`MDN documentation page for HTMLElement`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement"
|
||
},
|
||
/** HTMLParagraphElement */
|
||
mdn_p: {
|
||
title: t`MDN documentation page for HTMLParagraphElement (\`p\` tag)`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLParagraphElement"
|
||
},
|
||
/** `[a, b] = [1, 2]` */
|
||
mdn_destruct: {
|
||
title: t`MDN page about destructuring assignment syntax (e.g. \`[a, b] = [1, 2]\`)`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment",
|
||
},
|
||
/** document.createElementNS() */
|
||
mdn_ns: {
|
||
title: t`MDN documentation page for document.createElementNS() (e.g. for SVG elements)`,
|
||
href: "https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS",
|
||
}
|
||
};
|
||
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
||
export function page({ pkg, info }){
|
||
const page_id= info.id;
|
||
return el(simplePage, { info, pkg }).append(
|
||
el("h2", t`Native JavaScript DOM elements creations`),
|
||
el("p", t`
|
||
Let’s go through all patterns we would like to use and what needs to be improved for better experience.
|
||
`),
|
||
|
||
el(code, { src: fileURL("./components/examples/elements/intro.js"), page_id }),
|
||
|
||
el(h3, t`Creating element(s) (with custom attributes)`),
|
||
el("p").append(...T`
|
||
You can create a native DOM element by using the ${el("a", references.mdn_create).append(
|
||
el("code", "document.createElement()") )}. It is also possible to provide a some attribute(s) declaratively
|
||
using ${el("code", "Object.assign()")}. More precisely, this way you can sets some
|
||
${el("a", references.mdn_idl).append( el("abbr", { textContent: "IDL", title: "Interface Description Language" }))}
|
||
also known as a JavaScript property.
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/nativeCreateElement.js"), page_id }),
|
||
el("p").append(...T`
|
||
To make this easier, you can use the ${el("code", "el")} function. Internally in basic examples,
|
||
it is wrapper around ${el("code", "assign(document.createElement(…), { … })")}.
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/dekaCreateElement.js"), page_id }),
|
||
el("p").append(...T`
|
||
The ${el("code", "assign")} function provides improved behaviour of ${el("code", "Object.assign()")}.
|
||
You can declaratively sets any IDL and attribute of the given element. Function prefers IDL and fallback
|
||
to the ${el("code", "element.setAttribute")} if there is no writable property in the element prototype.
|
||
`),
|
||
el("p").append(...T`
|
||
You can study all JavaScript elements interfaces to the corresponding HTML elements. All HTML elements
|
||
inherits from ${el("a", { textContent: "HTMLElement", ...references.mdn_el })}. To see
|
||
all available IDLs for example for paragraphs, see ${el("a", { textContent: "HTMLParagraphElement", ...references.mdn_p })}.
|
||
Moreover, the ${el("code", "assign")} provides a way to sets declaratively some convenient properties:
|
||
`),
|
||
el("ul").append(
|
||
el("li").append(...T`
|
||
It is possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attributes using object notation.
|
||
`),
|
||
el("li").append(...T`
|
||
In opposite, it is also possible to sets ${el("code", "data-*")}/${el("code", "aria-*")} attribute
|
||
using camelCase notation.
|
||
`),
|
||
el("li").append(...T`You can use string or object as a value for ${el("code", "style")} property.`),
|
||
el("li").append(...T`
|
||
${el("code", "className")} (IDL – preffered)/${el("code", "class")} are ways to add CSS classes
|
||
to the element. You can use string (similarly to ${el("code", "class=\"…\"")} syntax in HTML) or
|
||
array of strings. This is handy to concat conditional classes.
|
||
`),
|
||
el("li").append(...T`
|
||
Use ${el("code", "classList")} to toggle specific classes. This will be handy later when
|
||
the reactivity via signals is beeing introduced.
|
||
`),
|
||
el("li").append(...T`
|
||
The ${el("code", "assign")} also accepts the ${el("code", "undefined")} as a value for any property
|
||
to remove it from the element declaratively. Also for some IDL the corresponding attribute is removed
|
||
as it can be confusing. ${el("em").append(...T`For example, natievly the element’s ${el("code", "id")}
|
||
is removed by setting the IDL to an empty string.`)}
|
||
`),
|
||
el("li").append(...T`
|
||
You can use ${el("code", "=")} or ${el("code", ".")} to force processing given key as attribute/property
|
||
of the element.
|
||
`)
|
||
),
|
||
el("p").append(...T`
|
||
For processing, the ${el("code", "assign")} internally uses ${el("code", "assignAttribute")} and
|
||
${el("code", "classListDeclarative")}.
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/dekaAssign.js"), page_id }),
|
||
|
||
el(h3, t`Native JavaScript templating`),
|
||
el("p", t`By default, the native JS has no good way to define HTML template using DOM API:`),
|
||
el(example, { src: fileURL("./components/examples/elements/nativeAppend.js"), page_id }),
|
||
el("p").append(...T`
|
||
This library therefore overwrites the ${el("code", "append")} method of created elements to always return
|
||
parent element.
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/dekaAppend.js"), page_id }),
|
||
|
||
|
||
el(h3, t`Basic (state-less) components`),
|
||
el("p").append(...T`
|
||
You can use functions for encapsulation (repeating) logic. The ${el("code", "el")} accepts function
|
||
as first argument. In that case, the function should return dom elements and the second argument for
|
||
${el("code", "el")} is argument for given element.
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/dekaBasicComponent.js"), page_id }),
|
||
el("p").append(...T`
|
||
As you can see, in case of state-less/basic components there is no difference between calling component
|
||
function directly or using ${el("code", "el")} function.
|
||
`),
|
||
el("p", { className: "notice" }).append(...T`
|
||
It is nice to use similar naming convention as native DOM API. This allows us to use
|
||
${el("a", { textContent: t`the destructuring assignment syntax`, ...references.mdn_destruct })} and keep
|
||
track of the native API (things are best remembered through regular use).
|
||
`),
|
||
|
||
el(h3, t`Creating non-HTML elements`),
|
||
el("p").append(...T`
|
||
Similarly to the native DOM API (${el("a", references.mdn_ns).append(el("code", "document.createElementNS"))})
|
||
for non-HTML elements we need to tell JavaScript which kind of the element to create. We can use
|
||
the ${el("code", "elNS")} function:
|
||
`),
|
||
el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }),
|
||
|
||
el(mnemonic)
|
||
);
|
||
}
|