LotosLabo

プログラミング技術とか気になった情報を載せていきます

Backbone.jsについて2

eventを作る

まずindex.htmlの方に追加して行きます。

<script type="text/template" id="task-template">
	  <%- title %><span class="command">command</span>
</script>



ここのみ追加しました。

次にapp.jsに追加していきます。

(function() {

// Model
var Task = Backbone.Model.extend({
	defaults: {
		title: "do something!",
		completed: false
	}
});
var task = new Task();

//View
var TaskView = Backbone.View.extend({
		tagName: 'li',
		events:{
		"click .command": "sayHello"
		},
		sayHello: function() {
			alert('hello');
		},
template: _.template( $('#task-template').html() ),
render: function() {
		var template = this.template( this.model.toJSON() );
		this.$el.html(template);
		return this;
	}

});

var taskView = new TaskView({ model:task });
console.log(taskView.render().el);
$('body').append(taskView.render().el);
})();



eventsでcommandクラスをクリックすることでsayHelloとアラートを出すようにしました。

f:id:lo25131:20140402173837g:plain


Collectionを作る

コレクションというのを作っていきます。

var Tasks = Backbone.Collection.extend({
	model: Task
});
var tasks = new Tasks();



簡単な型としてはこんなかんじになります。これにいくつか追加して実践的にしたいと思います。

例:

(function() {
// Model
var Task = Backbone.Model.extend({
	defaults: {
		title: "do something!",
		completed: false
	}
});
var task = new Task();

//View
var TaskView = Backbone.View.extend({
		tagName: 'li',
template: _.template( $('#task-template').html() ),
render: function() {
		var template = this.template( this.model.toJSON() );
		this.$el.html(template);
		return this;
	}
});

// Collection
var Tasks = Backbone.Collection.extend({
	model: Task
});
var tasks = new Tasks([
	{
		title: 'task1',
		completed: true
	},
	{
		title: 'task2'
	},
	{	
		title: 'task3'
	}
]);
console.log(tasks.toJSON());
})();



コレクションを3つほど作成しました。

出力結果はこんなかんじになります。
[Object, Object, Object]

CollectionのViewを作る

CollectionのViewとなる部分を作っていきます。

例: index.html 追加した部分のみ

	<div id="tasks"></div>


スクリプトの方
例: app.js

(function() {

// Model
var Task = Backbone.Model.extend({
	defaults: {
		title:"do something!",
		completed: false
	}
});
var task = new Task();


//View

var TaskView = Backbone.View.extend({
	tagName: 'li',
	template: _.template( $('#task-template').html() ),
	render: function() {
		var template = this.template( this.model.toJSON() );
		this.$el.html(template);
		return this;
	}

});

//Collection
var Tasks = Backbone.Collection.extend({
	model: Task
});

var TasksView = Backbone.View.extend({
	tagName: 'ul',
	render: function() {
		this.collection.each(function(task){
			var taskView = new TaskView({model: task});
			this.$el.append(taskView.render().el);
		},this);
		return this;
	}
});
var tasks = new Tasks([
{
	title: 'task1',
	completed: true
},
{
	title: 'task2'
},
{	
	title: 'task3'
}
]);
var taskView = new TasksView({collection: tasks});
$('#tasks').html(taskView.render().el);


})();


出力結果はこうなりました

f:id:lo25131:20140402180050j:plain




ToDoアプリを作っていく


app.jsを一番最初の状態に戻して書いていきます。

今回はコードとgif画像のみ載せる形となります。

index.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>BACKBONE 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="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
	<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
	<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
	<script type="text/javascript" src="app.js"></script>
</body>
</html>




app.js

(function() {

//Model
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);
		})
	}
});

//Collection
var Tasks = Backbone.Collection.extend({ model: Task});

//Model View
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 sure?')) {
			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;
	}
});

//Collection View
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;
	}
});

//AddTaskView
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);

})();



こんなかんじになります。

f:id:lo25131:20140402184649g:plain