Source code

Revision control

Copy as Markdown

Other Tools

{"version":3,"sources":["webpack:///bundle.app.930ad8b83126862d7445.js","webpack:///./helpers.js","webpack:///./app.js","webpack:///./controller.js","webpack:///./memory.js","webpack:///./model.js","webpack:///./store.js","webpack:///./template.js","webpack:///./todo.js","webpack:///./view.js","webpack:///./bootstrap.js"],"names":["webpackJsonp","module","exports","__webpack_require__","qs","selector","scope","document","querySelector","qsa","querySelectorAll","$on","target","type","callback","useCapture","addEventListener","$delegate","handler","dispatchEvent","event","targetElement","potentialElements","hasMatch","Array","prototype","indexOf","call","$parent","element","tagName","parentNode","toLowerCase","remove","array","thing","index","splice","d","NodeList","forEach","onLoad","i","__WEBPACK_IMPORTED_MODULE_3__todo__","__WEBPACK_IMPORTED_MODULE_0_todomvc_app_css_index_css__","__WEBPACK_IMPORTED_MODULE_1__app_css__","n","Controller","model","view","that","this","bind","title","addItem","item","editItem","id","editItemSave","editItemCancel","removeItem","toggleComplete","completed","removeCompletedItems","status","toggleAll","setView","locationHash","route","split","page","_updateFilterState","showAll","read","data","render","showActive","showCompleted","trim","create","_filter","update","silent","_updateCount","getCount","todos","active","visible","checked","total","force","activeRoute","_activeRoute","charAt","toUpperCase","substr","_lastActiveRoute","currentPage","_typeof","Symbol","iterator","obj","constructor","root","localStorageMemory","cache","length","getItem","key","setItem","value","hasOwnProperty","Object","keys","clear","Model","storage","newItem","save","query","queryType","findAll","parseInt","find","removeAll","drop","todo","Store","name","_dbName","__WEBPACK_IMPORTED_MODULE_1__memory__","JSON","stringify","parse","subscribers","__WEBPACK_IMPORTED_MODULE_0__helpers__","uniqueID","subscribe","subscriber","_this","push","_notify","s","filter","q","updateData","Template","defaultTemplate","htmlEscapes","&","<",">","\"","'","`","escapeHtmlChar","chr","reUnescapedHtml","reHasUnescapedHtml","RegExp","source","escape","string","test","replace","show","l","template","itemCounter","activeTodos","plural","clearCompletedButton","completedTodos","Todo","__WEBPACK_IMPORTED_MODULE_3__store__","__WEBPACK_IMPORTED_MODULE_2__model__","__WEBPACK_IMPORTED_MODULE_4__template__","__WEBPACK_IMPORTED_MODULE_0__view__","controller","__WEBPACK_IMPORTED_MODULE_1__controller__","updateTodo","location","hash","_classCallCheck","instance","Constructor","TypeError","_setFilter","className","_elementComplete","listItem","_editItem","input","createElement","appendChild","focus","_itemId","li","dataset","_createClass","defineProperties","props","descriptor","enumerable","configurable","writable","defineProperty","protoProps","staticProps","View","ENTER_KEY","ESCAPE_KEY","$todoList","$todoItemCounter","$clearCompleted","$main","$footer","$toggleAll","$newTodo","elem","removeChild","completedCount","innerHTML","style","display","label","textContent","viewCmd","parameter","viewCommands","showEntries","_removeItem","updateElementCount","_clearCompletedButton","contentBlockVisibility","setFilter","clearNewTodo","elementComplete","editItemDone","_editItemDone","iscanceled","keyCode","blur","_bindItemEditDone","_bindItemEditCancel","bootstrap","__WEBPACK_IMPORTED_MODULE_1__helpers__","window","__WEBPACK_IMPORTED_MODULE_0__app__","readyState"],"mappings":"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","file":"bundle.app.930ad8b83126862d7445.js","sourcesContent":["webpackJsonp([0,2],[\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/* harmony export */ __webpack_require__.d(exports, \"a\", function() { return qs; });\n/* harmony export */ __webpack_require__.d(exports, \"b\", function() { return qsa; });\n/* harmony export */ __webpack_require__.d(exports, \"d\", function() { return $on; });\n/* harmony export */ __webpack_require__.d(exports, \"c\", function() { return $delegate; });\n/* harmony export */ __webpack_require__.d(exports, \"e\", function() { return $parent; });\n/* harmony export */ __webpack_require__.d(exports, \"f\", function() { return remove; });\n\n// Get element(s) by CSS selector:\nfunction qs(selector, scope) {\n return (scope || document).querySelector(selector);\n}\n\nfunction qsa(selector, scope) {\n return (scope || document).querySelectorAll(selector);\n}\n\n// addEventListener wrapper:\nfunction $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\nfunction $delegate(target, selector, type, handler) {\n // https://developer.mozilla.org/en-US/docs/Web/Events/blur\n var useCapture = type === 'blur' || type === 'focus';\n $on(target, type, dispatchEvent, useCapture);\n\n function dispatchEvent(event) {\n var targetElement = event.target;\n var potentialElements = qsa(selector, target);\n var hasMatch = Array.prototype.indexOf.call(potentialElements, targetElement) >= 0;\n\n if (hasMatch) {\n handler.call(targetElement, event);\n }\n }\n}\n\n// Find the element's parent with the given tag name:\n// $parent(qs('a'), 'div');\nfunction $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]\nfunction remove(array, thing) {\n var index = array.indexOf(thing);\n if (index === -1) {\n return array;\n }\n 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\n/***/ },\n/* 1 */,\n/* 2 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_todomvc_app_css_index_css__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_todomvc_app_css_index_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_todomvc_app_css_index_css__);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__app_css__ = __webpack_require__(10);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__app_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__app_css__);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__todo__ = __webpack_require__(8);\n/* harmony export */ exports[\"a\"] = onLoad;\n\n\n\n\n\nfunction onLoad() {\n // eslint-disable-line import/prefer-default-export\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__todo__[\"a\" /* updateTodo */])();\n}\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony default export */ exports[\"a\"] = Controller;\n\n/**\n* Takes a model and view and acts as the controller between them\n*\n* @constructor\n* @param {object} model The model instance\n* @param {object} view The view instance\n*/\nfunction Controller(model, view) {\n var that = this;\n that.model = model;\n that.view = view;\n\n that.view.bind('newTodo', function (title) {\n that.addItem(title);\n });\n\n that.view.bind('itemEdit', function (item) {\n that.editItem(item.id);\n });\n\n that.view.bind('itemEditDone', function (item) {\n that.editItemSave(item.id, item.title);\n });\n\n that.view.bind('itemEditCancel', function (item) {\n that.editItemCancel(item.id);\n });\n\n that.view.bind('itemRemove', function (item) {\n that.removeItem(item.id);\n });\n\n that.view.bind('itemToggle', function (item) {\n that.toggleComplete(item.id, item.completed);\n });\n\n that.view.bind('removeCompleted', function () {\n that.removeCompletedItems();\n });\n\n that.view.bind('toggleAll', function (status) {\n that.toggleAll(status.completed);\n });\n}\n\n/**\n* Loads and initialises the view\n*\n* @param {string} '' | 'active' | 'completed'\n*/\nController.prototype.setView = function (locationHash) {\n var route = locationHash.split('/')[1];\n var page = route || '';\n this._updateFilterState(page);\n};\n\n/**\n* An event to fire on load. Will get all items and display them in the\n* todo-list\n*/\nController.prototype.showAll = function () {\n var that = this;\n that.model.read(function (data) {\n that.view.render('showEntries', data);\n });\n};\n\n/**\n* Renders all active tasks\n*/\nController.prototype.showActive = function () {\n var that = this;\n that.model.read({ completed: false }, function (data) {\n that.view.render('showEntries', data);\n });\n};\n\n/**\n* Renders all completed tasks\n*/\nController.prototype.showCompleted = function () {\n var that = this;\n that.model.read({ completed: true }, function (data) {\n that.view.render('showEntries', data);\n });\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*/\nController.prototype.addItem = function (title) {\n var that = this;\n\n if (title.trim() === '') {\n return;\n }\n\n that.model.create(title, function () {\n that.view.render('clearNewTodo');\n that._filter(true);\n });\n};\n\n/*\n* Triggers the item editing mode.\n*/\nController.prototype.editItem = function (id) {\n var that = this;\n that.model.read(id, function (data) {\n that.view.render('editItem', { id: id, title: data[0].title });\n });\n};\n\n/*\n* Finishes the item editing mode successfully.\n*/\nController.prototype.editItemSave = function (id, title) {\n var that = this;\n if (title.trim()) {\n that.model.update(id, { title: title }, function () {\n that.view.render('editItemDone', { id: id, title: title });\n });\n } else {\n that.removeItem(id);\n }\n};\n\n/*\n* Cancels the item editing mode.\n*/\nController.prototype.editItemCancel = function (id) {\n var that = this;\n that.model.read(id, function (data) {\n that.view.render('editItemDone', { id: id, title: data[0].title });\n });\n};\n\n/**\n* By giving it an ID it'll find the DOM element matching that ID,\n* remove it from the DOM and also remove it from storage.\n*\n* @param {number} id The ID of the item to remove from the DOM and\n* storage\n*/\nController.prototype.removeItem = function (id) {\n var that = this;\n that.model.remove(id, function () {\n that.view.render('removeItem', id);\n });\n\n that._filter();\n};\n\n/**\n* Will remove all completed items from the DOM and storage.\n*/\nController.prototype.removeCompletedItems = function () {\n var that = this;\n that.model.read({ completed: true }, function (data) {\n data.forEach(function (item) {\n that.removeItem(item.id);\n });\n });\n\n that._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*/\nController.prototype.toggleComplete = function (id, completed, silent) {\n var that = this;\n that.model.update(id, { completed: completed }, function () {\n that.view.render('elementComplete', {\n id: id,\n completed: completed\n });\n });\n\n if (!silent) {\n that._filter();\n }\n};\n\n/**\n* Will toggle ALL checkboxes' on/off state and completeness of models.\n* Just pass in the event object.\n*/\nController.prototype.toggleAll = function (completed) {\n var that = this;\n that.model.read({ completed: !completed }, function (data) {\n data.forEach(function (item) {\n that.toggleComplete(item.id, completed, true);\n });\n });\n\n that._filter();\n};\n\n/**\n* Updates the pieces of the page which change depending on the remaining\n* number of todos.\n*/\nController.prototype._updateCount = function () {\n var that = this;\n that.model.getCount(function (todos) {\n that.view.render('updateElementCount', todos.active);\n that.view.render('clearCompletedButton', {\n completed: todos.completed,\n visible: todos.completed > 0\n });\n\n that.view.render('toggleAll', { checked: todos.completed === todos.total });\n that.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*/\nController.prototype._filter = function (force) {\n var activeRoute = this._activeRoute.charAt(0).toUpperCase() + this._activeRoute.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\n this._lastActiveRoute = activeRoute;\n};\n\n/**\n* Simply updates the filter nav's selected states\n*/\nController.prototype._updateFilterState = function (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 currentPage = currentPage.split('?')[0];\n this._activeRoute = currentPage;\n\n if (currentPage === '') {\n this._activeRoute = 'All';\n }\n\n this._filter();\n\n this.view.render('setFilter', currentPage);\n};\n\n/***/ },\n/* 4 */\n/***/ function(module, exports, __webpack_require__) {\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n(function (root) {\n var localStorageMemory = {};\n var cache = {};\n\n /**\n * number of stored items.\n */\n localStorageMemory.length = 0;\n\n /**\n * returns item for passed key, or null\n *\n * @para {String} key\n * name of item to be returned\n * @returns {String|null}\n */\n localStorageMemory.getItem = function (key) {\n return cache[key] || null;\n };\n\n /**\n * sets item for key to passed value, as String\n *\n * @para {String} key\n * name of item to be set\n * @para {String} value\n * value, will always be turned into a String\n * @returns {undefined}\n */\n localStorageMemory.setItem = function (key, value) {\n if (typeof value === 'undefined') {\n localStorageMemory.removeItem(key);\n } else {\n if (!cache.hasOwnProperty(key)) {\n localStorageMemory.length++;\n }\n\n cache[key] = '' + value;\n }\n };\n\n /**\n * removes item for passed key\n *\n * @para {String} key\n * name of item to be removed\n * @returns {undefined}\n */\n localStorageMemory.removeItem = function (key) {\n if (cache.hasOwnProperty(key)) {\n delete cache[key];\n localStorageMemory.length--;\n }\n };\n\n /**\n * returns name of key at passed index\n *\n * @para {Number} index\n * Position for key to be returned (starts at 0)\n * @returns {String|null}\n */\n localStorageMemory.key = function (index) {\n return Object.keys(cache)[index] || null;\n };\n\n /**\n * removes all stored items and sets length to 0\n *\n * @returns {undefined}\n */\n localStorageMemory.clear = function () {\n cache = {};\n localStorageMemory.length = 0;\n };\n\n if (( false ? 'undefined' : _typeof(exports)) === 'object') {\n module.exports = localStorageMemory;\n } else {\n root.localStorageMemory = localStorageMemory;\n }\n})(this);\n\n/***/ },\n/* 5 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\n/* harmony default export */ exports[\"a\"] = Model;\n\n/**\n* Creates a new Model instance and hooks up the storage.\n*\n* @constructor\n* @param {object} storage A reference to the client side storage class\n*/\nfunction Model(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*/\nModel.prototype.create = function (title, callback) {\n title = title || '';\n callback = callback || function () {};\n\n var 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 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 */\nModel.prototype.read = function (query, callback) {\n var queryType = typeof query === 'undefined' ? 'undefined' : _typeof(query);\n callback = callback || function () {};\n\n if (queryType === 'function') {\n callback = query;\n return 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 return undefined;\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*/\nModel.prototype.update = function (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*/\nModel.prototype.remove = function (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*/\nModel.prototype.removeAll = function (callback) {\n this.storage.drop(callback);\n};\n\n/**\n* Returns a count of all todos\n*/\nModel.prototype.getCount = function (callback) {\n var todos = {\n active: 0,\n completed: 0,\n total: 0\n };\n\n this.storage.findAll(function (data) {\n data.forEach(function (todo) {\n if (todo.completed) {\n todos.completed++;\n } else {\n todos.active++;\n }\n\n todos.total++;\n });\n callback(todos);\n });\n};\n\n/***/ },\n/* 6 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__helpers__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__memory__ = __webpack_require__(4);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__memory___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__memory__);\n\n\n/* harmony default export */ exports[\"a\"] = Store;\n\nvar uniqueID = 1;\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 */\nfunction Store(name, callback) {\n callback = callback || function () {};\n\n this._dbName = name;\n\n if (!__WEBPACK_IMPORTED_MODULE_1__memory__[name]) {\n var data = {\n todos: []\n };\n\n __WEBPACK_IMPORTED_MODULE_1__memory__[name] = JSON.stringify(data);\n }\n\n callback.call(this, JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[name]));\n this.subscribers = [];\n}\n\nStore.prototype.subscribe = function (subscriber) {\n var _this = this;\n\n this.subscribers.push(subscriber);\n return function () {\n return __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"f\" /* remove */])(_this.subscribers, subscriber);\n };\n};\n\nStore.prototype._notify = function () {\n this.subscribers.forEach(function (s) {\n return s();\n });\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*/\nStore.prototype.find = function (query, callback) {\n if (!callback) {\n return;\n }\n\n var todos = JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]).todos;\n\n callback.call(this, todos.filter(function (todo) {\n for (var q in query) {\n if (query[q] !== todo[q]) {\n return false;\n }\n }\n return true;\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*/\nStore.prototype.findAll = function (callback) {\n callback = callback || function () {};\n callback.call(this, JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[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*/\nStore.prototype.save = function (updateData, callback, id) {\n var data = JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]);\n var todos = data.todos;\n\n callback = callback || function () {};\n\n // If an ID was actually given, find the item and update each property\n if (id) {\n for (var i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n for (var key in updateData) {\n // eslint-disable-line guard-for-in\n todos[i][key] = updateData[key];\n }\n break;\n }\n }\n\n __WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName] = JSON.stringify(data);\n callback.call(this, JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]).todos);\n } else {\n // Generate an ID\n updateData.id = uniqueID++;\n\n todos.push(updateData);\n __WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName] = JSON.stringify(data);\n callback.call(this, [updateData]);\n }\n this._notify();\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*/\nStore.prototype.remove = function (id, callback) {\n var data = JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]);\n var todos = data.todos;\n\n for (var i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n todos.splice(i, 1);\n break;\n }\n }\n\n __WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName] = JSON.stringify(data);\n callback.call(this, JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]).todos);\n this._notify();\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*/\nStore.prototype.drop = function (callback) {\n __WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName] = JSON.stringify({ todos: [] });\n callback.call(this, JSON.parse(__WEBPACK_IMPORTED_MODULE_1__memory__[this._dbName]).todos);\n this._notify();\n};\n\n/***/ },\n/* 7 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony default export */ exports[\"a\"] = Template;\n\nvar htmlEscapes = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n '\\'': '&#x27;',\n '`': '&#x60;'\n};\n\nvar escapeHtmlChar = function escapeHtmlChar(chr) {\n return htmlEscapes[chr];\n};\n\nvar reUnescapedHtml = /[&<>\"'`]/g;\nvar reHasUnescapedHtml = new RegExp(reUnescapedHtml.source);\n\nvar escape = function escape(string) {\n if (string && reHasUnescapedHtml.test(string)) {\n return string.replace(reUnescapedHtml, escapeHtmlChar);\n } else {\n return string;\n }\n};\n\n/**\n* Sets up defaults for all the Template methods such as a default template\n*\n* @constructor\n*/\nfunction Template() {\n this.defaultTemplate = '\\n <li data-id=\"{{id}}\" class=\"{{completed}}\">\\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}\n\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 */\nTemplate.prototype.show = function (data) {\n var i, l;\n var view = '';\n\n for (i = 0, l = data.length; i < l; i++) {\n var template = this.defaultTemplate;\n var completed = '';\n var checked = '';\n\n if (data[i].completed) {\n completed = 'completed';\n checked = 'checked';\n }\n\n template = template.replace('{{id}}', data[i].id);\n template = template.replace('{{title}}', escape(data[i].title));\n template = template.replace('{{completed}}', completed);\n template = template.replace('{{checked}}', checked);\n\n view = view + template;\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 */\nTemplate.prototype.itemCounter = function (activeTodos) {\n var plural = activeTodos === 1 ? '' : 's';\n\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 */\nTemplate.prototype.clearCompletedButton = function (completedTodos) {\n if (completedTodos > 0) {\n return 'Clear completed';\n } else {\n return '';\n }\n};\n\n/***/ },\n/* 8 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__view__ = __webpack_require__(9);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__controller__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__model__ = __webpack_require__(5);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__store__ = __webpack_require__(6);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__template__ = __webpack_require__(7);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__helpers__ = __webpack_require__(0);\n\n/* harmony export */ __webpack_require__.d(exports, \"a\", function() { return updateTodo; });/* unused harmony export getTodo *//* unused harmony export subscribe */\n\n\n\n\n\n\n\n\nvar todo = void 0;\nvar subscribers = [];\n\n/**\n * Sets up a brand new Todo list.\n *\n * @param {string} name The name of your new to do list.\n */\nfunction Todo(name) {\n this.storage = new __WEBPACK_IMPORTED_MODULE_3__store__[\"a\" /* default */](name);\n this.model = new __WEBPACK_IMPORTED_MODULE_2__model__[\"a\" /* default */](this.storage);\n this.template = new __WEBPACK_IMPORTED_MODULE_4__template__[\"a\" /* default */]();\n this.view = new __WEBPACK_IMPORTED_MODULE_0__view__[\"a\" /* default */](this.template);\n this.controller = new __WEBPACK_IMPORTED_MODULE_1__controller__[\"a\" /* default */](this.model, this.view);\n}\n\nfunction updateTodo() {\n todo = new Todo('todos-vanillajs');\n todo.controller.setView(document.location.hash);\n subscribers.forEach(function (s) {\n return s();\n });\n}\n\nfunction getTodo() {\n return todo;\n}\n\nfunction subscribe(cb) {\n subscribers.push(cb);\n return function unsubscribe() {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_5__helpers__[\"f\" /* remove */])(subscribers, cb);\n };\n}\n\n/***/ },\n/* 9 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__helpers__ = __webpack_require__(0);\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/* eslint no-invalid-this: 0, complexity:[2, 9] */\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 */\n\nvar View = function () {\n function View(template) {\n _classCallCheck(this, View);\n\n this.template = template;\n\n this.ENTER_KEY = 13;\n this.ESCAPE_KEY = 27;\n\n this.$todoList = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.todo-list');\n this.$todoItemCounter = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.todo-count');\n this.$clearCompleted = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.clear-completed');\n this.$main = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.main');\n this.$footer = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.footer');\n this.$toggleAll = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.toggle-all');\n this.$newTodo = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.new-todo');\n }\n\n _createClass(View, [{\n key: '_removeItem',\n value: function _removeItem(id) {\n var elem = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('[data-id=\"' + id + '\"]');\n\n if (elem) {\n this.$todoList.removeChild(elem);\n }\n }\n }, {\n key: '_clearCompletedButton',\n value: function _clearCompletedButton(completedCount, visible) {\n this.$clearCompleted.innerHTML = this.template.clearCompletedButton(completedCount);\n this.$clearCompleted.style.display = visible ? 'block' : 'none';\n }\n }, {\n key: '_editItemDone',\n value: function _editItemDone(id, title) {\n var listItem = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('[data-id=\"' + id + '\"]');\n\n if (!listItem) {\n return;\n }\n\n var input = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('input.edit', listItem);\n listItem.removeChild(input);\n\n listItem.className = listItem.className.replace('editing', '');\n\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"b\" /* qsa */])('label', listItem).forEach(function (label) {\n label.textContent = title;\n });\n }\n }, {\n key: 'render',\n value: function render(viewCmd, parameter) {\n var that = this;\n var viewCommands = {\n showEntries: function showEntries() {\n that.$todoList.innerHTML = that.template.show(parameter);\n },\n removeItem: function removeItem() {\n that._removeItem(parameter);\n },\n updateElementCount: function updateElementCount() {\n that.$todoItemCounter.innerHTML = that.template.itemCounter(parameter);\n },\n clearCompletedButton: function clearCompletedButton() {\n that._clearCompletedButton(parameter.completed, parameter.visible);\n },\n contentBlockVisibility: function contentBlockVisibility() {\n that.$main.style.display = that.$footer.style.display = parameter.visible ? 'block' : 'none';\n },\n toggleAll: function toggleAll() {\n that.$toggleAll.checked = parameter.checked;\n },\n setFilter: function setFilter() {\n _setFilter(parameter);\n },\n clearNewTodo: function clearNewTodo() {\n that.$newTodo.value = '';\n },\n elementComplete: function elementComplete() {\n _elementComplete(parameter.id, parameter.completed);\n },\n editItem: function editItem() {\n _editItem(parameter.id, parameter.title);\n },\n editItemDone: function editItemDone() {\n that._editItemDone(parameter.id, parameter.title);\n }\n };\n\n viewCommands[viewCmd]();\n }\n }, {\n key: '_bindItemEditDone',\n value: function _bindItemEditDone(handler) {\n var that = this;\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, 'li .edit', 'blur', function () {\n if (!this.dataset.iscanceled) {\n handler({\n id: _itemId(this),\n title: this.value\n });\n }\n });\n\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, 'li .edit', 'keypress', function (event) {\n if (event.keyCode === that.ENTER_KEY) {\n // Remove the cursor from the input when you hit enter just like if it\n // were a real form\n this.blur();\n }\n });\n }\n }, {\n key: '_bindItemEditCancel',\n value: function _bindItemEditCancel(handler) {\n var that = this;\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, 'li .edit', 'keyup', function (event) {\n if (event.keyCode === that.ESCAPE_KEY) {\n this.dataset.iscanceled = true;\n this.blur();\n\n handler({ id: _itemId(this) });\n }\n });\n }\n }, {\n key: 'bind',\n value: function bind(event, handler) {\n var that = this;\n if (event === 'newTodo') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"d\" /* $on */])(that.$newTodo, 'change', function () {\n handler(that.$newTodo.value);\n });\n } else if (event === 'removeCompleted') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"d\" /* $on */])(that.$clearCompleted, 'click', function () {\n handler();\n });\n } else if (event === 'toggleAll') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"d\" /* $on */])(that.$toggleAll, 'click', function () {\n handler({ completed: this.checked });\n });\n } else if (event === 'itemEdit') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, 'li label', 'dblclick', function () {\n handler({ id: _itemId(this) });\n });\n } else if (event === 'itemRemove') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, '.destroy', 'click', function () {\n handler({ id: _itemId(this) });\n });\n } else if (event === 'itemToggle') {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"c\" /* $delegate */])(that.$todoList, '.toggle', 'click', function () {\n handler({\n id: _itemId(this),\n completed: this.checked\n });\n });\n } else if (event === 'itemEditDone') {\n that._bindItemEditDone(handler);\n } else if (event === 'itemEditCancel') {\n that._bindItemEditCancel(handler);\n }\n }\n }]);\n\n return View;\n}();\n\n/* harmony default export */ exports[\"a\"] = View;\n\n\nfunction _setFilter(currentPage) {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.filters .selected').className = '';\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('.filters [href=\"#/' + currentPage + '\"]').className = 'selected';\n}\n\nfunction _elementComplete(id, completed) {\n var listItem = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('[data-id=\"' + id + '\"]');\n\n if (!listItem) {\n return;\n }\n\n listItem.className = completed ? 'completed' : '';\n\n // In case it was toggled from an event and not by clicking the checkbox\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('input', listItem).checked = completed;\n}\n\nfunction _editItem(id, title) {\n var listItem = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"a\" /* qs */])('[data-id=\"' + id + '\"]');\n\n if (!listItem) {\n return;\n }\n\n listItem.className = listItem.className + ' editing';\n\n var input = document.createElement('input');\n input.className = 'edit';\n\n listItem.appendChild(input);\n input.focus();\n input.value = title;\n}\n\nfunction _itemId(element) {\n var li = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__helpers__[\"e\" /* $parent */])(element, 'li');\n return parseInt(li.dataset.id, 10);\n}\n\n/***/ },\n/* 10 */\n/***/ function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ },\n/* 11 */\n/***/ function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__app__ = __webpack_require__(2);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__helpers__ = __webpack_require__(0);\n/* eslint no-console:0 */\n\n\n\n// this is only relevant when using `hot` mode with webpack\n// special thanks to Eric Clemmons: https://github.com/ericclemmons/webpack-hot-server-example\nvar reloading = document.readyState === 'complete';\nif (false) {\n module.hot.accept(function (err) {});\n if (reloading) {\n onLoad();\n } else {\n bootstrap();\n }\n} else {\n bootstrap();\n}\n\nfunction bootstrap() {\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__helpers__[\"d\" /* $on */])(window, 'load', __WEBPACK_IMPORTED_MODULE_0__app__[\"a\" /* onLoad */]);\n __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__helpers__[\"d\" /* $on */])(window, 'hashchange', __WEBPACK_IMPORTED_MODULE_0__app__[\"a\" /* onLoad */]);\n}\n\n/***/ }\n],[11]);\n\n\n// WEBPACK FOOTER //\n// bundle.app.930ad8b83126862d7445.js","export {qs, qsa, $on, $delegate, $parent, remove}\n\n// Get element(s) by CSS selector:\nfunction qs(selector, scope) {\n return (scope || document).querySelector(selector)\n}\n\nfunction qsa(selector, scope) {\n return (scope || document).querySelectorAll(selector)\n}\n\n// addEventListener wrapper:\nfunction $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\nfunction $delegate(target, selector, type, handler) {\n // https://developer.mozilla.org/en-US/docs/Web/Events/blur\n var useCapture = type === 'blur' || type === 'focus'\n $on(target, type, dispatchEvent, useCapture)\n\n function dispatchEvent(event) {\n var targetElement = event.target\n var potentialElements = qsa(selector, target)\n var hasMatch = Array.prototype.indexOf.call(potentialElements, targetElement) >= 0\n\n if (hasMatch) {\n handler.call(targetElement, event)\n }\n }\n}\n\n// Find the element's parent with the given tag name:\n// $parent(qs('a'), 'div');\nfunction $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]\nfunction remove(array, thing) {\n const index = array.indexOf(thing)\n if (index === -1) {\n return array\n }\n 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\n\n\n// WEBPACK FOOTER //\n// ./helpers.js","import 'todomvc-app-css/index.css'\nimport './app.css'\n\nimport {$on} from './helpers'\nimport {updateTodo} from './todo'\n\nexport function onLoad() { // eslint-disable-line import/prefer-default-export\n updateTodo()\n}\n\n\n\n// WEBPACK FOOTER //\n// ./app.js","export default Controller\n\n/**\n* Takes a model and view and acts as the controller between them\n*\n* @constructor\n* @param {object} model The model instance\n* @param {object} view The view instance\n*/\nfunction Controller(model, view) {\n var that = this\n that.model = model\n that.view = view\n\n that.view.bind('newTodo', function(title) {\n that.addItem(title)\n })\n\n that.view.bind('itemEdit', function(item) {\n that.editItem(item.id)\n })\n\n that.view.bind('itemEditDone', function(item) {\n that.editItemSave(item.id, item.title)\n })\n\n that.view.bind('itemEditCancel', function(item) {\n that.editItemCancel(item.id)\n })\n\n that.view.bind('itemRemove', function(item) {\n that.removeItem(item.id)\n })\n\n that.view.bind('itemToggle', function(item) {\n that.toggleComplete(item.id, item.completed)\n })\n\n that.view.bind('removeCompleted', function() {\n that.removeCompletedItems()\n })\n\n that.view.bind('toggleAll', function(status) {\n that.toggleAll(status.completed)\n })\n}\n\n/**\n* Loads and initialises the view\n*\n* @param {string} '' | 'active' | 'completed'\n*/\nController.prototype.setView = function(locationHash) {\n var route = locationHash.split('/')[1]\n var page = route || ''\n this._updateFilterState(page)\n}\n\n/**\n* An event to fire on load. Will get all items and display them in the\n* todo-list\n*/\nController.prototype.showAll = function() {\n var that = this\n that.model.read(function(data) {\n that.view.render('showEntries', data)\n })\n}\n\n/**\n* Renders all active tasks\n*/\nController.prototype.showActive = function() {\n var that = this\n that.model.read({completed: false}, function(data) {\n that.view.render('showEntries', data)\n })\n}\n\n/**\n* Renders all completed tasks\n*/\nController.prototype.showCompleted = function() {\n var that = this\n that.model.read({completed: true}, function(data) {\n that.view.render('showEntries', data)\n })\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*/\nController.prototype.addItem = function(title) {\n var that = this\n\n if (title.trim() === '') {\n return\n }\n\n that.model.create(title, function() {\n that.view.render('clearNewTodo')\n that._filter(true)\n })\n}\n\n/*\n* Triggers the item editing mode.\n*/\nController.prototype.editItem = function(id) {\n var that = this\n that.model.read(id, function(data) {\n that.view.render('editItem', {id, title: data[0].title})\n })\n}\n\n/*\n* Finishes the item editing mode successfully.\n*/\nController.prototype.editItemSave = function(id, title) {\n var that = this\n if (title.trim()) {\n that.model.update(id, {title}, function() {\n that.view.render('editItemDone', {id, title})\n })\n } else {\n that.removeItem(id)\n }\n}\n\n/*\n* Cancels the item editing mode.\n*/\nController.prototype.editItemCancel = function(id) {\n var that = this\n that.model.read(id, function(data) {\n that.view.render('editItemDone', {id, title: data[0].title})\n })\n}\n\n/**\n* By giving it an ID it'll find the DOM element matching that ID,\n* remove it from the DOM and also remove it from storage.\n*\n* @param {number} id The ID of the item to remove from the DOM and\n* storage\n*/\nController.prototype.removeItem = function(id) {\n var that = this\n that.model.remove(id, function() {\n that.view.render('removeItem', id)\n })\n\n that._filter()\n}\n\n/**\n* Will remove all completed items from the DOM and storage.\n*/\nController.prototype.removeCompletedItems = function() {\n var that = this\n that.model.read({completed: true}, function(data) {\n data.forEach(function(item) {\n that.removeItem(item.id)\n })\n })\n\n that._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*/\nController.prototype.toggleComplete = function(id, completed, silent) {\n var that = this\n that.model.update(id, {completed}, function() {\n that.view.render('elementComplete', {\n id,\n completed,\n })\n })\n\n if (!silent) {\n that._filter()\n }\n}\n\n/**\n* Will toggle ALL checkboxes' on/off state and completeness of models.\n* Just pass in the event object.\n*/\nController.prototype.toggleAll = function(completed) {\n var that = this\n that.model.read({completed: !completed}, function(data) {\n data.forEach(function(item) {\n that.toggleComplete(item.id, completed, true)\n })\n })\n\n that._filter()\n}\n\n/**\n* Updates the pieces of the page which change depending on the remaining\n* number of todos.\n*/\nController.prototype._updateCount = function() {\n var that = this\n that.model.getCount(function(todos) {\n that.view.render('updateElementCount', todos.active)\n that.view.render('clearCompletedButton', {\n completed: todos.completed,\n visible: todos.completed > 0\n })\n\n that.view.render('toggleAll', {checked: todos.completed === todos.total})\n that.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*/\nController.prototype._filter = function(force) {\n var activeRoute = this._activeRoute.charAt(0).toUpperCase() + this._activeRoute.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\n this._lastActiveRoute = activeRoute\n}\n\n/**\n* Simply updates the filter nav's selected states\n*/\nController.prototype._updateFilterState = function(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 currentPage = currentPage.split('?')[0]\n this._activeRoute = currentPage\n\n if (currentPage === '') {\n this._activeRoute = 'All'\n }\n\n this._filter()\n\n this.view.render('setFilter', currentPage)\n}\n\n\n\n// WEBPACK FOOTER //\n// ./controller.js","(function(root) {\n var localStorageMemory = {};\n var cache = {};\n\n /**\n * number of stored items.\n */\n localStorageMemory.length = 0;\n\n /**\n * returns item for passed key, or null\n *\n * @para {String} key\n * name of item to be returned\n * @returns {String|null}\n */\n localStorageMemory.getItem = function(key) {\n return cache[key] || null;\n };\n\n /**\n * sets item for key to passed value, as String\n *\n * @para {String} key\n * name of item to be set\n * @para {String} value\n * value, will always be turned into a String\n * @returns {undefined}\n */\n localStorageMemory.setItem = function(key, value) {\n if (typeof value === 'undefined') {\n localStorageMemory.removeItem(key);\n } else {\n if (!(cache.hasOwnProperty(key))) {\n localStorageMemory.length++;\n }\n\n cache[key] = '' + value;\n }\n };\n\n /**\n * removes item for passed key\n *\n * @para {String} key\n * name of item to be removed\n * @returns {undefined}\n */\n localStorageMemory.removeItem = function(key) {\n if (cache.hasOwnProperty(key)) {\n delete cache[key];\n localStorageMemory.length--;\n }\n };\n\n /**\n * returns name of key at passed index\n *\n * @para {Number} index\n * Position for key to be returned (starts at 0)\n * @returns {String|null}\n */\n localStorageMemory.key = function(index) {\n return Object.keys(cache)[index] || null;\n };\n\n /**\n * removes all stored items and sets length to 0\n *\n * @returns {undefined}\n */\n localStorageMemory.clear = function() {\n cache = {};\n localStorageMemory.length = 0;\n };\n\n if (typeof exports === 'object') {\n module.exports = localStorageMemory;\n } else {\n root.localStorageMemory = localStorageMemory;\n }\n})(this);\n\n\n// WEBPACK FOOTER //\n// ./memory.js","export default Model\n\n/**\n* Creates a new Model instance and hooks up the storage.\n*\n* @constructor\n* @param {object} storage A reference to the client side storage class\n*/\nfunction Model(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*/\nModel.prototype.create = function(title, callback) {\n title = title || ''\n callback = callback || function() {\n }\n\n var 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 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 */\nModel.prototype.read = function(query, callback) {\n var queryType = typeof query\n callback = callback || function() {\n }\n\n if (queryType === 'function') {\n callback = query\n return 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 return undefined\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*/\nModel.prototype.update = function(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*/\nModel.prototype.remove = function(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*/\nModel.prototype.removeAll = function(callback) {\n this.storage.drop(callback)\n}\n\n/**\n* Returns a count of all todos\n*/\nModel.prototype.getCount = function(callback) {\n var todos = {\n active: 0,\n completed: 0,\n total: 0\n }\n\n this.storage.findAll(function(data) {\n data.forEach(function(todo) {\n if (todo.completed) {\n todos.completed++\n } else {\n todos.active++\n }\n\n todos.total++\n })\n callback(todos)\n })\n}\n\n\n\n// WEBPACK FOOTER //\n// ./model.js","import {remove} from './helpers'\nimport * as localStorageMemory from './memory'\nexport default Store\n\nvar uniqueID = 1;\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 */\nfunction Store(name, callback) {\n callback = callback || function() {\n }\n\n this._dbName = name\n\n if (!localStorageMemory[name]) {\n var data = {\n todos: []\n }\n\n localStorageMemory[name] = JSON.stringify(data)\n }\n\n callback.call(this, JSON.parse(localStorageMemory[name]))\n this.subscribers = []\n}\n\nStore.prototype.subscribe = function(subscriber) {\n this.subscribers.push(subscriber)\n return () => remove(this.subscribers, subscriber)\n}\n\nStore.prototype._notify = function() {\n this.subscribers.forEach(s => s())\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*/\nStore.prototype.find = function(query, callback) {\n if (!callback) {\n return\n }\n\n var todos = JSON.parse(localStorageMemory[this._dbName]).todos\n\n callback.call(this, todos.filter(function(todo) {\n for (var q in query) {\n if (query[q] !== todo[q]) {\n return false\n }\n }\n return true\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*/\nStore.prototype.findAll = function(callback) {\n callback = callback || function() {\n }\n callback.call(this, JSON.parse(localStorageMemory[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*/\nStore.prototype.save = function(updateData, callback, id) {\n var data = JSON.parse(localStorageMemory[this._dbName])\n var todos = data.todos\n\n callback = callback || function() {\n }\n\n // If an ID was actually given, find the item and update each property\n if (id) {\n for (var i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n for (var key in updateData) { // eslint-disable-line guard-for-in\n todos[i][key] = updateData[key]\n }\n break\n }\n }\n\n localStorageMemory[this._dbName] = JSON.stringify(data)\n callback.call(this, JSON.parse(localStorageMemory[this._dbName]).todos)\n } else {\n // Generate an ID\n updateData.id = uniqueID++;\n\n todos.push(updateData)\n localStorageMemory[this._dbName] = JSON.stringify(data)\n callback.call(this, [updateData])\n }\n this._notify()\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*/\nStore.prototype.remove = function(id, callback) {\n var data = JSON.parse(localStorageMemory[this._dbName])\n var todos = data.todos\n\n for (var i = 0; i < todos.length; i++) {\n if (todos[i].id === id) {\n todos.splice(i, 1)\n break\n }\n }\n\n localStorageMemory[this._dbName] = JSON.stringify(data)\n callback.call(this, JSON.parse(localStorageMemory[this._dbName]).todos)\n this._notify()\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*/\nStore.prototype.drop = function(callback) {\n localStorageMemory[this._dbName] = JSON.stringify({todos: []})\n callback.call(this, JSON.parse(localStorageMemory[this._dbName]).todos)\n this._notify()\n}\n\n\n\n// WEBPACK FOOTER //\n// ./store.js","export default Template\n\nvar htmlEscapes = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n '\\'': '&#x27;',\n '`': '&#x60;'\n}\n\nvar escapeHtmlChar = function(chr) {\n return htmlEscapes[chr]\n}\n\nvar reUnescapedHtml = /[&<>\"'`]/g\nvar reHasUnescapedHtml = new RegExp(reUnescapedHtml.source)\n\nvar escape = function(string) {\n if (string && reHasUnescapedHtml.test(string)) {\n return string.replace(reUnescapedHtml, escapeHtmlChar)\n } else {\n return string\n }\n}\n\n/**\n* Sets up defaults for all the Template methods such as a default template\n*\n* @constructor\n*/\nfunction Template() {\n this.defaultTemplate = `\n <li data-id=\"{{id}}\" class=\"{{completed}}\">\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}\n\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 */\nTemplate.prototype.show = function(data) {\n var i, l\n var view = ''\n\n for (i = 0, l = data.length; i < l; i++) {\n var template = this.defaultTemplate\n var completed = ''\n var checked = ''\n\n if (data[i].completed) {\n completed = 'completed'\n checked = 'checked'\n }\n\n template = template.replace('{{id}}', data[i].id)\n template = template.replace('{{title}}', escape(data[i].title))\n template = template.replace('{{completed}}', completed)\n template = template.replace('{{checked}}', checked)\n\n view = view + template\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 */\nTemplate.prototype.itemCounter = function(activeTodos) {\n var plural = activeTodos === 1 ? '' : 's'\n\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 */\nTemplate.prototype.clearCompletedButton = function(completedTodos) {\n if (completedTodos > 0) {\n return 'Clear completed'\n } else {\n return ''\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./template.js","import View from './view'\nimport Controller from './controller'\nimport Model from './model'\nimport Store from './store'\nimport Template from './template'\nimport {remove} from './helpers'\n\nexport {updateTodo, getTodo, subscribe}\n\nlet todo\nconst subscribers = []\n\n/**\n * Sets up a brand new Todo list.\n *\n * @param {string} name The name of your new to do list.\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\nfunction updateTodo() {\n todo = new Todo('todos-vanillajs')\n todo.controller.setView(document.location.hash)\n subscribers.forEach(s => s())\n}\n\nfunction getTodo() {\n return todo\n}\n\nfunction subscribe(cb) {\n subscribers.push(cb)\n return function unsubscribe() {\n remove(subscribers, cb)\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./todo.js","/* eslint no-invalid-this: 0, complexity:[2, 9] */\nimport {qs, qsa, $on, $parent, $delegate} from './helpers'\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.ENTER_KEY = 13\n this.ESCAPE_KEY = 27\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.$toggleAll = qs('.toggle-all')\n this.$newTodo = qs('.new-todo')\n }\n\n _removeItem(id) {\n var elem = qs('[data-id=\"' + id + '\"]')\n\n if (elem) {\n this.$todoList.removeChild(elem)\n }\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 _editItemDone(id, title) {\n var listItem = qs('[data-id=\"' + id + '\"]')\n\n if (!listItem) {\n return\n }\n\n var input = qs('input.edit', listItem)\n listItem.removeChild(input)\n\n listItem.className = listItem.className.replace('editing', '')\n\n qsa('label', listItem).forEach(function(label) {\n label.textContent = title\n })\n }\n\n render(viewCmd, parameter) {\n var that = this\n var viewCommands = {\n showEntries: function() {\n that.$todoList.innerHTML = that.template.show(parameter)\n },\n removeItem: function() {\n that._removeItem(parameter)\n },\n updateElementCount: function() {\n that.$todoItemCounter.innerHTML = that.template.itemCounter(parameter)\n },\n clearCompletedButton: function() {\n that._clearCompletedButton(parameter.completed, parameter.visible)\n },\n contentBlockVisibility: function() {\n that.$main.style.display = that.$footer.style.display = parameter.visible ? 'block' : 'none'\n },\n toggleAll: function() {\n that.$toggleAll.checked = parameter.checked\n },\n setFilter: function() {\n _setFilter(parameter)\n },\n clearNewTodo: function() {\n that.$newTodo.value = ''\n },\n elementComplete: function() {\n _elementComplete(parameter.id, parameter.completed)\n },\n editItem: function() {\n _editItem(parameter.id, parameter.title)\n },\n editItemDone: function() {\n that._editItemDone(parameter.id, parameter.title)\n }\n }\n\n viewCommands[viewCmd]()\n }\n\n _bindItemEditDone(handler) {\n var that = this\n $delegate(that.$todoList, 'li .edit', 'blur', function() {\n if (!this.dataset.iscanceled) {\n handler({\n id: _itemId(this),\n title: this.value\n })\n }\n })\n\n $delegate(that.$todoList, 'li .edit', 'keypress', function(event) {\n if (event.keyCode === that.ENTER_KEY) {\n // Remove the cursor from the input when you hit enter just like if it\n // were a real form\n this.blur()\n }\n })\n }\n\n _bindItemEditCancel(handler) {\n var that = this\n $delegate(that.$todoList, 'li .edit', 'keyup', function(event) {\n if (event.keyCode === that.ESCAPE_KEY) {\n this.dataset.iscanceled = true\n this.blur()\n\n handler({id: _itemId(this)})\n }\n })\n }\n\n bind(event, handler) {\n var that = this\n if (event === 'newTodo') {\n $on(that.$newTodo, 'change', function() {\n handler(that.$newTodo.value)\n })\n\n } else if (event === 'removeCompleted') {\n $on(that.$clearCompleted, 'click', function() {\n handler()\n })\n\n } else if (event === 'toggleAll') {\n $on(that.$toggleAll, 'click', function() {\n handler({completed: this.checked})\n })\n\n } else if (event === 'itemEdit') {\n $delegate(that.$todoList, 'li label', 'dblclick', function() {\n handler({id: _itemId(this)})\n })\n\n } else if (event === 'itemRemove') {\n $delegate(that.$todoList, '.destroy', 'click', function() {\n handler({id: _itemId(this)})\n })\n\n } else if (event === 'itemToggle') {\n $delegate(that.$todoList, '.toggle', 'click', function() {\n handler({\n id: _itemId(this),\n completed: this.checked\n })\n })\n\n } else if (event === 'itemEditDone') {\n that._bindItemEditDone(handler)\n\n } else if (event === 'itemEditCancel') {\n that._bindItemEditCancel(handler)\n }\n }\n}\n\nfunction _setFilter(currentPage) {\n qs('.filters .selected').className = ''\n qs('.filters [href=\"#/' + currentPage + '\"]').className = 'selected'\n}\n\nfunction _elementComplete(id, completed) {\n var listItem = qs('[data-id=\"' + id + '\"]')\n\n if (!listItem) {\n return\n }\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\nfunction _editItem(id, title) {\n var listItem = qs('[data-id=\"' + id + '\"]')\n\n if (!listItem) {\n return\n }\n\n listItem.className = listItem.className + ' editing'\n\n var input = document.createElement('input')\n input.className = 'edit'\n\n listItem.appendChild(input)\n input.focus()\n input.value = title\n}\n\nfunction _itemId(element) {\n var li = $parent(element, 'li')\n return parseInt(li.dataset.id, 10)\n}\n\n\n\n// WEBPACK FOOTER //\n// ./view.js","/* eslint no-console:0 */\nimport {onLoad} from './app'\nimport {$on} from './helpers'\n\n// this is only relevant when using `hot` mode with webpack\n// special thanks to Eric Clemmons: https://github.com/ericclemmons/webpack-hot-server-example\nconst reloading = document.readyState === 'complete'\nif (module.hot) {\n module.hot.accept(function(err) {\n })\n if (reloading) {\n onLoad()\n } else {\n bootstrap()\n }\n} else {\n bootstrap()\n}\n\nfunction bootstrap() {\n $on(window, 'load', onLoad)\n $on(window, 'hashchange', onLoad)\n}\n\n\n\n// WEBPACK FOOTER //\n// ./bootstrap.js"],"sourceRoot":""}