raptor-widgets
The raptor-widgets
module provides a simple and efficient mechanism for binding behavior to UI components rendered on either the server or in the browser. This module also supports inter-widget communication and provides a simple framework that encourages best practices and makes it easy to "wire up" complex applications. Out of the box, bindings are provided for Raptor Templates and Dust. There is no complex widget class hierarchy or complex API and you are free to use jQuery or any other library for working with the DOM.
Table of Contents generated with DocToc
- Installation
- Glossary
- Usage
- API
- Widget
- Methods
- $(querySelector)
- addEventListener(eventType, listener)
- appendTo(targetEl)
- destroy()
- detach()
- emit(eventType, arg1, arg2, ...)
- getEl(widgetElId)
- getElId(widgetElId)
- insertAfter(targetEl)
- insertBefore(targetEl)
- isDestroyed()
- on(eventType, listener)
- prependTo(targetEl)
- ready(callback)
- replace(targetEl)
- replaceChildrenOf(targetEl)
- rerender(data, callback)
- subscribeTo(target)
- Properties
- Methods
- WidgetCollection
- Widget
Installation
npm install raptor-widgets --save
Glossary
A few definitions before you get started:
- A "widget" is the "client-side behavior" of a UI component
- A widget instance has the following characteristics
- All widget instances are bound to a DOM element
- All widgets are event emitters
- Client-side behavior includes the following:
- Attaching DOM event listeners (mouse click, keyboard press, etc.)
- Attaching listeners to other widgets
- Manipulating the DOM
- Publishing client-side events
- etc.
Usage
Binding Behavior
Using the bindings for Raptor Templates, you can bind a widget to a rendered DOM element using the custom w-bind
attribute as shown in the following sample template:
Click Me
The widget bound to the <div>
should then be implemented as a CommonJS module that exports a constructor function. During client-side initialization, a new instance of your widget will be created for each rendered DOM element that the widget is bound to. A sample widget implementation is shown in the following JavaScript code:
src/pages/index/widget.js:
{ var rootEl = thisel; // this.el returns the root element that the widget is bound to var self = this; rootEl;} Widgetprototype = { thisel; }; moduleexports = Widget;
In order for everything to work on the client-side we need to include the code for the raptor-widgets
module and the ./widget.js
module as part of the client bundle and we also need to use the custom <w-init-widgets>
tag to let the client know which widgets rendered on the server need to be initialized on the client. To include the client-side dependencies will be using the raptor-optimizer module and the taglib that it provides. Our final page template is shown below:
src/pages/index/template.rhtml:
Widgets Demo <!-- Bind a widget to a div element using the "w-bind" attribute --> Click Me
The optimizer.json
that includes the required client-side code is shown below:
src/pages/index/optimizer.json:
"dependencies": "require raptor-widgets" "require ./widget"
In the above example, the final HTML will be similar to the following:
Widgets Demo Click Me
▶️ To try out and experiment with this code please see the documentation and source code for the widgets-bind-behavior sample app.
Referencing Widgets
The raptor-widgets
taglib also provides support for allowing a widget to communicate directly with nested widgets. A nested widget can be assigned a widget ID (only needs to be unique within the scope of the containing widget) and the containing widget can then reference the nested widget by the assigned widget ID using the this.widgets
collection.
The following HTML template fragment contains a widget that has three nested sample-button widgets. Each nested sample-button is assigned an ID (i.e. primaryButton
, successButton
and dangerButton
).
...
The containing widget can then refer to a particular nested widget as shown in the following sample JavaScript code:
thiswidgetsdangerButton;
▶️ To try out and experiment with this code please see the documentation and source code for the widgets-communication sample app.
Referencing Widget DOM Elements
DOM elements nested within a widget can be given unique IDs based on the containing widget's ID. These DOM elements can then be efficiently looked up by the containing widget using methods provided. The w-el-id
custom attribute can be used to assign DOM element IDs to HTML elements that are prefixed with the widget's ID. For example, given the following HTML template fragment:
... Submit Cancel
Assuming the unique ID assigned to the widget is w123
, the following would be the HTML output:
... Submit Cancel
Finally, to reference a widget's nested DOM element's the following code can be used in the containing widget:
var submitButton = this; // submitButton.id === 'w123-submitButton'var cancelButton = this; // cancelButton.id === 'w123-cancelButton' submitButtonstyleborder = '1px solid red';
The object returned by this.getEl()
will be a raw HTML element. If you want a jQuery wrapped element you can do either of the following:
Option 1) Use jQuery directly:
var $submitButton = ;
Option 2) Use the this.$()
method:
var $submitButton = this;
Rendering Widgets in the Browser
TODO
API
Widget
Methods
$(querySelector)
This is a convenience method for accessing a widget's DOM elements when jQuery is available. This mixin method serves as a proxy to jQuery to ease building queries based on widget element IDs.
Internally, this jQuery proxy method will resolve widget element IDs to their actual DOM element ID by prefixing widget element IDs with the widget ID. For example, where this is a widget with an ID of w123
:
this ➡ this ➡
The usage of this mixin method is described below:
$()
Convenience usage to access the root widget DOM element wrapped as a jQuery object. All of the following are equivalent:
this
$('#<widget-el-id>')
Convenience usage to access a nested widget DOM element wrapped as a jQuery object. All of the following are equivalent:
this
$('<selector>')
Convenience usage to query nested DOM elements scoped to the root widget DOM element. All of the following are equivalent:
this
$('<selector>', '<widget-el-id>')
Convenience usage to query nested DOM elements scoped to a nested widget DOM element. All of the following are equivalent:
thisthis
$('#<widget-el-id> <selector>')
Convenience usage to query nested DOM elements scoped to a nested widget DOM element. All of the following are equivalent:
thisthis
$(callbackFunction)
Convenience usage to add a listener for the "on DOM ready" event and have the this object for the provided callback function be the current widget instance. All of the following are equivalent:
this;; // Using Function.prototype.bind;
addEventListener(eventType, listener)
appendTo(targetEl)
Moves the widget's root DOM node from the current parent element to a new parent element. For example:
this;
destroy()
Destroys the widget by unsubscribing from all listeners made using the subscribeTo
method and then detaching the widget's root element from the DOM. All nested widgets (discovered by querying the DOM) are also destroyed.
detach()
Detaches the widget's root element from the DOM by removing the node from its parent node.
emit(eventType, arg1, arg2, ...)
Emits an event. This method is inherited from EventEmitter (see Node.js Events: EventsEmitter
getEl(widgetElId)
Returns a nested DOM element by prefixing the provided widgetElId
with the widget's ID. For Raptor Templates, nested DOM elements should be assigned an ID using the w-el-id
custom attribute. Returns this.el
if no widgetElId
is provided.
getElId(widgetElId)
Similar to getEl
, but only returns the String ID of the DOM element instead of the actual DOM element.
insertAfter(targetEl)
insertBefore(targetEl)
isDestroyed()
on(eventType, listener)
prependTo(targetEl)
ready(callback)
replace(targetEl)
replaceChildrenOf(targetEl)
rerender(data, callback)
subscribeTo(target)
Properties
this.el
The root HTML element that the widget is bound to.
this.id
The String ID of the root HTML element that the widget is bound to.
this.widgets
An instance of WidgetCollection
(see below) that holds references to all nested widgets with an assigned widget ID (e.g., but using the w-id
custom attribute). For example:
var submitButton = thiswidgetssubmitButton;