Source code
Revision control
Copy as Markdown
Other Tools
{"version":3,"file":"app.bundle.js","mappings":"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","sources":["webpack://todomvc-javascript-es6-webpack/./src/helpers.js","webpack://todomvc-javascript-es6-webpack/./src/view.js","webpack://todomvc-javascript-es6-webpack/./src/controller.js","webpack://todomvc-javascript-es6-webpack/./src/model.js","webpack://todomvc-javascript-es6-webpack/./src/store.js","webpack://todomvc-javascript-es6-webpack/./src/template.js","webpack://todomvc-javascript-es6-webpack/./src/app.js"],"sourcesContent":["export { qs, qsa, $on, $delegate, $parent, remove };\n\n// Get element(s) by CSS selector:\nconst qs = (selector, scope) => {\n return (scope || document).querySelector(selector);\n};\n\nconst qsa = (selector, scope) => {\n return (scope || document).querySelectorAll(selector);\n};\n\n// addEventListener wrapper:\nconst $on = (target, type, callback, useCapture) => {\n target.addEventListener(type, callback, !!useCapture);\n};\n\n// Attach a handler to event for all elements that match the selector,\n// now or in the future, based on a root element\nconst $delegate = (target, selector, type, handler) => {\n // https://developer.mozilla.org/en-US/docs/Web/Events/blur\n const useCapture = type === \"blur\" || type === \"focus\";\n $on(target, type, dispatchEvent, useCapture);\n\n function dispatchEvent(event) {\n const targetElement = event.target;\n const potentialElements = qsa(selector, target);\n const hasMatch = Array.prototype.indexOf.call(potentialElements, targetElement) >= 0;\n\n if (hasMatch)\n handler.call(targetElement, event);\n }\n};\n\n// Find the element's parent with the given tag name:\n// $parent(qs('a'), 'div');\nconst $parent = (element, tagName) => {\n if (!element.parentNode)\n return undefined;\n\n if (element.parentNode.tagName.toLowerCase() === tagName.toLowerCase())\n return element.parentNode;\n\n return $parent(element.parentNode, tagName);\n};\n\n// removes an element from an array\n// const x = [1,2,3]\n// remove(x, 2)\n// x ~== [1,3]\nconst remove = (array, thing) => {\n const index = array.indexOf(thing);\n if (index === -1)\n return array;\n\n return array.splice(index, 1);\n};\n\n// Allow for looping on nodes by chaining:\n// qsa('.foo').forEach(function () {})\nNodeList.prototype.forEach = Array.prototype.forEach;\n","/* eslint no-invalid-this: 0, complexity:[2, 9] */\nimport { qs, qsa, $on, $parent, $delegate } from \"./helpers\";\n\nconst ENTER_KEY = 13;\nconst ESCAPE_KEY = 27;\n\nconst _setFilter = (currentPage) => {\n qs(\".filters .selected\").className = \"\";\n qs(`.filters [href=\"#/${currentPage}\"]`).className = \"selected\";\n};\n\nconst _elementComplete = (id, completed) => {\n const listItem = qs(`[data-id=\"${id}\"]`);\n\n if (!listItem)\n return;\n\n listItem.className = completed ? \"completed\" : \"\";\n\n // In case it was toggled from an event and not by clicking the checkbox\n qs(\"input\", listItem).checked = completed;\n};\n\nconst _editItem = (id, title) => {\n const listItem = qs(`[data-id=\"${id}\"]`);\n\n if (!listItem)\n return;\n\n listItem.className = `${listItem.className} editing`;\n\n const input = document.createElement(\"input\");\n input.className = \"edit\";\n\n listItem.appendChild(input);\n input.focus();\n input.value = title;\n};\n\nconst _editItemDone = (id, title) => {\n const listItem = qs(`[data-id=\"${id}\"]`);\n\n if (!listItem)\n return;\n\n const input = qs(\"input.edit\", listItem);\n listItem.removeChild(input);\n\n listItem.className = listItem.className.replace(\" editing\", \"\");\n\n qsa(\"label\", listItem).forEach((label) => {\n label.textContent = title;\n });\n};\n\nconst _itemId = (element) => {\n const li = $parent(element, \"li\");\n return parseInt(li.dataset.id, 10);\n};\n\nconst _removeItem = (id, list) => {\n const elem = qs(`[data-id=\"${id}\"]`);\n\n if (elem)\n list.removeChild(elem);\n};\n\n/**\n * View that abstracts away the browser's DOM completely.\n * It has two simple entry points:\n *\n * - bind(eventName, handler)\n * Takes a todo application event and registers the handler\n * - render(command, parameterObject)\n * Renders the given command with the options\n */\nexport default class View {\n constructor(template) {\n this.template = template;\n\n this.$todoList = qs(\".todo-list\");\n this.$todoItemCounter = qs(\".todo-count\");\n this.$clearCompleted = qs(\".clear-completed\");\n this.$main = qs(\".main\");\n this.$footer = qs(\".footer\");\n this.$toggleAllInput = qs(\".toggle-all\");\n this.$toggleAll = qs(\".toggle-all-label\");\n this.$newTodo = qs(\".new-todo\");\n\n this.render = this.render.bind(this);\n this.bindCallback = this.bindCallback.bind(this);\n }\n\n _clearCompletedButton(completedCount, visible) {\n this.$clearCompleted.innerHTML = this.template.clearCompletedButton(completedCount);\n this.$clearCompleted.style.display = visible ? \"block\" : \"none\";\n }\n\n // eslint-disable-next-line complexity\n render(viewCmd, parameter) {\n switch (viewCmd) {\n case \"showEntries\":\n this.$todoList.innerHTML = this.template.show(parameter);\n break;\n case \"updateElementCount\":\n this.$todoItemCounter.innerHTML = this.template.itemCounter(parameter);\n break;\n case \"contentBlockVisibility\":\n this.$main.style.display = this.$footer.style.display = parameter.visible ? \"block\" : \"none\";\n break;\n case \"toggleAll\":\n this.$toggleAllInput.checked = parameter.checked;\n break;\n case \"clearNewTodo\":\n this.$newTodo.value = \"\";\n break;\n case \"removeItem\":\n _removeItem(parameter, this.$todoList);\n break;\n case \"setFilter\":\n _setFilter(parameter);\n break;\n case \"elementComplete\":\n _elementComplete(parameter.id, parameter.completed);\n break;\n case \"editItem\":\n _editItem(parameter.id, parameter.title);\n break;\n case \"editItemDone\":\n _editItemDone(parameter.id, parameter.title);\n break;\n case \"clearCompletedButton\":\n this._clearCompletedButton(parameter.completed, parameter.visible, this.clearCompletedButton);\n break;\n }\n }\n\n bindCallback(event, handler) {\n switch (event) {\n case \"newTodo\":\n $on(this.$newTodo, \"change\", () => handler(this.$newTodo.value));\n break;\n case \"removeCompleted\":\n $on(this.$clearCompleted, \"click\", handler);\n break;\n case \"toggleAll\":\n $on(this.$toggleAll, \"click\", () => {\n this.$toggleAllInput.click();\n handler({ completed: this.$toggleAllInput.checked });\n });\n break;\n case \"itemEdit\":\n $delegate(this.$todoList, \"li label\", \"dblclick\", (e) => handler({ id: _itemId(e.target) }));\n break;\n case \"itemRemove\":\n $delegate(this.$todoList, \".destroy\", \"click\", (e) => handler({ id: _itemId(e.target) }));\n break;\n case \"itemToggle\":\n $delegate(this.$todoList, \".toggle\", \"click\", (e) => handler({ id: _itemId(e.target), completed: e.target.checked }));\n break;\n case \"itemEditDone\":\n $delegate(this.$todoList, \"li .edit\", \"blur\", function (e) {\n if (!e.target.dataset.iscanceled) {\n handler({\n id: _itemId(e.target),\n title: e.target.value,\n });\n }\n });\n $delegate(this.$todoList, \"li .edit\", \"keypress\", function (e) {\n if (e.keyCode === ENTER_KEY)\n e.target.blur();\n });\n break;\n case \"itemEditCancel\":\n $delegate(this.$todoList, \"li .edit\", \"keyup\", (e) => {\n if (e.keyCode === ESCAPE_KEY) {\n e.target.dataset.iscanceled = true;\n e.target.blur();\n handler({ id: _itemId(e.target) });\n }\n });\n break;\n }\n }\n}\n","class Controller {\n /**\n * Take a model & view, then act as controller between them\n * @param {object} model The model instance\n * @param {object} view The view instance\n */\n constructor(model, view) {\n this.model = model;\n this.view = view;\n\n this.view.bindCallback(\"newTodo\", (title) => this.addItem(title));\n this.view.bindCallback(\"itemEdit\", (item) => this.editItem(item.id));\n this.view.bindCallback(\"itemEditDone\", (item) => this.editItemSave(item.id, item.title));\n this.view.bindCallback(\"itemEditCancel\", (item) => this.editItemCancel(item.id));\n this.view.bindCallback(\"itemRemove\", (item) => this.removeItem(item.id));\n this.view.bindCallback(\"itemToggle\", (item) => this.toggleComplete(item.id, item.completed));\n this.view.bindCallback(\"removeCompleted\", () => this.removeCompletedItems());\n this.view.bindCallback(\"toggleAll\", (status) => this.toggleAll(status.completed));\n }\n\n /**\n * Load & Initialize the view\n * @param {string} '' | 'active' | 'completed'\n */\n setView(hash) {\n const route = hash.split(\"/\")[1];\n const page = route || \"\";\n this._updateFilter(page);\n }\n\n /**\n * Event fires on load. Gets all items & displays them\n */\n showAll() {\n this.model.read((data) => this.view.render(\"showEntries\", data));\n }\n\n /**\n * Renders all active tasks\n */\n showActive() {\n this.model.read({ completed: false }, (data) => this.view.render(\"showEntries\", data));\n }\n\n /**\n * Renders all completed tasks\n */\n showCompleted() {\n this.model.read({ completed: true }, (data) => this.view.render(\"showEntries\", data));\n }\n\n /**\n * An event to fire whenever you want to add an item. Simply pass in the event\n * object and it'll handle the DOM insertion and saving of the new item.\n */\n addItem(title) {\n if (title.trim() === \"\")\n return;\n\n this.model.create(title, () => {\n this.view.render(\"clearNewTodo\");\n this._filter(true);\n });\n }\n\n /*\n * Triggers the item editing mode.\n */\n editItem(id) {\n this.model.read(id, (data) => {\n let title = data[0].title;\n this.view.render(\"editItem\", { id, title });\n });\n }\n\n /*\n * Finishes the item editing mode successfully.\n */\n editItemSave(id, title) {\n title = title.trim();\n\n if (title.length !== 0) {\n this.model.update(id, { title }, () => {\n this.view.render(\"editItemDone\", { id, title });\n });\n } else {\n this.removeItem(id);\n }\n }\n\n /*\n * Cancels the item editing mode.\n */\n editItemCancel(id) {\n this.model.read(id, (data) => {\n const title = data[0].title;\n this.view.render(\"editItemDone\", { id, title });\n });\n }\n\n /**\n * Find the DOM element with given ID,\n * Then remove it from DOM & Storage\n */\n removeItem(id) {\n this.model.remove(id, () => this.view.render(\"removeItem\", id));\n this._filter();\n }\n\n /**\n * Will remove all completed items from the DOM and storage.\n */\n removeCompletedItems() {\n this.model.read({ completed: true }, (data) => {\n for (let item of data)\n this.removeItem(item.id);\n });\n\n this._filter();\n }\n\n /**\n * Give it an ID of a model and a checkbox and it will update the item\n * in storage based on the checkbox's state.\n *\n * @param {number} id The ID of the element to complete or uncomplete\n * @param {object} checkbox The checkbox to check the state of complete\n * or not\n * @param {boolean|undefined} silent Prevent re-filtering the todo items\n */\n toggleComplete(id, completed, silent) {\n this.model.update(id, { completed }, () => {\n this.view.render(\"elementComplete\", { id, completed });\n });\n\n if (!silent)\n this._filter();\n }\n\n /**\n * Will toggle ALL checkboxes' on/off state and completeness of models.\n * Just pass in the event object.\n */\n toggleAll(completed) {\n this.model.read({ completed: !completed }, (data) => {\n for (let item of data)\n this.toggleComplete(item.id, completed, true);\n });\n\n this._filter();\n }\n\n /**\n * Updates the pieces of the page which change depending on the remaining\n * number of todos.\n */\n _updateCount() {\n this.model.getCount((todos) => {\n const completed = todos.completed;\n const visible = completed > 0;\n const checked = completed === todos.total;\n\n this.view.render(\"updateElementCount\", todos.active);\n this.view.render(\"clearCompletedButton\", { completed, visible });\n this.view.render(\"toggleAll\", { checked });\n this.view.render(\"contentBlockVisibility\", { visible: todos.total > 0 });\n });\n }\n\n /**\n * Re-filters the todo items, based on the active route.\n * @param {boolean|undefined} force forces a re-painting of todo items.\n */\n _filter(force) {\n const active = this._activeRoute;\n const activeRoute = active.charAt(0).toUpperCase() + active.substr(1);\n\n // Update the elements on the page, which change with each completed todo\n this._updateCount();\n\n // If the last active route isn't \"All\", or we're switching routes, we\n // re-create the todo item elements, calling:\n // this.show[All|Active|Completed]()\n if (force || this._lastActiveRoute !== \"All\" || this._lastActiveRoute !== activeRoute)\n this[`show${activeRoute}`]();\n\n this._lastActiveRoute = activeRoute;\n }\n\n /**\n * Simply updates the filter nav's selected states\n */\n _updateFilter(currentPage) {\n // Store a reference to the active route, allowing us to re-filter todo\n // items as they are marked complete or incomplete.\n this._activeRoute = currentPage;\n\n if (currentPage === \"\")\n this._activeRoute = \"All\";\n\n this._filter();\n\n this.view.render(\"setFilter\", currentPage);\n }\n}\n\nexport default Controller;\n","/**\n * Creates a new Model instance and hooks up the storage.\n * @constructor\n * @param {object} storage A reference to the client side storage class\n */\nclass Model {\n constructor(storage) {\n this.storage = storage;\n }\n\n /**\n * Creates a new todo model\n *\n * @param {string} [title] The title of the task\n * @param {function} [callback] The callback to fire after the model is created\n */\n create(title, callback) {\n title = title || \"\";\n\n const newItem = {\n title: title.trim(),\n completed: false,\n };\n\n this.storage.save(newItem, callback);\n }\n\n /**\n * Finds and returns a model in storage. If no query is given it'll simply\n * return everything. If you pass in a string or number it'll look that up as\n * the ID of the model to find. Lastly, you can pass it an object to match\n * against.\n *\n * @param {string|number|object} [query] A query to match models against\n * @param {function} [callback] The callback to fire after the model is found\n *\n * @example\n * model.read(1, func) // Will find the model with an ID of 1\n * model.read('1') // Same as above\n * //Below will find a model with foo equalling bar and hello equalling world.\n * model.read({ foo: 'bar', hello: 'world' })\n */\n read(query, callback) {\n const queryType = typeof query;\n\n if (queryType === \"function\") {\n callback = query;\n this.storage.findAll(callback);\n } else if (queryType === \"string\" || queryType === \"number\") {\n query = parseInt(query, 10);\n this.storage.find({ id: query }, callback);\n } else {\n this.storage.find(query, callback);\n }\n }\n\n /**\n * Updates a model by giving it an ID, data to update, and a callback to fire when\n * the update is complete.\n *\n * @param {number} id The id of the model to update\n * @param {object} data The properties to update and their new value\n * @param {function} callback The callback to fire when the update is complete.\n */\n update(id, data, callback) {\n this.storage.save(data, callback, id);\n }\n\n /**\n * Removes a model from storage\n *\n * @param {number} id The ID of the model to remove\n * @param {function} callback The callback to fire when the removal is complete.\n */\n remove(id, callback) {\n this.storage.remove(id, callback);\n }\n\n /**\n * WARNING: Will remove ALL data from storage.\n *\n * @param {function} callback The callback to fire when the storage is wiped.\n */\n removeAll(callback) {\n this.storage.drop(callback);\n }\n\n /**\n * Returns a count of all todos\n */\n getCount(callback) {\n if (!callback)\n return;\n\n const stats = {\n active: 0,\n completed: 0,\n total: 0,\n };\n\n this.storage.findAll((data) => {\n for (let todo of data) {\n if (todo.completed)\n stats.completed++;\n else\n stats.active++;\n\n stats.total++;\n }\n\n callback(stats);\n });\n }\n}\n\nexport default Model;\n","let uniqueID = 1;\n/* HOT MODULE SPECIFIC\n * Since hot reload blows away class instances, storage object is\n * moved outside of the class.\n */\nlet memoryStorage = {};\n\n/**\n * Creates a new client side storage object and will create an empty\n * collection if no collection already exists.\n *\n * @param {string} name The name of our DB we want to use\n * @param {function} callback Our fake DB uses callbacks because in\n * real life you probably would be making AJAX calls\n */\nexport class Store {\n constructor(name, callback) {\n this._dbName = name;\n\n if (!memoryStorage[name]) {\n const data = {\n todos: [],\n };\n\n memoryStorage[name] = JSON.stringify(data);\n }\n\n if (callback)\n callback(JSON.parse(memoryStorage[name]));\n }\n\n /**\n * Finds items based on a query given as a JS object\n *\n * @param {object} query The query to match against (i.e. {foo: 'bar'})\n * @param {function} callback The callback to fire when the query has\n * completed running\n *\n * @example\n * db.find({foo: 'bar', hello: 'world'}, function (data) {\n * // data will return any items that have foo: bar and\n * // hello: world in their properties\n * })\n */\n find(query, callback) {\n if (!callback)\n return;\n\n const { todos } = JSON.parse(memoryStorage[this._dbName]);\n\n callback(\n todos.filter((todo) => {\n for (let q in query) {\n if (query[q] !== todo[q])\n return false;\n }\n\n return true;\n })\n );\n }\n\n /**\n * Will retrieve all data from the collection\n *\n * @param {function} callback The callback to fire upon retrieving data\n */\n findAll(callback) {\n if (!callback)\n return;\n\n callback(JSON.parse(memoryStorage[this._dbName]).todos);\n }\n\n /**\n * Will save the given data to the DB. If no item exists it will create a new\n * item, otherwise it'll simply update an existing item's properties\n *\n * @param {object} updateData The data to save back into the DB\n * @param {function} callback The callback to fire after saving\n * @param {number} id An optional param to enter an ID of an item to update\n */\n save(updateData, callback, id) {\n const data = JSON.parse(memoryStorage[this._dbName]);\n const { todos } = data;\n\n // If an ID was actually given, find the item and update each property\n if (id) {\n for (let i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n for (let key in updateData)\n todos[i][key] = updateData[key];\n\n break;\n }\n }\n\n memoryStorage[this._dbName] = JSON.stringify(data);\n\n if (callback)\n callback(JSON.parse(memoryStorage[this._dbName]).todos);\n } else {\n // Generate an ID\n updateData.id = uniqueID++;\n\n todos.push(updateData);\n memoryStorage[this._dbName] = JSON.stringify(data);\n\n if (callback)\n callback([updateData]);\n }\n }\n\n /**\n * Will remove an item from the Store based on its ID\n *\n * @param {number} id The ID of the item you want to remove\n * @param {function} callback The callback to fire after saving\n */\n remove(id, callback) {\n const data = JSON.parse(memoryStorage[this._dbName]);\n const { todos } = data;\n\n for (let i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n todos.splice(i, 1);\n break;\n }\n }\n\n memoryStorage[this._dbName] = JSON.stringify(data);\n\n if (callback)\n callback(JSON.parse(memoryStorage[this._dbName]).todos);\n }\n\n /**\n * Will drop all storage and start fresh\n *\n * @param {function} callback The callback to fire after dropping the data\n */\n drop(callback) {\n memoryStorage[this._dbName] = JSON.stringify({ todos: [] });\n\n if (callback)\n callback(JSON.parse(memoryStorage[this._dbName]).todos);\n }\n}\n\nexport default Store;\n","\"use strict\";\n\nconst htmlEscapes = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n \"`\": \"`\",\n};\n\nconst reUnescapedHtml = /[&<>\"'`]/g;\nconst reHasUnescapedHtml = new RegExp(reUnescapedHtml.source);\n\nconst escape = (str) => str && reHasUnescapedHtml.test(str) ? str.replace(reUnescapedHtml, escapeHtmlChar) : str;\nconst escapeHtmlChar = (chr) => htmlEscapes[chr];\n\nconst createTodoItem = ({ id, title, completed, checked, index }) => `\n<li data-id=\"${id}\" class=\"${completed}\" data-priority=\"${4 - (index % 5)}\">\n <div class=\"view\">\n <input class=\"toggle\" type=\"checkbox\" ${checked}>\n <label>${title}</label>\n <button class=\"destroy\"></button>\n </div>\n</li>\n`;\n\nclass Template {\n /**\n * Creates an <li> HTML string and returns it for placement in your app.\n *\n * NOTE: In real life you should be using a templating engine such as Mustache\n * or Handlebars, however, this is a vanilla JS example.\n *\n * @param {object} data The object containing keys you want to find in the\n * template to replace.\n * @returns {string} HTML String of an <li> element\n *\n * @example\n * view.show({\n * id: 1,\n * title: \"Hello World\",\n * completed: 0,\n * })\n */\n show(data) {\n let view = \"\";\n\n data.reverse().forEach((item, index) => {\n view += createTodoItem({\n id: item.id,\n title: escape(item.title),\n completed: item.completed ? \"completed\" : \"\",\n checked: item.completed ? \"checked\" : \"\",\n index: index,\n });\n });\n\n return view;\n }\n\n /**\n * Displays a counter of how many to dos are left to complete\n *\n * @param {number} activeTodos The number of active todos.\n * @returns {string} String containing the count\n */\n itemCounter(activeTodos) {\n const plural = activeTodos === 1 ? \"\" : \"s\";\n return `<strong>${activeTodos}</strong> item${plural} left`;\n }\n\n /**\n * Updates the text within the \"Clear completed\" button\n *\n * @param {[type]} completedTodos The number of completed todos.\n * @returns {string} String containing the count\n */\n clearCompletedButton(completedTodos) {\n return completedTodos > 0 ? \"Clear completed\" : \"\";\n }\n}\n\nexport default Template;\n","import View from \"./view\";\nimport Controller from \"./controller\";\nimport Model from \"./model\";\nimport Store from \"./store\";\nimport Template from \"./template\";\n\nimport \"todomvc-app-css/index.css\";\nimport \"./app.css\";\n\nlet todo;\nconst onHashChange = () => {\n todo.controller.setView(document.location.hash);\n};\n\nconst onLoad = () => {\n todo = new Todo(\"javascript-es6-webpack\");\n onHashChange();\n};\n\nfunction Todo(name) {\n this.storage = new Store(name);\n this.model = new Model(this.storage);\n this.template = new Template();\n this.view = new View(this.template);\n this.controller = new Controller(this.model, this.view);\n}\n\n/* HOT MODULE SPECIFIC */\nif (module.hot) {\n module.hot.accept(function (err) {});\n if (document.readyState === \"complete\")\n onLoad();\n}\n\nwindow.addEventListener(\"load\", onLoad);\nwindow.addEventListener(\"hashchange\", onHashChange);\n"],"names":["qs","selector","scope","document","querySelector","qsa","querySelectorAll","$on","target","type","callback","useCapture","addEventListener","$delegate","handler","event","targetElement","potentialElements","Array","prototype","indexOf","call","$parent","element","tagName","parentNode","toLowerCase","NodeList","forEach","_itemId","li","parseInt","dataset","id","View","constructor","template","this","$todoList","$todoItemCounter","$clearCompleted","$main","$footer","$toggleAllInput","$toggleAll","$newTodo","render","bind","bindCallback","_clearCompletedButton","completedCount","visible","innerHTML","clearCompletedButton","style","display","viewCmd","parameter","show","itemCounter","checked","value","list","elem","removeChild","_removeItem","currentPage","className","completed","listItem","_elementComplete","title","input","createElement","appendChild","focus","_editItem","replace","label","textContent","_editItemDone","click","e","iscanceled","keyCode","blur","model","view","addItem","item","editItem","editItemSave","editItemCancel","removeItem","toggleComplete","removeCompletedItems","status","toggleAll","setView","hash","page","split","_updateFilter","showAll","read","data","showActive","showCompleted","trim","create","_filter","length","update","remove","silent","_updateCount","getCount","todos","total","active","force","_activeRoute","activeRoute","charAt","toUpperCase","substr","_lastActiveRoute","storage","newItem","save","query","queryType","findAll","find","removeAll","drop","stats","todo","uniqueID","memoryStorage","name","_dbName","JSON","stringify","parse","filter","q","updateData","i","key","push","splice","htmlEscapes","reUnescapedHtml","reHasUnescapedHtml","RegExp","source","escapeHtmlChar","chr","reverse","index","str","createTodoItem","test","activeTodos","completedTodos","onHashChange","controller","location","Todo","window"],"sourceRoot":""}