Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save linuxenko/f10e1457ffc3439a03af to your computer and use it in GitHub Desktop.
Save linuxenko/f10e1457ffc3439a03af to your computer and use it in GitHub Desktop.
Retro Frameworks (backbone.js) TodoList
<section class="todoapp">
<header class="header">
<h1>backbone.js</h1>
<input id="todo-input" class="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<section class="main">
<input class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list" class="todo-list">
</ul>
</section>
<footer class="footer">
<span class="todo-count"><strong id="todo-count">0</strong> item left</span>
<ul class="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#active">Active</a>
</li>
<li>
<a href="#completed">Completed</a>
</li>
</ul>
<button class="clear-completed">Clear completed</button>
</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
</footer>
var Todo = Backbone.Model.extend({
defaults : {
title : 'Empty todo...',
completed : false
},
toggle : function() {
this.set('completed', this.get('completed') === true ? false : true);
}
});
var TodoCollection = Backbone.Collection.extend({
model : Todo
});
var TodoItem = Backbone.View.extend({
item : null,
events : {
'click .toggle' : 'toggle',
'dblclick label' : 'editing',
'keydown input' : 'rename',
'click .destroy' : 'destroy',
'click .view' : 'uneditAll'
},
tagName : 'li',
initialize : function() {
this.model.on('change', this.update.bind(this));
},
update : function() {
this.render();
},
render : function() {
var template = _.template('<div class="view"><input class="toggle" type="checkbox" <% if (completed===true) { %>checked<% } %>><label><%= title %></label><button class="destroy"></button></div><input class="edit" value="<%= title %>">');
this.$el.html(template(this.model.toJSON()));
if (this.model.get('completed')) {
this.$el.addClass('completed');
} else {
this.$el.removeClass('completed');
}
return this;
},
uneditAll : function() {
$('.editing').removeClass('editing');
},
destroy : function() {
this.model.destroy();
},
rename : function(e) {
if (e.keyCode === 13 && e.target.value.length > 0) {
this.model.set('title', e.target.value);
this.$el.removeClass('editing');
}
},
editing : function() {
this.$el.addClass('editing');
this.$el.find('input').focus();
},
toggle : function() {
this.model.toggle();
}
});
var TodoList = Backbone.View.extend({
el : 'section.todoapp',
showFilter : '',
events : {
'keydown #todo-input': 'addTodo',
'click .clear-completed' : 'clearCompleted'
},
initialize : function() {
this.model.bind('add', this.render.bind(this));
this.model.bind('remove', this.render.bind(this));
//this.model.bind('change', this.render.bind(this));
},
render : function() {
var self = this;
var counter = 0;
$('#todo-list').empty();
this.model.models.forEach(function(m) {
var display = self.showFilter === null ? true : false;
if (self.showFilter === 'active' && m.get('completed') === false) {
display = true;
}
if (self.showFilter === 'completed' && m.get('completed') === true) {
display = true;
}
if (display === true) {
$('#todo-list').append(new TodoItem({model : m}).render().el);
}
if (m.get('completed') === false) {
counter += 1;
}
});
$('#todo-count').text(counter);
},
clearCompleted : function() {
var destroyable = [];
for(var i = 0 ; i < this.model.models.length; i++) {
if (this.model.models[i].get('completed') === true) {
destroyable.push(this.model.models[i]);
}
}
destroyable.forEach(function(m) { m.destroy(); });
destroyable = null;
},
filter : function(f) {
this.showFilter = f;
$('.filters a').each(function() {
$(this).removeClass('selected');
if ($(this).text().toLowerCase() === f) {
$(this).addClass('selected');
}
if (f === null && $(this).text().toLowerCase() === 'all') {
$(this).addClass('selected');
}
});
this.render();
},
addTodo : function(e) {
if (e.keyCode === 13 && e.target.value.length > 0) {
var todo = new Todo({title : e.target.value});
this.model.add(todo);
e.target.value = '';
}
}
});
var Router = Backbone.Router.extend({
routes : {
'*filter' : 'changeFilter'
},
changeFilter : function(f) {
todoList.filter(f);
}
});
var todoList = new TodoList({ model : new TodoCollection() });
var router = new Router();
Backbone.history.start();
todoList.model.add({title : 'Forget this Experience'});
todoList.model.add({title : 'Remove this Pen'});
todoList.model.add({title : 'Make Retro Framework Todo', completed : true});
todoList.model.add({title : 'Complete Filters', completed : true});
todoList.model.add({title : 'Editing Todo Support', completed : true});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<link href="https://cdn.rawgit.com/tastejs/todomvc-app-css/master/index.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment