Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of github.com:snodgrass23/knockoutjs-demo

  • Loading branch information...
commit bb64eaea5db9d418cb5dcab9d57793e7da93c057 2 parents 68b6f87 + 30490b5
@dbecher dbecher authored
Showing with 12 additions and 88 deletions.
  1. +0 −72 backbone.js
  2. +6 −12 index.html
  3. +1 −0  main.css
  4. +5 −4 main.js
View
72 backbone.js
@@ -1,33 +1,19 @@
-// An example Backbone application contributed by
-// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple
-// [LocalStorage adapter](backbone-localstorage.html)
-// to persist Backbone models within your browser.
-
-// Load the application once the DOM is ready, using `jQuery.ready`:
$(function(){
- // Todo Model
- // ----------
-
- // Our basic **Todo** model has `content`, `order`, and `done` attributes.
window.Todo = Backbone.Model.extend({
- // If you don't provide a todo, one will be provided for you.
EMPTY: "empty todo...",
- // Ensure that each todo created has `content`.
initialize: function() {
if (!this.get("content")) {
this.set({"content": this.EMPTY});
}
},
- // Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
},
- // Remove this Todo from *localStorage* and delete its view.
clear: function() {
this.destroy();
this.view.remove();
@@ -35,59 +21,39 @@ $(function(){
});
- // Todo Collection
- // ---------------
-
- // The collection of todos is backed by *localStorage* instead of a remote
- // server.
window.TodoList = Backbone.Collection.extend({
- // Reference to this collection's model.
model: Todo,
- // Save all of the todo items under the `"todos"` namespace.
localStorage: new Store("todos"),
- // Filter down the list of all todo items that are finished.
done: function() {
return this.filter(function(todo){ return todo.get('done'); });
},
- // Filter down the list to only todo items that are still not finished.
remaining: function() {
return this.without.apply(this, this.done());
},
- // We keep the Todos in sequential order, despite being saved by unordered
- // GUID in the database. This generates the next order number for new items.
nextOrder: function() {
if (!this.length) return 1;
return this.last().get('order') + 1;
},
- // Todos are sorted by their original insertion order.
comparator: function(todo) {
return todo.get('order');
}
});
- // Create our global collection of **Todos**.
window.Todos = new TodoList;
- // Todo Item View
- // --------------
-
- // The DOM element for a todo item...
window.TodoView = Backbone.View.extend({
- //... is a list tag.
tagName: "li",
- // Cache the template function for a single item.
template: _.template($('#item-template').html()),
- // The DOM events specific to an item.
events: {
"click .check" : "toggleDone",
"dblclick div.todo-content" : "edit",
@@ -95,24 +61,18 @@ $(function(){
"keypress .todo-input" : "updateOnEnter"
},
- // The TodoView listens for changes to its model, re-rendering. Since there's
- // a one-to-one correspondence between a **Todo** and a **TodoView** in this
- // app, we set a direct reference on the model for convenience.
initialize: function() {
_.bindAll(this, 'render', 'close');
this.model.bind('change', this.render);
this.model.view = this;
},
- // Re-render the contents of the todo item.
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
this.setContent();
return this;
},
- // To avoid XSS (not that it would be harmful in this particular app),
- // we use `jQuery.text` to set the contents of the todo item.
setContent: function() {
var content = this.model.get('content');
this.$('.todo-content').text(content);
@@ -121,63 +81,44 @@ $(function(){
this.input.val(content);
},
- // Toggle the `"done"` state of the model.
toggleDone: function() {
this.model.toggle();
},
-
- // Switch this view into `"editing"` mode, displaying the input field.
edit: function() {
$(this.el).addClass("editing");
this.input.focus();
},
-
- // Close the `"editing"` mode, saving changes to the todo.
close: function() {
this.model.save({content: this.input.val()});
$(this.el).removeClass("editing");
},
- // If you hit `enter`, we're through editing the item.
updateOnEnter: function(e) {
if (e.keyCode == 13) this.close();
},
- // Remove this view from the DOM.
remove: function() {
$(this.el).remove();
},
- // Remove the item, destroy the model.
clear: function() {
this.model.clear();
}
});
- // The Application
- // ---------------
-
- // Our overall **AppView** is the top-level piece of UI.
window.AppView = Backbone.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()),
- // Delegated events for creating new items, and clearing completed ones.
events: {
"keypress #new-todo": "createOnEnter",
"keyup #new-todo": "showTooltip",
"click .todo-clear a": "clearCompleted"
},
- // At initialization we bind to the relevant events on the `Todos`
- // collection, when items are added or changed. Kick things off by
- // loading any preexisting todos that might be saved in *localStorage*.
initialize: function() {
_.bindAll(this, 'addOne', 'addAll', 'render');
@@ -190,8 +131,6 @@ $(function(){
Todos.fetch();
},
- // Re-rendering the App just means refreshing the statistics -- the rest
- // of the app doesn't change.
render: function() {
var done = Todos.done().length;
this.$('#todo-stats').html(this.statsTemplate({
@@ -200,20 +139,15 @@ $(function(){
remaining: Todos.remaining().length
}));
},
-
- // Add a single todo item to the list by creating a view for it, and
- // appending its element to the `<ul>`.
addOne: function(todo) {
var view = new TodoView({model: todo});
this.$("#todo-list").append(view.render().el);
},
- // Add all items in the **Todos** collection at once.
addAll: function() {
Todos.each(this.addOne);
},
- // Generate the attributes for a new Todo item.
newAttributes: function() {
return {
content: this.input.val(),
@@ -222,22 +156,17 @@ $(function(){
};
},
- // If you hit return in the main input field, create new **Todo** model,
- // persisting it to *localStorage*.
createOnEnter: function(e) {
if (e.keyCode != 13) return;
Todos.create(this.newAttributes());
this.input.val('');
},
- // Clear all done todo items, destroying their models.
clearCompleted: function() {
_.each(Todos.done(), function(todo){ todo.clear(); });
return false;
},
- // Lazily show the tooltip that tells you to press `enter` to save
- // a new todo item, after one second.
showTooltip: function(e) {
var tooltip = this.$(".ui-tooltip-top");
var val = this.input.val();
@@ -250,7 +179,6 @@ $(function(){
});
- // Finally, we kick things off by creating the **App**.
window.App = new AppView;
});
View
18 index.html
@@ -32,8 +32,8 @@ <h2 id="current_task">Current Task: <span data-bind="text: first().item"></span>
<div class="content">
<div id="create-todo">
- <input id="new-todo" placeholder="What needs to be done?" type="text" />
- <input id="new-todo-hours" placeholder="hours?" type="text" />
+ <input id="new-todo" placeholder="What needs to be done?" type="text" data-bind='value:itemToAdd, valueUpdate: "afterkeydown"' />
+ <input id="new-todo-hours" placeholder="hours?" type="text" data-bind='value:addTime, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="click: addItem" id="addItemButton">Add</button>
<span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span>
</div>
@@ -50,15 +50,10 @@ <h2 id="current_task">Current Task: <span data-bind="text: first().item"></span>
</div>
<ul id="instructions">
- <li>Double-click to edit a todo.</li>
+ <li>Add item with hours expected to take.</li>
+ <li>Do cool shit...</li>
</ul>
- <div id="credits">
- Created by
- <br />
- Skookum
- </div>
-
<!-- Templates -->
<script type="text/html" id="itemTemplate">
@@ -71,9 +66,8 @@ <h2 id="current_task">Current Task: <span data-bind="text: first().item"></span>
<input data-bind="value: item, valueUpdate: 'afterkeydown'" class="enteredItem" />
</div>
<div class="todo-hours">
- <input data-bind="value: enteredTime, valueUpdate: 'afterkeydown', disable: isDone" class="enteredTime" /> /
- <input data-bind="value: hours, valueUpdate: 'afterkeydown', disable: isDone" class="totalTime" />
-
+ <input data-bind="value: enteredTime, valueUpdate: 'afterkeydown', disable: isDone" class="enteredTime" /> /
+ <input data-bind="value: hours, valueUpdate: 'afterkeydown', disable: isDone" class="totalTime" />
</div>
<span class="todo-destroy" data-bind="click: remove"></span>
</div>
View
1  main.css
@@ -422,6 +422,7 @@ ul li.danger, ul li.danger input{
.done .todo-hours, .done .todo-hours input{
color: #ccc;
+ background:#FFF;
}
.done input.enteredItem{
text-decoration: line-through;
View
9 main.js
@@ -23,8 +23,9 @@ var taskList = function() {
}, this);
this.time_remaining = ko.dependentObservable(function() {
var total = 0;
- for(var i in this.tasks()) {
- total += this.tasks()[i].timeRemaining();
+ for(var i in this.tasks()) {
+ if (!this.tasks()[i].isDone())
+ total += this.tasks()[i].timeRemaining();
}
return total;
}, this);
@@ -56,8 +57,8 @@ taskList.prototype = {
addItem: function() {
this.tasks.push(new itemViewModel({
- name: this.itemToAdd(),
- totalTime: parseInt(this.addTime())
+ item: this.itemToAdd(),
+ hours: parseInt(this.addTime()) || 1
}));
this.itemToAdd("");
this.addTime("");
Please sign in to comment.
Something went wrong with that request. Please try again.