backbone.jsによるToDoアプリ

引き続き、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>

ブラウザでの表示です。
task