backbone-dom-view
=================
Better View class for Backbone
Main idea of this view class is in configuration template object which looks like this
```javascript
var View = Backbone.DOMView.extend({
template: {
"jquery-selector": {
"helper-name": {
"first-option": "value",
"second-option": {
"model-event #view-event": function () {
//..
}
}
}
}
}
});
```
`DOMView` class is extended from base `Backbone.View` class.
For example view for Todo model
```javascript
var TodoView = Backbone.DOMView.extend({
template: {
".title": {
text: "@title"
},
".state": {
'class': {
"done": "@is_done",
"selected": {
"change:selected": function () {
return this.model.get('selected');
}
}
}
}
}
});
```
Which means:
* Change `.title` text to model's `title` field value and listen `change:title` for future changes
* Add to `.state` class `done` when model's `is_done` field will be equal truthy value
* Add to `.state` class `selected` when model will trigger `change:selected` event and callback will return truthy value
## Installation
Bower:
`bower install backbone-dom-view`
**AMD ready**
## Properties
### ui:
Used to create alias of jQuery selectors. Instead of calling dozen times `this.$('.title')` you can use `this.ui.title`, so if you need to change selector in extended classs, you will change it only in one place. As value of `ui:` you can use `Object` or `Function` (which should return an object). Also you can use this alias in `template:` instead of selectors. When you extend views, `ui:` field will be merged with all parents prototypes.
You can use names of aliases in other aliases selector.
```javascript
Backbone.DOMView.extend({
ui: {
title: 'input.title',
edit: '{title} ~ .edit'
},
template: {
'title': {
'class': {
'error': {
'validate': function () {
return this.ui.title.val() === '';
}
}
}
},
'edit': {
prop: {
'value': '@title'
}
}
}
});
```
By default `ui:` has one alias `root` which is alias to `this.$el`.
### template:
Hash where keys are jQuery selectors or `ui` fields names or both of them but then you need put `ui` names in curly brackets. Values of `template:` fields are hashes of [helpers](https://github.com/redexp/backbone-dom-view/blob/master/#helpers) names. When you extend views, `template:` field will be merged with all parent `template` fields. Merged result will written as own `view.template` property and will be available in `initialize` function before processing template, so you can do last modification to it. When `template` will be prepared, will be triggered [template-ready](https://github.com/redexp/backbone-dom-view/blob/master/#template-ready) event.
```javascript
Backbone.DOMView.extend({
ui: {
name: 'input'
},
initialize: function () {
if (this.model.get('disabled')) {
delete this.template.root['class'].selected;
}
},
template: {
'root': {
'class': {
'selected': '@selected'
}
},
'name': {
'prop': {
'value': '@name'
}
},
'{name} + label': {
'text': '@name'
}
}
});
```
As value of `template:` you can use `Object` or `Function` (which should return an object). Function will get utility `extendDeep` as first argument
```javascript
Backbone.DOMView.extend({
template: function (extendDeep) {
var tpl = {
'root': {
'class': {
'selected': '@selected'
}
}
};
this.$('input').each(function (i, inp) {
var selector = 'input[name=' + inp.name + ']';
tpl[selector] = {
prop: {
'value': '@' + inp.name
}
};
});
return tpl;
}
});
```
### defaults:
Same as `Backbone.Model::defaults` option, see [get, set, has](https://github.com/redexp/backbone-dom-view/blob/master/#get-set-has) in [Methods](https://github.com/redexp/backbone-dom-view/blob/master/#methods) section.
### .callbacks
I'v added this property because it useful to return control from view back to your controller. You can pass callbacks with options when you create new instance or just add functions by your self and save one indentation
```javascript
var View = Backbone.DOMView.extend({
initialize: function () {
this.listenElement(this.find('button'), 'click', function () {
this.callbacks.onSomeAction();
});
}
});
```
```javascript
var view = new View({
el: '#test',
onSomeAction: function () {
// ...
}
});
view.callbacks.onSomeAction //> function
```
```javascript
var view = new View({
el: '#test'
});
view.callbacks.onSomeAction = function () {
// ...
};
```
### .parent
[each](https://github.com/redexp/backbone-dom-view/blob/master/#each) helper will add to children views field `parent` which will be link to current view.
## Methods
* [get, set, has](https://github.com/redexp/backbone-dom-view/blob/master/#get-set-has)
* [matches](https://github.com/redexp/backbone-dom-view/blob/master/#matches)
* [find](https://github.com/redexp/backbone-dom-view/blob/master/#find)
* [bind](https://github.com/redexp/backbone-dom-view/blob/master/#bind)
* [bindTo](https://github.com/redexp/backbone-dom-view/blob/master/#bindTo)
* [listenElement](https://github.com/redexp/backbone-dom-view/blob/master/#listenelementelement-event-callback)
* [listenElementOnce](https://github.com/redexp/backbone-dom-view/blob/master/#listenelementonce)
* [stopListeningElement](https://github.com/redexp/backbone-dom-view/blob/master/#stoplisteningelement)
### get, set, has
`DOMView` can listen model attributes, but many times you will need extra attributes to store current state of view like `selected` or `editing`, so for this purpose view inherited `get`, `set` and `has` methods from `Backbone.Model`.
```javascript
Backbone.DOMView.extend({
defaults: {
error: false,
message: ''
},
initialize: function () {
this.listenTo(this.model, 'invalid', function (error) {
this.set({
'error': true,
'message': error
});
});
},
template: {
'root': {
'class': {
'error': '@error'
}
},
'.message': {
text: '@message'
}
}
});
```
### find()
Same as view's `.$(selector)` but it can accept empty value to return `.$el` it self or `ui:` property name or selector with `ui:` property name in curly brackets. This method was created for `template:` selectors.
```javascript
Backbone.DOMView.extend({
el: '