Skip to content

Instantly share code, notes, and snippets.

@Qard
Created January 24, 2012 08:06
Show Gist options
  • Save Qard/1668781 to your computer and use it in GitHub Desktop.
Save Qard/1668781 to your computer and use it in GitHub Desktop.
Behaviour abstraction system for backbone.js
!function (Backbone) {
// Store blank stuff here
var blankEl = $()
, blankModel = new Backbone.Model.extend()
, blankCollection = new Backbone.Collection.extend({
model: blankModel
})
, blankView = new Backbone.View.extend({
el: blankEl
})
// Construct behaviour manager
Backbone.Behaviour = function (options) {
// Store options
if (this.options) {
options = _.extend({}, this.options, options)
}
this.options = options
// Attach model
this.model = options.model || blankModel
this.collection = options.collection || blankCollection
// Prepare view
var view = options.view || blankView
view.model = this.model
view.render && view.render()
// Attach view
this.view = view
// Finally, initialize
this.initialize.apply(this, arguments)
}
// Just copy an existing extender
Backbone.Behaviour.extend = Backbone.Model.extend
}(window.Backbone || {})
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js"></script>
<script type="text/javascript" src="./backbone.behaviour.js"></script>
<script type="text/javascript">
$(function () {
// Empty model
var Model = Backbone.Model.extend({ })
// Fairly standard view, other than serialize.
// Renders model state to an underscore template.
var View = Backbone.View.extend({
template: _.template($('#form-template').text()),
render: function () {
this.el.html(this.template(this.model.attributes))
},
// Serialize form data and convert
// it to a usable property list.
serialize: function () {
var a = this.el.find('form').serializeArray()
return _.reduce(a, function (m, v) {
m[v.name] = v.value
return m
}, {})
}
})
// Here's the neat stuff; defining behaviours.
// How does the model react and how does the view react?
// JQuery.delegate is very handy for live view events.
var LiveForm = Backbone.Behaviour.extend({
initialize: function () {
var self = this
// Listen for change events on existing or future elements.
this.view.el.delegate('input,textarea,select', 'keyup', function () {
self.model.set(self.view.serialize())
})
// Bind will attempt to bind on model.
// Will fail silently if no model supplied.
this.model.bind('change', function (model) {
data = model.toJSON()
_(data).each(function (val, key) {
self.view.el.find('[name='+key+']').val(val)
})
})
}
})
// Just some dummy data
var data = {
foo: 'bar',
text: 'Some text',
seconds: 0
}
// Expose stuff
window.App = {}
App.model = new Model(data)
App.view = new View({ el: $('#container') })
App.liveform = new LiveForm(App)
// Increment seconds value
setInterval(function () {
data.seconds++
data.seconds > 20 && (data.seconds = 0)
App.model.set(data)
}, 1000)
})
</script>
<!-- Underscore form template -->
<script type="text/template" id="form-template">
<form>
<label>Foo:
<input type="text" name="foo" value="<%= foo %>" />
</label>
<label>Text:
<textarea name="text"><%= text %></textarea>
</label>
<label>Seconds:
<select name="seconds">
<% _.each(_.range(20), function (i) { %>
<option value="<%= i %>"<% i === seconds ? ' selected="selected"' : ''; %>><%= i %></option>
<% }); %>
</select>
</label>
</form>
</script>
<style type="text/css">
html, body { font-family: Helvetica; }
#container { width: 400px; }
label, input, textarea, select { width: 100%; }
label { display: block; margin: 20px 10px; }
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment