Created
March 14, 2016 21:01
-
-
Save JBreit/6427fb523f319711f9ad to your computer and use it in GitHub Desktop.
Simple ES6 Todo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #todoApp | |
| #addTodo | |
| %input{:name => "todo", :type => "text", :placeholder => "Write something..."} | |
| %input{:type => "submit", :value => "Add"} | |
| %ul#todos | |
| #options | |
| -# %button#complete Complete All | |
| -# %button#clear Clear |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class TodoItem { | |
| constructor({id = 'todo-es6-0', title = "", completed = false}) { | |
| // ES6 can't overload... lame :( | |
| this.id = id | |
| this.title = title | |
| this.completed = completed | |
| this._save() | |
| } | |
| _getProperties() { | |
| return { | |
| id: this.id, | |
| title: this.title, | |
| completed: this.completed | |
| } | |
| } | |
| _save() { | |
| localStorage.setItem(this.id, JSON.stringify(this._getProperties())) | |
| } | |
| isCompleted() { | |
| return this.completed | |
| } | |
| update(updates) { | |
| Object.keys(updates).map(prop => this[prop] = updates[prop]) | |
| this._save() | |
| return this | |
| } | |
| } | |
| class TodoStore { | |
| static create(title, completed = false) { | |
| return new TodoItem({id: `todo-es6-${TodoStore.getAll().length}`, title, completed}) | |
| } | |
| static update(id, properties) { | |
| return TodoStore.get(id).update(properties) | |
| } | |
| static completeAll() { | |
| TodoStore.getAllIncompleted().map(todo => TodoStore.update(todo.id, { completed: true })) | |
| } | |
| static get(id) { | |
| return new TodoItem(JSON.parse(localStorage.getItem(id))) | |
| } | |
| static getAll() { | |
| return Object.keys(localStorage).map(id => TodoStore.get(id)).sort((a, b) => b.id - a.id) | |
| } | |
| static getAllCompleted() { | |
| return TodoStore.getAll().find(todo => todo.isCompleted()) | |
| } | |
| static getAllIncomplete() { | |
| return TodoStore.getAll().find(todo => ! todo.isCompleted()) | |
| } | |
| static destroy(id) { | |
| localStorage.removeItem(id) | |
| } | |
| static destroyAllCompleted() { | |
| TodoStore.getAllCompleted().map(todo => TodoStore.destroy(todo.id)) | |
| } | |
| static destroyAll() { | |
| TodoStore.getAll().map(todo => TodoStore.destroy(todo.id)) | |
| } | |
| } | |
| TodoStore.destroyAll() | |
| TodoStore.create("Go for a walk") | |
| TodoStore.create("Write a letter") | |
| TodoStore.create("Get baby to sleep", true) | |
| // TodoStore.completeAll() | |
| // TodoStore.destroyAllCompleted() | |
| // TodoStore.destroyAll() | |
| /** | |
| * Wire up the UI | |
| */ | |
| window.onload = () => { | |
| addExistingTodos() | |
| attachItemCreation() | |
| focusInput() | |
| } | |
| const focusInput = () => document.querySelectorAll("input[name='todo']")[0].focus() | |
| const addExistingTodos = () => { | |
| TodoStore.getAll().map(todo => addTodoItem(todo)) | |
| } | |
| const attachItemCreation = () => { | |
| const $input = document.querySelectorAll("input[type='submit']")[0] | |
| const inputClickHandler = () => { | |
| const $todoInput = document.querySelectorAll("input[name='todo']")[0] | |
| addTodoItem(TodoStore.create($todoInput.value)) | |
| $todoInput.value = "" | |
| focusInput() | |
| } | |
| // Has to be a function name, not an inline function | |
| $input.onclick = inputClickHandler | |
| } | |
| const addTodoItem = todo => { | |
| const $list = document.getElementById("todos") | |
| const $listItem = document.createElement("li") | |
| const $checkbox = document.createElement("input") | |
| $checkbox.type = "checkbox" | |
| $checkbox.id = `${todo.id}` | |
| const checkboxClickHandler = (event) => { | |
| const $checkbox = event.target | |
| const $label = $checkbox.parentElement | |
| const todo = TodoStore.update($checkbox.id, {completed: $checkbox.checked}) | |
| if (todo.completed) { | |
| $label.className = "checked" | |
| } else { | |
| $label.className = "" | |
| } | |
| } | |
| $checkbox.onclick = checkboxClickHandler | |
| const $label = document.createElement('label') | |
| $label.htmlFor = $checkbox.id | |
| $label.appendChild($checkbox) | |
| $label.appendChild(document.createTextNode(todo.title)) | |
| if (todo.completed) { | |
| $label.className = "checked" | |
| $checkbox.checked = true | |
| } | |
| $listItem.appendChild($label) | |
| $list.appendChild($listItem) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body, #todos { | |
| margin: 0; | |
| padding: 0; | |
| } | |
| #todoApp { | |
| padding: 0; | |
| margin: 1em; | |
| max-width: 20em; | |
| border: 1px solid #000; | |
| } | |
| #addTodo { | |
| display: flex; | |
| text-align: center; | |
| input[type='text'] { | |
| flex: 3; | |
| margin-right: .5em; | |
| } | |
| padding: 1em; | |
| border-bottom: 1px solid #000; | |
| } | |
| #todos { | |
| background-color: #eee; | |
| list-style: none; | |
| li { | |
| padding: .5em 1em; | |
| border-bottom: 1px solid #999; | |
| input[type='checkbox'] { | |
| margin-right: .5em; | |
| } | |
| &:last-child { | |
| border-bottom: none; | |
| } | |
| } | |
| } | |
| .checked { | |
| text-decoration: line-through; | |
| color: #ccc; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment