Skip to content

Commit b250b26

Browse files
committed
15: add my JavaScript code
Signed-off-by: Soshi Katsuta <soshi.katsuta@gmail.com>
1 parent 3afbad8 commit b250b26

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

15 - LocalStorage/index-START.html

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,7 @@ <h2>LOCAL TAPAS</h2>
2525
</form>
2626
</div>
2727

28-
<script>
29-
const addItems = document.querySelector('.add-items');
30-
const itemsList = document.querySelector('.plates');
31-
const items = [];
32-
33-
</script>
28+
<script src="script.js"></script>
3429

3530

3631
</body>

15 - LocalStorage/script.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
'use strict';
2+
3+
class Notifier {
4+
constructor() {
5+
this.handlers = [];
6+
}
7+
8+
addHandler(handler) {
9+
this.handlers.push(handler);
10+
}
11+
12+
notify() {
13+
this.handlers.forEach(handler => handler());
14+
}
15+
}
16+
17+
class ItemsStore {
18+
constructor(notifier) {
19+
this.notifier = notifier;
20+
this.key = 'items';
21+
this.items = JSON.parse(localStorage.getItem(this.key)) || [];
22+
}
23+
24+
addHandler(handler) {
25+
this.notifier.addHandler(handler);
26+
}
27+
28+
persistAndNotify() {
29+
localStorage.setItem(this.key, JSON.stringify(this.items));
30+
this.notifier.notify();
31+
}
32+
33+
add(item) {
34+
this.items.push(item);
35+
this.persistAndNotify();
36+
}
37+
38+
toggle(index) {
39+
this.items[index].done = !this.items[index].done;
40+
this.persistAndNotify();
41+
}
42+
}
43+
44+
class ViewModel {
45+
constructor(itemsList, addItemInput) {
46+
this.itemsList = itemsList;
47+
this.addItemInput = addItemInput;
48+
this.itemsStore = new ItemsStore(new Notifier());
49+
50+
this.itemsStore.addHandler(() => {
51+
this.items = this.itemsStore.items;
52+
});
53+
this.itemsStore.persistAndNotify();
54+
55+
this.populateList = () => {
56+
const html = this.items.map((item, i) => {
57+
const checked = item.done ? 'checked' : '';
58+
return `
59+
<li>
60+
<input id="item${i}" type="checkbox" data-index="${i}" ${checked}/>
61+
<label for="item${i}">${item.text}</label>
62+
</li>`;
63+
}).join("\n");
64+
65+
this.itemsList.innerHTML = html;
66+
}
67+
this.populateList();
68+
}
69+
70+
addItem(ev) {
71+
ev.preventDefault();
72+
73+
const item = {
74+
text: this.addItemInput.value,
75+
done: false
76+
};
77+
this.itemsStore.add(item);
78+
79+
this.populateList();
80+
81+
// clear input form
82+
this.addItemInput.value = '';
83+
}
84+
85+
toggle(ev) {
86+
if (!ev.target.matches('input[type="checkbox"]')) { return; }
87+
88+
const index = ev.target.dataset.index;
89+
this.itemsStore.toggle(index);
90+
91+
this.populateList();
92+
}
93+
}
94+
95+
const itemsList = document.querySelector('ul.plates');
96+
const addItemForm = document.querySelector('form.add-items');
97+
const addItemInput = addItemForm.querySelector('input[name="item"]');
98+
const vm = new ViewModel(itemsList, addItemInput);
99+
100+
addItemForm.addEventListener('submit', ev => vm.addItem(ev));
101+
itemsList.addEventListener('click', ev => vm.toggle(ev));

0 commit comments

Comments
 (0)