引き続き、todoアプリを作ります。
(function(){
var Task = Backbone.Model.extend({
defaults: {
title: 'do something',
completed: false
},
validate: function(attrs){
if ( _.isEmpty(attrs.title)){
return 'title must not be empty';
}
},
initialize: function(){
this.on('invalid', function(model, error){
$('#error').html(error);
})
}
});
var Tasks = Backbone.Collection.extend({ model: Task });
var TaskView = Backbone.View.extend({
tagName: 'li',
initialize: function(){
this.model.on('destroy', this.remove, this);
this.model.on('change', this.render, this);
},
events: {
'click .delete': 'destroy',
'click .toggle': 'toggle'
},
toggle: function(){
this.model.set('completed', !this.model.get('completed'));
},
destroy: function(){
if (confirm('are you shure?')){
this.model.destroy();
}
},
remove: function(){
this.$el.remove();
},
template: _.template($('#task-template').html()),
render: function(){
var template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
}
});
var TasksView = Backbone.View.extend({
tagName: 'ul',
initialize: function(){
this.collection.on('add', this.addNew, this);
this.collection.on('change', this.updateCount, this);
this.collection.on('destroy', this.updateCount, this);
},
addNew: function(task){
var taskView = new TaskView({model: task});
this.$el.append(taskView.render().el);
$('#title').val('').focus();
this.updateCount();
},
updateCount: function(){
var uncompletedTasks = this.collection.filter(function(task){
return !task.get('completed');
});
$('#count').html(uncompletedTasks.length);
},
render: function(){
this.collection.each(function(task){
var taskView = new TaskView({model: task});
this.$el.append(taskView.render().el);
}, this);
this.updateCount();
return this;
}
});
var AddTaskView = Backbone.View.extend({
el: '#addTask',
events: {
'submit': 'submit'
},
submit: function(e){
e.preventDefault();
// var task = new Task({title: $('#title').val()});
var task = new Task();
if (task.set({title: $('#title').val()}, {validate: true})){
this.collection.add(task);
$('#error').empty();
}
}
});
var tasks = new Tasks([
{
title: 'task1',
completed: true
},
{
title: 'task2'
},
{
title: 'task3'
}
]);
var tasksView = new TasksView({collection: tasks});
var addTaskView = new AddTaskView({collection: tasks});
$('#tasks').html(tasksView.render().el);
})();
htmlです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Backbone.js</title>
<style>
.completed{
text-decoration: line-through;
color: gray;
}
</style>
</head>
<body>
<h1>Tasks</h1>
<form id="addTask">
<input type="text" id="title">
<input type="submit" value="add">
<span id="error"></span>
</form>
<div id="tasks">
</div>
<p>Tasks left: <span id="count"></span></p>
<script type="text/template" id="task-template">
<input type="checkbox" class="toggle" <%= completed ? 'checked': '' %>>
<span class="<%= completed ? 'completed' : '' %>">
<%- title %>
</span>
<span class="delete">[x]</span>
</script>
<script src="js/underscore.js"></script>
<script src="js/jquery.js"></script>
<script src="js/backbone.js"></script>
<script src="js/app.js"></script>
</body>
</html>
ブラウザでの表示です。