DOM Mode

DOM mode provides an output mode which generates DOM Elements from DOMBuilder.createElement() calls and DOM DocumentFragments from DOMBuilder.fragment() calls.

The DOM mode API is exposed through DOMBuilder.modes.dom.api.

Mode-specific element functions are exposed through DOMBuilder.dom.

DOMBuilder.dom

Element functions which will always create DOM Element output.

New in version 2.0.

Attributes

Some attributes are given special treatment based on their name.

Event Handlers

Event handlers can be specified by supplying an event name as one of the element’s attributes and an event handling function as the corresponding value. Any of the following events can be registered in this manner:

Event Names
blur focus focusin focusout load resize
scroll unload click dblclick mousedown mouseup
mousemove mouseover mouseout mouseenter mouseleave change
select submit keydown keypress keyup error

These correspond to events which have jQuery shortcut methods, which will be used for event handler registration if jQuery is available, otherwise legacy event registration will be used.

For example, the following will create a text input which displays a default value, clearing it when the input is focused and restoring the default if the input is left blank:

var defaultInput =
    el.INPUT({
        type: 'text', name: 'email'
      , value: 'email@host.com', defaultValue: 'email@host.com'
      , focus: function() {
          if (this.value == this.defaultValue) {
            this.value = ''
          }
        }
      , blur: function() {
          if (this.value == '') {
            this.value = this.defaultValue
          }
        }
      }
    )

Other ‘Special’ Attributes

Other attributes which trigger special handling or explicit compatibility handling between DOM and HTML modes.

innerHTML

If you specify an innerHTML attribute, the given String will be the sole source used to provide the element’s contents, even if you pass more contents in as arguments.

  • In DOM mode, the element’s innerHTML property will be set and no further children will be appended, even if given.
  • In HTML mode, the given HTML will be used, unescaped, as the element’s contents.

Document Fragments

A DOM DocumentFragment is a lightweight container for elements which allows you to append its entire contents with a single call to the destination element’s appendChild() method.

If you’re thinking of adding a wrapper <div> solely to be able to insert a number of sibling elements at the same time, a DocumentFragment will do the same job without the need for the redundant element. This single append functionality also makes it a handy container for content which needs to be inserted repeatedly, calling cloneNode(true) for each insertion.

DOMBuilder provides a DOMBuilder.fragment() wrapper function, which allows you to pass all the contents you want into a DocumentFragment in one call, and also allows you make use of this functionality in HTML mode by creating equivalent Mock DOM Objects as appropriate. This will allow you to, for example, unit test functionality you’ve written which makes use of DocumentFragment objects by using HTML mode to verify output against HTML strings, rather than against DOM trees.

See http://ejohn.org/blog/dom-documentfragments/ for more information about DocumentFragment objects.

Mapping Fragments

DOMBuilder.fragment.map(items, mappingFunction)

Creates a fragment wrapping content created for (potentially) every item in a list.

Arguments:
  • items (Array) – the list of items to use as the basis for creating fragment contents.
  • mappingFunction (Function) – a function to be called with each item in the list, to provide contents for the fragment.

The mapping function will be called with the following arguments:

mappingFunction(item, itemIndex)

The function can indicate that the given item shouldn’t generate any content for the fragment by returning null.

Contents created by the function can consist of a single value or a mixed Array.

This function is useful if you want to generate sibling content from a list of items without introducing redundant wrapper elements.

For example, with a newforms FormSet object, which contains multiple Form objects. If you wanted to generate a heading and a table for each form object and have the whole lot sitting side-by-side in the document:

var formFragment = DOMBuilder.fragment.map(formset.forms, function(form, loop) {
  return [
    H2('Widget ' + (loop.index + 1)),
    TABLE(TBODY(
      TR.map(form.boundFields(), function(field) {
        return [TH(field.labelTag()), TD(field.asWidget())]
      })
    ))
  ]
})

Appending formFragment would result in the equivalent of the following HTML:

<h2>Widget 1</h2>
<table> ... </table>
<h2>Widget 2</h2>
<table> ... </table>
<h2>Widget 3</h2>
<table> ... </table>
...