Revision 261548ff
Added by koszko about 2 years ago
html/options_main.js | ||
---|---|---|
5 | 5 |
* Redistribution terms are gathered in the `copyright' file. |
6 | 6 |
*/ |
7 | 7 |
|
8 |
"use strict"; |
|
9 |
|
|
10 |
(() => { |
|
11 |
const get_storage = window.get_storage; |
|
12 |
const TYPE_PREFIX = window.TYPE_PREFIX; |
|
13 |
const TYPE_NAME = window.TYPE_NAME; |
|
14 |
const list_prefixes = window.list_prefixes; |
|
15 |
|
|
16 |
var storage; |
|
17 |
function by_id(id) |
|
18 |
{ |
|
19 |
return document.getElementById(id); |
|
20 |
} |
|
21 |
|
|
22 |
function nice_name(prefix, name) |
|
23 |
{ |
|
24 |
return `${name} (${TYPE_NAME[prefix]})`; |
|
25 |
} |
|
26 |
|
|
27 |
const item_li_template = by_id("item_li_template"); |
|
28 |
const bag_component_li_template = by_id("bag_component_li_template"); |
|
29 |
const chbx_component_li_template = by_id("chbx_component_li_template"); |
|
30 |
const radio_component_li_template = by_id("radio_component_li_template"); |
|
31 |
const import_li_template = by_id("import_li_template"); |
|
32 |
/* Make sure they are later cloned without id. */ |
|
33 |
item_li_template.removeAttribute("id"); |
|
34 |
bag_component_li_template.removeAttribute("id"); |
|
35 |
chbx_component_li_template.removeAttribute("id"); |
|
36 |
radio_component_li_template.removeAttribute("id"); |
|
37 |
import_li_template.removeAttribute("id"); |
|
38 |
|
|
39 |
function item_li_id(prefix, item) |
|
40 |
{ |
|
41 |
return `li_${prefix}_${item}`; |
|
42 |
} |
|
43 |
|
|
44 |
/* Insert into list of bags/pages/scripts */ |
|
45 |
function add_li(prefix, item, at_the_end=false) |
|
46 |
{ |
|
47 |
let ul = ul_by_prefix[prefix]; |
|
48 |
let li = item_li_template.cloneNode(true); |
|
49 |
li.id = item_li_id(prefix, item); |
|
50 |
|
|
51 |
let span = li.firstElementChild; |
|
52 |
span.textContent = item; |
|
53 |
|
|
54 |
let edit_button = span.nextElementSibling; |
|
55 |
edit_button.addEventListener("click", () => edit_item(prefix, item)); |
|
56 |
|
|
57 |
let remove_button = edit_button.nextElementSibling; |
|
58 |
remove_button.addEventListener("click", |
|
59 |
() => storage.remove(prefix, item)); |
|
60 |
|
|
61 |
let export_button = remove_button.nextElementSibling; |
|
62 |
export_button.addEventListener("click", |
|
63 |
() => export_item(prefix, item)); |
|
8 |
/* |
|
9 |
* IMPORTS_START |
|
10 |
* IMPORT get_remote_storage |
|
11 |
* IMPORT TYPE_PREFIX |
|
12 |
* IMPORT TYPE_NAME |
|
13 |
* IMPORT list_prefixes |
|
14 |
* IMPORTS_END |
|
15 |
*/ |
|
64 | 16 |
|
65 |
if (!at_the_end) { |
|
66 |
for (let element of ul.ul.children) { |
|
67 |
if (element.id < li.id || element.id.startsWith("work_")) |
|
68 |
continue; |
|
17 |
var storage; |
|
18 |
function by_id(id) |
|
19 |
{ |
|
20 |
return document.getElementById(id); |
|
21 |
} |
|
22 |
|
|
23 |
function nice_name(prefix, name) |
|
24 |
{ |
|
25 |
return `${name} (${TYPE_NAME[prefix]})`; |
|
26 |
} |
|
27 |
|
|
28 |
const item_li_template = by_id("item_li_template"); |
|
29 |
const bag_component_li_template = by_id("bag_component_li_template"); |
|
30 |
const chbx_component_li_template = by_id("chbx_component_li_template"); |
|
31 |
const radio_component_li_template = by_id("radio_component_li_template"); |
|
32 |
const import_li_template = by_id("import_li_template"); |
|
33 |
/* Make sure they are later cloned without id. */ |
|
34 |
item_li_template.removeAttribute("id"); |
|
35 |
bag_component_li_template.removeAttribute("id"); |
|
36 |
chbx_component_li_template.removeAttribute("id"); |
|
37 |
radio_component_li_template.removeAttribute("id"); |
|
38 |
import_li_template.removeAttribute("id"); |
|
39 |
|
|
40 |
function item_li_id(prefix, item) |
|
41 |
{ |
|
42 |
return `li_${prefix}_${item}`; |
|
43 |
} |
|
44 |
|
|
45 |
/* Insert into list of bags/pages/scripts */ |
|
46 |
function add_li(prefix, item, at_the_end=false) |
|
47 |
{ |
|
48 |
let ul = ul_by_prefix[prefix]; |
|
49 |
let li = item_li_template.cloneNode(true); |
|
50 |
li.id = item_li_id(prefix, item); |
|
51 |
|
|
52 |
let span = li.firstElementChild; |
|
53 |
span.textContent = item; |
|
54 |
|
|
55 |
let edit_button = span.nextElementSibling; |
|
56 |
edit_button.addEventListener("click", () => edit_item(prefix, item)); |
|
57 |
|
|
58 |
let remove_button = edit_button.nextElementSibling; |
|
59 |
remove_button.addEventListener("click", |
|
60 |
() => storage.remove(prefix, item)); |
|
61 |
|
|
62 |
let export_button = remove_button.nextElementSibling; |
|
63 |
export_button.addEventListener("click", |
|
64 |
() => export_item(prefix, item)); |
|
65 |
|
|
66 |
if (!at_the_end) { |
|
67 |
for (let element of ul.ul.children) { |
|
68 |
if (element.id < li.id || element.id.startsWith("work_")) |
|
69 |
continue; |
|
69 | 70 |
|
70 |
ul.ul.insertBefore(li, element); |
|
71 |
return; |
|
72 |
} |
|
71 |
ul.ul.insertBefore(li, element); |
|
72 |
return; |
|
73 | 73 |
} |
74 |
|
|
75 |
ul.ul.appendChild(li); |
|
76 | 74 |
} |
77 | 75 |
|
78 |
const chbx_components_ul = by_id("chbx_components_ul");
|
|
79 |
const radio_components_ul = by_id("radio_components_ul");
|
|
76 |
ul.ul.appendChild(li);
|
|
77 |
}
|
|
80 | 78 |
|
81 |
function chbx_li_id(prefix, item) |
|
82 |
{ |
|
83 |
return `cli_${prefix}_${item}`; |
|
84 |
} |
|
79 |
const chbx_components_ul = by_id("chbx_components_ul"); |
|
80 |
const radio_components_ul = by_id("radio_components_ul"); |
|
85 | 81 |
|
86 |
function radio_li_id(prefix, item)
|
|
87 |
{
|
|
88 |
return `rli_${prefix}_${item}`;
|
|
89 |
}
|
|
82 |
function chbx_li_id(prefix, item)
|
|
83 |
{ |
|
84 |
return `cli_${prefix}_${item}`;
|
|
85 |
} |
|
90 | 86 |
|
91 |
//TODO: refactor the 2 functions below |
|
87 |
function radio_li_id(prefix, item) |
|
88 |
{ |
|
89 |
return `rli_${prefix}_${item}`; |
|
90 |
} |
|
92 | 91 |
|
93 |
function add_chbx_li(prefix, name) |
|
94 |
{ |
|
95 |
if (prefix === TYPE_PREFIX.PAGE) |
|
96 |
return; |
|
92 |
//TODO: refactor the 2 functions below |
|
97 | 93 |
|
98 |
let li = chbx_component_li_template.cloneNode(true); |
|
99 |
li.id = chbx_li_id(prefix, name); |
|
100 |
li.setAttribute("data-prefix", prefix); |
|
101 |
li.setAttribute("data-name", name); |
|
102 |
|
|
103 |
let chbx = li.firstElementChild; |
|
104 |
let span = chbx.nextElementSibling; |
|
105 |
|
|
106 |
span.textContent = nice_name(prefix, name); |
|
107 |
|
|
108 |
chbx_components_ul.appendChild(li); |
|
109 |
} |
|
110 |
|
|
111 |
var radio_component_none_li = by_id("radio_component_none_li"); |
|
94 |
function add_chbx_li(prefix, name) |
|
95 |
{ |
|
96 |
if (prefix === TYPE_PREFIX.PAGE) |
|
97 |
return; |
|
112 | 98 |
|
113 |
function add_radio_li(prefix, name)
|
|
114 |
{
|
|
115 |
if (prefix === TYPE_PREFIX.PAGE)
|
|
116 |
return;
|
|
99 |
let li = chbx_component_li_template.cloneNode(true);
|
|
100 |
li.id = chbx_li_id(prefix, name);
|
|
101 |
li.setAttribute("data-prefix", prefix);
|
|
102 |
li.setAttribute("data-name", name);
|
|
117 | 103 |
|
118 |
let li = radio_component_li_template.cloneNode(true); |
|
119 |
li.id = radio_li_id(prefix, name); |
|
120 |
li.setAttribute("data-prefix", prefix); |
|
121 |
li.setAttribute("data-name", name); |
|
104 |
let chbx = li.firstElementChild; |
|
105 |
let span = chbx.nextElementSibling; |
|
122 | 106 |
|
123 |
let radio = li.firstElementChild; |
|
124 |
let span = radio.nextElementSibling; |
|
107 |
span.textContent = nice_name(prefix, name); |
|
125 | 108 |
|
126 |
span.textContent = nice_name(prefix, name); |
|
109 |
chbx_components_ul.appendChild(li); |
|
110 |
} |
|
127 | 111 |
|
128 |
radio_components_ul.insertBefore(li, radio_component_none_li); |
|
129 |
} |
|
130 |
|
|
131 |
const page_payload_span = by_id("page_payload"); |
|
132 |
|
|
133 |
function set_page_components(components) |
|
134 |
{ |
|
135 |
if (components === undefined) { |
|
136 |
page_payload_span.setAttribute("data-payload", "no"); |
|
137 |
page_payload_span.textContent = "(None)"; |
|
138 |
} else { |
|
139 |
page_payload_span.setAttribute("data-payload", "yes"); |
|
140 |
let [prefix, name] = components; |
|
141 |
page_payload_span.setAttribute("data-prefix", prefix); |
|
142 |
page_payload_span.setAttribute("data-name", name); |
|
143 |
page_payload_span.textContent = nice_name(prefix, name); |
|
144 |
} |
|
145 |
} |
|
112 |
var radio_component_none_li = by_id("radio_component_none_li"); |
|
146 | 113 |
|
147 |
const page_allow_chbx = by_id("page_allow_chbx"); |
|
114 |
function add_radio_li(prefix, name) |
|
115 |
{ |
|
116 |
if (prefix === TYPE_PREFIX.PAGE) |
|
117 |
return; |
|
148 | 118 |
|
149 |
/* Used to reset edited page. */ |
|
150 |
function reset_work_page_li(ul, item, settings) |
|
151 |
{ |
|
152 |
ul.work_name_input.value = maybe_string(item); |
|
153 |
settings = settings || {allow: false, components: undefined}; |
|
154 |
page_allow_chbx.checked = !!settings.allow; |
|
119 |
let li = radio_component_li_template.cloneNode(true); |
|
120 |
li.id = radio_li_id(prefix, name); |
|
121 |
li.setAttribute("data-prefix", prefix); |
|
122 |
li.setAttribute("data-name", name); |
|
155 | 123 |
|
156 |
set_page_components(settings.components);
|
|
157 |
}
|
|
124 |
let radio = li.firstElementChild;
|
|
125 |
let span = radio.nextElementSibling;
|
|
158 | 126 |
|
159 |
function work_page_li_components() |
|
160 |
{ |
|
161 |
if (page_payload_span.getAttribute("data-payload") === "no") |
|
162 |
return undefined; |
|
127 |
span.textContent = nice_name(prefix, name); |
|
163 | 128 |
|
164 |
let prefix = page_payload_span.getAttribute("data-prefix"); |
|
165 |
let name = page_payload_span.getAttribute("data-name"); |
|
166 |
return [prefix, name]; |
|
167 |
} |
|
129 |
radio_components_ul.insertBefore(li, radio_component_none_li); |
|
130 |
} |
|
168 | 131 |
|
169 |
/* Used to get edited page data for saving. */ |
|
170 |
function work_page_li_data(ul) |
|
171 |
{ |
|
172 |
let url = ul.work_name_input.value; |
|
173 |
let settings = { |
|
174 |
components : work_page_li_components(), |
|
175 |
allow : !!page_allow_chbx.checked |
|
176 |
}; |
|
132 |
const page_payload_span = by_id("page_payload"); |
|
177 | 133 |
|
178 |
return [url, settings]; |
|
134 |
function set_page_components(components) |
|
135 |
{ |
|
136 |
if (components === undefined) { |
|
137 |
page_payload_span.setAttribute("data-payload", "no"); |
|
138 |
page_payload_span.textContent = "(None)"; |
|
139 |
} else { |
|
140 |
page_payload_span.setAttribute("data-payload", "yes"); |
|
141 |
let [prefix, name] = components; |
|
142 |
page_payload_span.setAttribute("data-prefix", prefix); |
|
143 |
page_payload_span.setAttribute("data-name", name); |
|
144 |
page_payload_span.textContent = nice_name(prefix, name); |
|
179 | 145 |
} |
146 |
} |
|
180 | 147 |
|
181 |
const empty_bag_component_li = by_id("empty_bag_component_li"); |
|
182 |
var bag_components_ul = by_id("bag_components_ul"); |
|
183 |
|
|
184 |
/* Used to construct and update components list of edited bag. */ |
|
185 |
function add_bag_components(components) |
|
186 |
{ |
|
187 |
for (let component of components) { |
|
188 |
let [prefix, name] = component; |
|
189 |
let li = bag_component_li_template.cloneNode(true); |
|
190 |
li.setAttribute("data-prefix", prefix); |
|
191 |
li.setAttribute("data-name", name); |
|
192 |
let span = li.firstElementChild; |
|
193 |
span.textContent = nice_name(prefix, name); |
|
194 |
let remove_but = span.nextElementSibling; |
|
195 |
remove_but.addEventListener("click", () => |
|
196 |
bag_components_ul.removeChild(li)); |
|
197 |
bag_components_ul.appendChild(li); |
|
198 |
} |
|
199 |
|
|
200 |
bag_components_ul.appendChild(empty_bag_component_li); |
|
201 |
} |
|
148 |
const page_allow_chbx = by_id("page_allow_chbx"); |
|
202 | 149 |
|
203 |
/* Used to reset edited bag. */ |
|
204 |
function reset_work_bag_li(ul, item, components) |
|
205 |
{ |
|
206 |
components = components || []; |
|
150 |
/* Used to reset edited page. */ |
|
151 |
function reset_work_page_li(ul, item, settings) |
|
152 |
{ |
|
153 |
ul.work_name_input.value = maybe_string(item); |
|
154 |
settings = settings || {allow: false, components: undefined}; |
|
155 |
page_allow_chbx.checked = !!settings.allow; |
|
207 | 156 |
|
208 |
ul.work_name_input.value = maybe_string(item); |
|
209 |
let old_components_ul = bag_components_ul; |
|
210 |
bag_components_ul = old_components_ul.cloneNode(false); |
|
157 |
set_page_components(settings.components); |
|
158 |
} |
|
211 | 159 |
|
212 |
ul.work_li.insertBefore(bag_components_ul, old_components_ul); |
|
213 |
ul.work_li.removeChild(old_components_ul); |
|
160 |
function work_page_li_components() |
|
161 |
{ |
|
162 |
if (page_payload_span.getAttribute("data-payload") === "no") |
|
163 |
return undefined; |
|
214 | 164 |
|
215 |
add_bag_components(components); |
|
216 |
} |
|
165 |
let prefix = page_payload_span.getAttribute("data-prefix"); |
|
166 |
let name = page_payload_span.getAttribute("data-name"); |
|
167 |
return [prefix, name]; |
|
168 |
} |
|
217 | 169 |
|
218 |
/* Used to get edited bag data for saving. */ |
|
219 |
function work_bag_li_data(ul) |
|
220 |
{ |
|
221 |
let components_ul = ul.work_name_input.nextElementSibling; |
|
222 |
let component_li = components_ul.firstElementChild; |
|
170 |
/* Used to get edited page data for saving. */ |
|
171 |
function work_page_li_data(ul) |
|
172 |
{ |
|
173 |
let url = ul.work_name_input.value; |
|
174 |
let settings = { |
|
175 |
components : work_page_li_components(), |
|
176 |
allow : !!page_allow_chbx.checked |
|
177 |
}; |
|
223 | 178 |
|
224 |
let components = []; |
|
179 |
return [url, settings]; |
|
180 |
} |
|
225 | 181 |
|
226 |
/* Last list element is empty li with id set. */ |
|
227 |
while (component_li.id === '') { |
|
228 |
components.push([component_li.getAttribute("data-prefix"), |
|
229 |
component_li.getAttribute("data-name")]); |
|
230 |
component_li = component_li.nextElementSibling; |
|
231 |
} |
|
182 |
const empty_bag_component_li = by_id("empty_bag_component_li"); |
|
183 |
var bag_components_ul = by_id("bag_components_ul"); |
|
232 | 184 |
|
233 |
return [ul.work_name_input.value, components]; |
|
185 |
/* Used to construct and update components list of edited bag. */ |
|
186 |
function add_bag_components(components) |
|
187 |
{ |
|
188 |
for (let component of components) { |
|
189 |
let [prefix, name] = component; |
|
190 |
let li = bag_component_li_template.cloneNode(true); |
|
191 |
li.setAttribute("data-prefix", prefix); |
|
192 |
li.setAttribute("data-name", name); |
|
193 |
let span = li.firstElementChild; |
|
194 |
span.textContent = nice_name(prefix, name); |
|
195 |
let remove_but = span.nextElementSibling; |
|
196 |
remove_but.addEventListener("click", () => |
|
197 |
bag_components_ul.removeChild(li)); |
|
198 |
bag_components_ul.appendChild(li); |
|
234 | 199 |
} |
235 | 200 |
|
236 |
const script_url_input = by_id("script_url_field"); |
|
237 |
const script_sha256_input = by_id("script_sha256_field"); |
|
238 |
const script_contents_field = by_id("script_contents_field"); |
|
201 |
bag_components_ul.appendChild(empty_bag_component_li); |
|
202 |
} |
|
239 | 203 |
|
240 |
function maybe_string(maybe_defined)
|
|
241 |
{
|
|
242 |
return maybe_defined === undefined ? "" : maybe_defined + "";
|
|
243 |
}
|
|
204 |
/* Used to reset edited bag. */
|
|
205 |
function reset_work_bag_li(ul, item, components)
|
|
206 |
{
|
|
207 |
components = components || [];
|
|
244 | 208 |
|
245 |
/* Used to reset edited script. */ |
|
246 |
function reset_work_script_li(ul, name, data) |
|
247 |
{ |
|
248 |
ul.work_name_input.value = maybe_string(name); |
|
249 |
if (data === undefined) |
|
250 |
data = {}; |
|
251 |
script_url_input.value = maybe_string(data.url); |
|
252 |
script_sha256_input.value = maybe_string(data.hash); |
|
253 |
script_contents_field.value = maybe_string(data.text); |
|
254 |
} |
|
209 |
ul.work_name_input.value = maybe_string(item); |
|
210 |
let old_components_ul = bag_components_ul; |
|
211 |
bag_components_ul = old_components_ul.cloneNode(false); |
|
255 | 212 |
|
256 |
/* Used to get edited script data for saving. */ |
|
257 |
function work_script_li_data(ul) |
|
258 |
{ |
|
259 |
return [ul.work_name_input.value, { |
|
260 |
url : script_url_input.value, |
|
261 |
hash : script_sha256_input.value, |
|
262 |
text : script_contents_field.value |
|
263 |
}]; |
|
264 |
} |
|
213 |
ul.work_li.insertBefore(bag_components_ul, old_components_ul); |
|
214 |
ul.work_li.removeChild(old_components_ul); |
|
265 | 215 |
|
266 |
function cancel_work(prefix) |
|
267 |
{ |
|
268 |
let ul = ul_by_prefix[prefix]; |
|
216 |
add_bag_components(components); |
|
217 |
} |
|
269 | 218 |
|
270 |
if (ul.state === UL_STATE.IDLE) |
|
271 |
return; |
|
219 |
/* Used to get edited bag data for saving. */ |
|
220 |
function work_bag_li_data(ul) |
|
221 |
{ |
|
222 |
let components_ul = ul.work_name_input.nextElementSibling; |
|
223 |
let component_li = components_ul.firstElementChild; |
|
272 | 224 |
|
273 |
if (ul.state === UL_STATE.EDITING_ENTRY) { |
|
274 |
add_li(prefix, ul.edited_item); |
|
275 |
} |
|
225 |
let components = []; |
|
276 | 226 |
|
277 |
ul.work_li.classList.add("hide"); |
|
278 |
ul.state = UL_STATE.IDLE; |
|
227 |
/* Last list element is empty li with id set. */ |
|
228 |
while (component_li.id === '') { |
|
229 |
components.push([component_li.getAttribute("data-prefix"), |
|
230 |
component_li.getAttribute("data-name")]); |
|
231 |
component_li = component_li.nextElementSibling; |
|
279 | 232 |
} |
280 | 233 |
|
281 |
function save_work(prefix) |
|
282 |
{ |
|
283 |
let ul = ul_by_prefix[prefix]; |
|
234 |
return [ul.work_name_input.value, components]; |
|
235 |
} |
|
284 | 236 |
|
285 |
if (ul.state === UL_STATE.IDLE) |
|
286 |
return; |
|
237 |
const script_url_input = by_id("script_url_field"); |
|
238 |
const script_sha256_input = by_id("script_sha256_field"); |
|
239 |
const script_contents_field = by_id("script_contents_field"); |
|
287 | 240 |
|
288 |
let [item, data] = ul.get_work_li_data(ul); |
|
241 |
function maybe_string(maybe_defined) |
|
242 |
{ |
|
243 |
return maybe_defined === undefined ? "" : maybe_defined + ""; |
|
244 |
} |
|
289 | 245 |
|
290 |
/* Here we fire promises and return without waiting. */ |
|
246 |
/* Used to reset edited script. */ |
|
247 |
function reset_work_script_li(ul, name, data) |
|
248 |
{ |
|
249 |
ul.work_name_input.value = maybe_string(name); |
|
250 |
if (data === undefined) |
|
251 |
data = {}; |
|
252 |
script_url_input.value = maybe_string(data.url); |
|
253 |
script_sha256_input.value = maybe_string(data.hash); |
|
254 |
script_contents_field.value = maybe_string(data.text); |
|
255 |
} |
|
291 | 256 |
|
292 |
if (ul.state === UL_STATE.EDITING_ENTRY) |
|
293 |
storage.replace(prefix, ul.edited_item, item, data); |
|
294 |
if (ul.state === UL_STATE.ADDING_ENTRY) |
|
295 |
storage.set(prefix, item, data); |
|
257 |
/* Used to get edited script data for saving. */ |
|
258 |
function work_script_li_data(ul) |
|
259 |
{ |
|
260 |
return [ul.work_name_input.value, { |
|
261 |
url : script_url_input.value, |
|
262 |
hash : script_sha256_input.value, |
|
263 |
text : script_contents_field.value |
|
264 |
}]; |
|
265 |
} |
|
296 | 266 |
|
297 |
cancel_work(prefix); |
|
298 |
} |
|
267 |
function cancel_work(prefix) |
|
268 |
{ |
|
269 |
let ul = ul_by_prefix[prefix]; |
|
299 | 270 |
|
300 |
function edit_item(prefix, item) |
|
301 |
{ |
|
302 |
cancel_work(prefix); |
|
271 |
if (ul.state === UL_STATE.IDLE) |
|
272 |
return; |
|
303 | 273 |
|
304 |
let ul = ul_by_prefix[prefix]; |
|
305 |
let li = by_id(item_li_id(prefix, item)); |
|
306 |
ul.reset_work_li(ul, item, storage.get(prefix, item)); |
|
307 |
ul.ul.insertBefore(ul.work_li, li); |
|
308 |
ul.ul.removeChild(li); |
|
309 |
ul.work_li.classList.remove("hide"); |
|
310 |
|
|
311 |
ul.state = UL_STATE.EDITING_ENTRY; |
|
312 |
ul.edited_item = item; |
|
274 |
if (ul.state === UL_STATE.EDITING_ENTRY) { |
|
275 |
add_li(prefix, ul.edited_item); |
|
313 | 276 |
} |
314 | 277 |
|
315 |
const file_downloader = by_id("file_downloader"); |
|
278 |
ul.work_li.classList.add("hide"); |
|
279 |
ul.state = UL_STATE.IDLE; |
|
280 |
} |
|
316 | 281 |
|
317 |
function recursively_export_item(prefix, name, added_items, items_data)
|
|
318 |
{
|
|
319 |
let key = prefix + name;
|
|
282 |
function save_work(prefix)
|
|
283 |
{ |
|
284 |
let ul = ul_by_prefix[prefix];
|
|
320 | 285 |
|
321 |
if (added_items.has(key))
|
|
322 |
return;
|
|
286 |
if (ul.state === UL_STATE.IDLE)
|
|
287 |
return; |
|
323 | 288 |
|
324 |
let data = storage.get(prefix, name); |
|
325 |
if (data === undefined) { |
|
326 |
console.log(`${TYPE_NAME[prefix]} '${name}' for export not found`); |
|
327 |
return; |
|
328 |
} |
|
289 |
let [item, data] = ul.get_work_li_data(ul); |
|
329 | 290 |
|
330 |
if (prefix !== TYPE_PREFIX.SCRIPT) { |
|
331 |
let components = prefix === TYPE_PREFIX.BAG ? |
|
332 |
data : [data.components]; |
|
291 |
/* Here we fire promises and return without waiting. */ |
|
333 | 292 |
|
334 |
for (let [comp_prefix, comp_name] of components) { |
|
335 |
recursively_export_item(comp_prefix, comp_name, |
|
336 |
added_items, items_data); |
|
337 |
} |
|
338 |
} |
|
293 |
if (ul.state === UL_STATE.EDITING_ENTRY) |
|
294 |
storage.replace(prefix, ul.edited_item, item, data); |
|
295 |
if (ul.state === UL_STATE.ADDING_ENTRY) |
|
296 |
storage.set(prefix, item, data); |
|
339 | 297 |
|
340 |
items_data.push({[key]: data}); |
|
341 |
added_items.add(key); |
|
342 |
} |
|
298 |
cancel_work(prefix); |
|
299 |
} |
|
343 | 300 |
|
344 |
function export_item(prefix, name) |
|
345 |
{ |
|
346 |
let added_items = new Set(); |
|
347 |
let items_data = []; |
|
348 |
recursively_export_item(prefix, name, added_items, items_data); |
|
349 |
let file = new Blob([JSON.stringify(items_data)], |
|
350 |
{type: "application/json"}); |
|
351 |
let url = URL.createObjectURL(file); |
|
352 |
file_downloader.setAttribute("href", url); |
|
353 |
file_downloader.setAttribute("download", prefix + name + ".json"); |
|
354 |
file_downloader.click(); |
|
355 |
file_downloader.removeAttribute("href"); |
|
356 |
URL.revokeObjectURL(url); |
|
357 |
} |
|
301 |
function edit_item(prefix, item) |
|
302 |
{ |
|
303 |
cancel_work(prefix); |
|
358 | 304 |
|
359 |
function add_new_item(prefix) |
|
360 |
{ |
|
361 |
cancel_work(prefix); |
|
305 |
let ul = ul_by_prefix[prefix]; |
|
306 |
let li = by_id(item_li_id(prefix, item)); |
|
307 |
ul.reset_work_li(ul, item, storage.get(prefix, item)); |
|
308 |
ul.ul.insertBefore(ul.work_li, li); |
|
309 |
ul.ul.removeChild(li); |
|
310 |
ul.work_li.classList.remove("hide"); |
|
362 | 311 |
|
363 |
let ul = ul_by_prefix[prefix]; |
|
364 |
ul.reset_work_li(ul); |
|
365 |
ul.work_li.classList.remove("hide"); |
|
366 |
ul.ul.appendChild(ul.work_li); |
|
312 |
ul.state = UL_STATE.EDITING_ENTRY; |
|
313 |
ul.edited_item = item; |
|
314 |
} |
|
367 | 315 |
|
368 |
ul.state = UL_STATE.ADDING_ENTRY; |
|
369 |
} |
|
316 |
const file_downloader = by_id("file_downloader"); |
|
370 | 317 |
|
371 |
const chbx_components_window = by_id("chbx_components_window"); |
|
318 |
function recursively_export_item(prefix, name, added_items, items_data) |
|
319 |
{ |
|
320 |
let key = prefix + name; |
|
372 | 321 |
|
373 |
function bag_components() |
|
374 |
{ |
|
375 |
chbx_components_window.classList.remove("hide"); |
|
376 |
radio_components_window.classList.add("hide"); |
|
322 |
if (added_items.has(key)) |
|
323 |
return; |
|
377 | 324 |
|
378 |
for (let li of chbx_components_ul.children) {
|
|
379 |
let chbx = li.firstElementChild;
|
|
380 |
chbx.checked = false;
|
|
381 |
}
|
|
325 |
let data = storage.get(prefix, name);
|
|
326 |
if (data === undefined) {
|
|
327 |
console.log(`${TYPE_NAME[prefix]} '${name}' for export not found`);
|
|
328 |
return;
|
|
382 | 329 |
} |
383 | 330 |
|
384 |
function commit_bag_components() |
|
385 |
{ |
|
386 |
let selected = []; |
|
387 |
|
|
388 |
for (let li of chbx_components_ul.children) { |
|
389 |
let chbx = li.firstElementChild; |
|
390 |
if (!chbx.checked) |
|
391 |
continue; |
|
392 |
|
|
393 |
selected.push([li.getAttribute("data-prefix"), |
|
394 |
li.getAttribute("data-name")]); |
|
331 |
if (prefix !== TYPE_PREFIX.SCRIPT) { |
|
332 |
let components = prefix === TYPE_PREFIX.BAG ? |
|
333 |
data : [data.components]; |
|
334 |
|
|
335 |
for (let [comp_prefix, comp_name] of components) { |
|
336 |
recursively_export_item(comp_prefix, comp_name, |
|
337 |
added_items, items_data); |
|
395 | 338 |
} |
396 |
|
|
397 |
add_bag_components(selected); |
|
398 |
cancel_components(); |
|
399 | 339 |
} |
400 | 340 |
|
401 |
const radio_components_window = by_id("radio_components_window"); |
|
402 |
var radio_component_none_input = by_id("radio_component_none_input"); |
|
403 |
|
|
404 |
function page_components() |
|
405 |
{ |
|
406 |
radio_components_window.classList.remove("hide"); |
|
407 |
chbx_components_window.classList.add("hide"); |
|
341 |
items_data.push({[key]: data}); |
|
342 |
added_items.add(key); |
|
343 |
} |
|
344 |
|
|
345 |
function export_item(prefix, name) |
|
346 |
{ |
|
347 |
let added_items = new Set(); |
|
348 |
let items_data = []; |
|
349 |
recursively_export_item(prefix, name, added_items, items_data); |
|
350 |
let file = new Blob([JSON.stringify(items_data)], |
|
351 |
{type: "application/json"}); |
|
352 |
let url = URL.createObjectURL(file); |
|
353 |
file_downloader.setAttribute("href", url); |
|
354 |
file_downloader.setAttribute("download", prefix + name + ".json"); |
|
355 |
file_downloader.click(); |
|
356 |
file_downloader.removeAttribute("href"); |
|
357 |
URL.revokeObjectURL(url); |
|
358 |
} |
|
359 |
|
|
360 |
function add_new_item(prefix) |
|
361 |
{ |
|
362 |
cancel_work(prefix); |
|
363 |
|
|
364 |
let ul = ul_by_prefix[prefix]; |
|
365 |
ul.reset_work_li(ul); |
|
366 |
ul.work_li.classList.remove("hide"); |
|
367 |
ul.ul.appendChild(ul.work_li); |
|
368 |
|
|
369 |
ul.state = UL_STATE.ADDING_ENTRY; |
|
370 |
} |
|
371 |
|
|
372 |
const chbx_components_window = by_id("chbx_components_window"); |
|
373 |
|
|
374 |
function bag_components() |
|
375 |
{ |
|
376 |
chbx_components_window.classList.remove("hide"); |
|
377 |
radio_components_window.classList.add("hide"); |
|
378 |
|
|
379 |
for (let li of chbx_components_ul.children) { |
|
380 |
let chbx = li.firstElementChild; |
|
381 |
chbx.checked = false; |
|
382 |
} |
|
383 |
} |
|
408 | 384 |
|
409 |
radio_component_none_input.checked = true; |
|
385 |
function commit_bag_components() |
|
386 |
{ |
|
387 |
let selected = []; |
|
410 | 388 |
|
411 |
let components = work_page_li_components(); |
|
412 |
if (components === undefined) |
|
413 |
return; |
|
389 |
for (let li of chbx_components_ul.children) { |
|
390 |
let chbx = li.firstElementChild; |
|
391 |
if (!chbx.checked) |
|
392 |
continue; |
|
414 | 393 |
|
415 |
let [prefix, item] = components; |
|
416 |
let li = by_id(radio_li_id(prefix, item)); |
|
417 |
if (li === null) |
|
418 |
radio_component_none_input.checked = false; |
|
419 |
else |
|
420 |
li.firstElementChild.checked = true; |
|
394 |
selected.push([li.getAttribute("data-prefix"), |
|
395 |
li.getAttribute("data-name")]); |
|
421 | 396 |
} |
422 | 397 |
|
423 |
function commit_page_components()
|
|
424 |
{
|
|
425 |
let components = null;
|
|
398 |
add_bag_components(selected);
|
|
399 |
cancel_components();
|
|
400 |
}
|
|
426 | 401 |
|
427 |
for (let li of radio_components_ul.children) { |
|
428 |
let radio = li.firstElementChild; |
|
429 |
if (!radio.checked) |
|
430 |
continue; |
|
402 |
const radio_components_window = by_id("radio_components_window"); |
|
403 |
var radio_component_none_input = by_id("radio_component_none_input"); |
|
431 | 404 |
|
432 |
components = [li.getAttribute("data-prefix"), |
|
433 |
li.getAttribute("data-name")]; |
|
405 |
function page_components() |
|
406 |
{ |
|
407 |
radio_components_window.classList.remove("hide"); |
|
408 |
chbx_components_window.classList.add("hide"); |
|
434 | 409 |
|
435 |
if (radio.id === "radio_component_none_input") |
|
436 |
components = undefined; |
|
410 |
radio_component_none_input.checked = true; |
|
437 | 411 |
|
438 |
break; |
|
439 |
} |
|
412 |
let components = work_page_li_components(); |
|
413 |
if (components === undefined) |
|
414 |
return; |
|
440 | 415 |
|
441 |
if (components !== null) |
|
442 |
set_page_components(components); |
|
443 |
cancel_components(); |
|
444 |
} |
|
416 |
let [prefix, item] = components; |
|
417 |
let li = by_id(radio_li_id(prefix, item)); |
|
418 |
if (li === null) |
|
419 |
radio_component_none_input.checked = false; |
|
420 |
else |
|
421 |
li.firstElementChild.checked = true; |
|
422 |
} |
|
445 | 423 |
|
446 |
function cancel_components() |
|
447 |
{ |
|
448 |
chbx_components_window.classList.add("hide"); |
|
449 |
radio_components_window.classList.add("hide"); |
|
450 |
} |
|
424 |
function commit_page_components() |
|
425 |
{ |
|
426 |
let components = null; |
|
451 | 427 |
|
452 |
const UL_STATE = { |
|
453 |
EDITING_ENTRY : 0, |
|
454 |
ADDING_ENTRY : 1, |
|
455 |
IDLE : 2 |
|
456 |
}; |
|
457 |
|
|
458 |
const ul_by_prefix = { |
|
459 |
[TYPE_PREFIX.PAGE] : { |
|
460 |
ul : by_id("pages_ul"), |
|
461 |
work_li : by_id("work_page_li"), |
|
462 |
work_name_input : by_id("page_url_field"), |
|
463 |
reset_work_li : reset_work_page_li, |
|
464 |
get_work_li_data : work_page_li_data, |
|
465 |
select_components : page_components, |
|
466 |
commit_components : commit_page_components, |
|
467 |
state : UL_STATE.IDLE, |
|
468 |
edited_item : undefined, |
|
469 |
}, |
|
470 |
[TYPE_PREFIX.BAG] : { |
|
471 |
ul : by_id("bags_ul"), |
|
472 |
work_li : by_id("work_bag_li"), |
|
473 |
work_name_input : by_id("bag_name_field"), |
|
474 |
reset_work_li : reset_work_bag_li, |
|
475 |
get_work_li_data : work_bag_li_data, |
|
476 |
select_components : bag_components, |
|
477 |
commit_components : commit_bag_components, |
|
478 |
state : UL_STATE.IDLE, |
|
479 |
edited_item : undefined, |
|
480 |
}, |
|
481 |
[TYPE_PREFIX.SCRIPT] : { |
|
482 |
ul : by_id("scripts_ul"), |
|
483 |
work_li : by_id("work_script_li"), |
|
484 |
work_name_input : by_id("script_name_field"), |
|
485 |
reset_work_li : reset_work_script_li, |
|
486 |
get_work_li_data : work_script_li_data, |
|
487 |
state : UL_STATE.IDLE, |
|
488 |
edited_item : undefined, |
|
489 |
} |
|
490 |
} |
|
428 |
for (let li of radio_components_ul.children) { |
|
429 |
let radio = li.firstElementChild; |
|
430 |
if (!radio.checked) |
|
431 |
continue; |
|
432 |
|
|
433 |
components = [li.getAttribute("data-prefix"), |
|
434 |
li.getAttribute("data-name")]; |
|
435 |
|
|
436 |
if (radio.id === "radio_component_none_input") |
|
437 |
components = undefined; |
|
438 |
|
|
439 |
break; |
|
440 |
} |
|
441 |
|
|
442 |
if (components !== null) |
|
443 |
set_page_components(components); |
|
444 |
cancel_components(); |
|
445 |
} |
|
446 |
|
|
447 |
function cancel_components() |
|
448 |
{ |
|
449 |
chbx_components_window.classList.add("hide"); |
|
450 |
radio_components_window.classList.add("hide"); |
|
451 |
} |
|
452 |
|
|
453 |
const UL_STATE = { |
|
454 |
EDITING_ENTRY : 0, |
|
455 |
ADDING_ENTRY : 1, |
|
456 |
IDLE : 2 |
|
457 |
}; |
|
458 |
|
|
459 |
const ul_by_prefix = { |
|
460 |
[TYPE_PREFIX.PAGE] : { |
|
461 |
ul : by_id("pages_ul"), |
|
462 |
work_li : by_id("work_page_li"), |
|
463 |
work_name_input : by_id("page_url_field"), |
|
464 |
reset_work_li : reset_work_page_li, |
|
465 |
get_work_li_data : work_page_li_data, |
|
466 |
select_components : page_components, |
|
467 |
commit_components : commit_page_components, |
|
468 |
state : UL_STATE.IDLE, |
|
469 |
edited_item : undefined, |
|
470 |
}, |
|
471 |
[TYPE_PREFIX.BAG] : { |
|
472 |
ul : by_id("bags_ul"), |
|
473 |
work_li : by_id("work_bag_li"), |
|
474 |
work_name_input : by_id("bag_name_field"), |
|
475 |
reset_work_li : reset_work_bag_li, |
|
476 |
get_work_li_data : work_bag_li_data, |
|
477 |
select_components : bag_components, |
|
478 |
commit_components : commit_bag_components, |
|
479 |
state : UL_STATE.IDLE, |
|
480 |
edited_item : undefined, |
|
481 |
}, |
|
482 |
[TYPE_PREFIX.SCRIPT] : { |
|
483 |
ul : by_id("scripts_ul"), |
|
484 |
work_li : by_id("work_script_li"), |
|
485 |
work_name_input : by_id("script_name_field"), |
|
486 |
reset_work_li : reset_work_script_li, |
|
487 |
get_work_li_data : work_script_li_data, |
|
488 |
state : UL_STATE.IDLE, |
|
489 |
edited_item : undefined, |
|
490 |
} |
|
491 |
} |
|
492 |
|
|
493 |
const import_window = by_id("import_window"); |
|
494 |
const import_loading_radio = by_id("import_loading_radio"); |
|
495 |
const import_failed_radio = by_id("import_failed_radio"); |
|
496 |
const import_selection_radio = by_id("import_selection_radio"); |
|
497 |
const bad_file_errormsg = by_id("bad_file_errormsg"); |
|
498 |
|
|
499 |
/* |
|
500 |
* Newer browsers could utilise `text' method of File objects. |
|
501 |
* Older ones require FileReader. |
|
502 |
*/ |
|
491 | 503 |
|
492 |
const import_window = by_id("import_window"); |
|
493 |
const import_loading_radio = by_id("import_loading_radio"); |
|
494 |
const import_failed_radio = by_id("import_failed_radio"); |
|
495 |
const import_selection_radio = by_id("import_selection_radio"); |
|
496 |
const bad_file_errormsg = by_id("bad_file_errormsg"); |
|
504 |
function _read_file(file, resolve, reject) |
|
505 |
{ |
|
506 |
let reader = new FileReader(); |
|
507 |
|
|
508 |
reader.onload = () => resolve(reader.result); |
|
509 |
reader.onerror = () => reject(reader.error); |
|
510 |
reader.readAsText(file); |
|
511 |
} |
|
512 |
|
|
513 |
function read_file(file) |
|
514 |
{ |
|
515 |
return new Promise((resolve, reject) => |
|
516 |
_read_file(file, resolve, reject)); |
|
517 |
} |
|
518 |
|
|
519 |
async function import_from_file(event) |
|
520 |
{ |
|
521 |
let files = event.target.files; |
|
522 |
if (files.length < 1) |
|
523 |
return; |
|
524 |
|
|
525 |
import_window.classList.remove("hide"); |
|
526 |
import_loading_radio.checked = true; |
|
527 |
|
|
528 |
let result = undefined; |
|
529 |
|
|
530 |
try { |
|
531 |
result = JSON.parse(await read_file(files[0])); |
|
532 |
} catch(e) { |
|
533 |
bad_file_errormsg.textContent = "" + e; |
|
534 |
import_failed_radio.checked = true; |
|
535 |
return; |
|
536 |
} |
|
537 |
|
|
538 |
let errormsg = validate_settings(result); |
|
539 |
if (errormsg !== false) { |
|
540 |
bad_file_errormsg.textContent = errormsg; |
|
541 |
import_failed_radio.checked = true; |
|
542 |
return; |
|
543 |
} |
|
544 |
|
|
545 |
populate_import_list(result); |
|
546 |
import_selection_radio.checked = true; |
|
547 |
} |
|
548 |
|
|
549 |
function validate_settings(settings) |
|
550 |
{ |
|
551 |
// TODO |
|
552 |
return false; |
|
553 |
} |
|
554 |
|
|
555 |
function import_li_id(prefix, item) |
|
556 |
{ |
|
557 |
return `ili_${prefix}_${item}`; |
|
558 |
} |
|
559 |
|
|
560 |
let import_ul = by_id("import_ul"); |
|
561 |
let import_chbxs_colliding = undefined; |
|
562 |
let settings_import_map = undefined; |
|
563 |
|
|
564 |
function populate_import_list(settings) |
|
565 |
{ |
|
566 |
let old_children = import_ul.children; |
|
567 |
while (old_children[0] !== undefined) |
|
568 |
import_ul.removeChild(old_children[0]); |
|
569 |
|
|
570 |
import_chbxs_colliding = []; |
|
571 |
settings_import_map = new Map(); |
|
572 |
|
|
573 |
for (let setting of settings) { |
|
574 |
let [key, value] = Object.entries(setting)[0]; |
|
575 |
let prefix = key[0]; |
|
576 |
let name = key.substring(1); |
|
577 |
add_import_li(prefix, name); |
|
578 |
settings_import_map.set(key, value); |
|
579 |
} |
|
580 |
} |
|
581 |
|
|
582 |
function add_import_li(prefix, name) |
|
583 |
{ |
|
584 |
let li = import_li_template.cloneNode(true); |
|
585 |
let name_span = li.firstElementChild; |
|
586 |
let chbx = name_span.nextElementSibling; |
|
587 |
let warning_span = chbx.nextElementSibling; |
|
588 |
|
|
589 |
li.setAttribute("data-prefix", prefix); |
|
590 |
li.setAttribute("data-name", name); |
|
591 |
li.id = import_li_id(prefix, name); |
|
592 |
name_span.textContent = nice_name(prefix, name); |
|
593 |
|
|
594 |
if (storage.get(prefix, name) !== undefined) { |
|
595 |
import_chbxs_colliding.push(chbx); |
|
596 |
warning_span.textContent = "(will overwrite existing setting!)"; |
|
597 |
} |
|
598 |
|
|
599 |
import_ul.appendChild(li); |
|
600 |
} |
|
601 |
|
|
602 |
function check_all_imports() |
|
603 |
{ |
|
604 |
for (let li of import_ul.children) |
|
605 |
li.firstElementChild.nextElementSibling.checked = true; |
|
606 |
} |
|
607 |
|
|
608 |
function uncheck_all_imports() |
|
609 |
{ |
|
610 |
for (let li of import_ul.children) |
|
611 |
li.firstElementChild.nextElementSibling.checked = false; |
|
612 |
} |
|
613 |
|
|
614 |
function uncheck_colliding_imports() |
|
615 |
{ |
|
616 |
for (let chbx of import_chbxs_colliding) |
|
617 |
chbx.checked = false; |
|
618 |
} |
|
619 |
|
|
620 |
const file_opener_form = by_id("file_opener_form"); |
|
621 |
|
|
622 |
function hide_import_window() |
|
623 |
{ |
|
624 |
import_window.classList.add("hide"); |
|
625 |
/* Let GC free some memory */ |
|
626 |
import_chbxs_colliding = undefined; |
|
627 |
settings_import_map = undefined; |
|
497 | 628 |
|
498 | 629 |
/* |
499 |
* Newer browsers could utilise `text' method of File objects.
|
|
500 |
* Older ones require FileReader.
|
|
630 |
* Reset file <input>. Without this, a second attempt to import the same
|
|
631 |
* file would result in "change" event on happening on <input> element.
|
|
501 | 632 |
*/ |
633 |
file_opener_form.reset(); |
|
634 |
} |
|
502 | 635 |
|
503 |
function _read_file(file, resolve, reject) |
|
504 |
{ |
|
505 |
let reader = new FileReader(); |
|
636 |
function commit_import() |
|
637 |
{ |
|
638 |
for (let li of import_ul.children) { |
|
639 |
let chbx = li.firstElementChild.nextElementSibling; |
|
506 | 640 |
|
507 |
reader.onload = () => resolve(reader.result); |
|
508 |
reader.onerror = () => reject(reader.error); |
|
509 |
reader.readAsText(file); |
|
510 |
} |
|
511 |
|
|
512 |
function read_file(file) |
|
513 |
{ |
|
514 |
return new Promise((resolve, reject) => |
|
515 |
_read_file(file, resolve, reject)); |
|
516 |
} |
|
641 |
if (!chbx.checked) |
|
642 |
continue; |
|
517 | 643 |
|
518 |
async function import_from_file(event) |
|
519 |
{ |
|
520 |
let files = event.target.files; |
|
521 |
if (files.length < 1) |
|
522 |
return; |
|
523 |
|
|
524 |
import_window.classList.remove("hide"); |
|
525 |
import_loading_radio.checked = true; |
|
526 |
|
|
527 |
let result = undefined; |
|
528 |
|
|
529 |
try { |
|
530 |
result = JSON.parse(await read_file(files[0])); |
|
531 |
} catch(e) { |
|
532 |
bad_file_errormsg.textContent = "" + e; |
|
533 |
import_failed_radio.checked = true; |
|
534 |
return; |
|
535 |
} |
|
536 |
|
|
537 |
let errormsg = validate_settings(result); |
|
538 |
if (errormsg !== false) { |
|
539 |
bad_file_errormsg.textContent = errormsg; |
|
540 |
import_failed_radio.checked = true; |
|
541 |
return; |
|
644 |
let prefix = li.getAttribute("data-prefix"); |
|
645 |
let name = li.getAttribute("data-name"); |
|
646 |
let key = prefix + name; |
|
647 |
let value = settings_import_map.get(key); |
|
648 |
storage.set(prefix, name, value); |
|
649 |
} |
|
650 |
|
|
651 |
hide_import_window(); |
|
652 |
} |
|
653 |
|
|
654 |
function initialize_import_facility() |
|
655 |
{ |
|
656 |
let import_but = by_id("import_but"); |
|
657 |
let file_opener = by_id("file_opener"); |
|
658 |
let import_failok_but = by_id("import_failok_but"); |
|
659 |
let check_all_import_but = by_id("check_all_import_but"); |
|
660 |
let uncheck_all_import_but = by_id("uncheck_all_import_but"); |
|
661 |
let uncheck_existing_import_but = by_id("uncheck_existing_import_but"); |
|
662 |
let commit_import_but = by_id("commit_import_but"); |
|
663 |
let cancel_import_but = by_id("cancel_import_but"); |
|
664 |
import_but.addEventListener("click", () => file_opener.click()); |
|
665 |
file_opener.addEventListener("change", import_from_file); |
|
666 |
import_failok_but.addEventListener("click", hide_import_window); |
|
667 |
check_all_import_but.addEventListener("click", check_all_imports); |
|
668 |
uncheck_all_import_but.addEventListener("click", uncheck_all_imports); |
|
669 |
uncheck_colliding_import_but |
|
670 |
.addEventListener("click", uncheck_colliding_imports); |
|
671 |
commit_import_but.addEventListener("click", commit_import); |
|
672 |
cancel_import_but.addEventListener("click", hide_import_window); |
|
673 |
} |
|
674 |
|
|
675 |
async function main() |
|
676 |
{ |
|
677 |
storage = await get_remote_storage(); |
|
678 |
|
|
679 |
for (let prefix of list_prefixes) { |
|
680 |
for (let item of storage.get_all_names(prefix).sort()) { |
|
681 |
add_li(prefix, item, true); |
|
682 |
add_chbx_li(prefix, item); |
|
683 |
add_radio_li(prefix, item); |
|
542 | 684 |
} |
543 | 685 |
|
544 |
populate_import_list(result); |
|
545 |
import_selection_radio.checked = true; |
|
546 |
} |
|
547 |
|
|
548 |
function validate_settings(settings) |
|
549 |
{ |
|
550 |
// TODO |
|
551 |
return false; |
|
552 |
} |
|
686 |
let name = TYPE_NAME[prefix]; |
|
553 | 687 |
|
554 |
function import_li_id(prefix, item) |
|
555 |
{ |
|
556 |
return `ili_${prefix}_${item}`; |
|
557 |
} |
|
688 |
let add_but = by_id(`add_${name}_but`); |
|
689 |
let discard_but = by_id(`discard_${name}_but`); |
|
690 |
let save_but = by_id(`save_${name}_but`); |
|
558 | 691 |
|
559 |
let import_ul = by_id("import_ul"); |
|
560 |
let import_chbxs_colliding = undefined; |
|
561 |
let settings_import_map = undefined; |
|
562 |
|
|
563 |
function populate_import_list(settings) |
|
564 |
{ |
|
565 |
let old_children = import_ul.children; |
|
566 |
while (old_children[0] !== undefined) |
|
567 |
import_ul.removeChild(old_children[0]); |
|
568 |
|
|
569 |
import_chbxs_colliding = []; |
|
570 |
settings_import_map = new Map(); |
|
571 |
|
|
572 |
for (let setting of settings) { |
|
573 |
let [key, value] = Object.entries(setting)[0]; |
|
574 |
let prefix = key[0]; |
|
575 |
let name = key.substring(1); |
|
576 |
add_import_li(prefix, name); |
|
577 |
settings_import_map.set(key, value); |
|
578 |
} |
|
579 |
} |
|
692 |
add_but.addEventListener("click", () => add_new_item(prefix)); |
|
693 |
discard_but.addEventListener("click", () => cancel_work(prefix)); |
|
694 |
save_but.addEventListener("click", () => save_work(prefix)); |
|
580 | 695 |
|
581 |
function add_import_li(prefix, name) |
|
582 |
{ |
|
583 |
let li = import_li_template.cloneNode(true); |
|
584 |
let name_span = li.firstElementChild; |
|
585 |
let chbx = name_span.nextElementSibling; |
|
586 |
let warning_span = chbx.nextElementSibling; |
|
696 |
if (prefix === TYPE_PREFIX.SCRIPT) |
|
697 |
continue; |
|
587 | 698 |
|
588 |
li.setAttribute("data-prefix", prefix); |
|
589 |
li.setAttribute("data-name", name); |
|
590 |
li.id = import_li_id(prefix, name); |
|
591 |
name_span.textContent = nice_name(prefix, name); |
|
592 |
|
|
593 |
if (storage.get(prefix, name) !== undefined) { |
|
594 |
import_chbxs_colliding.push(chbx); |
|
595 |
warning_span.textContent = "(will overwrite existing setting!)"; |
|
596 |
} |
|
699 |
let ul = ul_by_prefix[prefix]; |
|
597 | 700 |
|
598 |
import_ul.appendChild(li); |
|
599 |
} |
|
701 |
let commit_components_but = by_id(`commit_${name}_components_but`); |
|
702 |
let cancel_components_but = by_id(`cancel_${name}_components_but`); |
|
703 |
let select_components_but = by_id(`select_${name}_components_but`); |
|
600 | 704 |
|
601 |
function check_all_imports() |
|
602 |
{ |
|
603 |
for (let li of import_ul.children) |
|
604 |
li.firstElementChild.nextElementSibling.checked = true; |
|
705 |
commit_components_but |
|
706 |
.addEventListener("click", ul.commit_components); |
|
707 |
select_components_but |
|
708 |
.addEventListener("click", ul.select_components); |
|
709 |
cancel_components_but.addEventListener("click", cancel_components); |
|
605 | 710 |
} |
606 | 711 |
|
607 |
function uncheck_all_imports() |
|
608 |
{ |
|
609 |
for (let li of import_ul.children) |
|
610 |
li.firstElementChild.nextElementSibling.checked = false; |
|
611 |
} |
|
612 |
|
|
613 |
function uncheck_colliding_imports() |
|
614 |
{ |
|
615 |
for (let chbx of import_chbxs_colliding) |
|
616 |
chbx.checked = false; |
|
617 |
} |
|
712 |
initialize_import_facility(); |
|
618 | 713 |
|
619 |
const file_opener_form = by_id("file_opener_form"); |
|
714 |
storage.add_change_listener(handle_change); |
|
715 |
} |
|
620 | 716 |
|
621 |
function hide_import_window()
|
|
622 |
{
|
|
623 |
import_window.classList.add("hide");
|
|
624 |
/* Let GC free some memory */
|
|
625 |
import_chbxs_colliding = undefined;
|
|
626 |
settings_import_map = undefined;
|
|
717 |
function handle_change(change)
|
|
718 |
{ |
|
719 |
if (change.old_val === undefined) {
|
|
720 |
add_li(change.prefix, change.item);
|
|
721 |
add_chbx_li(change.prefix, change.item);
|
|
722 |
add_radio_li(change.prefix, change.item);
|
|
627 | 723 |
|
628 |
/* |
|
629 |
* Reset file <input>. Without this, a second attempt to import the same |
|
630 |
* file would result in "change" event on happening on <input> element. |
|
631 |
*/ |
|
632 |
file_opener_form.reset(); |
|
724 |
return; |
|
633 | 725 |
} |
634 | 726 |
|
635 |
function commit_import() |
|
636 |
{ |
|
637 |
for (let li of import_ul.children) { |
|
638 |
let chbx = li.firstElementChild.nextElementSibling; |
|
639 |
|
|
640 |
if (!chbx.checked) |
|
641 |
continue; |
|
642 |
|
|
643 |
let prefix = li.getAttribute("data-prefix"); |
|
644 |
let name = li.getAttribute("data-name"); |
|
645 |
let key = prefix + name; |
|
646 |
let value = settings_import_map.get(key); |
|
647 |
storage.set(prefix, name, value); |
|
648 |
} |
|
649 |
|
|
650 |
hide_import_window(); |
|
651 |
} |
|
727 |
if (change.new_val !== undefined) |
|
728 |
return; |
|
652 | 729 |
|
653 |
function initialize_import_facility() |
|
654 |
{ |
|
655 |
let import_but = by_id("import_but"); |
|
656 |
let file_opener = by_id("file_opener"); |
|
657 |
let import_failok_but = by_id("import_failok_but"); |
|
658 |
let check_all_import_but = by_id("check_all_import_but"); |
|
659 |
let uncheck_all_import_but = by_id("uncheck_all_import_but"); |
|
660 |
let uncheck_existing_import_but = by_id("uncheck_existing_import_but"); |
|
661 |
let commit_import_but = by_id("commit_import_but"); |
|
662 |
let cancel_import_but = by_id("cancel_import_but"); |
|
663 |
import_but.addEventListener("click", () => file_opener.click()); |
|
664 |
file_opener.addEventListener("change", import_from_file); |
|
665 |
import_failok_but.addEventListener("click", hide_import_window); |
|
666 |
check_all_import_but.addEventListener("click", check_all_imports); |
|
667 |
uncheck_all_import_but.addEventListener("click", uncheck_all_imports); |
|
668 |
uncheck_colliding_import_but |
|
669 |
.addEventListener("click", uncheck_colliding_imports); |
|
670 |
commit_import_but.addEventListener("click", commit_import); |
|
671 |
cancel_import_but.addEventListener("click", hide_import_window); |
|
730 |
let ul = ul_by_prefix[change.prefix]; |
|
731 |
if (ul.state === UL_STATE.EDITING_ENTRY && |
|
732 |
ul.edited_item === change.item) { |
|
733 |
ul.state = UL_STATE.ADDING_ENTRY; |
|
734 |
return; |
|
672 | 735 |
} |
673 | 736 |
|
674 |
async function main() |
|
675 |
{ |
|
676 |
storage = await get_storage(); |
|
677 |
|
|
678 |
for (let prefix of list_prefixes) { |
|
679 |
for (let item of storage.get_all_names(prefix).sort()) { |
|
680 |
add_li(prefix, item, true); |
|
681 |
add_chbx_li(prefix, item); |
|
682 |
add_radio_li(prefix, item); |
|
683 |
} |
|
684 |
|
|
685 |
let name = TYPE_NAME[prefix]; |
|
686 |
|
|
687 |
let add_but = by_id(`add_${name}_but`); |
|
688 |
let discard_but = by_id(`discard_${name}_but`); |
|
689 |
let save_but = by_id(`save_${name}_but`); |
|
690 |
|
|
691 |
add_but.addEventListener("click", () => add_new_item(prefix)); |
|
692 |
discard_but.addEventListener("click", () => cancel_work(prefix)); |
|
693 |
save_but.addEventListener("click", () => save_work(prefix)); |
|
694 |
|
|
695 |
if (prefix === TYPE_PREFIX.SCRIPT) |
|
696 |
continue; |
|
697 |
|
|
698 |
let ul = ul_by_prefix[prefix]; |
|
699 |
|
|
700 |
let commit_components_but = by_id(`commit_${name}_components_but`); |
|
701 |
let cancel_components_but = by_id(`cancel_${name}_components_but`); |
|
702 |
let select_components_but = by_id(`select_${name}_components_but`); |
|
703 |
|
|
704 |
commit_components_but |
|
705 |
.addEventListener("click", ul.commit_components); |
|
706 |
select_components_but |
|
707 |
.addEventListener("click", ul.select_components); |
|
708 |
cancel_components_but.addEventListener("click", cancel_components); |
|
709 |
} |
|
710 |
|
|
711 |
initialize_import_facility(); |
|
737 |
let uls_creators = [[ul.ul, item_li_id]]; |
|
712 | 738 |
|
713 |
storage.add_change_listener(handle_change); |
|
739 |
if (change.prefix !== TYPE_PREFIX.PAGE) { |
|
740 |
uls_creators.push([chbx_components_ul, chbx_li_id]); |
|
741 |
uls_creators.push([radio_components_ul, radio_li_id]); |
|
714 | 742 |
} |
715 | 743 |
|
716 |
function handle_change(change) |
|
717 |
{ |
|
718 |
if (change.old_val === undefined) { |
|
719 |
add_li(change.prefix, change.item); |
|
720 |
add_chbx_li(change.prefix, change.item); |
|
721 |
add_radio_li(change.prefix, change.item); |
|
722 |
|
|
723 |
return; |
|
724 |
} |
|
725 |
|
|
726 |
if (change.new_val !== undefined) |
|
727 |
return; |
|
728 |
|
|
729 |
let ul = ul_by_prefix[change.prefix]; |
|
730 |
if (ul.state === UL_STATE.EDITING_ENTRY && |
|
731 |
ul.edited_item === change.item) { |
|
732 |
ul.state = UL_STATE.ADDING_ENTRY; |
|
733 |
return; |
|
734 |
} |
|
735 |
|
|
736 |
let uls_creators = [[ul.ul, item_li_id]]; |
|
737 |
|
|
738 |
if (change.prefix !== TYPE_PREFIX.PAGE) { |
|
739 |
uls_creators.push([chbx_components_ul, chbx_li_id]); |
|
740 |
uls_creators.push([radio_components_ul, radio_li_id]); |
|
741 |
} |
|
742 |
|
|
743 |
for (let [components_ul, id_creator] of uls_creators) { |
|
744 |
let li = by_id(id_creator(change.prefix, change.item)); |
|
745 |
components_ul.removeChild(li); |
|
746 |
} |
|
744 |
for (let [components_ul, id_creator] of uls_creators) { |
|
745 |
let li = by_id(id_creator(change.prefix, change.item)); |
|
746 |
components_ul.removeChild(li); |
|
747 | 747 |
} |
748 |
} |
|
748 | 749 |
|
749 |
main(); |
|
750 |
})(); |
|
750 |
main(); |
Also available in: Unified diff
emply an sh-based build system; make some changes to blocking