-
Notifications
You must be signed in to change notification settings - Fork 0
/
Todo.elm
110 lines (91 loc) · 2.54 KB
/
Todo.elm
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module Todo where
import Basics
import Html (..)
import Html.Attributes (..)
import Html.Events (..)
import List
import Maybe
import Random
import Signal
import String
{---- State ----}
type alias State =
{ todos: List Todo
, field: String
, uid: Int
}
type alias Todo =
{ title: String
, completed: Bool
, id: Int
}
{---- Evolution ----}
type Delta
= NoOp
| UpdateField String
| TodoAdd Todo
| TodoToggle Int Bool
| TodoDelete Int
| SetState State
step : Delta -> State -> State
step delta state =
case delta of
NoOp -> state
UpdateField str ->
{ state | field <- str }
TodoAdd todo ->
{ state | todos <- state.todos ++ [todo]
, field <- ""
, uid <- fst (Random.generate (Random.int 0 10000) (Random.initialSeed state.uid))
}
TodoToggle id isCompleted ->
let updateTodo t = if t.id == id then {t | completed <- isCompleted} else t
in
{ state | todos <- List.map updateTodo state.todos }
TodoDelete id ->
{ state | todos <- List.filter (\t -> t.id /= id) state.todos }
SetState newstate ->
{ state | todos <- newstate.todos
, uid <- Basics.max newstate.uid state.uid
}
{---- View ----}
view : State -> Html
view state =
div
[]
[ input [ placeholder "A New Todo"
, value state.field
, on "input" targetValue (Signal.send updates << UpdateField)
, onKeyPress (\key -> if key == 13 then (Signal.send updates (TodoAdd { title = state.field, completed = False, id = state.uid + 1})) else (Signal.send updates NoOp))
, autofocus True
]
[]
, ul [] (List.map todoItemView state.todos)
, button [ onClick (Signal.send updates (SetState {todos = [], field = "", uid = 0}))] [ text "clear" ]
]
todoItemView : Todo -> Html
todoItemView todo =
li
[]
[ input [ type' "checkbox"
, checked todo.completed
, onClick (Signal.send updates (TodoToggle todo.id (not todo.completed)))
]
[]
, text todo.title
, button [onClick (Signal.send updates (TodoDelete todo.id))] [text "x"]
]
{---- Signals ----}
updates : Signal.Channel Delta
updates = Signal.channel NoOp
state : Signal State
state =
Signal.foldp step emptyState (Signal.merge (Signal.map (\s -> SetState s) getState) (Signal.subscribe updates))
{---- Portals ----}
main : Signal Html
main = Signal.map view state
emptyState : State
emptyState = State [] "" 0
port getState : Signal State
port saveState : Signal State
port saveState = state