Skip to content

Commit

Permalink
Change TODOs
Browse files Browse the repository at this point in the history
  • Loading branch information
glibin committed Feb 24, 2012
1 parent 82b3a91 commit ce1928d
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 39 deletions.
33 changes: 1 addition & 32 deletions index.html
Expand Up @@ -9,6 +9,7 @@
<script src="js/underscore-1.3.1.js"></script> <script src="js/underscore-1.3.1.js"></script>
<script src="js/backbone.js"></script> <script src="js/backbone.js"></script>
<script src="js/backbone-localstorage.js"></script> <script src="js/backbone-localstorage.js"></script>
<script src="js/core.js"></script>
<script src="js/todos.js"></script> <script src="js/todos.js"></script>
</head> </head>


Expand Down Expand Up @@ -50,38 +51,6 @@ <h1>Todos</h1>
<a href="http://jgn.me/">J&eacute;r&ocirc;me Gravel-Niquet</a> <a href="http://jgn.me/">J&eacute;r&ocirc;me Gravel-Niquet</a>
</div> </div>


<!-- Templates -->

<script type="text/template" id="item-template">
<div class="todo <%= done ? 'done' : '' %>">
<div class="display">
<input class="check" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
<div class="todo-text"></div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="" />
</div>
</div>
</script>

<script type="text/template" id="stats-template">
<% if (total) { %>
<span class="todo-count">
<span class="number"><%= remaining %></span>
<span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left.
</span>
<% } %>
<% if (done) { %>
<span class="todo-clear">
<a href="#">
Clear <span class="number-done"><%= done %></span>
completed <span class="word-done"><%= done == 1 ? 'item' : 'items' %></span>
</a>
</span>
<% } %>
</script>

</body> </body>


