Document Render Kit

A kit of conventional tools for coordinated DOM manipulation.
Rendering Context
The kit attaches and maintains a DOM rendering context for document nodes.
The rendering context serves several purposes:
- Provides a render scheduler suitable for performant DOM manipulations.
- Provides a namespace aliaser.
- Provides a settlement phase of rendering. A DOM node (e.g. custom element) may use to perform custom actions before
it is added to the document.
- Notifies when node added (connected) to document.
The rendering context of particular DOM node may be obtained using drekContextOf function.
There are three kinds of rendering contexts:
-
Document rendering context.
Such context is always available in document and returned by drekContextOf function for any DOM node connected
to the document.
-
Fragment content rendering context.
It is created for each rendered fragment and is available via DrekFragment.innerContext property.
The drekContextOf function returns this context for fragment's content, as well as for each DOM node added to it.
-
Unrooted rendering context.
When a DOM node is neither connected to a document, nor part of a rendered fragment's content, the drekContextOf
function creates an unrooted context for the root node of that node.
Unrooted context tracks a document connection and settlement semi-automatically. A DrekContext.lift method can be
used to forcibly update them.
Semi-automatic tracking means that each time an unrooted context created, it is registered for automatic lifting.
The lifting happens either asynchronously, or synchronously right before the drekBuild function exit.
Alternatively, a drekLift function can be used to lift a context of the root node after adding it to another one.
Rendered Fragment
A DrekFragment is a fragment of DOM tree, which content is to be placed to the document once rendered.
The content of rendered fragment is a DocumentFragment.
The rendered fragment provides a separate rendering context for its content nodes. The latter informs content nodes
when they are added to document. It also establishes a settlement phase for them.
import { drekAppender, drekContextOf, DrekFragment } from '@frontmeans/drek';
const fragment = new DrekTarget(drekAppender(document.body));
render(fragment.content);
fragment.whenRendered(() => {
});
fragment.render();
function render(content: Node): void {
const context = drekContextOf(content);
context.scheduler()(() => {
content.append('rendered content');
});
context.whenConnected(() => {
});
}
Settlement Phase
A settlement phase is designed primarily for custom elements.
A custom element rendering consists of two main phases:
An element constructor can not manipulate DOM tree. So typically, the DOM manipulations happen inside
connectedCallback. This, however, is a source of potential performance issues, as connectedCallback is called
only after the element is added to document, while custom element rendering may be slow. E.g. when a custom element
renders nested ones.
The better approach would be to render custom elements to DocumentFragment and then add the fully rendered fragment
to the document.
This requires an additional settlement callback that is available via rendering context. An event is sent by
DrekFragment.settle method. A custom element may receive this event via DrekContext.whenSettled method and start
rendering right away, before it is added to the document.
Here is a usage example.
import { drekAppender, drekContextOf, DrekFragment } from '@frontmeans/drek';
const fragment = new DrekTarget(drekAppender(document.body));
render(fragment.content);
fragment.settle();
fragment.render();
function render(content: Node): void {
const context = drekContextOf(content);
context.scheduler()(() => {
const indicator = content.appendChild(document.createElement('div'));
context.whenSettled(() => {
indicator.innerText = `Settled at ${new Date().toISOString()}`;
});
});
}
Rendering Target
A rendering target (DrekTarget) represents a part of the DOM tree to place the rendered content to.
There are several convenient target implementations available:
-
drekAppender - Creates a rendering target that appends content to parent node.
-
drekCharger - Creates a rendering target that charges rendered content prior to placing it to another target.
By default, encloses the rendered content into comments. The ongoing content updates replace the nodes between
comments thus making the updated content occupy the same place.
-
drekInserter - Creates a rendering target that inserts content to parent node at particular position.
-
drekReplacer - Creates a rendering target that replaces content of the given node.
Miscellaneous
A DrekCssClasses is an accessor to CSS classes of some element. With it, element's CSS classes can be manipulated
concurrently in a safe manner. E.g. multiple parties may add and remove CSS classes to the same element, even if the
class names are the same.