app.js | |
|---|---|
FinancesFinances is a small, proof-of-concept application to show off some of the cool functionality that Backbone.js can provide. The code is freely distributable under the terms of the BSD license. | (function($) { |
| the classic jQuery | $(function() { |
Models | |
| The
This will be automatically serialized to a JSON object when saving the object to the database, so bear that in mind. | var Entry = Backbone.Model.extend({
initialize: function() { |
| In addition to our model's | var d = new Date(this.get('date'));
var dateString = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
this.set({
humanDate: dateString
});
}
}); |
Views | |
|
| var AppView = Backbone.View.extend({ |
| The pre-existing DOM element to which we'll bind. | el: $('#app'),
events: {
'click #submit-button': 'submit'
}, |
|
| initialize: function() { |
|
| _.bindAll(this, 'addAll', 'addOne', 'render'); |
| Create an instance of the | this.entries = new EntryList;
this.entries.bind('add', this.addOne);
this.entries.bind('refresh', this.addAll);
this.entries.bind('all', this.render); |
| Ask the database (server, localStorage or otherwise) for entries | this.entries.fetch(); |
| Store references to some important DOM elements. Note that the
| this.description = this.$('#entry-form .desc input');
this.amount = this.$('#entry-form .amount input');
},
addAll: function() {
this.entries.each(this.addOne);
},
addOne: function(entry) { |
| Given a model object from the database, create its view, render the view and and add it to the DOM. | var view = new EntryView({model: entry});
this.$('#entries').append(view.render().el);
},
render: function() { |
| The | var total = this.entries.getTotal();
this.$('#total .amount').html('$ ' + total);
},
submit: function() { |
|
| this.entries.create({
description: this.description.val(),
amount: parseFloat(this.amount.val(), 10),
date: new Date
}); |
| Clear the form | this.description.val('');
this.amount.val('');
}
}); |
|
| var EntryView = Backbone.View.extend({ |
| Underscore.js template. The template is present in the DOM on page load, so we look it up and store its contents in memory. | template: _.template($('#entry-template').html()), |
| Here we define all the events and their handlers that this piece of UI understands. | events: {
'click input.delete': 'deleteEntry',
'focus span.amount': 'amountFocus',
'blur span.amount': 'amountBlur',
'focus span.desc': 'descFocus',
'blur span.desc': 'descBlur'
}, |
| Constructor function. Again, we bind the correct | initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.view = this;
}, |
| Delete entry from both UI and from the database. | deleteEntry: function() {
this.model.destroy();
this.remove();
}, |
| Rendering is done via Underscore.js templating. The model is converted
to JSON and passed as context to the templating function. We return
| render: function() {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}, |
| the | amountFocus: function() {
this.amountBefore = this.$('span.amount').text();
},
amountBlur: function() {
var now = this.$('span.amount').text();
if (this.amountBefore != now) {
now = parseFloat(now, 10);
this.model.set({amount: now});
this.model.save();
}
},
descFocus: function() {
this.descBefore = this.$('span.desc').text();
},
descBlur: function() {
var now = this.$('span.desc').text();
if (this.descBefore != now) {
this.model.set({
description: now
});
this.model.save();
}
}
}); |
Collections | |
| The | var EntryList = Backbone.Collection.extend({
model: Entry,
localStorage: new Store('finances'),
getTotal: function() { |
| Here we loop through all the entries in the collection and add all the amounts together to produce a total. | var t = 0;
this.each(function(item) {
t += item.get('amount');
}); |
| And round it to 2 decimals. | return Math.round(t*100) / 100;
}
}); |
Start the engines | var app = new AppView;
});
})(jQuery);
|