Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Change TODOs

  • Loading branch information...
commit ce1928d2b9a95ffb6bb9115edffb5aa7f95a246c 1 parent 82b3a91
@glibin authored
View
33 index.html
@@ -9,6 +9,7 @@
<script src="js/underscore-1.3.1.js"></script>
<script src="js/backbone.js"></script>
<script src="js/backbone-localstorage.js"></script>
+ <script src="js/core.js"></script>
<script src="js/todos.js"></script>
</head>
@@ -50,38 +51,6 @@
<a href="http://jgn.me/">J&eacute;r&ocirc;me Gravel-Niquet</a>
</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>
</html>
View
95 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);
+ }
+ });
+
+})();
View
18 js/todos.js
@@ -71,13 +71,13 @@ $(function(){
// --------------
// The DOM element for a todo item...
- window.TodoView = Backbone.View.extend({
+ window.TodoView = Core.View.extend({
//... is a list tag.
tagName: "li",
// Cache the template function for a single item.
- template: _.template($('#item-template').html()),
+ templateUrl: 'templates/item.html',
// The DOM events specific to an item.
events: {
@@ -89,12 +89,14 @@ $(function(){
// The TodoView listens for changes to its model, re-rendering.
initialize: function() {
+ TodoView.__super__.initialize.apply(this);
+
this.model.bind('change', this.render, this);
this.model.bind('destroy', this.remove, this);
},
// Re-render the contents of the todo item.
- render: function() {
+ _render: function() {
$(this.el).html(this.template(this.model.toJSON()));
this.setText();
return this;
@@ -147,14 +149,14 @@ $(function(){
// ---------------
// 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
// the App already present in the HTML.
el: $("#todoapp"),
// 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.
events: {
@@ -167,6 +169,8 @@ $(function(){
// collection, when items are added or changed. Kick things off by
// loading any preexisting todos that might be saved in *localStorage*.
initialize: function() {
+ AppView.__super__.initialize.apply(this);
+
this.input = this.$("#new-todo");
Todos.bind('add', this.addOne, this);
@@ -178,8 +182,8 @@ $(function(){
// Re-rendering the App just means refreshing the statistics -- the rest
// of the app doesn't change.
- render: function() {
- this.$('#todo-stats').html(this.statsTemplate({
+ _render: function() {
+ this.$('#todo-stats').html(this.template({
total: Todos.length,
done: Todos.done().length,
remaining: Todos.remaining().length
View
10 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>
View
14 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>
+<% } %>
Please sign in to comment.
Something went wrong with that request. Please try again.