-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
75 lines (56 loc) · 2.62 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { merge, map, chain, tap, filter, scan, startWith, take } from 'most'
import { submit, change, click, dblclick, keyup, focusout, hashchange } from '@most/dom-event'
import snabbdom from 'snabbdom'
import props from 'snabbdom/modules/props'
import attrs from 'snabbdom/modules/attributes'
import clss from 'snabbdom/modules/class'
import { render } from './view'
import { initStore } from './store'
import {
addTodoAction, removeTodoAction, updateTodoAction, updateAllAction,
clearCompleteAction, updateViewAction,
beginEditAction, endEditAction, abortEditAction
} from './action'
const applyAction = (state, action) => action(state)
const preventDefault = s => tap(doPreventDefault, s)
const doPreventDefault = e => e.preventDefault()
const isKey = (code, s) => filter(e => e.keyCode === code, s)
const match = (query, s) => filter(e => e.target.matches(query), s)
const ENTER_KEY = 13
const ESC_KEY = 27
const listActions = el => {
const clicks = click(el)
const changes = change(el)
const add = map(addTodoAction, preventDefault(match('.add-todo', submit(el))))
const remove = map(removeTodoAction, match('.destroy', clicks))
const complete = map(updateTodoAction, match('.toggle', changes))
const all = map(updateAllAction, match('.toggle-all', changes))
const clear = map(clearCompleteAction, match('.clear-completed', clicks))
return merge(add, remove, complete, all, clear)
}
const editActions = el =>
chain(editTodo(el), match('label', dblclick(el)))
const editTodo = el => e => {
const editKey = match('.edit', keyup(el))
const enter = isKey(ENTER_KEY, editKey)
const blurEdit = match('.edit', focusout(el))
const saveEdit = map(endEditAction, merge(enter, blurEdit))
const escape = isKey(ESC_KEY, editKey)
const abortEdit = map(abortEditAction, escape)
const endEdit = take(1, merge(saveEdit, abortEdit))
return startWith(beginEditAction(e), endEdit)
}
const filterActions = window =>
map(updateViewAction, hashchange(window))
const todos = (window, container, initialState) => {
const actions = merge(listActions(container), editActions(container), filterActions(window))
return scan(applyAction, initialState, actions)
}
const root = document.querySelector('.todoapp')
const container = root.parentNode
const patch = snabbdom.init([props, attrs, clss])
const updateApp = (node, state) => patch(node, render(state))
/* global localStorage */
const [initialState, store] = initStore(localStorage, 'todos', { todos: [], editing: '', view: 'all' })
const updateStore = (store, value) => ({ seed: store(value), value })
todos(window, container, initialState).loop(updateStore, store).reduce(updateApp, root)