Commit 87d90ac8 authored by Pascal Hartig's avatar Pascal Hartig Committed by Sindre Sorhus

TroopJS Update

Closes #422
parent bd8155f5
......@@ -5,7 +5,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Troop.js • TodoMVC</title>
<link rel="stylesheet" href="../../../assets/base.css">
<!-- CSS overrides - remove if you don't need it -->
<link rel="stylesheet" href="css/app.css">
<!--[if IE]>
<script src="../../../assets/ie.js"></script>
......@@ -17,17 +16,13 @@
<h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus data-weave="widget/create">
</header>
<!-- This section should be hidden by default and shown when there are todos -->
<section id="main" data-weave="widget/display">
<input id="toggle-all" type="checkbox" data-weave="widget/mark">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list" data-weave="widget/list"></ul>
</section>
<!-- This footer should hidden by default and shown when there are todos -->
<footer id="footer" data-weave="widget/display">
<!-- This should be `0 items left` by default -->
<span id="todo-count" data-weave="widget/count"><strong>0</strong> items left</span>
<!-- Remove this if you don't implement routing -->
<ul id="filters" data-weave="widget/filters">
<li>
<a href="#/">All</a>
......@@ -44,11 +39,9 @@
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<!-- Change this out with your name and url ↓ -->
<p>Created by <a href="http://github.com/mikaelkaron">Mikael Karon</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<!-- Scripts here. Don't remove this ↓ -->
<script src="../../../assets/base.js"></script>
<script type="text/javascript" data-main="js/app.js" src="../../../assets/require.min.js"></script>
</body>
......
require({
"paths" : {
"jquery" : "../../../../assets/jquery.min",
"troopjs-bundle" : "lib/troopjs-bundle.min"
},
}, [ "require", "jquery", "troopjs-bundle" ], function Deps(parentRequire, jQuery) {
'paths': {
'jquery': '../../../../assets/jquery.min',
'troopjs-bundle': 'lib/troopjs-bundle.min'
}
}, [ 'require', 'jquery', 'troopjs-bundle' ], function Deps(parentRequire, jQuery) {
// Application and plug-ins
parentRequire([
"widget/application",
"troopjs-jquery/weave",
"troopjs-jquery/destroy",
"troopjs-jquery/hashchange",
"troopjs-jquery/action" ], function App(Application) {
'widget/application',
'troopjs-jquery/weave',
'troopjs-jquery/destroy',
'troopjs-jquery/hashchange',
'troopjs-jquery/action' ], function App(Application) {
// Hook ready
jQuery(document).ready(function ready($) {
Application($(this.body), "app/todos").start();
Application($(this.body), 'app/todos').start();
});
});
});
define({
"store": "todos-troopjs"
'store': 'todos-troopjs'
});
define( [ "troopjs-core/widget/application", "troopjs-core/route/router", "jquery" ], function ApplicationModule(Application, Router, $) {
define( [ 'troopjs-core/widget/application', 'troopjs-core/route/router', 'jquery' ], function ApplicationModule(Application, Router, $) {
function forward(signal, deferred) {
var services = $.map(this.services, function map(service, index) {
......@@ -13,11 +13,11 @@ define( [ "troopjs-core/widget/application", "troopjs-core/route/router", "jquer
}
return Application.extend({
"sig/initialize" : forward,
"sig/finalize" : forward,
"sig/start" : forward,
"sif/stop" : forward,
'sig/initialize': forward,
'sig/finalize': forward,
'sig/start': forward,
'sif/stop': forward,
services : [ Router($(window)) ]
services: [ Router($(window)) ]
});
});
define( [ "troopjs-core/component/widget", "jquery" ], function ClearModule(Widget, $) {
define( [ 'troopjs-core/component/widget', 'jquery' ], function ClearModule(Widget, $) {
function filter(item, index) {
return item === null || !item.completed;
}
return Widget.extend({
"hub:memory/todos/change" : function onChange(topic, items) {
'hub:memory/todos/change': function onChange(topic, items) {
var count = $.grep(items, filter, true).length;
this.$element.text("Clear completed (" + count + ")")[count > 0 ? "show" : "hide"]();
this.$element.text('Clear completed (' + count + ')')[count > 0 ? 'show' : 'hide']();
},
"dom/click" : function onClear(topic, $event) {
this.publish("todos/clear");
'dom/click': function onClear(topic, $event) {
this.publish('todos/clear');
}
});
});
define( [ "troopjs-core/component/widget", "jquery" ], function CountModule(Widget, $) {
define( [ 'troopjs-core/component/widget', 'jquery' ], function CountModule(Widget, $) {
function filter(item, index) {
return item === null || item.completed;
}
return Widget.extend({
"hub:memory/todos/change" : function onChange(topic, items) {
'hub:memory/todos/change': function onChange(topic, items) {
var count = $.grep(items, filter, true).length;
this.$element.html("<strong>" + count + "</strong> " + (count === 1 ? "item" : "items") + " left");
this.$element.html('<strong>' + count + '</strong> ' + (count === 1 ? 'item' : 'items') + ' left');
}
});
});
define( [ "troopjs-core/component/widget" ], function CreateModule(Widget) {
define( [ 'troopjs-core/component/widget' ], function CreateModule(Widget) {
var ENTER_KEY = 13;
return Widget.extend({
"dom/keyup" : function onKeyUp(topic, $event) {
var self = this;
var $element = self.$element;
'dom/keyup': function onKeyUp(topic, $event) {
var $element = this.$element;
var value;
switch($event.keyCode) {
case ENTER_KEY:
if ($event.keyCode === ENTER_KEY) {
value = $element.val().trim();
if (value !== "") {
self.publish("todos/add", value);
if (value !== '') {
this.publish('todos/add', value);
$element.val("");
$element.val('');
}
}
}
......
define( [ "troopjs-core/component/widget", "jquery" ], function DisplayModule(Widget, $) {
define( [ 'troopjs-core/component/widget', 'jquery' ], function DisplayModule(Widget, $) {
function filter(item, index) {
return item === null;
}
return Widget.extend({
"hub:memory/todos/change": function onChange(topic, items) {
this.$element[$.grep(items, filter, true).length > 0 ? "show" : "hide"]();
'hub:memory/todos/change': function onChange(topic, items) {
this.$element[$.grep(items, filter, true).length > 0 ? 'show' : 'hide']();
}
});
});
define( ['jquery'], function EscapeModule($) {
var entityMap = {
escape: {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'/': '&#x2F;'
}
},
invert = function(obj) {
var result = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
result[obj[key]] = key;
}
}
return result;
},
nativeKeys = Object.keys,
keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) {
throw new TypeError('Invalid object');
}
var keys = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
keys[keys.length] = key;
}
}
return keys;
};
exports = {};
entityMap.unescape = invert(entityMap.escape);
var entityRegexes = {
escape: new RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'),
unescape: new RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g')
};
$.each(['escape', 'unescape'], function(i, method) {
exports[method] = function(string) {
if (string == null) {
return '';
}
return ('' + string).replace(entityRegexes[method], function(match) {
return entityMap[method][match];
});
};
});
return exports;
});
define( [ "troopjs-core/component/widget", "jquery" ], function FiltersModule(Widget, $) {
define( [ 'troopjs-core/component/widget', 'jquery' ], function FiltersModule(Widget, $) {
return Widget.extend({
"hub:memory/route" : function onRoute(topic, uri) {
this.publish("todos/filter", uri.source);
'hub:memory/route': function onRoute(topic, uri) {
this.publish('todos/filter', uri.source);
},
"hub:memory/todos/filter" : function onFilter(topic, filter) {
filter = filter || "/";
'hub:memory/todos/filter': function onFilter(topic, filter) {
filter = filter || '/';
// Update UI
$("a[href^='#']")
.removeClass("selected")
.filter("[href='#" + filter + "']")
.addClass("selected");
$('a[href^="#"]')
.removeClass('selected')
.filter('[href="#' + filter + '"]')
.addClass('selected');
}
});
});
<%
var i = data.i;
var item = data.item;
var title = data.itemTitle;
var completed = item.completed;
%>
<li class="<%= (completed ? 'completed' : 'active') %>">
<div class="view" data-action="prepare(<%= i %>)">
<input class="toggle" type="checkbox" <%= (completed ? 'checked' : '') %> data-action="status(<%= i %>)">
<label><%= item.title %></label>
<label><%= title %></label>
<button class="destroy" data-action="delete(<%= i %>)"></button>
</div>
<input class="edit" data-action="commit(<%= i %>)">
......
define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery", "template!./item.html" ], function ListModule(Widget, store, $, template) {
define( [ './escape', 'troopjs-core/component/widget', 'troopjs-core/store/local', 'jquery', 'template!./item.html' ], function ListModule(Escaper, Widget, store, $, template) {
var ENTER_KEY = 13;
var FILTER_ACTIVE = "filter-active";
var FILTER_COMPLETED = "filter-completed";
var FILTER_ACTIVE = 'filter-active';
var FILTER_COMPLETED = 'filter-completed';
function filter(item, index) {
return item === null;
......@@ -26,16 +26,17 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
$.each(items, function itemIterator(i, item) {
// Append to self
self.append(template, {
"i": i,
"item": item
'i': i,
'item': item,
'itemTitle': Escaper.escape(item.title)
});
});
})
.done(function doneInit(items) {
self.publish("todos/change", items);
self.publish('todos/change', items);
});
}, {
"hub/todos/add" : function onAdd(topic, title) {
'hub/todos/add': function onAdd(topic, title) {
var self = this;
// Defer set
......@@ -50,14 +51,15 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
// Create new item, store in items
var item = items[i] = {
"completed": false,
"title": title
'completed': false,
'title': title
};
// Append new item to self
self.append(template, {
"i": i,
"item": item
'i': i,
'item': item,
'itemTitle': Escaper.escape(item.title)
});
// Set items and resolve set
......@@ -65,51 +67,51 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
});
})
.done(function doneSet(items) {
self.publish("todos/change", items);
self.publish('todos/change', items);
});
},
"hub/todos/mark" : function onMark(topic, value) {
this.$element.find(":checkbox").prop("checked", value).change();
'hub/todos/mark': function onMark(topic, value) {
this.$element.find(':checkbox').prop('checked', value).change();
},
"hub/todos/clear" : function onClear(topic) {
this.$element.find(".completed .destroy").click();
'hub/todos/clear': function onClear(topic) {
this.$element.find('.completed .destroy').click();
},
"hub:memory/todos/filter" : function onFilter(topic, filter) {
'hub:memory/todos/filter': function onFilter(topic, filter) {
var $element = this.$element;
switch (filter) {
case "/completed":
case '/completed':
$element
.removeClass(FILTER_ACTIVE)
.addClass(FILTER_COMPLETED);
break;
case "/active":
case '/active':
$element
.removeClass(FILTER_COMPLETED)
.addClass(FILTER_ACTIVE);
break;
default:
$element.removeClass([FILTER_ACTIVE, FILTER_COMPLETED].join(" "));
$element.removeClass([FILTER_ACTIVE, FILTER_COMPLETED].join(' '));
}
},
"dom/action.change.click.dblclick.focusout.keyup" : $.noop,
'dom/action.change.click.dblclick.focusout.keyup': $.noop,
"dom/action/status.change" : function onStatus(topic, $event, index) {
'dom/action/status.change': function onStatus(topic, $event, index) {
var self = this;
var $target = $($event.target);
var completed = $target.prop("checked");
var completed = $target.prop('checked');
// Update UI
$target
.closest("li")
.toggleClass("completed", completed)
.toggleClass("active", !completed);
.closest('li')
.toggleClass('completed', completed)
.toggleClass('active', !completed);
// Defer set
$.Deferred(function deferredSet(deferSet) {
......@@ -126,16 +128,16 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
});
})
.done(function doneSet(items) {
self.publish("todos/change", items);
self.publish('todos/change', items);
});
},
"dom/action/delete.click" : function onDelete(topic, $event, index) {
'dom/action/delete.click': function onDelete(topic, $event, index) {
var self = this;
// Update UI
$($event.target)
.closest("li")
.closest('li')
.remove();
// Defer set
......@@ -154,22 +156,22 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
});
})
.done(function doneSet(items) {
self.publish("todos/change", items);
self.publish('todos/change', items);
});
},
"dom/action/prepare.dblclick" : function onPrepare(topic, $event, index) {
'dom/action/prepare.dblclick': function onPrepare(topic, $event, index) {
var self = this;
// Get LI and update
var $li = $($event.target)
.closest("li")
.addClass("editing");
.closest('li')
.addClass('editing');
// Get INPUT and disable
var $input = $li
.find("input")
.prop("disabled", true);
.find('input')
.prop('disabled', true);
// Defer get
$.Deferred(function deferredGet(deferGet) {
......@@ -180,38 +182,37 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
// Update input value, enable and select
$input
.val(items[index].title)
.removeProp("disabled")
.removeProp('disabled')
.focus();
})
.fail(function failGet() {
$li.removeClass("editing");
$li.removeClass('editing');
});
},
"dom/action/commit.keyup" : function onCommitKeyUp(topic, $event) {
switch($event.originalEvent.keyCode) {
case ENTER_KEY:
'dom/action/commit.keyup': function onCommitKeyUp(topic, $event) {
if ($event.originalEvent.keyCode === ENTER_KEY) {
$($event.target).focusout();
}
},
"dom/action/commit.focusout" : function onCommitFocusOut(topic, $event, index) {
'dom/action/commit.focusout': function onCommitFocusOut(topic, $event, index) {
var self = this;
var $target = $($event.target);
var title = $target.val().trim();
if (title === "") {
if (title === '') {
$target
.closest("li.editing")
.removeClass("editing")
.find(".destroy")
.closest('li.editing')
.removeClass('editing')
.find('.destroy')
.click();
}
else {
// Defer set
$.Deferred(function deferredSet(deferSet) {
// Disable
$target.prop("disabled", true);
$target.prop('disabled', true);
// Defer get
$.Deferred(function deferredGet(deferGet) {
......@@ -229,16 +230,16 @@ define( [ "troopjs-core/component/widget", "troopjs-core/store/local", "jquery",
.done(function doneSet(items) {
// Update UI
$target
.closest("li")
.removeClass("editing")
.find("label")
.closest('li')
.removeClass('editing')
.find('label')
.text(title);
self.publish("todos/change", items);
self.publish('todos/change', items);
})
.always(function alwaysSet() {
// Enable
$target.removeProp("disabled");
$target.removeProp('disabled');
});
}
}
......
define( [ "troopjs-core/component/widget" ], function MarkModule(Widget) {
define( [ 'troopjs-core/component/widget' ], function MarkModule(Widget) {
return Widget.extend({
"hub:memory/todos/change" : function onChange(topic, items) {
'hub:memory/todos/change': function onChange(topic, items) {
var total = 0;
var count = 0;
var $element = this.$element;
......@@ -20,23 +20,23 @@ define( [ "troopjs-core/component/widget" ], function MarkModule(Widget) {
if (count === 0) {
$element
.prop("indeterminate", false)
.prop("checked", false);
.prop('indeterminate', false)
.prop('checked', false);
}
else if (count === total) {
$element
.prop("indeterminate", false)
.prop("checked", true);
.prop('indeterminate', false)
.prop('checked', true);
}
else {
$element
.prop("indeterminate", true)
.prop("checked", false);
.prop('indeterminate', true)
.prop('checked', false);
}
},
"dom/change" : function onMark(topic, $event) {
this.publish("todos/mark", $($event.target).prop("checked"));
'dom/change': function onMark(topic, $event) {
this.publish('todos/mark', $($event.target).prop('checked'));
}
});
});
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