</html> </html>
95 changes: 95 additions & 0 deletions js/core.js
@@ -0,0 +1,95 @@
(function(){
var Core = this.Core = {};

Core.Model = Backbone.Model.extend({
urlRoot : '/data',
defaults: {
id: null,
name: ''
},

clear: function() {
this.destroy();
this.view.remove();
}
});

Core.Collection = Backbone.Collection.extend({
model: Core.Model,
url: '/data',
/* To prevent JSON array hijacking (http://haacked.com/archive/2009/06/25/json-hijacking.aspx)
all collection data returned from the server should look like: {data : [...]}
*/
parse : function(resp, xhr) {
if (resp.data) {
return resp.data;
}
return [];
}
});

Core.Template = {
cache: {}, //cached templates
pending: {}, // queue of callbacks, waiting for template to load
load: function(url, callback) {
if (this.cache[url]) { //template loaded, call cb
if (callback) callback(this.cache[url]);
return;
}

this.pending[url] = this.pending[url] || [];
if (callback) this.pending[url].push(callback); //add callback to the queue

jQuery.ajax({ //load template
url : url,
dataType: 'text',
complete: function(resp) {
var cache =
this.cache[url] = _.template(resp.responseText); // cache it

// proccess all pending callbacks
_.each(this.pending[url], function(cb) {
cb(cache);
});

delete this.pending[url];
}.bind(this),
error: function() {
throw new Error("Could not load " + url);
}
});
}
};

Core.View = Backbone.View.extend({
el: null,
renderQueue: false,

initialize: function() {
if (this.templateUrl) {
Core.Template.load(this.templateUrl, function(data) {
this.template = data;
if (this.renderQueue !== false) {
_.each(this.renderQueue, function(item) {
this._render.apply(this, item);
}.bind(this));

this.renderQueue = false;
}
}.bind(this));
}
},

_render: function() {}, //Override this for render proccess

render: function() {
if (!this.template) {
this.renderQueue = this.renderQueue || [];
this.renderQueue.push(arguments);
return this;
}
return this._render.apply(this, arguments);
}
});

})();
18 changes: 11 additions & 7 deletions js/todos.js
Expand Up @@ -71,13 +71,13 @@ $(function(){
// -------------- // --------------


// The DOM element for a todo item... // The DOM element for a todo item...
window.TodoView = Backbone.View.extend({ window.TodoView = Core.View.extend({


//... is a list tag. //... is a list tag.
tagName: "li", tagName: "li",


// Cache the template function for a single item. // Cache the template function for a single item.
template: _.template($('#item-template').html()), templateUrl: 'templates/item.html',


// The DOM events specific to an item. // The DOM events specific to an item.
events: { events: {
Expand All @@ -89,12 +89,14 @@ $(function(){


// The TodoView listens for changes to its model, re-rendering. // The TodoView listens for changes to its model, re-rendering.
initialize: function() { initialize: function() {
TodoView.__super__.initialize.apply(this);

this.model.bind('change', this.render, this); this.model.bind('change', this.render, this);
this.model.bind('destroy', this.remove, this); this.model.bind('destroy', this.remove, this);
}, },


// Re-render the contents of the todo item. // Re-render the contents of the todo item.
render: function() { _render: function() {
$(this.el).html(this.template(this.model.toJSON())); $(this.el).html(this.template(this.model.toJSON()));
this.setText(); this.setText();
return this; return this;
Expand Down Expand Up @@ -147,14 +149,14 @@ $(function(){
// --------------- // ---------------


// Our overall **AppView** is the top-level piece of UI. // Our overall **AppView** is the top-level piece of UI.
window.AppView = Backbone.View.extend({ window.AppView = Core.View.extend({


// Instead of generating a new element, bind to the existing skeleton of // Instead of generating a new element, bind to the existing skeleton of
// the App already present in the HTML. // the App already present in the HTML.
el: $("#todoapp"), el: $("#todoapp"),


// Our template for the line of statistics at the bottom of the app. // Our template for the line of statistics at the bottom of the app.
statsTemplate: _.template($('#stats-template').html()), templateUrl: 'templates/stats.html',


// Delegated events for creating new items, and clearing completed ones. // Delegated events for creating new items, and clearing completed ones.
events: { events: {
Expand All @@ -167,6 +169,8 @@ $(function(){
// collection, when items are added or changed. Kick things off by // collection, when items are added or changed. Kick things off by
// loading any preexisting todos that might be saved in *localStorage*. // loading any preexisting todos that might be saved in *localStorage*.
initialize: function() { initialize: function() {
AppView.__super__.initialize.apply(this);

this.input = this.$("#new-todo"); this.input = this.$("#new-todo");


Todos.bind('add', this.addOne, this); Todos.bind('add', this.addOne, this);
Expand All @@ -178,8 +182,8 @@ $(function(){


// Re-rendering the App just means refreshing the statistics -- the rest // Re-rendering the App just means refreshing the statistics -- the rest
// of the app doesn't change. // of the app doesn't change.
render: function() { _render: function() {
this.$('#todo-stats').html(this.statsTemplate({ this.$('#todo-stats').html(this.template({
total: Todos.length, total: Todos.length,
done: Todos.done().length, done: Todos.done().length,
remaining: Todos.remaining().length remaining: Todos.remaining().length
Expand Down
10 changes: 10 additions & 0 deletions templates/item.html
@@ -0,0 +1,10 @@
<div class="todo <%= done ? 'done' : '' %>">
<div class="display">
<input class="check" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
<div class="todo-text"></div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="" />
</div>
</div>
14 changes: 14 additions & 0 deletions templates/stats.html
@@ -0,0 +1,14 @@
<% if (total) { %>
<span class="todo-count">
<span class="number"><%= remaining %></span>
<span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left.
</span>
<% } %>
<% if (done) { %>
<span class="todo-clear">
<a href="#">
Clear <span class="number-done"><%= done %></span>
completed <span class="word-done"><%= done == 1 ? 'item' : 'items' %></span>
</a>
</span>
<% } %>

0 comments on commit ce1928d

Please sign in to comment.