Skip to content

statewalker/statewalker-utils-dom

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@statewalker/utils-dom: DOM Utilities

This package contains the following DOM utilities used in other packages:

  • bindView(iterator, action, options) - creates and returns a DOM element which is updated each time when the given iterator returns a new value
  • getElementInvalidation(element) - returns a Promise instance associated with the given DOM element; the returned promise is resolved when the element is removed from the DOM tree
  • replaceDomContent(element, node) - replaces the content of the given DOM element by the given DOM node (element or text node).
  • trackDomNode(node, { onAdd, onRemove, getContainer }) - tracks the node and calls the specified onAdd/onRemove methods when the node is attached/removed from the DOM
  • toDomNode(value, doc) - transforms the given JavaScript value to a DOM node; text, numbers and boolean values are tranformed to Text instances; objects are serialized (with the JSON.stringify method) and also transformed to Text instances; DOM nodes are returned "as is", without modifications.

getElementInvalidation(element)

This method returns a Promise instance associated with the given DOM element; the returned promise is resolved when the element is removed from the DOM tree.

This method returns a single Promise instance for the specific DOM element. This Promise is stored in the invalidation field of the element.

const div = document.createElement("div");
document.body.appendChild(div);

// Get the invalidation promise associated with the given element:
const invalidation = getElementInvalidation(div);
...
// This function is called when the DOM element is detached from the DOM tree:
const onDetach = () => console.log('The element was detached from DOM...');
invalidation.then(onDetach);

// Check that the second time this method returns the same invalidation instance:
const invalidation2 = getElementInvalidation(div);
assert(invalidation === invalidation2);

// Shows this message:
// 'The element was detached from DOM...'

bindView(iterator, action, options)

This utility function allows to update HTML elements when the specified iterator yields a new value. It also allows to easily initialize the element and cleanup associated resources when this element is detached from DOM.

const elm: Element = bindView(
  // Async iterator returning new values to visualize:
  iterator : AsyncIterator,

  // The function returning the element
  action : Function,

  // Optional parameters:
  options : Object = {
    // Function used to handle errors
    handleError = console.error,

    // This function returns the root element to listen
    getRoot
    
  } : object = {}
)

The action(...) callback method recieves the following structure:

  • params : parameters object
  • params.init - sets the initialization function; it is called when the view is attached to the DOM
  • params.done - sets the finalization function which is called when the view is removed from the DOM
  • params.update - sets a new function to call on each value update; the function defined with the update method has the following signature: (view, value, oldValue) => { ... }

Example 1: in this example the activation method registers only one method to init/done/update the created view.

import { bindView } from '@statewalker/utils-dom'

// Generate a new sequence of values to update
// (see below for the implementation of the "generateValues" method):
const it = generateValues(50, 2000);

// Create a new view to append to the document.
const view = bindView(it, ({ init, update, done }) => {
  // View initialization:
  init((view) => view.innerHTML = "Initializing...");
  // Destroys the view and cleans up all associated resources:
  done((view) => view.innerHTML = "Destroying...");
  // This method is called each time when the iterator returns a new value:
  update((view, value, oldValue) => {
    view.innerText = `Counter: ${value}!`;
  })
  // Create and returns the view to update:
  return document.createElement("div");
})

// Append the resulting view to the document:
document.body.appendChild(view);

Example 2: in this example the activation method registers two methods for each of the "init/done/update" stages:

import { bindView } from '@statewalker/utils-dom'

// Generate a new sequence of values to update:
// (see below for the implementation of the "generateValues" method):
const it = generateValues(50, 2000);

// In this example the activation function registers two callbacks 
// for each of the "init/update/done" stages:
// - one method changes the conntent of the view
// - the second method prints some messages in the log
const div = bindView(it, ({ init, update, done }) => {
  
  // View initialization:
  init((view) => view.innerHTML = "Initializing...");
  // The second function to call on the view initialization:
  init(() => console.log("Init."))
  
  // Destroys the view and cleans up all associated resources:
  done((view) => view.innerHTML = "Destroying...");
  // The second method to call on initialization:
  done(() => console.log("Done."))

  // This method is called each time when the iterator returns a new value:
  update((view, value, oldValue) => {
    view.innerText = `Counter: ${value}!`;
  })
  // Print the values returned by the iterator:
  done((view, newValue, oldValue) => console.log("- Update:", { oldValue, newValue }));

  // Create and returns the view to update:
  return document.createElement("div");
})
// Append the resulting view to the document:
document.body.appendChild(div);

The generateValues method used in the examples above:

// This function generates values used to update the view
async function* generateValues(count = 100, maxTimeout = 1000) {
  for (let i = 0; i < count; i++) {
    yield i;
    await new Promise(r => setTimeout(Math.random() * maxTimeout));
  }
}

replaceDomContent(element, node)

This method replaces the content of the given DOM element by the given DOM node (element or text node).

Example:

import { replaceDomContent } from '@statewalker/utils-dom'

const root = document.querySelector("#root");

const div = document.createElement("div");
div.innerText = 'Hello, world';
replaceDomContent(root, div);

## trackDomNode(node, { onAdd, onRemove, getContainer })

This method tracks the node and calls the specified onAdd/onRemove methods when the node is attached/removed from the DOM.

Parameters:

  • node - the DOM node to track
  • params - an object containing method parameters
  • params.onAdd - an optional callback method invoked after the node is attached to DOM; it takes the node as the single parameter
  • params.onRemove - an optional callback method invoked when the node is removed from DOM; it recieves two parameters: the node itself and a boolean flag showing if the node was notified as attached or not (if the onAdd method was called before)
  • params.getContainer - returns the container to track for the specified node

toDomNode(value, doc)

This method transforms the given JavaScript value to a DOM node; text, numbers and boolean values are tranformed to Text instances; objects are serialized (with the JSON.stringify method) and also transformed to Text instances; DOM nodes are returned "as is", without modifications.

Example:

import { toDomNode } from '@statewalker/utils-dom'

const root = document.querySelector("#root");

// Transforms string a Text instance:
root.appendChild(toDomNode("Hello, world")) 

// Transforms the given number to a Text instance:
root.appendChild(toDomNode(12345)) 

// Returnes the DOM node without modifications: 
const h3 = toDomNode(document.createElement("h3"));
h3.innerHTML = "Hello, there!"
root.appendChild(h3)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published