Skip to content

Instantly share code, notes, and snippets.

@JBreit
Created March 14, 2016 21:01
Show Gist options
  • Select an option

  • Save JBreit/6427fb523f319711f9ad to your computer and use it in GitHub Desktop.

Select an option

Save JBreit/6427fb523f319711f9ad to your computer and use it in GitHub Desktop.
Simple ES6 Todo
#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
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)
}
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