-
Notifications
You must be signed in to change notification settings - Fork 0
/
TodoMVC.svelte
129 lines (122 loc) · 3.49 KB
/
TodoMVC.svelte
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<script>
const ENTER_KEY = 13;
const ESCAPE_KEY = 27;
let currentFilter = 'all';
let items = [];
let editing = null;
try {
items = JSON.parse(localStorage.getItem('todos-svelte')) || [];
} catch (err) {
items = [];
}
const updateView = () => {
currentFilter = 'all';
if (window.location.hash === '#/active') {
currentFilter = 'active';
} else if (window.location.hash === '#/completed') {
currentFilter = 'completed';
}
};
window.addEventListener('hashchange', updateView);
updateView();
function clearCompleted() {
items = items.filter(item => !item.completed);
}
function remove(index) {
items = items.slice(0, index).concat(items.slice(index + 1));
}
function toggleAll(event) {
items = items.map(item => ({
id: item.id,
description: item.description,
completed: event.target.checked
}));
}
function createNew(event) {
if (event.which === ENTER_KEY) {
items = items.concat({
id: uuid(),
description: event.target.value,
completed: false
});
event.target.value = '';
}
}
function handleEdit(event) {
if (event.which === ENTER_KEY) event.target.blur();
else if (event.which === ESCAPE_KEY) editing = null;
}
function submit(event) {
items[editing].description = event.target.value;
editing = null;
}
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
$: filtered = currentFilter === 'all'
? items
: currentFilter === 'completed'
? items.filter(item => item.completed)
: items.filter(item => !item.completed);
$: numActive = items.filter(item => !item.completed).length;
$: numCompleted = items.filter(item => item.completed).length;
$: try {
localStorage.setItem('todos-svelte', JSON.stringify(items));
} catch (err) {
// noop
}
</script>
<header class="header">
<h1>todos</h1>
<input
class="new-todo"
on:keydown={createNew}
placeholder="What needs to be done?"
autofocus
>
</header>
{#if items.length > 0}
<section class="main">
<input id="toggle-all" class="toggle-all" type="checkbox" on:change={toggleAll} checked="{numCompleted === items.length}">
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list">
{#each filtered as item, index (item.id)}
<li class="{item.completed ? 'completed' : ''} {editing === index ? 'editing' : ''}">
<div class="view">
<input class="toggle" type="checkbox" bind:checked={item.completed}>
<label on:dblclick="{() => editing = index}">{item.description}</label>
<button on:click="{() => remove(index)}" class="destroy"></button>
</div>
{#if editing === index}
<input
value='{item.description}'
id="edit"
class="edit"
on:keydown={handleEdit}
on:blur={submit}
autofocus
>
{/if}
</li>
{/each}
</ul>
<footer class="footer">
<span class="todo-count">
<strong>{numActive}</strong> {numActive === 1 ? 'item' : 'items'} left
</span>
<ul class="filters">
<li><a class="{currentFilter === 'all' ? 'selected' : ''}" href="#/">All</a></li>
<li><a class="{currentFilter === 'active' ? 'selected' : ''}" href="#/active">Active</a></li>
<li><a class="{currentFilter === 'completed' ? 'selected' : ''}" href="#/completed">Completed</a></li>
</ul>
{#if numCompleted}
<button class="clear-completed" on:click={clearCompleted}>
Clear completed
</button>
{/if}
</footer>
</section>
{/if}