Commit a543e298 authored by Sindre Sorhus's avatar Sindre Sorhus

Flight - code style

parent 994d727a
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'./data/todos', './data/todos',
'./data/stats', './data/stats',
...@@ -25,11 +25,11 @@ define( ...@@ -25,11 +25,11 @@ define(
StatsData.attachTo(document); StatsData.attachTo(document);
TodosData.attachTo(document); TodosData.attachTo(document);
NewItemUI.attachTo('#new-todo'); NewItemUI.attachTo('#new-todo');
MainSelectorUI.attachTo("#main"); MainSelectorUI.attachTo('#main');
StatsUI.attachTo('#footer'); StatsUI.attachTo('#footer');
ToggleAllUI.attachTo('#toggle-all'); ToggleAllUI.attachTo('#toggle-all');
TodoListUI.attachTo('#todo-list'); TodoListUI.attachTo('#todo-list');
} };
return { return {
initialize: initialize initialize: initialize
......
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'flight/component', 'flight/component',
'../store' '../store'
], ],
function (defineComponent, dataStore) { function (defineComponent, dataStore) {
return defineComponent(stats); return defineComponent(stats);
function stats() { function stats() {
...@@ -16,7 +15,7 @@ define( ...@@ -16,7 +15,7 @@ define(
var todos = dataStore.all(); var todos = dataStore.all();
var all = todos.length; var all = todos.length;
var remaining = todos.reduce(function (memo, each) { var remaining = todos.reduce(function (memo, each) {
return memo += (each.completed) ? 0 : 1; return memo += each.completed ? 0 : 1;
}, 0); }, 0);
this.trigger('dataStatsCounted', { this.trigger('dataStatsCounted', {
...@@ -25,7 +24,7 @@ define( ...@@ -25,7 +24,7 @@ define(
completed: all - remaining, completed: all - remaining,
filter: localStorage.getItem('filter') || '' filter: localStorage.getItem('filter') || ''
}); });
} };
this.after('initialize', function () { this.after('initialize', function () {
this.on(document, 'dataTodosLoaded', this.recount); this.on(document, 'dataTodosLoaded', this.recount);
......
/*global define */
'use strict'; 'use strict';
define( define(
[
[ 'flight/component',
'flight/component', '../store'
'../store' ],
],
function (defineComponent, dataStore) {
function (defineComponent, dataStore) { return defineComponent(todos);
return defineComponent(todos); function todos() {
var filter;
function todos() {
this.add = function (e, data) {
var filter; var todo = dataStore.save({
title: data.title,
this.add = function (e, data) { completed: false
var todo = dataStore.save({ });
title: data.title,
completed: false this.trigger('dataTodoAdded', { todo: todo, filter: filter });
}); };
this.trigger('dataTodoAdded', { todo: todo, filter: filter }); this.remove = function (e, data) {
} var todo = dataStore.destroy(data.id);
this.remove = function (e, data) { this.trigger('dataTodoRemoved', todo);
var todo = dataStore.destroy(data.id); };
this.trigger('dataTodoRemoved', todo); this.load = function (e, data) {
} var todos;
this.load = function (e, data) { filter = localStorage.getItem('filter');
var todos; todos = this.find();
this.trigger('dataTodosLoaded', { todos: todos });
filter = localStorage.getItem('filter'); };
todos = this.find();
this.trigger('dataTodosLoaded', { todos: todos }); this.update = function (e, data) {
} dataStore.save(data);
};
this.update = function (e, data) {
dataStore.save(data); this.toggleCompleted = function (e, data) {
} var eventType;
var todo = dataStore.get(data.id);
this.toggleCompleted = function (e, data) {
var eventType; todo.completed = !todo.completed;
var todo = dataStore.get(data.id); dataStore.save(todo);
todo.completed = !todo.completed; eventType = filter ? 'dataTodoRemoved' : 'dataTodoToggled';
dataStore.save(todo);
this.trigger(eventType, todo);
eventType = (filter) ? 'dataTodoRemoved' : 'dataTodoToggled'; };
this.trigger(eventType, todo); this.toggleAllCompleted = function (e, data) {
} dataStore.updateAll({ completed: data.completed });
this.trigger('dataTodoToggledAll', { todos: this.find(filter) });
this.toggleAllCompleted = function (e, data) { };
dataStore.updateAll({ completed: data.completed });
this.trigger('dataTodoToggledAll', { todos: this.find(filter) }); this.filter = function (e, data) {
} var todos;
this.filter = function (e, data) { localStorage.setItem('filter', data.filter);
var todos; filter = data.filter;
todos = this.find();
localStorage.setItem('filter', data.filter);
filter = data.filter; this.trigger('dataTodosFiltered', { todos: todos });
todos = this.find(); };
this.trigger('dataTodosFiltered', { todos: todos }); this.find = function () {
} var todos;
this.find = function () { if (filter) {
var todos; todos = dataStore.find(function (each) {
return (typeof each[filter] !== 'undefined') ? each.completed : !each.completed;
if (filter) { });
todos = dataStore.find(function (each) { }
return (typeof each[filter] !== 'undefined') ? each.completed : !each.completed; else {
}); todos = dataStore.all();
} }
else {
todos = dataStore.all(); return todos;
} };
return todos; this.clearCompleted = function () {
} var todos;
this.clearCompleted = function () { dataStore.destroyAll({ completed: true });
var todos; todos = dataStore.all();
this.trigger('dataClearedCompleted', { todos: todos });
dataStore.destroyAll({ completed: true }); };
todos = dataStore.all();
this.trigger('dataClearedCompleted', { todos: todos }); this.after('initialize', function () {
} this.on(document, 'uiAddRequested', this.add);
this.on(document, 'uiUpdateRequested', this.update);
this.after('initialize', function () { this.on(document, 'uiRemoveRequested', this.remove);
this.on(document, 'uiAddRequested', this.add); this.on(document, 'uiLoadRequested', this.load);
this.on(document, 'uiUpdateRequested', this.update); this.on(document, 'uiToggleRequested', this.toggleCompleted);
this.on(document, 'uiRemoveRequested', this.remove); this.on(document, 'uiToggleAllRequested', this.toggleAllCompleted);
this.on(document, 'uiLoadRequested', this.load); this.on(document, 'uiClearRequested', this.clearCompleted);
this.on(document, 'uiToggleRequested', this.toggleCompleted); this.on(document, 'uiFilterRequested', this.filter);
this.on(document, 'uiToggleAllRequested', this.toggleAllCompleted); });
this.on(document, 'uiClearRequested', this.clearCompleted); }
this.on(document, 'uiFilterRequested', this.filter); }
});
}
}
); );
'use strict'; 'use strict';
define( define(
[ [
'depot' 'depot'
], ],
......
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'flight/component' 'flight/component'
], ],
function (defineComponent) { function (defineComponent) {
return defineComponent(mainSelector); return defineComponent(mainSelector);
function mainSelector() { function mainSelector() {
this.toggle = function (e, data) { this.toggle = function (e, data) {
var toggle = data.all > 0; var toggle = data.all > 0;
this.$node.toggle(toggle); this.$node.toggle(toggle);
} };
this.after('initialize', function () { this.after('initialize', function () {
this.$node.hide(); this.$node.hide();
......
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'flight/component' 'flight/component'
], ],
function (defineComponent) { function (defineComponent) {
return defineComponent(newItem); return defineComponent(newItem);
function newItem() { function newItem() {
var ENTER_KEY = 13; var ENTER_KEY = 13;
this.createOnEnter = function (e) { this.createOnEnter = function (e) {
...@@ -25,7 +23,7 @@ define( ...@@ -25,7 +23,7 @@ define(
}); });
this.$node.val(''); this.$node.val('');
} };
this.after('initialize', function () { this.after('initialize', function () {
this.on('keydown', this.createOnEnter); this.on('keydown', this.createOnEnter);
......
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'flight/component', 'flight/component',
'./with_filters', './with_filters',
...@@ -10,7 +10,6 @@ define( ...@@ -10,7 +10,6 @@ define(
], ],
function (defineComponent, withFilters, statsTmpl, utils) { function (defineComponent, withFilters, statsTmpl, utils) {
return defineComponent(stats, withFilters); return defineComponent(stats, withFilters);
function stats() { function stats() {
...@@ -26,11 +25,11 @@ define( ...@@ -26,11 +25,11 @@ define(
this.$node.html(template(data)); this.$node.html(template(data));
this.$node.toggle(toggle); this.$node.toggle(toggle);
this.markSelected(data.filter); this.markSelected(data.filter);
} };
this.clearCompleted = function (e, data) { this.clearCompleted = function (e, data) {
this.trigger('uiClearRequested'); this.trigger('uiClearRequested');
} };
this.after('initialize', function () { this.after('initialize', function () {
this.$node.hide(); this.$node.hide();
......
/*global define $ */
'use strict'; 'use strict';
define( define(
[ [
'flight/component', 'flight/component',
'text!app/templates/todo.html', 'text!app/templates/todo.html',
...@@ -9,11 +9,9 @@ define( ...@@ -9,11 +9,9 @@ define(
], ],
function (defineComponent, todoTmpl, utils) { function (defineComponent, todoTmpl, utils) {
return defineComponent(todoList); return defineComponent(todoList);
function todoList() { function todoList() {
var ENTER_KEY = 13; var ENTER_KEY = 13;
var template = utils.tmpl(todoTmpl); var template = utils.tmpl(todoTmpl);
...@@ -29,29 +27,28 @@ define( ...@@ -29,29 +27,28 @@ define(
data.todos.forEach(function (each) { data.todos.forEach(function (each) {
this.render(e, { todo: each }); this.render(e, { todo: each });
}, this); }, this);
} };
this.render = function (e, data) { this.render = function (e, data) {
if (e.type == 'dataTodoAdded' if (e.type === 'dataTodoAdded' && data.filter === 'completed') {
&& data.filter == 'completed') {
return; return;
} }
this.$node.append(template(data.todo)); this.$node.append(template(data.todo));
} };
this.edit = function (e, data) { this.edit = function (e, data) {
var $todoEl = $(data.el).parents('li'); var $todoEl = $(data.el).parents('li');
$todoEl.addClass('editing'); $todoEl.addClass('editing');
this.select('editSelector').focus(); this.select('editSelector').focus();
} };
this.requestUpdate = function (e, data) { this.requestUpdate = function (e, data) {
var $inputEl = $(e.currentTarget); var $inputEl = $(e.currentTarget);
var $todoEl = $inputEl.parents('li'); var $todoEl = $inputEl.parents('li');
var value = $inputEl.val().trim(); var value = $inputEl.val().trim();
var id = $todoEl.attr('id'); var id = $todoEl.attr('id');
if (!$todoEl.hasClass('editing')) { if (!$todoEl.hasClass('editing')) {
return; return;
...@@ -65,30 +62,30 @@ define( ...@@ -65,30 +62,30 @@ define(
} else { } else {
this.trigger('uiRemoveRequested', { id: id }); this.trigger('uiRemoveRequested', { id: id });
} }
}, };
this.requestUpdateOnEnter = function (e, data) { this.requestUpdateOnEnter = function (e, data) {
if (e.which === ENTER_KEY) { if (e.which === ENTER_KEY) {
this.requestUpdate(e, data); this.requestUpdate(e, data);
} }
}, };
this.requestRemove = function (e, data) { this.requestRemove = function (e, data) {
var id = $(data.el).attr('id').split('_')[1]; var id = $(data.el).attr('id').split('_')[1];
this.trigger('uiRemoveRequested', { id: id }); this.trigger('uiRemoveRequested', { id: id });
} };
this.remove = function (e, data) { this.remove = function (e, data) {
var $todoEl = this.$node.find('#' + data.id); var $todoEl = this.$node.find('#' + data.id);
$todoEl.remove(); $todoEl.remove();
} };
this.toggle = function (e, data) { this.toggle = function (e, data) {
var $todoEl = $(data.el).parents('li'); var $todoEl = $(data.el).parents('li');
$todoEl.toggleClass('completed'); $todoEl.toggleClass('completed');
this.trigger('uiToggleRequested', { id: $todoEl.attr('id') }); this.trigger('uiToggleRequested', { id: $todoEl.attr('id') });
} };
this.after('initialize', function () { this.after('initialize', function () {
this.on(document, 'dataTodoAdded', this.render); this.on(document, 'dataTodoAdded', this.render);
......
/*global define */
'use strict'; 'use strict';
define( define(
[ [
'flight/component' 'flight/component'
], ],
function (defineComponent) { function (defineComponent) {
return defineComponent(toggleAll); return defineComponent(toggleAll);
function toggleAll() { function toggleAll() {
...@@ -15,11 +14,11 @@ define( ...@@ -15,11 +14,11 @@ define(
this.trigger('uiToggleAllRequested', { this.trigger('uiToggleAllRequested', {
completed: this.$node.is(':checked') completed: this.$node.is(':checked')
}); });
} };
this.toggleCheckbox = function (e, data) { this.toggleCheckbox = function (e, data) {
this.$node[0].checked = !data.remaining; this.$node[0].checked = !data.remaining;
} };
this.after('initialize', function () { this.after('initialize', function () {
this.on('click', this.toggleAllComplete); this.on('click', this.toggleAllComplete);
......
/*global define $ */
'use strict'; 'use strict';
define( define(
function () {
function() { return function withFilters() {
return withFilters;
function withFilters() {
this.defaultAttrs({ this.defaultAttrs({
filterSelector: '#filters a' filterSelector: '#filters a'
}); });
...@@ -17,15 +14,15 @@ define( ...@@ -17,15 +14,15 @@ define(
this.select('filterSelector').removeClass('selected'); this.select('filterSelector').removeClass('selected');
$(data.el).addClass('selected'); $(data.el).addClass('selected');
this.trigger('uiFilterRequested', { filter: filter }); this.trigger('uiFilterRequested', { filter: filter });
} };
this.markSelected = function (filter) { this.markSelected = function (filter) {
this.$node.find('[href="#/' + filter + '"]').addClass('selected'); this.$node.find('[href="#/' + filter + '"]').addClass('selected');
} };
this.after('initialize', function() { this.after('initialize', function () {
this.on('click', { filterSelector: this.chooseFilter }); this.on('click', { filterSelector: this.chooseFilter });
}); });
} };
} }
); );
/*global define */
'use strict'; 'use strict';
// tmpl function scooped from underscore. // tmpl function scooped from underscore.
...@@ -13,6 +14,7 @@ define(function () { ...@@ -13,6 +14,7 @@ define(function () {
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
/*jshint quotmark:false */
"'": '&#x27;', "'": '&#x27;',
'/': '&#x2F;' '/': '&#x2F;'
} }
...@@ -28,28 +30,32 @@ define(function () { ...@@ -28,28 +30,32 @@ define(function () {
}; };
// Functions for escaping and unescaping strings to/from HTML interpolation. // Functions for escaping and unescaping strings to/from HTML interpolation.
['escape', 'unescape'].forEach(function(method) { ['escape', 'unescape'].forEach(function (method) {
_[method] = function(string) { _[method] = function (string) {
if (string == null) return ''; if (string === null || string === undefined) {
return ('' + string).replace(entityRegexes[method], function(match) { return '';
}
return ('' + string).replace(entityRegexes[method], function (match) {
return entityMap[method][match]; return entityMap[method][match];
}); });
}; };
}); });
var settings = { var settings = {
evaluate : /<%([\s\S]+?)%>/g, evaluate: /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g, interpolate: /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g escape: /<%-([\s\S]+?)%>/g
}; };
var noMatch = /(.)^/; var noMatch = /(.)^/;
var escapes = { var escapes = {
"'": "'", /*jshint quotmark:false */
'\\': '\\', "'": "'",
'\r': 'r', '\\': '\\',
'\n': 'n', '\r': 'r',
'\t': 't', '\n': 'n',
'\t': 't',
'\u2028': 'u2028', '\u2028': 'u2028',
'\u2029': 'u2029' '\u2029': 'u2029'
}; };
...@@ -59,22 +65,24 @@ define(function () { ...@@ -59,22 +65,24 @@ define(function () {
// JavaScript micro-templating, similar to John Resig's implementation. // JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
var template = function(text, data) { var template = function (text, data) {
var render; var render;
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
var matcher = new RegExp([ var matcher = new RegExp([
(settings.escape || noMatch).source, (settings.escape || noMatch).source,
(settings.interpolate || noMatch).source, (settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source (settings.evaluate || noMatch).source
].join('|') + '|$', 'g'); ].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately. // Compile the template source, escaping string literals appropriately.
var index = 0; var index = 0;
var source = "__p+='"; var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function (match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; }); .replace(escaper, function (match) {
return '\\' + escapes[match];
});
if (escape) { if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
...@@ -91,7 +99,9 @@ define(function () { ...@@ -91,7 +99,9 @@ define(function () {
source += "';\n"; source += "';\n";
// If a variable is not specified, place data values in local scope. // If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; if (!settings.variable) {
source = 'with(obj||{}){\n' + source + '}\n';
}
source = "var __t,__p='',__j=Array.prototype.join," + source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" + "print=function(){__p+=__j.call(arguments,'');};\n" +
...@@ -99,13 +109,16 @@ define(function () { ...@@ -99,13 +109,16 @@ define(function () {
try { try {
render = new Function(settings.variable || 'obj', '_', source); render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (err) {
e.source = source; err.source = source;
throw e; throw err;
}
if (data) {
return render(data, _);
} }
if (data) return render(data, _); var template = function (data) {
var template = function(data) {
return render.call(this, data, _); return render.call(this, data, _);
}; };
......
...@@ -6,24 +6,25 @@ ...@@ -6,24 +6,25 @@
<title>Flight • Todo</title> <title>Flight • Todo</title>
<link rel="stylesheet" href="../../assets/base.css"> <link rel="stylesheet" href="../../assets/base.css">
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus> <input id="new-todo" placeholder="What needs to be done?" autofocus>
</header> </header>
<section id="main"> <section id="main">
<input id="toggle-all" type="checkbox"> <input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul> <ul id="todo-list"></ul>
</section>
<footer id="footer"></footer>
</section> </section>
<footer id="footer"></footer> <footer id="info">
</section> <p>Double-click to edit a todo</p>
<footer id="info"> <p>Created by <a href="http://github.com/mkuklis">Michal Kuklis</a></p>
<p>Double-click to edit a todo</p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
<p>Created by <a href="http://github.com/mkuklis">Michal Kuklis</a></p> </footer>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <script src="../../assets/base.js"></script>
</footer> <script data-main="app/js/main" src="components/requirejs/requirejs.js"></script>
<script data-main="app/js/main" src="components/requirejs/requirejs.js"></script> </body>
</body>
</html> </html>
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Template • TodoMVC</title> <title>Template • TodoMVC</title>
<link rel="stylesheet" href="../assets/base.css"> <link rel="stylesheet" href="../assets/base.css">
<!-- CSS overrides - remove if you don't need it --> <!-- CSS overrides - remove if you don't need it -->
<link rel="stylesheet" href="css/app.css"> <link rel="stylesheet" href="css/app.css">
<!--[if IE]> <!--[if IE]>
<script src="../assets/ie.js"></script> <script src="../assets/ie.js"></script>
<![endif]--> <![endif]-->
</head> </head>
<body> <body>
<section id="todoapp"> <section id="todoapp">
<header id="header"> <header id="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" placeholder="What needs to be done?" autofocus> <input id="new-todo" placeholder="What needs to be done?" autofocus>
</header> </header>
<!-- This section should be hidden by default and shown when there are todos --> <!-- This section should be hidden by default and shown when there are todos -->
<section id="main"> <section id="main">
<input id="toggle-all" type="checkbox"> <input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"> <ul id="todo-list">
<!-- These are here just to show the structure of the list items --> <!-- These are here just to show the structure of the list items -->
<!-- List items should get the class `editing` when editing and `completed` when marked as completed --> <!-- List items should get the class `editing` when editing and `completed` when marked as completed -->
<li class="completed"> <li class="completed">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" checked> <input class="toggle" type="checkbox" checked>
<label>Create a TodoMVC template</label> <label>Create a TodoMVC template</label>
<button class="destroy"></button> <button class="destroy"></button>
</div> </div>
<input class="edit" value="Create a TodoMVC template"> <input class="edit" value="Create a TodoMVC template">
</li> </li>
<li> <li>
<div class="view"> <div class="view">
<input class="toggle" type="checkbox"> <input class="toggle" type="checkbox">
<label>Rule the web</label> <label>Rule the web</label>
<button class="destroy"></button> <button class="destroy"></button>
</div> </div>
<input class="edit" value="Rule the web"> <input class="edit" value="Rule the web">
</li> </li>
</ul> </ul>
</section>
<!-- This footer should hidden by default and shown when there are todos -->
<footer id="footer">
<!-- This should be `0 items left` by default -->
<span id="todo-count"><strong>1</strong> item left</span>
<!-- Remove this if you don't implement routing -->
<ul id="filters">
<li>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed">Clear completed (1)</button>
</footer>
</section> </section>
<!-- This footer should hidden by default and shown when there are todos --> <footer id="info">
<footer id="footer"> <p>Double-click to edit a todo</p>
<!-- This should be `0 items left` by default --> <!-- Remove the below line ↓ -->
<span id="todo-count"><strong>1</strong> item left</span> <p>Template by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<!-- Remove this if you don't implement routing --> <!-- Change this out with your name and url ↓ -->
<ul id="filters"> <p>Created by <a href="http://todomvc.com">you</a></p>
<li> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
<a class="selected" href="#/">All</a>
</li>
<li>
<a href="#/active">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
</li>
</ul>
<button id="clear-completed">Clear completed (1)</button>
</footer> </footer>
</section> <!-- Scripts here. Don't remove this ↓ -->
<footer id="info"> <script src="../assets/base.js"></script>
<p>Double-click to edit a todo</p> <script src="js/app.js"></script>
<!-- Remove the below line ↓ --> </body>
<p>Template by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<!-- Change this out with your name and url ↓ -->
<p>Created by <a href="http://todomvc.com">you</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 src="js/app.js"></script>
</body>
</html> </html>
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