Backbone Todo
Make backbone todo
by erick
HTML
<script src="http://documentcloud.github.com/underscore/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="https://raw.github.com/amccloud/backbone-bindings/master/backbone-bindings.js"></script>
<script src="https://github.com/jeromegn/Backbone.localStorage/raw/master/backbone.localStorage-min.js"></script>
<div id="todo">
<input id="create-todo" type="text" placeholder="What do you have todo?">
<script id="todo-view" type="text/template">
<div class="controls">
<span class="grip" title="Drag to prioritize">— — —</span>
<input name="completed" type="checkbox" title="Mark completed">
</div>
<div class="title"><input name="title" type="text" title="Click to edit"></div>
<button class="remove" title="Remove todo">x</button>
</script>
</div>
CSS
* {
font-size: 14px;
margin: 0px;
padding: 0px;
outline: none;
}
body {
background: #222;
font-family: Helvetica, arial;
}
div#todo {
overflow: hidden;
}
div#todo input#create-todo {
background: #000;
border: none;
padding: 10px;
width: 100%;
}
div#todo input#create-todo:focus {
color: #fff;
}
div#todo ul.todo-list {
list-style: none;
padding: 0px;
}
div#todo ul.todo-list li {
background: #fff;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid rgba(255, 255, 255, 0.2);
cursor: move;
height: 37px;
zoom: 1;
}
div#todo ul.todo-list li:after {
display: block;
visibility: hidden;
height: 0;
clear: both;
content: ".";
}
div#todo ul.todo-list li input[name="completed"] {
margin-left: 10px;
}
div#todo ul.todo-list li input[name="title"] {
background: none;
border: none;
font-weight: bold;
float: left;
margin: 10px 0px 10px 5px;
width: 100%;
}
div#todo ul.todo-list li button.remove {
background: #000;
border: none;
color: #fff;
cursor: pointer;
font-weight: bold;
float: right;
height: 39px;
padding: 0px 20px 0px 10px;
position: relative;
top: -1px;
visibility: hidden;
}
div#todo ul.todo-list li button.remove:hover {
color: #f00;
}
div#todo ul.todo-list li div.controls {
float: left;
padding: 10px 0px;
}
div#todo ul.todo-list li span.grip {
color: rgba(0, 0, 0, 0.3);
display: inline-block;
font-weight: bold;
line-height: 4px;
margin-left: 5px;
width: 10px;
}
div#todo ul.todo-list li div.title {
padding: 0px 45px;
}
div#todo ul.todo-list li:hover button.remove {
visibility: visible;
}
div#todo ul.todo-list li:hover span.grip {
color: #000;
}
div#todo ul.todo-list li.ui-sortable-helper {
border-top: 1px solid rgba(0, 0, 0, 0.3);
}
div#todo ul.todo-list li.ui-sortable-helper button.remove {
visibility: hidden;
}
div#todo ul.todo-list li.completed input[name="title"] {
color: rgba(0, 0, 0, 0.4);
text-decoration: line-through;
}
div#todo...
JavaScript
var completedClassTransformer = function(value) {
return (value) ? 'completed' : 'todo';
};
var priorityTransformer = function(value) {
return 'hsl(' + (value * 5) + ', 95%, 55%)';
};
var Todo = Backbone.Model.extend({
defaults: {
title: "",
position: 0,
complete: false
},
validate: function(attrs) {
if (!attrs.title || attrs.title === "")
return "error";
}
});
var Todos = Backbone.Collection.extend({
localStorage: new Backbone.LocalStorage('Todos'),
model: Todo,
comparator: function(todo) {
return -todo.get('position');
}
});
var TodoView = Backbone.View.extend({
tagName: 'li',
bindings: {
'data-id': 'id',
'class': ['completed', completedClassTransformer],
'checked input[name="completed"]': 'completed',
'readonly input[name="title"]': 'completed',
'value input[name="title"]': 'title',
'background-color': ['position', priorityTransformer]
},
events: {
'click button.remove': 'remove',
'keydown input[name="title"]': 'saveOnEnter'
},
initialize: function() {
_.bindAll(this, 'saveOnEnter', 'save', 'remove', 'destroy', 'template', 'render');
this.model.on('change', this.save);
this.model.on('remove', this.destroy);
},
saveOnEnter: function(event) {
if (event.which != 13)
return;
$(event.currentTarget).blur();
this.save();
},
save: function() {
this.model.save();
},
remove: function() {
this.model.destroy();
},
destroy: function() {
this.$el.addClass('destroyed').slideUp(200, function() {
$(this).remove();
});
},
template: function() {
return $('#todo-view').html();
},
render: function() {
this.$el.html(this.template());
return this.bindModel();
}
});
var TodoListView = Backbone.View.extend({
tagName:...