Commit fcc5981c authored by Stephen Sawchuk's avatar Stephen Sawchuk

knockoutjs_require codestyle.

parent 27850eac
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" type="text" data-bind="value: current, valueUpdate: 'afterkeydown', enterKey: add" <input id="new-todo" type="text" data-bind="value: current, valueUpdate: 'afterkeydown', enterKey: add" placeholder="What needs to be done?" autofocus>
placeholder="What needs to be done?" autofocus>
</header> </header>
<section id="main" data-bind="visible: todos().length"> <section id="main" data-bind="visible: todos().length">
<input id="toggle-all" type="checkbox" data-bind="checked: allCompleted"> <input id="toggle-all" type="checkbox" data-bind="checked: allCompleted">
......
/*global define */
// Author: Loïc Knuchel <loicknuchel@gmail.com> // Author: Loïc Knuchel <loicknuchel@gmail.com>
define({ define({
ENTER_KEY: 13, ENTER_KEY: 13,
localStorageItem: 'todos-knockout-require' localStorageItem: 'todos-knockout-require'
}); });
/*global define */
define([ define([
'knockout', 'knockout',
'config/global' 'config/global'
], function(ko, g){ ], function (ko, g) {
'use strict'; 'use strict';
// a custom binding to handle the enter key (could go in a separate library)
ko.bindingHandlers.enterKey = { // a custom binding to handle the enter key (could go in a separate library)
init: function( element, valueAccessor, allBindingsAccessor, data ) { ko.bindingHandlers.enterKey = {
var wrappedHandler, newValueAccessor; init: function (element, valueAccessor, allBindingsAccessor, data) {
var wrappedHandler;
var newValueAccessor;
// wrap the handler with a check for the enter key // wrap the handler with a check for the enter key
wrappedHandler = function( data, event ) { wrappedHandler = function (data, event) {
if ( event.keyCode === g.ENTER_KEY ) { if (event.keyCode === g.ENTER_KEY) {
valueAccessor().call( this, data, event ); valueAccessor().call(this, data, event);
} }
}; };
// create a valueAccessor with the options that we would want to pass to the event binding // create a valueAccessor with the options that we would want to pass to the event binding
newValueAccessor = function() { newValueAccessor = function () {
return { return {
keyup: wrappedHandler keyup: wrappedHandler
}; };
}; };
// call the real event binding's init function // call the real event binding's init function
ko.bindingHandlers.event.init( element, newValueAccessor, allBindingsAccessor, data ); ko.bindingHandlers.event.init(element, newValueAccessor, allBindingsAccessor, data);
} }
}; };
// wrapper to hasfocus that also selects text and applies focus async // wrapper to hasfocus that also selects text and applies focus async
ko.bindingHandlers.selectAndFocus = { ko.bindingHandlers.selectAndFocus = {
init: function( element, valueAccessor, allBindingsAccessor ) { init: function (element, valueAccessor, allBindingsAccessor) {
ko.bindingHandlers.hasfocus.init( element, valueAccessor, allBindingsAccessor ); ko.bindingHandlers.hasfocus.init(element, valueAccessor, allBindingsAccessor);
ko.utils.registerEventHandler( element, 'focus', function() { ko.utils.registerEventHandler(element, 'focus', function () {
element.focus(); element.focus();
} ); });
}, },
update: function( element, valueAccessor ) { update: function (element, valueAccessor) {
ko.utils.unwrapObservable( valueAccessor() ); // for dependency ko.utils.unwrapObservable(valueAccessor()); // for dependency
// ensure that element is visible before trying to focus // ensure that element is visible before trying to focus
setTimeout(function() { setTimeout(function () {
ko.bindingHandlers.hasfocus.update( element, valueAccessor ); ko.bindingHandlers.hasfocus.update(element, valueAccessor);
}, 0 ); }, 0);
} }
}; };
}); });
define(function(){
'use strict';
// trim polyfill
if ( !String.prototype.trim ) {
String.prototype.trim = function() {
return this.replace( /^\s+|\s+$/g, '' );
};
}
});
/*global require, window */
// Author: Loïc Knuchel <loicknuchel@gmail.com> // Author: Loïc Knuchel <loicknuchel@gmail.com>
// Require.js allows us to configure shortcut alias // Require.js allows us to configure shortcut alias
require.config({ require.config({
paths: { paths: {
knockout: '../bower_components/knockout.js/knockout' knockout: '../bower_components/knockout.js/knockout'
} }
}); });
require([ require([
'knockout', 'knockout',
'config/global', 'config/global',
'viewmodels/todo', 'viewmodels/todo',
'extends/handlers', 'extends/handlers'
'extends/native' ], function (ko, g, TodoViewModel) {
], function(ko, g, TodoViewModel){ 'use strict';
'use strict';
// var app_view = new AppView(); // var app_view = new AppView();
// check local storage for todos // check local storage for todos
var todos = ko.utils.parseJson( localStorage.getItem( g.localStorageItem ) ); var todos = ko.utils.parseJson(window.localStorage.getItem(g.localStorageItem));
// bind a new instance of our view model to the page // bind a new instance of our view model to the page
ko.applyBindings( new TodoViewModel( todos || [] ) ); ko.applyBindings(new TodoViewModel(todos || []));
}); });
/*global define */
define([ define([
'knockout' 'knockout'
], function(ko){ ], function (ko) {
'use strict'; 'use strict';
// represent a single todo item
var Todo = function( title, completed ) { // represent a single todo item
this.title = ko.observable( title ); var Todo = function (title, completed) {
this.completed = ko.observable( completed ); this.title = ko.observable(title);
this.editing = ko.observable( false ); this.completed = ko.observable(completed);
}; this.editing = ko.observable(false);
return Todo; };
return Todo;
}); });
/*global define, window */
define([ define([
'knockout', 'knockout',
'config/global', 'config/global',
'models/Todo' 'models/Todo'
], function(ko, g, Todo){ ], function (ko, g, Todo) {
'use strict'; 'use strict';
// our main view model
var ViewModel = function( todos ) { // our main view model
var self = this; var ViewModel = function (todos) {
var self = this;
// map array of passed in todos to an observableArray of Todo objects
self.todos = ko.observableArray( ko.utils.arrayMap( todos, function( todo ) { // map array of passed in todos to an observableArray of Todo objects
return new Todo( todo.title, todo.completed ); self.todos = ko.observableArray(ko.utils.arrayMap(todos, function (todo) {
})); return new Todo(todo.title, todo.completed);
}));
// store the new todo value being entered
self.current = ko.observable(); // store the new todo value being entered
self.current = ko.observable();
// add a new todo, when enter key is pressed
// add a new todo, when enter key is pressed self.add = function () {
self.add = function() { var current = self.current().trim();
var current = self.current().trim();
if ( current ) { if (current) {
self.todos.push( new Todo( current ) ); self.todos.push(new Todo(current));
self.current( '' ); self.current('');
} }
}; };
// remove a single todo // remove a single todo
self.remove = function( todo ) { self.remove = function (todo) {
self.todos.remove( todo ); self.todos.remove(todo);
}; };
// remove all completed todos // remove all completed todos
self.removeCompleted = function() { self.removeCompleted = function () {
self.todos.remove(function( todo ) { self.todos.remove(function (todo) {
return todo.completed(); return todo.completed();
}); });
}; };
// edit an item // edit an item
self.editItem = function( item ) { self.editItem = function (item) {
item.editing( true ); item.editing(true);
}; };
// stop editing an item. Remove the item, if it is now empty // stop editing an item. Remove the item, if it is now empty
self.stopEditing = function( item ) { self.stopEditing = function (item) {
item.editing( false ); item.editing(false);
if ( !item.title().trim() ) {
self.remove( item ); if (!item.title().trim()) {
} self.remove(item);
}; }
};
// count of all completed todos
self.completedCount = ko.computed(function() { // count of all completed todos
return ko.utils.arrayFilter( self.todos(), function(todo) { self.completedCount = ko.computed(function () {
return todo.completed(); return ko.utils.arrayFilter(self.todos(), function (todo) {
} ).length; return todo.completed();
}); }).length;
});
// count of todos that are not complete
self.remainingCount = ko.computed(function() { // count of todos that are not complete
return self.todos().length - self.completedCount(); self.remainingCount = ko.computed(function () {
}); return self.todos().length - self.completedCount();
});
// writeable computed observable to handle marking all complete/incomplete
self.allCompleted = ko.computed({ // writeable computed observable to handle marking all complete/incomplete
//always return true/false based on the done flag of all todos self.allCompleted = ko.computed({
read: function() { //always return true/false based on the done flag of all todos
return !self.remainingCount(); read: function () {
}, return !self.remainingCount();
// set all todos to the written value (true/false) },
write: function( newValue ) { // set all todos to the written value (true/false)
ko.utils.arrayForEach(self.todos(), function( todo ) { write: function (newValue) {
// set even if value is the same, as subscribers are not notified in that case ko.utils.arrayForEach(self.todos(), function (todo) {
todo.completed( newValue ); // set even if value is the same, as subscribers are not notified in that case
}); todo.completed(newValue);
} });
}); }
});
// helper function to keep expressions out of markup
self.getLabel = function( count ) { // helper function to keep expressions out of markup
return ko.utils.unwrapObservable( count ) === 1 ? 'item' : 'items'; self.getLabel = function (count) {
}; return ko.utils.unwrapObservable(count) === 1 ? 'item' : 'items';
};
// internal computed observable that fires whenever anything changes in our todos
ko.computed(function() { // internal computed observable that fires whenever anything changes in our todos
// store a clean copy to local storage, which also creates a dependency on the observableArray and all observables in each item ko.computed(function () {
localStorage.setItem( g.localStorageItem, ko.toJSON( self.todos ) ); // store a clean copy to local storage, which also creates a dependency on the observableArray and all observables in each item
}).extend({ window.localStorage.setItem(g.localStorageItem, ko.toJSON(self.todos));
throttle: 500 }).extend({
}); // save at most twice per second throttle: 500
}); // save at most twice per second
}; };
return ViewModel;
return ViewModel;
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment