updates

System for applying batch updates to component attributes and properties

Overview

The Element prototype exposes several properties that expose a collection that can be modified but not set directly: attributes, childNodes, classList, and (for HTMLElement and SVGElement) style. Although these properties cannot be directly set (you can't write element.attributes = newAttributes), we can define simple and useful write semantics for updating these properties in bulk.

These helpers, especially apply, are designed to let components declare a bulk set of updates they would like to apply to themselves or their elements in their shadow trees. Both RenderUpdatesMixin and ContentItemsMixin use the same dictionary format supported by apply.

API

apply(element, updates) static method

Apply bulk updates to an element's attributes, child nodes, classes, styles, and shadow elements.

This takes an updates dictionary. Certain keys of this dictionary are handled specially:

All other name: value entries are interpreted as custom properties.

Example:

import * as updates from 'elix/src/updates.js';

const div = document.createElement('div');
div.classList.add('foo bar');
updates.apply({
  classList: {
    bar: false, // Removes bar
    baz: true   // Adds baz
  }
});
div.classList.value // "foo baz"

Note that apply updates the indicated properties, leaving in place any other existing element attributes, classes, or styles not specifically referenced in the dictionary (e.g., the class "foo" above).

As noted above, apply can be used to set custom element properties. E.g.,

updates.apply(element, { foo: 'bar' });

is equivalent to calling:

element.foo = 'bar';

Parameters:

  • element: Elementthe element to update
  • updates: objectthe updates to apply

applyAttribute(element, name, value) static method

Update the given attribute on an element.

Passing a non-null value acts like a call to setAttribute(name, value). If the supplied value is nullish, this acts like a call to removeAttribute(name).

Boolean attributes are treated specially. If the attribute name matches one of the known HTML boolean attributes (checked, defer, disabled, hidden, ismap, multiple, noresize, readonly, selected), the attribute will be handled as a boolean attribute. A truthy value acts like a call to setAttribute(name, ''). A falsy value acts like removeAttribute(name).

Parameters:

  • element: Elementthe element to update
  • name: stringthe attribute name
  • value: string|booleanthe attribute value to set

applyAttributes(element, attributes) static method

Apply the indicated attributes to the element.

This takes a dictionary in which each name: value is results in a call to applyAttribute(name, value). See applyAttribute for details.

Parameters:

  • element: Elementthe element to update
  • attributes: objecta dictionary of attributes to apply

applyChildNodes(element, childNodes) static method

Sets the element's childNodes to the given set of nodes.

This adds or removes the element's childNodes as necessary to match the nodes indicated in the childNodes parameter.

As a performance optimization, if the supplied childNodes value is frozen and equivalent to the last call made to this function, the function assumes the child nodes are already correct and does no work.

Parameters:

  • element: Elementthe element to update
  • childNodes: NodeList|Array.the set of nodes to apply

applyClasses(element, classes) static method

Applies multiple classes at once. This takes a dictionary in which each name: value is equivalent to calling classList.toggle(name, value).

Parameters:

  • element: Elementthe element to update
  • classes: objecta dictionary of classes to apply

applyProperty(element, name, value) static method

Apply the indicated value to the element property with the given name.

If the value is plain JavaScript object, the value will be applied using the apply function. Otherwise, the indicated element property will be set directly to the indicated value.

Parameters:

  • element: Element
  • name: string
  • value: object

applyStyles(element, styles) static method

Sets multiple style values at once.

This takes a dictionary in which each name: value is equivalent to calling style[name] = value.

Parameters:

  • element: HTMLElement|SVGElementthe element to update
  • styles: objecta dictionary of styles to apply

current(element) static method

Returns a dictionary of the current attributes, classes, and styles of the indicated element.

The returned dictionary is in the same format as that supported by apply.

Parameters:

  • element: Elementthe element to examine

Returns: object a dictionary of the current attributes, classes, and styles

currentAttributes(element) static method

Returns a dictionary of the element's current attributes, using the same name: value format supported by applyAttributes.

Parameters:

  • element: Elementthe element to examine

Returns: object a dictionary of the element's current attributes

currentClasses(element) static method

Returns a dictionary of the element's current classes, using the same name: value format supported by applyClasses.

Parameters:

  • element: Elementthe element to examine

Returns: object a dictionary of the element's current classes

currentStyles(element) static method

Returns a dictionary of the element's current styles, using the same name: value format supported by applyStyles.

Parameters:

  • element: HTMLElement|SVGElementthe element to update

Returns: object a dictionary of the element's current styles

merge(sources) static method

Merge multiple sets of updates into a single update dictionary.

This is similar to Object.assign, but:

  • A new dictionary is always returned instead of merging into the first argument.
  • The merge is a deep instead of shallow.

Example:

merge(
  {
    attributes: { role: 'listbox' },
    classes: { foo: true, bar: true }
  },
  {
    classes: { foo: false, baz: true }
  }
);

returns

{
  attributes: { role: 'listbox' },
  classes: { foo: false, bar: true, baz: true }
}

Parameters:

  • sources: objecta set of zero or more update dictionaries to merge

Returns: object the merged updates