The browser module are unobtrusive widgets that "weave in" behaviors on DOM elements, typically reflecting the "V" layer in MVC. Widget delegates all interactions with the underlay DOM element, interfacing by hub topics and DOM events. Since widget is ultra lightweight and open-ended thus can easily embrace any data binding or rendering implementation.
TroopJS widgets are kind of components created by dom.component.widget
that is attached to a single DOM element and is to destroy along with the removal of the DOM element. A jQuery DOM element is referenced by it's $element
property,
In addition to having a special constructor, DOM widget also specialized in delegating all DOM events with the "dom" specials, or subscribes to hub topics with the "hub" special, through both ways components can communicate with each one, while depending on different usage scenarios using "dom" or "hub" could be different:
The "dom" special signature takes the form of dom:selector/type
, where selector is an optional CSS selector that matches the target element and type
is just the event type, equivalent to this jQuery event delegation
call -
this.$element.on('type', 'selector', handler)
. The following exemplify a simple widget that facilitates both DOM and hub events:
Imperatively draw the relationship between component and DOM element is obviously not the best, which leads to highly coupled code with HTML structure, and can easily becomes a maintenance hell.
Weave in terms of TroopJS is defined as the process of instantiating a widget component, starting it's life-circle and to associate with an DOM element, TroopJS inverse the control by declaratively map between the component
module and associate DOM element via a custom HTML attribute data-weave
, this is coincident with the Web component concept where internal presentation and behaviors of the HTML element is completely transparent to outside of
the element and can be altered with ease.
declarative weave widgets are created through a custom HTML attribute data-weave
on any element, where the attribute value is string that points to one or more widget's module id. The following HTML code declares a simple widget
to weave:
Then it's the containing element of the above HTML, that is responsible for weaving in the widgets as soon as:
By only declaring the widget DOM it's not get instantiated yet, also it's always up to your decision on when to actually start weaving them, there exists a few options for you to kick off weaving:
You can weave by just calling the dom/loom/weave
function, passing the jQuery object as argument:
Alternatively TroopJS extends all loom methods as jQuery plugins, it is straight forward to weave all elements of a jQuery object by simply calling $.fn.weave()
:
Eventually if you're lazy and don't want to be bothered by weaving manually, TroopJS proxies the following jQuery DOM manipulation methods on widget scope so whenever you call them TroopJS weaves all the descendants DOM elements afterward:
The proxy methods, instead of returning a jQuery chain-able, will instead return a promise that is to be resolved with all woven widgets:
Not only a single widget can be weaved on an element, multiple widgets could be sharing the same element, implements different features that eventually composed as layers. The following example that weaves two widgets that plays the submit and validation behaviors correspondingly on an element:
A DOM widget is considered to be stopped, either because it's underlay element has been removed from the DOM tree, or because you have intentionally called {@link browser.component.widget#unweave} as $('#foo').unweave();
so
it
unweaved living widgets that are found on this element, which will basically cleanup everything before detaching it from the DOM element (include data attributes and DOM listeners), if the widget has no other references it
will be garbage-collected.
When you unweave, in case you don't always have to unweave all living ones on the element, there's also data-unweave
attribute that TroopJS will check beforehand to selectively unweave only a certain widgets, e.g. the following code remove only the "validation" widget on element while remains the form submitting widget functional.
There must have to be some bootstrapping code that actually call weave
for DOM elements always, TroopJS constructs a special widget dom/application/widget
for this role - the only guaranteed singular application container
per page, which takes care of:
Other than regular widget that receives the DOM element as first argument, which could be either body
, html
or any root element that makes sense for your app, the application constructor should relieve a list of components
instances in starting order, application will start them in sequence and then to weave all widgets found in DOM tree descendants.
Find an error? Let us know →