diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..c771f77 --- /dev/null +++ b/LICENSE @@ -0,0 +1,128 @@ +Creative Commons CC0 1.0 Universal + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE +LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN +ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION +ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE +USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND +DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT +OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work +of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without +fear of later claims of infringement build upon, modify, incorporate in +other works, reuse and redistribute as freely as possible in any form +whatsoever and for any purposes, including without limitation commercial +purposes. These owners may contribute to the Commons to promote the +ideal of a free culture and the further production of creative, cultural +and scientific works, or to gain reputation or greater distribution for +their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or +she is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under +its terms, with knowledge of his or her Copyright and Related Rights in +the Work and the meaning and intended legal effect of CC0 on those +rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + +i. the right to reproduce, adapt, distribute, perform, display, +communicate, and translate a Work; + +ii. moral rights retained by the original author(s) and/or performer(s); + +iii. publicity and privacy rights pertaining to a person's image or +likeness depicted in a Work; + +iv. rights protecting against unfair competition in regards to a Work, +subject to the limitations in paragraph 4(a), below; + +v. rights protecting the extraction, dissemination, use and reuse of +data in a Work; + +vi. database rights (such as those arising under Directive 96/9/EC of +the European Parliament and of the Council of 11 March 1996 on the legal +protection of databases, and under any national implementation thereof, +including any amended or successor version of such directive); and + +vii. other similar, equivalent or corresponding rights throughout the +world based on applicable law or treaty, and any national +implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or +future medium and for any number of copies, and (iv) for any purpose +whatsoever, including without limitation commercial, advertising or +promotional purposes (the "Waiver"). Affirmer makes the Waiver for the +benefit of each member of the public at large and to the detriment of +Affirmer's heirs and successors, fully intending that such Waiver shall +not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of +the Work by the public as contemplated by Affirmer's express Statement +of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non +exclusive, irrevocable and unconditional license to exercise Affirmer's +Copyright and Related Rights in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or +future medium and for any number of copies, and (iv) for any purpose +whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed +effective as of the date CC0 was applied by Affirmer to the Work. Should +any part of the License for any reason be judged legally invalid or +ineffective under applicable law, such partial invalidity or +ineffectiveness shall not invalidate the remainder of the License, and +in such case Affirmer hereby affirms that he or she will not (i) +exercise any of his or her remaining Copyright and Related Rights in the +Work or (ii) assert any associated claims and causes of action with +respect to the Work, in either case contrary to Affirmer's express +Statement of Purpose. + +4. Limitations and Disclaimers. + +a. No trademark or patent rights held by Affirmer are waived, abandoned, +surrendered, licensed or otherwise affected by this document. + +b. Affirmer offers the Work as-is and makes no representations or +warranties of any kind concerning the Work, express, implied, statutory +or otherwise, including without limitation warranties of title, +merchantability, fitness for a particular purpose, non infringement, or +the absence of latent or other defects, accuracy, or the present or +absence of errors, whether or not discoverable, all to the greatest +extent permissible under applicable law. + +c. Affirmer disclaims responsibility for clearing rights of other +persons that may apply to the Work or any use thereof, including without +limitation any person's Copyright and Related Rights in the Work. +Further, Affirmer disclaims responsibility for obtaining any necessary +consents, permissions or other rights required for any use of the Work. + +d. Affirmer understands and acknowledges that Creative Commons is not a +party to this document and has no duty or obligation with respect to +this CC0 or use of the Work. diff --git a/README.markdown b/README.markdown new file mode 100755 index 0000000..26505a7 --- /dev/null +++ b/README.markdown @@ -0,0 +1,5 @@ +This is a sample application that showcases the [Parse JavaScript SDK](https://www.parse.com/docs/js_guide). It's based on the [canonical Backbone Todo app](http://addyosmani.github.com/todomvc/). + +[View the live application hosted on Parse here](http://todolist.parseapp.com). + +[Learn how we built it in the tutorial](https://parse.com/tutorials/todo-app-with-javascript). diff --git a/css/todos.css b/css/todos.css new file mode 100755 index 0000000..70ef34c --- /dev/null +++ b/css/todos.css @@ -0,0 +1,431 @@ +html, body { + margin: 0; + padding: 0; +} + + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + color: inherit; + -webkit-appearance: none; + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} +body { + font: 14px'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #eeeeee url('../images/background.jpg'); + color: #4d4d4d; + width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} + +h1 { + background: #fe921f; + color: #ffffff; + display: inline-block; + font-family: 'Lato', sans-serif; + font-size: 12px; + font-weight: bold; + line-height: 12px; + letter-spacing: 1px; + margin: 0 0 30px; + padding: 10px 15px 8px; + text-transform: uppercase; +} + +#todoapp { + background: #fff; + background: rgba(255, 255, 255, 0.9); + margin: 130px 0 40px 0; + border: 1px solid #ccc; + position: relative; + border-top-left-radius: 2px; + border-top-right-radius: 2px; + box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.15); +} +#todoapp:before { + content: ''; + border-left: 1px solid #f5d6d6; + border-right: 1px solid #f5d6d6; + width: 2px; + position: absolute; + top: 45px; + top: 0px; + left: 40px; + height: 100%; +} +#todoapp input::-webkit-input-placeholder { + font-style: italic; +} +#todoapp input:-moz-placeholder { + font-style: italic; + color: #a9a9a9; +} +#todoapp h1 { + position: absolute; + font-size: 14px; + line-height:16px; + padding:16px; + background: rgba(215, 94, 80, 0.9); + top: -80px; + width: 95%; + height:30px; + font-weight: bold; + text-align: center; + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + -ms-text-rendering: optimizeLegibility; + -o-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} +.section { + position: relative; +} +#header { + padding-top: 10px; + border-radius: inherit; +} +#header:before { + content: ''; + position: absolute; + top: 0; + right: 0; + left: 0; + height: 15px; + z-index: 2; + border-bottom: 1px solid #6c615c; + background: #8d7d77; + background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)), to(rgba(101, 84, 76, 0.8))); + background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8)); + filter: progid: DXImageTransform.Microsoft.gradient(GradientType=0, StartColorStr='#9d8b83', EndColorStr='#847670'); + border-top-left-radius: 1px; + border-top-right-radius: 1px; +} +#new-todo, .edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + line-height: 1.4em; + border: 0; + outline: none; + color: inherit; + padding: 6px; + border: 1px solid #999; + box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + -o-box-sizing: border-box; + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-font-smoothing: antialiased; + -ms-font-smoothing: antialiased; + -o-font-smoothing: antialiased; + font-smoothing: antialiased; +} +#new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.02); + z-index: 2; + box-shadow: none; +} +#main { + position: relative; + z-index: 2; + border-top: 1px dotted #adadad; +} +label[for='toggle-all'] { + display: none; +} +#toggle-all { + position: absolute; + top: -56px; + left: -15px; + width: 65px; + height: 41px; + text-align: center; + border: none; + /* Mobile Safari */ + + -webkit-appearance: none; + -ms-appearance: none; + -o-appearance: none; + appearance: none; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +#toggle-all:before { + content: '»'; + font-size: 28px; + color: #d9d9d9; + padding: 0 25px 7px; +} +#toggle-all:checked:before { + color: #737373; +} +#todo-list { + margin: 0; + padding: 0; + list-style: none; + text-align: center; +} +#todo-list .spinner { + margin: 15px auto; +} +#todo-list li { + text-align: left; + position: relative; + font-size: 24px; + border-bottom: 1px dotted #ccc; +} +#todo-list li:last-child { + border-bottom: none; +} +#todo-list li.editing { + border-bottom: none; + padding: 0; +} +#todo-list li.editing .edit { + display: block; + width: 506px; + padding: 13px 17px 12px 17px; + margin: 0 0 0 43px; +} +#todo-list li.editing .view { + display: none; +} +#todo-list li .toggle { + text-align: center; + width: 40px; + height: 40px; + position: absolute; + top: 0; + bottom: 0; + margin: auto 0; + border: none; + /* Mobile Safari */ + + -webkit-appearance: none; + -ms-appearance: none; + -o-appearance: none; + appearance: none; +} +#todo-list li .toggle:after { + font-size: 18px; + content: '✔'; + line-height: 43px; + /* 40 + a couple of pixels visual adjustment */ + + font-size: 20px; + color: #d9d9d9; + text-shadow: 0 -1px 0 #bfbfbf; +} +#todo-list li .toggle:checked:after { + color: #85ada7; + text-shadow: 0 1px 0 #669991; + bottom: 1px; + position: relative; +} +#todo-list li label { + word-break: break-word; + margin: 15px 15px 15px 60px; + display: inline-block; + line-height: 1.2; + -webkit-transition: color 0.4s; + -moz-transition: color 0.4s; + -ms-transition: color 0.4s; + -o-transition: color 0.4s; + transition: color 0.4s; +} +#todo-list li.completed label { + color: #a9a9a9; + text-decoration: line-through; +} +#todo-list li .todo-destroy { + display: none; + position: absolute; + top: 0; + right: 10px; + bottom: 0; + width: 40px; + height: 40px; + margin: auto 0; + font-size: 22px; + color: #a88a8a; + -webkit-transition: all 0.2s; + -moz-transition: all 0.2s; + -ms-transition: all 0.2s; + -o-transition: all 0.2s; + transition: all 0.2s; +} +#todo-list li .todo-destroy:hover { + text-shadow: 0 0 1px #000, 0 0 10px rgba(199, 107, 107, 0.8); + -webkit-transform: scale(1.3); + -moz-transform: scale(1.3); + -ms-transform: scale(1.3); + -o-transform: scale(1.3); + transform: scale(1.3); +} +#todo-list li .todo-destroy:after { + content: '✖'; +} +#todo-list li:hover .todo-destroy { + display: block; +} +#todo-list li .edit { + display: none; +} +#todo-list li.editing:last-child { + margin-bottom: -1px; +} +#footer { + color: #777; + padding: 0 15px; + position: absolute; + right: 0; + bottom: -31px; + left: 0; + z-index: 1; + text-align: center; +} +#footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 31px; + left: 0; + height: 100px; + z-index: -1; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 6px 0 -3px rgba(255, 255, 255, 0.8), 0 7px 1px -3px rgba(0, 0, 0, 0.3), 0 42px 0 -6px rgba(255, 255, 255, 0.8), 0 43px 2px -6px rgba(0, 0, 0, 0.2); +} +#todo-count { + float: left; + text-align: left; +} +#filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} +#filters li { + display: inline; +} +#filters li a { + color: #83756f; + margin: 2px; + text-decoration: none; +} +#filters li a.selected { + font-weight: bold; +} +#clear-completed { + float: right; + line-height: 20px; + text-decoration: none; + background: rgba(0, 0, 0, 0.1); + font-size: 11px; + padding: 0 10px; + position: relative; + border-radius: 3px; + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2); +} +#clear-completed:hover { + background: rgba(0, 0, 0, 0.15); + box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3); +} +#info { + margin: 65px auto 0; + color: #a6a6a6; + font-size: 12px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); + text-align: center; +} +#info a { + color: inherit; +} +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox and Opera + */ + +@media screen and (-webkit-min-device-pixel-ratio: 0) { + #toggle-all, #todo-list li .toggle { + background: none; + } +} +#todoapp .content .login { + width: 350px; + margin: 45px auto 25px auto; +} +#todoapp .content .login h2 { + font-weight: normal; + font-size: 25px; + margin-bottom: 20px; +} +#todoapp .content .login input { + display: block; + margin-bottom: 10px; + font-size: 20px; + padding: 5px; + width: 340px; + ; +} +#todoapp .content .login .signup-form { + margin-top: 25px; +} +#todoapp .content .login button { + padding: 5px 10px; + background: #eee; + font-size: 20px; + border: 1px solid #ccc; + border-radius: 5px; + margin-bottom: 25px; + font-family: "Helvetica Neue"; +} +#todoapp .content .login .error { + border: 1px solid red; + background: #FDEFF0; + padding: 5px 15px; + margin-bottom: 15px; +} +#todoapp .content #user-info { + padding: 5px 10px; + border-top: 1px solid #ededed; + margin-bottom: 0px; + text-align: right; +} +#todoapp .content .mark-all-done { + margin-left: 8px; +} +#credits { + color: #888; + text-align: center; + padding-top: 25px; +} +#credits a { + color: #888; +} \ No newline at end of file diff --git a/images/background.jpg b/images/background.jpg new file mode 100644 index 0000000..2495d75 Binary files /dev/null and b/images/background.jpg differ diff --git a/images/bg.png b/images/bg.png new file mode 100755 index 0000000..b2a7600 Binary files /dev/null and b/images/bg.png differ diff --git a/images/destroy.png b/images/destroy.png new file mode 100755 index 0000000..56d7637 Binary files /dev/null and b/images/destroy.png differ diff --git a/images/spinner.gif b/images/spinner.gif new file mode 100755 index 0000000..a377e16 Binary files /dev/null and b/images/spinner.gif differ diff --git a/index.html b/index.html old mode 100644 new mode 100755 index 33d38f7..55d4ea4 --- a/index.html +++ b/index.html @@ -1,9 +1,112 @@ - So-and-so's Stateful Assignment + + Parse JavaScript Todo App Amelia's Project based on this tutorial + + + + + + - YOUR PROJECT HERE + + + +
+
+

Amelia's trying to Parse
+ and make a to do list

+
+ +
+
+
+ + + + + + + + + + + + + + diff --git a/js/todos.js b/js/todos.js new file mode 100755 index 0000000..2ca8878 --- /dev/null +++ b/js/todos.js @@ -0,0 +1,407 @@ +// An example Parse.js Backbone application based on the todo app by +// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses Parse to persist +// the todo items and provide user authentication and sessions. + +$(function() { + + Parse.$ = jQuery; + + // Initialize Parse with your Parse application javascript keys + Parse.initialize("uyszhNIN81ETj9Pknwm9fm13fllUY8FAVRAx0N0K", + "PaEyhjgohqLytdYbMMLJUjJ80LvjGP6XLaw6Vgr9"); + + // Todo Model + // ---------- + + // Our basic Todo model has `content`, `order`, and `done` attributes. + var Todo = Parse.Object.extend("Todo", { + // Default attributes for the todo. + defaults: { + content: "empty todo...", + done: false + }, + + // Ensure that each todo created has `content`. + initialize: function() { + if (!this.get("content")) { + this.set({"content": this.defaults.content}); + } + }, + + // Toggle the `done` state of this todo item. + toggle: function() { + this.save({done: !this.get("done")}); + } + }); + + // This is the transient application state, not persisted on Parse + var AppState = Parse.Object.extend("AppState", { + defaults: { + filter: "all" + } + }); + + // Todo Collection + // --------------- + + var TodoList = Parse.Collection.extend({ + + // Reference to this collection's model. + model: Todo, + + // 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'); + } + + }); + + // Todo Item View + // -------------- + + // The DOM element for a todo item... + var TodoView = Parse.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 .toggle" : "toggleDone", + "dblclick label.todo-content" : "edit", + "click .todo-destroy" : "clear", + "keypress .edit" : "updateOnEnter", + "blur .edit" : "close" + }, + + // 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', 'remove'); + this.model.bind('change', this.render); + this.model.bind('destroy', this.remove); + }, + + // Re-render the contents of the todo item. + render: function() { + $(this.el).html(this.template(this.model.toJSON())); + this.input = this.$('.edit'); + return this; + }, + + // 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 the item, destroy the model. + clear: function() { + this.model.destroy(); + } + + }); + + // The Application + // --------------- + + // The main view that lets a user manage their todo items + var ManageTodosView = Parse.View.extend({ + + // 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", + "click #clear-completed": "clearCompleted", + "click #toggle-all": "toggleAllComplete", + "click .log-out": "logOut", + "click ul#filters a": "selectFilter" + }, + + el: ".content", + + // 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 to Parse. + initialize: function() { + var self = this; + + _.bindAll(this, 'addOne', 'addAll', 'addSome', 'render', 'toggleAllComplete', 'logOut', 'createOnEnter'); + + // Main todo management template + this.$el.html(_.template($("#manage-todos-template").html())); + + this.input = this.$("#new-todo"); + this.allCheckbox = this.$("#toggle-all")[0]; + + // Create our collection of Todos + this.todos = new TodoList; + + // Setup the query for the collection to look for todos from the current user + this.todos.query = new Parse.Query(Todo); + this.todos.query.equalTo("user", Parse.User.current()); + + this.todos.bind('add', this.addOne); + this.todos.bind('reset', this.addAll); + this.todos.bind('all', this.render); + + // Fetch all the todo items for this user + this.todos.fetch(); + + state.on("change", this.filter, this); + }, + + // Logs out the user and shows the login view + logOut: function(e) { + Parse.User.logOut(); + new LogInView(); + this.undelegateEvents(); + delete this; + }, + + // Re-rendering the App just means refreshing the statistics -- the rest + // of the app doesn't change. + render: function() { + var done = this.todos.done().length; + var remaining = this.todos.remaining().length; + + this.$('#todo-stats').html(this.statsTemplate({ + total: this.todos.length, + done: done, + remaining: remaining + })); + + this.delegateEvents(); + + this.allCheckbox.checked = !remaining; + }, + + // Filters the list based on which type of filter is selected + selectFilter: function(e) { + var el = $(e.target); + var filterValue = el.attr("id"); + state.set({filter: filterValue}); + Parse.history.navigate(filterValue); + }, + + filter: function() { + var filterValue = state.get("filter"); + this.$("ul#filters a").removeClass("selected"); + this.$("ul#filters a#" + filterValue).addClass("selected"); + if (filterValue === "all") { + this.addAll(); + } else if (filterValue === "completed") { + this.addSome(function(item) { return item.get('done') }); + } else { + this.addSome(function(item) { return !item.get('done') }); + } + }, + + // Resets the filters to display all todos + resetFilters: function() { + this.$("ul#filters a").removeClass("selected"); + this.$("ul#filters a#all").addClass("selected"); + this.addAll(); + }, + + // Add a single todo item to the list by creating a view for it, and + // appending its element to the `