diff --git a/www/todo/example/assets/todomvc-app-css/index.css b/www/todo/example/assets/todomvc-app-css/index.css deleted file mode 100644 index e6e089cbf..000000000 --- a/www/todo/example/assets/todomvc-app-css/index.css +++ /dev/null @@ -1,378 +0,0 @@ -html, -body { - margin: 0; - padding: 0; -} - -button { - margin: 0; - padding: 0; - border: 0; - background: none; - font-size: 100%; - vertical-align: baseline; - font-family: inherit; - font-weight: inherit; - color: inherit; - -webkit-appearance: none; - appearance: none; - -webkit-font-smoothing: antialiased; - -moz-font-smoothing: antialiased; - font-smoothing: antialiased; -} - -body { - font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; - line-height: 1.4em; - background: #f5f5f5; - color: #4d4d4d; - min-width: 230px; - max-width: 550px; - margin: 0 auto; - -webkit-font-smoothing: antialiased; - -moz-font-smoothing: antialiased; - font-smoothing: antialiased; - font-weight: 300; -} - -button, -input[type="checkbox"] { - outline: none; -} - -.hidden { - display: none; -} - -.todoapp { - background: #fff; - margin: 130px 0 40px 0; - position: relative; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), - 0 25px 50px 0 rgba(0, 0, 0, 0.1); -} - -.todoapp input::-webkit-input-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -.todoapp input::-moz-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -.todoapp input::input-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -.todoapp h1 { - position: absolute; - top: -155px; - width: 100%; - font-size: 100px; - font-weight: 100; - text-align: center; - color: rgba(175, 47, 47, 0.15); - -webkit-text-rendering: optimizeLegibility; - -moz-text-rendering: optimizeLegibility; - text-rendering: optimizeLegibility; -} - -.new-todo, -.edit { - position: relative; - margin: 0; - width: 100%; - font-size: 24px; - font-family: inherit; - font-weight: 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); - box-sizing: border-box; - -webkit-font-smoothing: antialiased; - -moz-font-smoothing: antialiased; - font-smoothing: antialiased; -} - -.new-todo { - padding: 16px 16px 16px 60px; - border: none; - background: rgba(0, 0, 0, 0.003); - box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); -} - -.main { - position: relative; - z-index: 2; - border-top: 1px solid #e6e6e6; -} - -label[for='toggle-all'] { - display: none; -} - -.toggle-all { - position: absolute; - top: -55px; - left: -12px; - width: 60px; - height: 34px; - text-align: center; - border: none; /* Mobile Safari */ -} - -.toggle-all:before { - content: '❯'; - font-size: 22px; - color: #e6e6e6; - padding: 10px 27px 10px 27px; -} - -.toggle-all:checked:before { - color: #737373; -} - -.todo-list { - margin: 0; - padding: 0; - list-style: none; -} - -.todo-list li { - position: relative; - font-size: 24px; - border-bottom: 1px solid #ededed; -} - -.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; - /* auto, since non-WebKit browsers doesn't support input styling */ - height: auto; - position: absolute; - top: 0; - bottom: 0; - margin: auto 0; - border: none; /* Mobile Safari */ - -webkit-appearance: none; - appearance: none; -} - -.todo-list li .toggle:after { - content: url('data:image/svg+xml;utf8,'); -} - -.todo-list li .toggle:checked:after { - content: url('data:image/svg+xml;utf8,'); -} - -.todo-list li label { - white-space: pre-line; - word-break: break-all; - padding: 15px 60px 15px 15px; - margin-left: 45px; - display: block; - line-height: 1.2; - transition: color 0.4s; -} - -.todo-list li.completed label { - color: #d9d9d9; - text-decoration: line-through; -} - -.todo-list li .destroy { - display: none; - position: absolute; - top: 0; - right: 10px; - bottom: 0; - width: 40px; - height: 40px; - margin: auto 0; - font-size: 30px; - color: #cc9a9a; - margin-bottom: 11px; - transition: color 0.2s ease-out; -} - -.todo-list li .destroy:hover { - color: #af5b5e; -} - -.todo-list li .destroy:after { - content: '×'; -} - -.todo-list li:hover .destroy { - display: block; -} - -.todo-list li .edit { - display: none; -} - -.todo-list li.editing:last-child { - margin-bottom: -1px; -} - -.footer { - color: #777; - padding: 10px 15px; - height: 20px; - text-align: center; - border-top: 1px solid #e6e6e6; -} - -.footer:before { - content: ''; - position: absolute; - right: 0; - bottom: 0; - left: 0; - height: 50px; - overflow: hidden; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), - 0 8px 0 -3px #f6f6f6, - 0 9px 1px -3px rgba(0, 0, 0, 0.2), - 0 16px 0 -6px #f6f6f6, - 0 17px 2px -6px rgba(0, 0, 0, 0.2); -} - -.todo-count { - float: left; - text-align: left; -} - -.todo-count strong { - font-weight: 300; -} - -.filters { - margin: 0; - padding: 0; - list-style: none; - position: absolute; - right: 0; - left: 0; -} - -.filters li { - display: inline; -} - -.filters li a { - color: inherit; - margin: 3px; - padding: 3px 7px; - text-decoration: none; - border: 1px solid transparent; - border-radius: 3px; -} - -.filters li a.selected, -.filters li a:hover { - border-color: rgba(175, 47, 47, 0.1); -} - -.filters li a.selected { - border-color: rgba(175, 47, 47, 0.2); -} - -.clear-completed, -html .clear-completed:active { - float: right; - position: relative; - line-height: 20px; - text-decoration: none; - cursor: pointer; - position: relative; -} - -.clear-completed:hover { - text-decoration: underline; -} - -.info { - margin: 65px auto 0; - color: #bfbfbf; - font-size: 10px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-align: center; -} - -.info p { - line-height: 1; -} - -.info a { - color: inherit; - text-decoration: none; - font-weight: 400; -} - -.info a:hover { - text-decoration: underline; -} - -/* - Hack to remove background from Mobile Safari. - Can't use it globally since it destroys checkboxes in Firefox -*/ -@media screen and (-webkit-min-device-pixel-ratio:0) { - .toggle-all, - .todo-list li .toggle { - background: none; - } - - .todo-list li .toggle { - height: 40px; - } - - .toggle-all { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); - -webkit-appearance: none; - appearance: none; - } -} - -@media (max-width: 430px) { - .footer { - height: 50px; - } - - .filters { - bottom: 10px; - } -} diff --git a/www/todo/example/assets/todomvc-common/base.css b/www/todo/example/assets/todomvc-common/base.css deleted file mode 100644 index da65968a7..000000000 --- a/www/todo/example/assets/todomvc-common/base.css +++ /dev/null @@ -1,141 +0,0 @@ -hr { - margin: 20px 0; - border: 0; - border-top: 1px dashed #c5c5c5; - border-bottom: 1px dashed #f7f7f7; -} - -.learn a { - font-weight: normal; - text-decoration: none; - color: #b83f45; -} - -.learn a:hover { - text-decoration: underline; - color: #787e7e; -} - -.learn h3, -.learn h4, -.learn h5 { - margin: 10px 0; - font-weight: 500; - line-height: 1.2; - color: #000; -} - -.learn h3 { - font-size: 24px; -} - -.learn h4 { - font-size: 18px; -} - -.learn h5 { - margin-bottom: 0; - font-size: 14px; -} - -.learn ul { - padding: 0; - margin: 0 0 30px 25px; -} - -.learn li { - line-height: 20px; -} - -.learn p { - font-size: 15px; - font-weight: 300; - line-height: 1.3; - margin-top: 0; - margin-bottom: 0; -} - -#issue-count { - display: none; -} - -.quote { - border: none; - margin: 20px 0 60px 0; -} - -.quote p { - font-style: italic; -} - -.quote p:before { - content: '“'; - font-size: 50px; - opacity: .15; - position: absolute; - top: -20px; - left: 3px; -} - -.quote p:after { - content: '”'; - font-size: 50px; - opacity: .15; - position: absolute; - bottom: -42px; - right: 3px; -} - -.quote footer { - position: absolute; - bottom: -40px; - right: 0; -} - -.quote footer img { - border-radius: 3px; -} - -.quote footer a { - margin-left: 5px; - vertical-align: middle; -} - -.speech-bubble { - position: relative; - padding: 10px; - background: rgba(0, 0, 0, .04); - border-radius: 5px; -} - -.speech-bubble:after { - content: ''; - position: absolute; - top: 100%; - right: 30px; - border: 13px solid transparent; - border-top-color: rgba(0, 0, 0, .04); -} - -.learn-bar > .learn { - position: absolute; - width: 272px; - top: 8px; - left: -300px; - padding: 10px; - border-radius: 5px; - background-color: rgba(255, 255, 255, .6); - transition-property: left; - transition-duration: 500ms; -} - -@media (min-width: 899px) { - .learn-bar { - width: auto; - padding-left: 300px; - } - - .learn-bar > .learn { - left: 8px; - } -} diff --git a/www/todo/example/assets/todomvc-common/base.js b/www/todo/example/assets/todomvc-common/base.js deleted file mode 100644 index 3c6723f39..000000000 --- a/www/todo/example/assets/todomvc-common/base.js +++ /dev/null @@ -1,249 +0,0 @@ -/* global _ */ -(function () { - 'use strict'; - - /* jshint ignore:start */ - // Underscore's Template Module - // Courtesy of underscorejs.org - var _ = (function (_) { - _.defaults = function (object) { - if (!object) { - return object; - } - for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) { - var iterable = arguments[argsIndex]; - if (iterable) { - for (var key in iterable) { - if (object[key] == null) { - object[key] = iterable[key]; - } - } - } - } - return object; - } - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\t': 't', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - _.template = function(text, data, settings) { - var render; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = new RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset) - .replace(escaper, function(match) { return '\\' + escapes[match]; }); - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } - if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } - if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - index = offset + match.length; - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + "return __p;\n"; - - try { - render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - if (data) return render(data, _); - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled function source as a convenience for precompilation. - template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; - - return template; - }; - - return _; - })({}); - - if (location.hostname === 'todomvc.com') { - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-31081062-1', 'auto'); - ga('send', 'pageview'); - } - /* jshint ignore:end */ - - function redirect() { - if (location.hostname === 'tastejs.github.io') { - location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com'); - } - } - - function findRoot() { - var base = location.href.indexOf('examples/'); - return location.href.substr(0, base); - } - - function getFile(file, callback) { - if (!location.host) { - return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.'); - } - - var xhr = new XMLHttpRequest(); - - xhr.open('GET', findRoot() + file, true); - xhr.send(); - - xhr.onload = function () { - if (xhr.status === 200 && callback) { - callback(xhr.responseText); - } - }; - } - - function Learn(learnJSON, config) { - if (!(this instanceof Learn)) { - return new Learn(learnJSON, config); - } - - var template, framework; - - if (typeof learnJSON !== 'object') { - try { - learnJSON = JSON.parse(learnJSON); - } catch (e) { - return; - } - } - - if (config) { - template = config.template; - framework = config.framework; - } - - if (!template && learnJSON.templates) { - template = learnJSON.templates.todomvc; - } - - if (!framework && document.querySelector('[data-framework]')) { - framework = document.querySelector('[data-framework]').dataset.framework; - } - - this.template = template; - - if (learnJSON.backend) { - this.frameworkJSON = learnJSON.backend; - this.frameworkJSON.issueLabel = framework; - this.append({ - backend: true - }); - } else if (learnJSON[framework]) { - this.frameworkJSON = learnJSON[framework]; - this.frameworkJSON.issueLabel = framework; - this.append(); - } - - this.fetchIssueCount(); - } - - Learn.prototype.append = function (opts) { - var aside = document.createElement('aside'); - aside.innerHTML = _.template(this.template, this.frameworkJSON); - aside.className = 'learn'; - - if (opts && opts.backend) { - // Remove demo link - var sourceLinks = aside.querySelector('.source-links'); - var heading = sourceLinks.firstElementChild; - var sourceLink = sourceLinks.lastElementChild; - // Correct link path - var href = sourceLink.getAttribute('href'); - sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http'))); - sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML; - } else { - // Localize demo links - var demoLinks = aside.querySelectorAll('.demo-link'); - Array.prototype.forEach.call(demoLinks, function (demoLink) { - if (demoLink.getAttribute('href').substr(0, 4) !== 'http') { - demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href')); - } - }); - } - - document.body.className = (document.body.className + ' learn-bar').trim(); - document.body.insertAdjacentHTML('afterBegin', aside.outerHTML); - }; - - Learn.prototype.fetchIssueCount = function () { - var issueLink = document.getElementById('issue-count-link'); - if (issueLink) { - var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos'); - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.onload = function (e) { - var parsedResponse = JSON.parse(e.target.responseText); - if (parsedResponse instanceof Array) { - var count = parsedResponse.length; - if (count !== 0) { - issueLink.innerHTML = 'This app has ' + count + ' open issues'; - document.getElementById('issue-count').style.display = 'inline'; - } - } - }; - xhr.send(); - } - }; - - redirect(); - getFile('learn.json', Learn); -})(); diff --git a/www/todo/example/index.html b/www/todo/example/index.html deleted file mode 100644 index 09070b71d..000000000 --- a/www/todo/example/index.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - - Crypt Todo - - - - -
-
-

todos

- -
-
- - - -
- -
- - - - - - - - - - - - diff --git a/www/todo/example/js/app.js b/www/todo/example/js/app.js deleted file mode 100644 index c37e2e6a2..000000000 --- a/www/todo/example/js/app.js +++ /dev/null @@ -1,25 +0,0 @@ -/*global app, $on */ -(function () { - 'use strict'; - - /** - * Sets up a brand new Todo list. - * - * @param {string} name The name of your new to do list. - */ - function Todo(name) { - this.storage = new app.Store(name); - this.model = new app.Model(this.storage); - this.template = new app.Template(); - this.view = new app.View(this.template); - this.controller = new app.Controller(this.model, this.view); - } - - var todo = new Todo('todos-vanillajs'); - - function setView() { - todo.controller.setView(document.location.hash); - } - $on(window, 'load', setView); - $on(window, 'hashchange', setView); -})(); diff --git a/www/todo/example/js/controller.js b/www/todo/example/js/controller.js deleted file mode 100644 index 0a3fb1d83..000000000 --- a/www/todo/example/js/controller.js +++ /dev/null @@ -1,270 +0,0 @@ -(function (window) { - 'use strict'; - - /** - * Takes a model and view and acts as the controller between them - * - * @constructor - * @param {object} model The model instance - * @param {object} view The view instance - */ - function Controller(model, view) { - var self = this; - self.model = model; - self.view = view; - - self.view.bind('newTodo', function (title) { - self.addItem(title); - }); - - self.view.bind('itemEdit', function (item) { - self.editItem(item.id); - }); - - self.view.bind('itemEditDone', function (item) { - self.editItemSave(item.id, item.title); - }); - - self.view.bind('itemEditCancel', function (item) { - self.editItemCancel(item.id); - }); - - self.view.bind('itemRemove', function (item) { - self.removeItem(item.id); - }); - - self.view.bind('itemToggle', function (item) { - self.toggleComplete(item.id, item.completed); - }); - - self.view.bind('removeCompleted', function () { - self.removeCompletedItems(); - }); - - self.view.bind('toggleAll', function (status) { - self.toggleAll(status.completed); - }); - } - - /** - * Loads and initialises the view - * - * @param {string} '' | 'active' | 'completed' - */ - Controller.prototype.setView = function (locationHash) { - var route = locationHash.split('/')[1]; - var page = route || ''; - this._updateFilterState(page); - }; - - /** - * An event to fire on load. Will get all items and display them in the - * todo-list - */ - Controller.prototype.showAll = function () { - var self = this; - self.model.read(function (data) { - self.view.render('showEntries', data); - }); - }; - - /** - * Renders all active tasks - */ - Controller.prototype.showActive = function () { - var self = this; - self.model.read({ completed: false }, function (data) { - self.view.render('showEntries', data); - }); - }; - - /** - * Renders all completed tasks - */ - Controller.prototype.showCompleted = function () { - var self = this; - self.model.read({ completed: true }, function (data) { - self.view.render('showEntries', data); - }); - }; - - /** - * An event to fire whenever you want to add an item. Simply pass in the event - * object and it'll handle the DOM insertion and saving of the new item. - */ - Controller.prototype.addItem = function (title) { - var self = this; - - if (title.trim() === '') { - return; - } - - self.model.create(title, function () { - self.view.render('clearNewTodo'); - self._filter(true); - }); - }; - - /* - * Triggers the item editing mode. - */ - Controller.prototype.editItem = function (id) { - var self = this; - self.model.read(id, function (data) { - self.view.render('editItem', {id: id, title: data[0].title}); - }); - }; - - /* - * Finishes the item editing mode successfully. - */ - Controller.prototype.editItemSave = function (id, title) { - var self = this; - title = title.trim(); - - if (title.length !== 0) { - self.model.update(id, {title: title}, function () { - self.view.render('editItemDone', {id: id, title: title}); - }); - } else { - self.removeItem(id); - } - }; - - /* - * Cancels the item editing mode. - */ - Controller.prototype.editItemCancel = function (id) { - var self = this; - self.model.read(id, function (data) { - self.view.render('editItemDone', {id: id, title: data[0].title}); - }); - }; - - /** - * By giving it an ID it'll find the DOM element matching that ID, - * remove it from the DOM and also remove it from storage. - * - * @param {number} id The ID of the item to remove from the DOM and - * storage - */ - Controller.prototype.removeItem = function (id) { - var self = this; - self.model.remove(id, function () { - self.view.render('removeItem', id); - }); - - self._filter(); - }; - - /** - * Will remove all completed items from the DOM and storage. - */ - Controller.prototype.removeCompletedItems = function () { - var self = this; - self.model.read({ completed: true }, function (data) { - data.forEach(function (item) { - self.removeItem(item.id); - }); - }); - - self._filter(); - }; - - /** - * Give it an ID of a model and a checkbox and it will update the item - * in storage based on the checkbox's state. - * - * @param {number} id The ID of the element to complete or uncomplete - * @param {object} checkbox The checkbox to check the state of complete - * or not - * @param {boolean|undefined} silent Prevent re-filtering the todo items - */ - Controller.prototype.toggleComplete = function (id, completed, silent) { - var self = this; - self.model.update(id, { completed: completed }, function () { - self.view.render('elementComplete', { - id: id, - completed: completed - }); - }); - - if (!silent) { - self._filter(); - } - }; - - /** - * Will toggle ALL checkboxes' on/off state and completeness of models. - * Just pass in the event object. - */ - Controller.prototype.toggleAll = function (completed) { - var self = this; - self.model.read({ completed: !completed }, function (data) { - data.forEach(function (item) { - self.toggleComplete(item.id, completed, true); - }); - }); - - self._filter(); - }; - - /** - * Updates the pieces of the page which change depending on the remaining - * number of todos. - */ - Controller.prototype._updateCount = function () { - var self = this; - self.model.getCount(function (todos) { - self.view.render('updateElementCount', todos.active); - self.view.render('clearCompletedButton', { - completed: todos.completed, - visible: todos.completed > 0 - }); - - self.view.render('toggleAll', {checked: todos.completed === todos.total}); - self.view.render('contentBlockVisibility', {visible: todos.total > 0}); - }); - }; - - /** - * Re-filters the todo items, based on the active route. - * @param {boolean|undefined} force forces a re-painting of todo items. - */ - Controller.prototype._filter = function (force) { - var activeRoute = this._activeRoute.charAt(0).toUpperCase() + this._activeRoute.substr(1); - - // Update the elements on the page, which change with each completed todo - this._updateCount(); - - // If the last active route isn't "All", or we're switching routes, we - // re-create the todo item elements, calling: - // this.show[All|Active|Completed](); - if (force || this._lastActiveRoute !== 'All' || this._lastActiveRoute !== activeRoute) { - this['show' + activeRoute](); - } - - this._lastActiveRoute = activeRoute; - }; - - /** - * Simply updates the filter nav's selected states - */ - Controller.prototype._updateFilterState = function (currentPage) { - // Store a reference to the active route, allowing us to re-filter todo - // items as they are marked complete or incomplete. - this._activeRoute = currentPage; - - if (currentPage === '') { - this._activeRoute = 'All'; - } - - this._filter(); - - this.view.render('setFilter', currentPage); - }; - - // Export to window - window.app = window.app || {}; - window.app.Controller = Controller; -})(window); diff --git a/www/todo/example/js/helpers.js b/www/todo/example/js/helpers.js deleted file mode 100644 index d59a72eff..000000000 --- a/www/todo/example/js/helpers.js +++ /dev/null @@ -1,52 +0,0 @@ -/*global NodeList */ -(function (window) { - 'use strict'; - - // Get element(s) by CSS selector: - window.qs = function (selector, scope) { - return (scope || document).querySelector(selector); - }; - window.qsa = function (selector, scope) { - return (scope || document).querySelectorAll(selector); - }; - - // addEventListener wrapper: - window.$on = function (target, type, callback, useCapture) { - target.addEventListener(type, callback, !!useCapture); - }; - - // Attach a handler to event for all elements that match the selector, - // now or in the future, based on a root element - window.$delegate = function (target, selector, type, handler) { - function dispatchEvent(event) { - var targetElement = event.target; - var potentialElements = window.qsa(selector, target); - var hasMatch = Array.prototype.indexOf.call(potentialElements, targetElement) >= 0; - - if (hasMatch) { - handler.call(targetElement, event); - } - } - - // https://developer.mozilla.org/en-US/docs/Web/Events/blur - var useCapture = type === 'blur' || type === 'focus'; - - window.$on(target, type, dispatchEvent, useCapture); - }; - - // Find the element's parent with the given tag name: - // $parent(qs('a'), 'div'); - window.$parent = function (element, tagName) { - if (!element.parentNode) { - return; - } - if (element.parentNode.tagName.toLowerCase() === tagName.toLowerCase()) { - return element.parentNode; - } - return window.$parent(element.parentNode, tagName); - }; - - // Allow for looping on nodes by chaining: - // qsa('.foo').forEach(function () {}) - NodeList.prototype.forEach = Array.prototype.forEach; -})(window); diff --git a/www/todo/example/js/model.js b/www/todo/example/js/model.js deleted file mode 100644 index 9da766abc..000000000 --- a/www/todo/example/js/model.js +++ /dev/null @@ -1,120 +0,0 @@ -(function (window) { - 'use strict'; - - /** - * Creates a new Model instance and hooks up the storage. - * - * @constructor - * @param {object} storage A reference to the client side storage class - */ - function Model(storage) { - this.storage = storage; - } - - /** - * Creates a new todo model - * - * @param {string} [title] The title of the task - * @param {function} [callback] The callback to fire after the model is created - */ - Model.prototype.create = function (title, callback) { - title = title || ''; - callback = callback || function () {}; - - var newItem = { - title: title.trim(), - completed: false - }; - - this.storage.save(newItem, callback); - }; - - /** - * Finds and returns a model in storage. If no query is given it'll simply - * return everything. If you pass in a string or number it'll look that up as - * the ID of the model to find. Lastly, you can pass it an object to match - * against. - * - * @param {string|number|object} [query] A query to match models against - * @param {function} [callback] The callback to fire after the model is found - * - * @example - * model.read(1, func); // Will find the model with an ID of 1 - * model.read('1'); // Same as above - * //Below will find a model with foo equalling bar and hello equalling world. - * model.read({ foo: 'bar', hello: 'world' }); - */ - Model.prototype.read = function (query, callback) { - var queryType = typeof query; - callback = callback || function () {}; - - if (queryType === 'function') { - callback = query; - return this.storage.findAll(callback); - } else if (queryType === 'string' || queryType === 'number') { - query = parseInt(query, 10); - this.storage.find({ id: query }, callback); - } else { - this.storage.find(query, callback); - } - }; - - /** - * Updates a model by giving it an ID, data to update, and a callback to fire when - * the update is complete. - * - * @param {number} id The id of the model to update - * @param {object} data The properties to update and their new value - * @param {function} callback The callback to fire when the update is complete. - */ - Model.prototype.update = function (id, data, callback) { - this.storage.save(data, callback, id); - }; - - /** - * Removes a model from storage - * - * @param {number} id The ID of the model to remove - * @param {function} callback The callback to fire when the removal is complete. - */ - Model.prototype.remove = function (id, callback) { - this.storage.remove(id, callback); - }; - - /** - * WARNING: Will remove ALL data from storage. - * - * @param {function} callback The callback to fire when the storage is wiped. - */ - Model.prototype.removeAll = function (callback) { - this.storage.drop(callback); - }; - - /** - * Returns a count of all todos - */ - Model.prototype.getCount = function (callback) { - var todos = { - active: 0, - completed: 0, - total: 0 - }; - - this.storage.findAll(function (data) { - data.forEach(function (todo) { - if (todo.completed) { - todos.completed++; - } else { - todos.active++; - } - - todos.total++; - }); - callback(todos); - }); - }; - - // Export to window - window.app = window.app || {}; - window.app.Model = Model; -})(window); diff --git a/www/todo/example/js/store.js b/www/todo/example/js/store.js deleted file mode 100644 index ea09816c8..000000000 --- a/www/todo/example/js/store.js +++ /dev/null @@ -1,141 +0,0 @@ -/*jshint eqeqeq:false */ -(function (window) { - 'use strict'; - - /** - * Creates a new client side storage object and will create an empty - * collection if no collection already exists. - * - * @param {string} name The name of our DB we want to use - * @param {function} callback Our fake DB uses callbacks because in - * real life you probably would be making AJAX calls - */ - function Store(name, callback) { - callback = callback || function () {}; - - this._dbName = name; - - if (!localStorage[name]) { - var data = { - todos: [] - }; - - localStorage[name] = JSON.stringify(data); - } - - callback.call(this, JSON.parse(localStorage[name])); - } - - /** - * Finds items based on a query given as a JS object - * - * @param {object} query The query to match against (i.e. {foo: 'bar'}) - * @param {function} callback The callback to fire when the query has - * completed running - * - * @example - * db.find({foo: 'bar', hello: 'world'}, function (data) { - * // data will return any items that have foo: bar and - * // hello: world in their properties - * }); - */ - Store.prototype.find = function (query, callback) { - if (!callback) { - return; - } - - var todos = JSON.parse(localStorage[this._dbName]).todos; - - callback.call(this, todos.filter(function (todo) { - for (var q in query) { - if (query[q] !== todo[q]) { - return false; - } - } - return true; - })); - }; - - /** - * Will retrieve all data from the collection - * - * @param {function} callback The callback to fire upon retrieving data - */ - Store.prototype.findAll = function (callback) { - callback = callback || function () {}; - callback.call(this, JSON.parse(localStorage[this._dbName]).todos); - }; - - /** - * Will save the given data to the DB. If no item exists it will create a new - * item, otherwise it'll simply update an existing item's properties - * - * @param {object} updateData The data to save back into the DB - * @param {function} callback The callback to fire after saving - * @param {number} id An optional param to enter an ID of an item to update - */ - Store.prototype.save = function (updateData, callback, id) { - var data = JSON.parse(localStorage[this._dbName]); - var todos = data.todos; - - callback = callback || function () {}; - - // If an ID was actually given, find the item and update each property - if (id) { - for (var i = 0; i < todos.length; i++) { - if (todos[i].id === id) { - for (var key in updateData) { - todos[i][key] = updateData[key]; - } - break; - } - } - - localStorage[this._dbName] = JSON.stringify(data); - callback.call(this, todos); - } else { - // Generate an ID - updateData.id = new Date().getTime(); - - todos.push(updateData); - localStorage[this._dbName] = JSON.stringify(data); - callback.call(this, [updateData]); - } - }; - - /** - * Will remove an item from the Store based on its ID - * - * @param {number} id The ID of the item you want to remove - * @param {function} callback The callback to fire after saving - */ - Store.prototype.remove = function (id, callback) { - var data = JSON.parse(localStorage[this._dbName]); - var todos = data.todos; - - for (var i = 0; i < todos.length; i++) { - if (todos[i].id == id) { - todos.splice(i, 1); - break; - } - } - - localStorage[this._dbName] = JSON.stringify(data); - callback.call(this, todos); - }; - - /** - * Will drop all storage and start fresh - * - * @param {function} callback The callback to fire after dropping the data - */ - Store.prototype.drop = function (callback) { - var data = {todos: []}; - localStorage[this._dbName] = JSON.stringify(data); - callback.call(this, data.todos); - }; - - // Export to window - window.app = window.app || {}; - window.app.Store = Store; -})(window); diff --git a/www/todo/example/js/template.js b/www/todo/example/js/template.js deleted file mode 100644 index a5587731f..000000000 --- a/www/todo/example/js/template.js +++ /dev/null @@ -1,114 +0,0 @@ -/*jshint laxbreak:true */ -(function (window) { - 'use strict'; - - var htmlEscapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - '\'': ''', - '`': '`' - }; - - var escapeHtmlChar = function (chr) { - return htmlEscapes[chr]; - }; - - var reUnescapedHtml = /[&<>"'`]/g; - var reHasUnescapedHtml = new RegExp(reUnescapedHtml.source); - - var escape = function (string) { - return (string && reHasUnescapedHtml.test(string)) - ? string.replace(reUnescapedHtml, escapeHtmlChar) - : string; - }; - - /** - * Sets up defaults for all the Template methods such as a default template - * - * @constructor - */ - function Template() { - this.defaultTemplate - = '
  • ' - + '
    ' - + '' - + '' - + '' - + '
    ' - + '
  • '; - } - - /** - * Creates an
  • HTML string and returns it for placement in your app. - * - * NOTE: In real life you should be using a templating engine such as Mustache - * or Handlebars, however, this is a vanilla JS example. - * - * @param {object} data The object containing keys you want to find in the - * template to replace. - * @returns {string} HTML String of an
  • element - * - * @example - * view.show({ - * id: 1, - * title: "Hello World", - * completed: 0, - * }); - */ - Template.prototype.show = function (data) { - var i = 0, l = data.length; - var view = ''; - - for (; i < l; i++) { - var template = this.defaultTemplate; - var completed = ''; - var checked = ''; - - if (data[i].completed) { - completed = 'completed'; - checked = 'checked'; - } - - template = template.replace('{{id}}', data[i].id); - template = template.replace('{{title}}', escape(data[i].title)); - template = template.replace('{{completed}}', completed); - template = template.replace('{{checked}}', checked); - - view = view + template; - } - - return view; - }; - - /** - * Displays a counter of how many to dos are left to complete - * - * @param {number} activeTodos The number of active todos. - * @returns {string} String containing the count - */ - Template.prototype.itemCounter = function (activeTodos) { - var plural = activeTodos === 1 ? '' : 's'; - - return '' + activeTodos + ' item' + plural + ' left'; - }; - - /** - * Updates the text within the "Clear completed" button - * - * @param {[type]} completedTodos The number of completed todos. - * @returns {string} String containing the count - */ - Template.prototype.clearCompletedButton = function (completedTodos) { - if (completedTodos > 0) { - return 'Clear completed'; - } else { - return ''; - } - }; - - // Export to window - window.app = window.app || {}; - window.app.Template = Template; -})(window); diff --git a/www/todo/example/js/view.js b/www/todo/example/js/view.js deleted file mode 100644 index d9f59611e..000000000 --- a/www/todo/example/js/view.js +++ /dev/null @@ -1,219 +0,0 @@ -/*global qs, qsa, $on, $parent, $delegate */ - -(function (window) { - 'use strict'; - - /** - * View that abstracts away the browser's DOM completely. - * It has two simple entry points: - * - * - bind(eventName, handler) - * Takes a todo application event and registers the handler - * - render(command, parameterObject) - * Renders the given command with the options - */ - function View(template) { - this.template = template; - - this.ENTER_KEY = 13; - this.ESCAPE_KEY = 27; - - this.$todoList = qs('.todo-list'); - this.$todoItemCounter = qs('.todo-count'); - this.$clearCompleted = qs('.clear-completed'); - this.$main = qs('.main'); - this.$footer = qs('.footer'); - this.$toggleAll = qs('.toggle-all'); - this.$newTodo = qs('.new-todo'); - } - - View.prototype._removeItem = function (id) { - var elem = qs('[data-id="' + id + '"]'); - - if (elem) { - this.$todoList.removeChild(elem); - } - }; - - View.prototype._clearCompletedButton = function (completedCount, visible) { - this.$clearCompleted.innerHTML = this.template.clearCompletedButton(completedCount); - this.$clearCompleted.style.display = visible ? 'block' : 'none'; - }; - - View.prototype._setFilter = function (currentPage) { - qs('.filters .selected').className = ''; - qs('.filters [href="#/' + currentPage + '"]').className = 'selected'; - }; - - View.prototype._elementComplete = function (id, completed) { - var listItem = qs('[data-id="' + id + '"]'); - - if (!listItem) { - return; - } - - listItem.className = completed ? 'completed' : ''; - - // In case it was toggled from an event and not by clicking the checkbox - qs('input', listItem).checked = completed; - }; - - View.prototype._editItem = function (id, title) { - var listItem = qs('[data-id="' + id + '"]'); - - if (!listItem) { - return; - } - - listItem.className = listItem.className + ' editing'; - - var input = document.createElement('input'); - input.className = 'edit'; - - listItem.appendChild(input); - input.focus(); - input.value = title; - }; - - View.prototype._editItemDone = function (id, title) { - var listItem = qs('[data-id="' + id + '"]'); - - if (!listItem) { - return; - } - - var input = qs('input.edit', listItem); - listItem.removeChild(input); - - listItem.className = listItem.className.replace('editing', ''); - - qsa('label', listItem).forEach(function (label) { - label.textContent = title; - }); - }; - - View.prototype.render = function (viewCmd, parameter) { - var self = this; - var viewCommands = { - showEntries: function () { - self.$todoList.innerHTML = self.template.show(parameter); - }, - removeItem: function () { - self._removeItem(parameter); - }, - updateElementCount: function () { - self.$todoItemCounter.innerHTML = self.template.itemCounter(parameter); - }, - clearCompletedButton: function () { - self._clearCompletedButton(parameter.completed, parameter.visible); - }, - contentBlockVisibility: function () { - self.$main.style.display = self.$footer.style.display = parameter.visible ? 'block' : 'none'; - }, - toggleAll: function () { - self.$toggleAll.checked = parameter.checked; - }, - setFilter: function () { - self._setFilter(parameter); - }, - clearNewTodo: function () { - self.$newTodo.value = ''; - }, - elementComplete: function () { - self._elementComplete(parameter.id, parameter.completed); - }, - editItem: function () { - self._editItem(parameter.id, parameter.title); - }, - editItemDone: function () { - self._editItemDone(parameter.id, parameter.title); - } - }; - - viewCommands[viewCmd](); - }; - - View.prototype._itemId = function (element) { - var li = $parent(element, 'li'); - return parseInt(li.dataset.id, 10); - }; - - View.prototype._bindItemEditDone = function (handler) { - var self = this; - $delegate(self.$todoList, 'li .edit', 'blur', function () { - if (!this.dataset.iscanceled) { - handler({ - id: self._itemId(this), - title: this.value - }); - } - }); - - $delegate(self.$todoList, 'li .edit', 'keypress', function (event) { - if (event.keyCode === self.ENTER_KEY) { - // Remove the cursor from the input when you hit enter just like if it - // were a real form - this.blur(); - } - }); - }; - - View.prototype._bindItemEditCancel = function (handler) { - var self = this; - $delegate(self.$todoList, 'li .edit', 'keyup', function (event) { - if (event.keyCode === self.ESCAPE_KEY) { - this.dataset.iscanceled = true; - this.blur(); - - handler({id: self._itemId(this)}); - } - }); - }; - - View.prototype.bind = function (event, handler) { - var self = this; - if (event === 'newTodo') { - $on(self.$newTodo, 'change', function () { - handler(self.$newTodo.value); - }); - - } else if (event === 'removeCompleted') { - $on(self.$clearCompleted, 'click', function () { - handler(); - }); - - } else if (event === 'toggleAll') { - $on(self.$toggleAll, 'click', function () { - handler({completed: this.checked}); - }); - - } else if (event === 'itemEdit') { - $delegate(self.$todoList, 'li label', 'dblclick', function () { - handler({id: self._itemId(this)}); - }); - - } else if (event === 'itemRemove') { - $delegate(self.$todoList, '.destroy', 'click', function () { - handler({id: self._itemId(this)}); - }); - - } else if (event === 'itemToggle') { - $delegate(self.$todoList, '.toggle', 'click', function () { - handler({ - id: self._itemId(this), - completed: this.checked - }); - }); - - } else if (event === 'itemEditDone') { - self._bindItemEditDone(handler); - - } else if (event === 'itemEditCancel') { - self._bindItemEditCancel(handler); - } - }; - - // Export to window - window.app = window.app || {}; - window.app.View = View; -}(window));