<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
body{
background-color: #eee;
margin: 0 auto;
width: 520px;
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
header,section,footer{
display: block;
}
.toDo{
padding: 20px;
border-radius: 0px 0px 5px 5px;
background-color: white;
-webkit-box-shadow: 0px 1px 2px 1px rgba(0, 0, 0, 0.2);
box-shadow: 0px 1px 5px 1px rgba(0, 0, 0, 0.2);
}
.toDo input[type="checkbox"]{
margin-right: 5px;
}
header>h1{
margin: 10px 0 20px 0;
font-size: 35px;
text-align: center;
}
header>input{
outline: none;
display: block;
width: 100%;
box-sizing: border-box;
height: 45px;
line-height: 35px;
padding: 5px;
font-style: italic;
font-size: 16px;
}
#views, footer{
display: none;
}
.select-all{
height: 25px;
line-height: 25px;
text-align: left;
}
.select-all>input,.select-all>label{
vertical-align: middle;
}
#todo-list{
margin: 10px 0;
}
#todo-list>li{
list-style-type: none;
padding: 15px 0;
border-bottom: 1px solid #ccc;
position: relative;
font-size: 20px;
}
#todo-list>li:last-child{
border-bottom: none;
}
#todo-list>li:hover .destroy{
display: block;
}
#todo-list>li .destroy{
position: absolute;
top: 16px;
right: 5px;
width: 20px;
height: 20px;
line-height: 20px;
border-radius: 10px;
color: white;
text-align: center;
background-color: darkgray;
font-size: 12px;
display: none;
}
#todo-list>li .destroy:hover{
cursor: pointer;
background-color: black;
}
#todo-list li.done label {
color: #777777;
text-decoration: line-through;
}
footer{
overflow: hidden;
margin-left: -20px;
margin-bottom: -20px;
padding: 10px 20px;
background-color: #f4fce8;
width: 100%;
border-radius: 0 0 5px 5px;
}
footer>#todo-count{
float: left;
}
footer>#clear-complete{
float: right;
padding: 2px 10px;
border-radius: 10px;
background-color: #cccccc;
}
footer>#clear-complete:hover{
color: white;
background-color: #a0a0a0;
cursor: pointer;
}
.edit{
display: none;
}
</style>
</head>
<body>
<div>
<header>
<h1>Todos</h1>
<input type="text" id="new-todo" placeholder="What needs to be done?"/>
</header>
<section id="views">
<div>
<input id="toggle-all" type="checkbox"/>
<label for="toggle-all">Mark all as complete</label>
</div>
<ul id="todo-list">
</ul>
</section>
<footer>
<!--<div id="todo-count">-->
<!--1 items left-->
<!--</div>-->
<!--<a id="clear-complete">Clear 0 completed</a>-->
</footer>
</div>
<!--done ? ‘checked="checked"‘ : ‘‘-->
<script src="jquery-1.11.2.min.js"></script>
<script src="handlebars-v3.0.0.js"></script>
<script src="json2.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<script type="text/x-handlebars-template" id="item-template">
<div>
<input type="checkbox" {{#if done}} checked {{else}} ‘‘ {{/if}} />
<label>{{title}}</label>
<a>X</a>
</div>
<input type="text" value="{{title}}" />
</script>
<script type="text/x-handlebars-template" id="footer">
<div id="todo-count">
<strong>{{remaining}}</strong> items left
</div>
{{#if done}}
<a id="clear-complete">
Clear <b>{{done}}</b> completed
</a>
{{/if}}
</script>
<script>
(function(){
var Todo = Backbone.Model.extend({
defaults: {
title: "empty todo",
done: false
},
toggle: function() {
this.set({done: !this.get("done")});
var flag = true;
$(‘.toDo .toggle‘).each(function(i, d){
if(!d.checked){
flag = false;
$(‘#toggle-all‘)[0].checked = false;
}
})
$(‘#toggle-all‘)[0].checked = flag;
}
})
var TodoList = Backbone.Collection.extend({
model: Todo,
initialize: function(){
},
addNew: function(model){
},
done: function(){
return this.where({done: true});
},
remaining: function(){
return this.where({done: false});
}
})
var todoList = new TodoList;
var TodoView = Backbone.View.extend({
tagName: ‘li‘,
template: Handlebars.compile($(‘#item-template‘).html()),
initialize: function(){
this.listenTo(this.model, ‘change‘, this.render);
this.listenTo(this.model, ‘destroy‘, this.destroyView);
},
events: {
"dblclick .view": "edit",
"click .toggle": "toggleDone",
"click a.destroy": "destroyView"
},
render: function(model){
if(this.model.get(‘destroy‘)){
this.destroyView();
}else{
this.$el.html(this.template(this.model.toJSON()));
this.$el.toggleClass(‘done‘, this.model.get(‘done‘));
this.input = this.$(‘.edit‘);
return this;
}
},
edit: function(event){
event = event ? event : window.event;
},
destroyView: function(){
this.remove();
todoList.remove(this.model);
},
toggleDone: function(){
this.model.toggle();
}
})
var AppView = Backbone.View.extend({
el: $(‘.toDo‘),
footerTemplate: Handlebars.compile($(‘#footer‘).html()),
initialize: function(){
this.input = this.$("#new-todo");
this.allCheckbox = this.$(‘#toggle-all‘)[0];
this.listenTo(todoList, ‘add‘, this.addOneView);
// this.listenTo(todoList, ‘remove‘, this.render);
this.listenTo(todoList, ‘all‘, this.render);
this.footer = this.$(‘footer‘);
this.views = this.$(‘#views‘);
this.renderLocalView();
},
events: {
"keypress #new-todo": "createOnEnter",
"click #toggle-all": "toggleAllComplete",
"click #clear-complete": "clearAllView"
},
addOneView: function(todo){
var view = new TodoView({model: todo});
this.$("#todo-list").append(view.render().$el);
this.render();
},
render: function(){
var done = todoList.done().length;
var remaining = todoList.remaining().length;
if(todoList.length){
this.views.show();
this.footer.html(this.footerTemplate({done:done,remaining:remaining}));
this.footer.show();
}else{
this.footer.hide();
this.views.hide();
}
localStorage.setItem(‘todoList‘, JSON.stringify(todoList));
},
createOnEnter: function(e){
console.log(e)
if(e.keyCode != 13) return 1;
if(!(this.input.val())) return 1;
this.$(‘#toggle-all‘)[0].checked = false;
todoList.add({title: this.input.val()});
this.input.val(‘‘);
},
toggleAllComplete: function(){
var done = this.allCheckbox.checked;
todoList.each(function (todo) {
todo.set({‘done‘: done});
});
},
clearAllView: function(){
// _.invoke(todoList.done(), ‘destroy‘);
while(todoList.length){
todoList.models[todoList.length-1].set(‘destroy‘, true);
}
return false;
},
renderLocalView: function(){
var models = JSON.parse(localStorage.getItem(‘todoList‘));
if(models){
var length = JSON.parse(localStorage.getItem(‘todoList‘)).length;
while(length--){
todoList.add(models[length]);
}
}
}
})
var appView = new AppView;
})()
</script>
</body>
</html>
原文:http://my.oschina.net/u/1992917/blog/391433