Commit 74d16714 authored by Burke Holland's avatar Burke Holland Committed by Sindre Sorhus

Close GH-810: Update to use Bower and new Kendo UI Router.

parent 101f4661
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"todomvc-common": "~0.1.6", "todomvc-common": "~0.1.6",
"jquery": "~2.0.0" "jquery": "~2.1.0",
"kendo-ui": "~2013.3.1119"
} }
} }
...@@ -9,15 +9,15 @@ ...@@ -9,15 +9,15 @@
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" data-bind="enter: saveTodo" <input id="new-todo" data-bind="enter: saveTodo, value: newTodo"
placeholder="What needs to be done?" autofocus> placeholder="What needs to be done?" autofocus>
</header> </header>
<section id="main" data-bind="visible: isVisible"> <section id="main" data-bind="attr: { class : isVisible }">
<input id="toggle-all" type="checkbox" data-bind="click: toggleAll, checked: allCompleted"> <input id="toggle-all" type="checkbox" data-bind="events: { click: toggleAll }, checked: allCompleted">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list" data-role="listview" data-template="item-template" data-bind="source: todos"></ul> <ul id="todo-list" data-template="item-template" data-bind="source: todos"></ul>
</section> </section>
<footer id="footer" data-bind="visible: isVisible"> <footer id="footer" class="hidden" data-bind="attr: { class: isVisible }">
<span id="todo-count"> <span id="todo-count">
<strong data-bind="text: activeCount"></strong> <strong data-bind="text: activeCount"></strong>
<span data-bind="text: activeCountText"></span> left <span data-bind="text: activeCountText"></span> left
...@@ -53,12 +53,15 @@ ...@@ -53,12 +53,15 @@
<button class="destroy" data-bind="click: destroy"> <button class="destroy" data-bind="click: destroy">
</button> </button>
</div> </div>
<input class="edit" data-bind="value: title, events: { change: endEdit, blur: endEdit }, enter: endEdit"> <input class="edit" data-bind="value: title, events: { blur: endEdit, change: endEdit }, enter: endEdit, escape: cancelEdit">
</li> </li>
</script> </script>
<script src="bower_components/todomvc-common/base.js"></script> <script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script> <script src="bower_components/jquery/jquery.js"></script>
<script src="js/lib/kendo.web.js"></script> <script src="bower_components/kendo-ui/src/js/kendo.core.js"></script>
<script src="bower_components/kendo-ui/src/js/kendo.data.js"></script>
<script src="bower_components/kendo-ui/src/js/kendo.binder.js"></script>
<script src="bower_components/kendo-ui/src/js/kendo.router.js"></script>
<script src="js/lib/kendo.bindings.custom.js"></script> <script src="js/lib/kendo.bindings.custom.js"></script>
<script src="js/lib/kendo.data.localstoragedatasource.js"></script> <script src="js/lib/kendo.data.localstoragedatasource.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
......
...@@ -10,22 +10,24 @@ var app = app || {}; ...@@ -10,22 +10,24 @@ var app = app || {};
}; };
// Route object to manage filtering the todo item list // Route object to manage filtering the todo item list
var routes = { var router = new kendo.Router();
'/': function () {
app.todoData.filter({}); router.route('/', function () {
app.todoViewModel.set('filter', ''); app.todoData.filter({});
}, app.todoViewModel.set('filter', '');
'/active': function () { });
filterBase.value = false;
app.todoData.filter(filterBase); router.route('/active', function () {
app.todoViewModel.set('filter', 'active'); filterBase.value = false;
}, app.todoData.filter(filterBase);
'/completed': function () { app.todoViewModel.set('filter', 'active');
filterBase.value = true; });
app.todoData.filter(filterBase);
app.todoViewModel.set('filter', 'completed'); router.route('/completed', function () {
} filterBase.value = true;
}; app.todoData.filter(filterBase);
app.todoViewModel.set('filter', 'completed');
});
// Todo Model Object // Todo Model Object
app.Todo = kendo.data.Model.define({ app.Todo = kendo.data.Model.define({
...@@ -46,6 +48,13 @@ var app = app || {}; ...@@ -46,6 +48,13 @@ var app = app || {};
itemBase: 'todos-kendo', itemBase: 'todos-kendo',
schema: { schema: {
model: app.Todo model: app.Todo
},
change: function () {
var completed = $.grep(this.data(), function (el) {
return el.get('completed');
});
app.todoViewModel.set('allCompleted', completed.length === this.data().length);
} }
}); });
...@@ -54,63 +63,71 @@ var app = app || {}; ...@@ -54,63 +63,71 @@ var app = app || {};
todos: app.todoData, todos: app.todoData,
filter: null, filter: null,
// Handle route changes and direct to the appropriate handler in our
// local routes object.
routeChanged: function (url) {
routes[url || '/'].call(this);
},
// Main element visibility handler // Main element visibility handler
isVisible: function () { isVisible: function () {
return this.get('todos').data().length; return this.get('todos').data().length ? '' : 'hidden';
}, },
// new todo value
newTodo: null,
// Core CRUD Methods // Core CRUD Methods
saveTodo: function () { saveTodo: function () {
var todos = this.get('todos'); var todos = this.get('todos');
var newTodo = $('#new-todo'); var newTodo = this.get('newTodo');
var todo = new app.Todo({ var todo = new app.Todo({
title: newTodo.val().trim(), title: newTodo.trim(),
completed: false, completed: false,
edit: false edit: false
}); });
todos.add(todo); todos.add(todo);
todos.sync(); todos.sync();
newTodo.val(''); this.set('newTodo', null);
}, },
toggleAll: function () { toggleAll: function () {
var completed = this.completedTodos().length === this.get('todos').data().length; var completed = this.completedTodos().length === this.get('todos').data().length;
$.grep(this.get('todos').data(), function (el) { $.grep(this.get('todos').data(), function (el) {
el.set('completed', !completed); el.set('completed', !completed);
}); });
}, },
startEdit: function (e) { startEdit: function (e) {
e.data.set('edit', true); e.data.set('edit', true);
$('li[data-uid=' + e.data.uid + ']').find('input').focus(); this.set('titleCache', e.data.get('title'));
$(e.target).closest('li').find('input').focus();
}, },
endEdit: function (e) { endEdit: function (e) {
var editData = e; var editData = e,
title;
if (e.data) { if (e.data) {
editData = e.data; editData = e.data;
title = e.data.get('title');
// If the todo has a title, set it's edit property // If the todo has a title, set it's edit property
// to false. Otherwise, delete it. // to false. Otherwise, delete it.
if (editData.title.trim()) { if (editData.title.trim()) {
editData.set('edit', false); editData.set('title', title.trim());
} else { } else {
this.destroy(e); this.destroy(e);
} }
} }
this.todos.sync();
editData.set('edit', false); editData.set('edit', false);
},
cancelEdit: function (e) {
e.set('title', this.get('titleCache'));
e.set('edit', false);
this.todos.sync(); this.todos.sync();
}, },
sync: function () { sync: function () {
this.todos.sync(); this.get('todos').sync();
}, },
destroy: function (e) { destroy: function (e) {
this.todos.remove(e.data); this.todos.remove(e.data);
...@@ -140,9 +157,8 @@ var app = app || {}; ...@@ -140,9 +157,8 @@ var app = app || {};
completedCount: function () { completedCount: function () {
return this.completedTodos().length; return this.completedTodos().length;
}, },
allCompleted: function () {
return this.completedTodos().length === this.get('todos').data().length; allCompleted: false,
},
// Text value bound methods // Text value bound methods
activeCountText: function () { activeCountText: function () {
...@@ -172,18 +188,9 @@ var app = app || {}; ...@@ -172,18 +188,9 @@ var app = app || {};
}); });
// Kendo History object for capturing hash changes and triggering
// our route-changed handler
kendo.history.start({
ready: function (e) {
app.todoViewModel.routeChanged(e.url);
},
change: function (e) {
app.todoViewModel.routeChanged(e.url);
}
});
// Bind the ViewModel to the todoapp DOM element // Bind the ViewModel to the todoapp DOM element
kendo.bind($('#todoapp'), app.todoViewModel); kendo.bind($('#todoapp'), app.todoViewModel);
router.start();
}($, kendo)); }($, kendo));
...@@ -26,4 +26,29 @@ ...@@ -26,4 +26,29 @@
refresh: function () {} refresh: function () {}
}); });
var ESCAPE_KEY = 27;
// Create a custom "enter" binding by extending the kendo.data.Binder
// object with a custom init function that binds to the keyup event and,
// if the enter key is pressed, will call a bound function.
kendo.data.binders.escape = kendo.data.Binder.extend({
init: function (widget, bindings, options) {
// Call the "base" init method
kendo.data.Binder.fn.init.call(this, widget, bindings, options);
$(this.element).bind('keyup', function (e) {
// If the keypressed is not the escape key, return
if (e.which !== ESCAPE_KEY) {
return;
}
// Otherwise, call the function specified in the enter binding
this.bindings['escape'].get();
}.bind(this));
},
// The refresh function must be specified in a custom binding,
// even when empty.
refresh: function () {}
});
})($, kendo); })($, kendo);
\ No newline at end of file
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