Backbone Todos
by Matt McCray
HTML
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<h1>Todo List</h1>
<form>
<input type="text" placeholder="Task name">
<input type="submit" value="Add Task">
</form>
<section id="tasks">
Loading...
</section>
<footer>By M@ McCray</footer>
CSS
body {
font-family: helvetica, arial, sans-serif;
font-size: 14px;
}
h1 {
font-size: 150%;
}
#tasks {
border: 1px solid #777;
margin: 10px 0px;
}
.task {
padding: 4px 10px;
position: relative;
}
.task:nth-child(even) {
background-color: #F0F0F0;
}
.task.complete {
opacity: 0.7;
}
.task.complete a {
color: #777;
}
.task input {
}
.task a {
padding: 0px 10px;
color:blue;
}
.task span {
color: maroon;
cursor: pointer;
position: absolute;
right: 10px;
}
.task span:hover {
color: red;
}
footer {
color: silver;
padding: 10px;
text-align: center;
}
JavaScript
// Views
var TaskView = Backbone.View.extend({
tagName: 'div',
className: 'task',
events: {
'change input': 'toggleComplete',
'click span': 'confirmDelete',
'click a': 'editName'
},
initialize: function() {
_.bindAll(this, 'render');
if(this.model) {
this.render();
this.model.bind('change', this.render);
}
},
render: function() {
$(this.el).html(_(TaskView.SRC).template( this.model.toJSON() ));
this.handleEvents();
if( this.model.get('complete') ) $(this.el).addClass('complete');
return this;
},
toggleComplete: function() {
var cb = $(this.el).find('input').get(0);
this.model.set({ complete:cb.checked });
this.model.save();
if(cb.checked) $(this.el).addClass('complete');
else $(this.el).removeClass('complete');
},
confirmDelete: function() {
if(confirm("This will permanently delete the task:\n\n - "+ this.model.get('name')+"\n\nIs that OK?" )) {
this.model.destroy();
}
},
editName: function() {
var newName = prompt("Edit task name:", this.model.get('name'));
if( newName != null && newName != "" ) {
this.model.set({ name:newName });
this.model.save();
}
}
});
// HTML source
TaskView.SRC = '\
<input type="checkbox" <% if(typeof complete != "undefined" && complete == true) { %>checked<% } %>/>\
<a href="#"><%= name %></a>\
<span> X </span>\
';
// Models
var Task = Backbone.Model.extend({
toJSON: function() {
return _({}).extend(_(this.attributes).clone(), { id:this.id });
}
});
var TaskCollection = Backbone.Collection.extend({
model: Task
});
window.taskCollection = new TaskCollection();
// Events
// Create a Task when the form is submitted
$('form').bind('submit', function(){
var fld = $(this).find('input[type=text]'),
value = fld.val();
if(value != null && value != "") {
taskCollection.create({ name:value, complete:false });
}
fld.val("");
return false;
});
//...