How to
In HTML
dom99 will browse the DOM and react if an element has one of the following attributes
- data-variable : Data binding between DOM element and JS variable
- data-element : Select an element
- data-function : Attaches an event listener
- data-list : Display a JS Array as a list in the DOM
- data-use: Which element to use a list item in combination with data-list
- data-template : Declare a html template to build components
- data-scope: Create a scope context
The general syntax is
<tag data-keyword="token1-token2" > text ... </tag>
If you are not using browserify or ES modules you need to include this script tag in your html before other scripts that access dom99.
<script src="./node_modules/dom99/built/dom99.iife.js"></script>
<script src="js/yourJavascriptFile.js"></script>
In JavaScript
import * as d from "./node_modules/dom99/source/dom99.js";
// to start using dom99 pre selected elements use this statement
d.start();
data-function and d.functions for event listeners
Store functions in the d.functions object
d.functions.functionName = aFunction;
aFunction is called when you click this button
<button data-function="click-functionName">Action</button>
data-variable and d.variables and d.feed for data binding
To changes the text of <p data-variable="talkings"></p>
and all other element that share the variable "talkings"
d.feed({talkings: `Hi`});
Use the same data-variable="talkings" on <input>
elements for two-way data-binding
data-list and data-use to display a list
<ol data-list="numbers" data-use="li"></ol>
d.feed(`numbers`, [
1,
2,
3,
]);
data-element and d.elements for direct element manipulation
d.elements.title.remove();
Removes <h1 data-element="title">Hello</h1>
data-template to declare templates
<template data-template="d-comment">
<p data-variable="text">default text</p>
<time data-variable="date">default time</time>
</template>
data-scope to put html templates copies
<d-comment data-scope="first"></d-comment>
<d-comment data-scope="second"></d-comment>
To edit the first <d-comment>
d.feed(`first`, {
text: `A new comment`,
date: `Today`
});
Complete overview
d.start();
Use start after having stored all the event handlers in d.functions, and before using references to nodes stored in d.elements.
This will look the for dom99 directives in the document tree.
Use HTML templates, it is healthy
There are 2 ways to use HTML templates
- Static Load time template rendering with custom elements
- Run time template rendering and insertion
Both ways are complementary and use the same core ideas. To illustrate this imagine you want to have a web page with an article and comments.
When the page loads you want to display the article and already display the 2 last comments without another client-server round-trip, later when the user scrolls down or clicks a button to show more
comments we load more comments into the page with dynamic template insertion. We here define a comment as some text and a date. What we want initially is something like this
Dynamic template injection in general
<body>
<template data-template="d-tagname">
<p data-variable="text" ></p>
Any HTML ...
</template>
...
<div data-element="target"></div>
</body>
// manual, see templates3.html to see how to use shortcuts
// 0 make a description
let customElementDescription = {
[`tagName`]: `d-tagname`,
[`data-scope`]: `key`
}
// 1 create HTML Element
let customElement = d.createElement2(customElementDescription);
// 2 link it
d.start({ startElement: customElement });
// 3 insert the Element that has a clone as a child in the DOM
d.elements[`target`].appendChild(customElement);
I encourage you to encapsulate what changes in functions.
About templates
If you have a <template>
in your page, it is inert and not rendered. However the template itself with a data-template
can be used to create copies of the content of the template. These copies can be inserted in your document. The value of the attribute data-scope is called the key in this documentation. You can use d.variables d.elements and d.functions inside templates. To differentiate the multiple template clones you use the key. For instance:
d.variables[`key>text`] = `A string`;
d.elements[`key>elementName`].className = `class-fun`;
Or
d.variables[d.scopeFromArray([`key`, `text`])] = `A string`;
d.elements[d.scopeFromArray([`key`, `elementName`])].className = ...
d.functions function the other way around. You use the same event handlers for all template copies
and handle differences with d.scopeFromEvent(event)
. Example
<!-- HTML -->
<template data-template="d-tagname">
<button data-function="close" >CLOSE (X)</button>
<button data-function="update" >Update (X)</button>
<p data-variable="text" >Default Text</p>
<div data-element="status" class="status" ></div>
<ul data-list="myList" data-use="li" >
<li>Default List Item</li>
</ul>
<div data-scope="encapsulated" >
<p data-variable="text" >Other Default Text</p>
</div>
Any HTML ...
</template>
<!-- used like -->
<d-tagName data-scope="myKey0"></d-tagName>
<!-- or -->
<div is="d-tagName" data-scope="myKey1"></div>
<!-- or -->
<div data-list="listKey" data-use="d-tagName"></div>
// JS
d.functions.update = function (event) {
const scope = d.scopeFromEvent(event);
// you can access variables, elements, lists scopes with d.scopeFromArray
// - text -
const textScope = d.scopeFromArray([scope, `text`]);
const textVariable = d.variables[textScope]; // read
d.feed(textScope, `New Text`); // write
// - elements -
const statusScope = d.scopeFromArray([scope, `status`]);
const statusDiv = d.variables[statusScope]; // read
statusDiv.classList.add(`updated`) // use
// - list -
const listScope = d.scopeFromArray([scope, `myList`]);
const listVariable = d.variables[listScope]; // read
d.feed(listScope, [
`a`,
`b`,
`c`
]); // write with side effect
// - encapsulated -
// here d.contextFromArray takes a 3 item list to go 1 level deeper the tree
const encapsulatedTextScope = d.contextFromArray([scope, `encapsulated`, `text`]);
const textVariable2 = d.variables[encapsulatedTextScope]; // read
d.feed(encapsulatedTextScope, `New Encapsulated Text`); // write
// this looks verbose but it works for any kind of deep html composition.
//If you want to target a specific element or variable you can directly write
d.variables[`key>text`];
};
Note that d.scopeFromEvent only works on child of an element that use data-scope or equivalent, not on the element with scopeFromEvent itself