An opinionated, battle tested Backbone + Handlebars framework to build large scale web applications.
Open the |
Node + LumbarRun |
Run |
Run |
Download 2.0.0b5 | Download 2.0.0b5 | Download 2.0.0b5 | Download 2.0.0b5 |
Thorax 2 is presently in beta, the stable source and documentation are still available.
Thorax can be used standalone in any JavaScript environment in addition the boilerplate projects provided above.
var view = new Thorax.View({
greeting: "Hello",
template: "{{greeting}} world!"
});
view.render();
$("body").append(view.el);
Editable Examples | Resources |
---|---|
All of the examples use the same sample data. |
Thorax creates a special hash for each type of class to store all subclasses in your application. The use of Thorax.Views
and Thorax.templates
is required to allow the view
, template
and other helper methods to operate, but the use of the others are optional and provided for consitency.
Class | Registry |
---|---|
Thorax.View | Thorax.Views |
Thorax.Model | Thorax.Models |
Thorax.Collection | Thorax.Collections |
Thorax.Router | Thorax.Routers |
templates | Thorax.templates |
If a name
property is passed to any Thorax classes' extend
method the resulting class will be automatically set in the corresponding registry.
//set class
Thorax.View.extend({
name: "my-view"
});
//get class
Thorax.Views["my-view"]
A hash of templates, used by various Thorax helpers. If using the node or Rails boilerplate projects this hash will be automatically generated from the files in your templates
directories. To manually add a template to the hash:
Thorax.templates['my-template-name'] = Handlebars.compile('template string');
If a View
has the same name
as a template in the templates
hash, it's `template' property will be automatically assigned.
The base Thorax.View
implementation is concerned only with Handlebars + Backbone integration. A variety of additional functionality is provided by the various included plugins. The boilerplate projects have a build of Thorax with all plugins included.
Thorax.View
provides mostly additive functionality over Backbone.View
but breaks compatibility in one imporant way in that it does not use an options
object. All properties passed to the constructor become available on the instance:
var view = new Thorax.View({
key: "value"
});
view.key === "value"
A hash of child view's indexed by cid
. Child views may become attached to the parent with the view
helper or may be automatically attached HelperView
instanced created by helpers created with regsterViewHelper
.
If a view was embedded inside another with the view
helper, or is a HelperView
created by a helper creted with registerViewHelper
the view will have a parent
attribute.
Assign a template to a view. This may be a string or a function which recieves a single context
argument and returns a string. If the view has a name
and a template of the same name
is available the template
will be auto-assigned.
new Thorax.View({
template: "{{key}}"
});
By default this will only call destroy
on all child views. Other plugins override this method to implement custom cleanup behaviors. Your own behaviors can be added with the destroyed
event. Pass children: false
to this method to prevent the view's children from being destroyed.
Renders the view's template
updating the view's el
with the result, triggering the rendered
event. content
may be empty (render the template
) or a function that will be called with the response from context
or a string.
//will render template
view.render()
//will insert custom content
view.render('custom html')
Used by render
to determine what attributes are available in the view's template
. The default context function returns this
. If the model plugin is used, this
+ model.attributes
will be the context.
Render a template with the view's context
plus any optional extraContext
parameters passed in.
Ensure that the view has been rendered at least once.
Get or set the innerHTML
of the view, without triggering the rendered
event.
Embed the template
from the parent view within the child template.
{{super}}
Embed a template inside of another, as a string. An associated view (if any) will not be initialized. By default the template will be called with the current scope but extra options may be passed which will be added to the context.
{{template "path/to/template" key="value"}}
If a block is used, the template will have a variable named yield
available that will contain the contents of the block.
{{#template "child"}}
content in the block will be available in a variable
named "yield" inside the template "child"
{{/template}}
This is useful when a child template will be called from multiple different parents.
Embed one view in another. The first argument may be the name of a new view to initialize or a reference to a view that has already been initialized.
{{view "path/to/view" key="value"}}
{{view viewInstance}}
If a block is specified it will be assigned as the template
to the view instance:
{{#view viewInstance}}
viewInstance will have this block
set as it's template property
{{/view}}
Embed a DOM element in the view. This uses a placeholder technique to work, if the placeholder must be of a certain type in order to work (for instance a tbody
inside of a table
) specify a tag
option.
{{element domElement tag="tbody"}}
Note that this differs from Handlebars.registerHelper
. Registers a helper that will create and append a new HelperView
instance, with it's template
attribute set to the value of the captured block. callback
will recieve any arguments passed to the helper followed by a HelperView
instance. Named arguments to the helper will be present on options
attribute of the HelperView
instance.
A HelperView
instance differs from a regular view instance in that it has a parent
attribute which is always set to the declaring view, and a context
which always returns the value of the parent
's context method. The collection
, empty
and other built in block view helpers are created with registerViewHelper
.
A helper that re-rendered a HelperView
every time an event was triggered on the declaring view could be implemented as:
Handlebars.registerViewHelper('on', function(eventName, helperView) {
helperView.listenTo(helperView.parent, eventName, function() {
helperView.render();
});
});
An example use of this would be to have a counter that would incriment each time a button was clicked. In Handlebars:
{{#on "incrimented"}}{{i}}{/on}}
{{#button trigger="incrimented"}}Add{{/button}}
And the corresponding view class:
new Thorax.View({
events: {
incrimented: function() {
++this.i;
}
},
initialize: function() {
this.i = 0;
},
template: ...
});
In addition, if a view class is specified as the second argument to registerViewHelper
, the helper will always initialize a view of that class instead of a HelperView
:
Handlebars.registerViewHelper('collection',
Thorax.CollectionView, function(collection, view) {
});
Generate an HTML string. All built in HTML generation uses this method. If context
is passed any Handlebars references inside of the htmlAttributes values will rendered with the context.
Thorax.Util.tag("div", {
id: "div-{{number}}"
}, "content of the div", {
number: 3
});
Get a reference to the nearest parent view. Pass helper: false
to options to exclude HelperView
s from the lookup. $.model
and $.collection
will also be available if you include the model and collection plugins.
$(event.target).view()
Triggered when the destroy
method is called.
Triggered when the rendered
method is called.
Triggered every time a child view is inserted into the view with the view
helper. Will not be triggered from view instances created by helper view helpers.
Triggered when a view helper (such as collection
, empty
, etc) create a new HelperView
instance.
Triggered when a given view helper creates a new HelperView
instance.
{{#collection cats}}{{/collection}}
view.on('helper:collection', function(collection, collectionView) {
});
Thorax and it's view helpers generate a number of custom HTML attributes that may be useful in debugging or generating CSS selectors to be used as arguments to $
or to create CSS. The *-cid
attributes are generally used only internally. See $.model
, $.collection
and $.view
to get a reference to objects directly from the DOM. The *-name
attributes will only be present if the given objects have a name
property.
Attribute Name | Attached To |
---|---|
data-view-cid | Every view instances' el |
data-view-name | Same as above, only present on named views |
data-collection-cid | Element generated by the `collection helper` |
data-collection-name | Same as above, only present when the bound collection is named |
data-collection-empty | Set to "true" or "false" depending on wether the bound collection isEmpty |
data-model-cid | A view's el if a model was bound to the view or each item element inside of elements generated by the collection helper |
data-model-name | Same as above, only present if the model is named |
data-layout-cid | The element generated by the layout helper or el inside of a LayoutView or ViewController instance |
data-view-helper | Elements generated by various helpers including collection and empty from the collection plugin |
data-call-method | Elements generated by the link and button helpers |
data-trigger-event | Elements generated by the link and button helpers |
When creating CSS selectors it's recommended to use the generated attributes (especially data-view-name
) rather than assigning custom IDs or class names for the sole purpose of styling.
[data-view-name="my-view-name"] {
border: 1px solid #ccc;
}
To use the command line utilities:
npm install -g thorax
Build a custom version of Thorax using a list of any of the given plugins:
- mixin
- event
- model
- collection
- helpers
- form
- layout
- loading
- mobile
Not specifying any plugins will build a version with all plugins except mobile. To build a version of Thorax with all plugins including the mobile plugin run:
thorax build ./thorax-mobile.js --mobile
Not specifying any arguments will build both the mobile and regular versions of Thorax in the dist
directory of the npm package:
thorax build
If using Thorax outside of the provided node or Rails downloads you can inline a directory of templates into a single file by running the thorax templates
command.
npm install -g thorax
thorax templates ./templates-dir ./templates.js
Bound DOM event handlers in Thorax are wrapped with a try / catch block, calling this function if an error is caught. This hook is provided primarily to allow for easier debugging in Android environments where it is difficult to determine the source of the error. The default error handler is simply:
function(name, error) {
throw error;
}
Override this function with your own logging / debugging handler. name
will be the event name where the error was thrown.