Dom

Frontbx's Dom Component is used throughout the library to manage interactions with the live DOM.



Access

Frontbx's Dom Component can be accessed globally via the Inversion container through the dom key.

const dom = frontbx.Dom();

Components

Frontbx uses a specific design pattern for DOM components. In Frontbx a DOM component is a JavaScript Class or Object Function that when "mounted" binds listeners or alters the Live DOM. Frontbx uses a base Component base that is extended to help build Components easily.

Lifecycle

When Frontbx first loads, it caches all DOM Components in it's container until it's ready to boot. Once ready, it loops through all DOM Components, instantiates an instance of each once, which triggers them to bind any listeners or alter the live DOM.

Once the Frontbx's DOM has loaded, if the Live DOM is altered, mutated or updated in any way Frontbx's Dom can be "refreshed", which removes any redundant listeners on nodes that were removed and checks for any new elements that need binding.

Usage

The base Component can be retrieved via the container:

const Component = frontbx.Component(frontbx.IMPORT_AS_REF);

In an extended component's constructor, this.super method should be called with a selector string, which constructs the base Component and queries any DOM selectors to this._DOMElements;

const Buttons = function()
{
    this.super('.js-special-btns');

    // "this._DOMElements" now contains all ".js-special-btns" nodes
    console.log(this._DOMElements);
};

Once this.super has been called and the Component has been constructed, the Component will loop through each node and call bind on the component

Buttons.prototype.bind = function(node)
{
    frontbx._().on(node, 'click', this._handler, this);
}

If Frontbx's Dom gets refreshed or the module gets refreshed specifically, unbind will be called with each DOM element:

Buttons.prototype.unbind = function(node)
{
    frontbx._().off(node, 'click', this._handler, this);
}

Dom components must contain a bind and unbind method which gets called by the base Component whenever Frontbx's Dom is refreshed.

To register a Component in the Frontbx Dom use the register method:

dom.register('Buttons', Buttons);

Refreshing a Component can be used whenever the Live DOM is altered and you want to to re-bind Components. For example, when inserting content that contains HTML Components into the Live DOM.

To refresh a Component call the refresh method. Refreshing a component will call the unbind method on each this._DOMElements node of the Component. Once completed, the Component will re-select all nodes with the original selector to re-populate this._DOMElements and call bind on each element.

The design pattern is intended to increase browser performance by ensuring deprecated event listeners are removed correctly.

dom.refresh('Buttons');

You can also refresh a Component to a specific context or element in the Live DOM:

dom.refresh('Buttons', document.querySelector('.wrapper'));

Or refresh all Dom Components:

dom.refresh();

Or refresh all Dom Components to a context element:

dom.refresh(document.querySelector('.wrapper'));

Below is a simple example of a complete Dom Component that console logs click events on buttons:

const Component = frontbx.Component(frontbx.IMPORT_AS_REF);

const [on, off, extend] = frontbx.import(['on','off','extend']).from('_');

const Buttons = function()
{
    this.super('button');

    // "this._DOMElements" now contains all "<button>" nodes
    console.log(this._DOMElements);
}

Buttons.prototype.bind = function(node)
{
    on('click', this._handler, this);
}

Buttons.prototype.unbind = function(node)
{
    off('click', this._handler, this);
}

Buttons.prototype._handler = function(e, node)
{
    console.log(this);

    console.log(e, node);
}

frontbx.Dom().register('Buttons', extend(Component, Buttons));

Instantiation

By default, Frontbx DOM Components are instantiated by HTML. However most Components offer JavaScript Instantiation to generate content dynamically.

JavaScript Components can be instantiated either directly via the Component, or via Frontbx's Dom with Component.create and will always return a DOMElement node.

let dropdown = frontbx.Dom().component('Dropdown').create(options);

document.querySelector('div').appendChild(dropdown);
let dropdown = frontbx.Dom().create('Dropdown', options);

document.querySelector('div').appendChild(dropdown);

Adding a second paramter to Component.create will append the returned DOMElement node to the target element

frontbx.Dom().create('Dropdown', options, document.querySelector('.div'));

Dynamic Content

When creating your own component, if you want a Component use Component.create use the template method to return a DOM element. The method will receive an object of passed properties merged with this.defaultProps on the Component.

const Component = frontbx.Component(frontbx.IMPORT_AS_REF);

const [dom_element] = frontbx.import(['dom_element']).from('_');

const Buttons = function()
{
    this.super();

    this.defaultProps = {
        class: 'btn btn-primary',
        text: 'Hello world!'
    }
}

Buttons.prototype.template = function(props)
{
    return dom_element({tag: 'button', class: props.class, innerText: props.text});
}

frontbx.Dom().register('Buttons', extend(Component, Buttons));

const button = frontbx.Dom().create('Buttons', {text: 'Click me!'});

Events

Frontbx will dispatch various events when DOM components are interacted with or the Live DOM is updated. All Frontbx events contain their data in event.detail.

Event Target element Properties Description
Frontbx:dom:ready window e.detail.dom Fired immediately after Frontbx Dom has booted and all Components are loaded.
Frontbx:dom:refresh window e.detail.context Fired immediately after Frontbx Dom has been refreshed and all Components are re-bound
Frontbx:dom:mutate DOMElement e.detail.DOMElement Fired immediately after content on live DOMElement node is mutated
Frontbx:dom:remove DOMElement e.detail.DOMElement Fired immediately after live DOMElement node is removed from the DOM
Frontbx:dom:bind:Component window e.detail.component e.detail.context Fired immediately after a Dom Component is bound
Frontbx:dom:unbind:Component window e.detail.component e.detail.context Fired immediately after a Dom Component is unbound
Frontbx:dom:refresh:Component window e.detail.component e.detail.context Fired immediately after a Dom Component is refreshed