-
Notifications
You must be signed in to change notification settings - Fork 0
/
shoppingList.html
153 lines (139 loc) · 4.65 KB
/
shoppingList.html
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="browser.script.iife.js"></script>
<title>Shopping List</title>
<style>
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background-color: #f5f5f5;
color: #333;
padding: 20px;
font-size: 1.4rem;
}
.shopping-list {
list-style: none;
padding: 0;
}
.shopping-list li {
margin: 10px 0;
display: flex;
align-items: center;
}
.shopping-list input[type="checkbox"] {
margin-right: 20px;
transform : scale(2);
}
.shopping-list label {
flex-grow: 1;
cursor: pointer;
}
.edit-input {
display: none;
}
.shopping-list li {
border-bottom: solid;
padding-bottom: 10px;
min-height: 40px;
}
:checked ~ label {
text-decoration: line-through;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
width: 40px;
height: 40px;
border-radius: 50%;
border-left-color: #09f;
animation: spin 1s ease infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<h2>Shopping List</h2>
<p>With autosave and in-place edit</p>
<input type="text" id="new-item" placeholder="Add new item" />
<button id="add-item">Add</button>
<ul class="shopping-list" id="shopping-list"></ul>
<div id="spinner" class="spinner"></div>
<script type="text/ruby" data-eval="async">
JS.global.document.getElementById("spinner").style.display = "none"
require "json"
@document = JS.global.document
@list = @document.getElementById("shopping-list")
@input = @document.getElementById("new-item")
@button = @document.getElementById("add-item")
@storage = JS.global.localStorage
def getItems()
@storage.getItem("shoppingItems")
end
def updateStorage()
items = []
@document.getElementById("shopping-list").querySelectorAll("li").to_a.each do |item|
label = item.querySelector("label").innerText
isChecked = item.querySelector("[type=checkbox]").checked
items.push({label:, isChecked:})
end
@storage.setItem("shoppingItems", JSON.generate(items))
end
def add_item(name, checked=false, shouldUpdateStorage=true)
return if name.nil? || name&.strip&.empty?
li = @document.createElement("li")
checkbox = @document.createElement("input")
checkbox.type = "checkbox"
checkbox.checked = checked
label = @document.createElement("label")
label.innerText = name
label.addEventListener("click") { |e| enable_editing(e.target) }
li.appendChild(checkbox)
li.appendChild(label)
input = @document.createElement("input")
input.type = "text"
input.className = "edit-input"
input.addEventListener("blur") { |e| update_item(e.target) }
input.addEventListener("keypress") do |e|
e.target.blur if e.key == "Enter"
end
li.appendChild(input)
@list.appendChild(li)
@input.value = ""
updateStorage if shouldUpdateStorage
end
def enable_editing(label)
input = label.nextSibling
input.value = label.innerText
label.style.display = "none"
input.style.display = "block"
input.focus
end
def update_item(input)
label = input.previousSibling
label.innerText = input.value.strip.empty? ? label.innerText : input.value
label.style.display = "block"
input.style.display = "none"
updateStorage()
end
@button.addEventListener("click") { add_item(@input.value) }
@input.addEventListener("keypress") do |e|
add_item(@input.value) if e.key == "Enter"
end
@list.addEventListener("change") do |e|
updateStorage
end
JSON.parse(getItems || "[]")&.to_a.each do |item|
p item
add_item(item["label"], item["isChecked"], false)
end
</script>
</body>
</html>