diff options
Diffstat (limited to 'html')
-rw-r--r-- | html/display-panel.html | 3 | ||||
-rw-r--r-- | html/display-panel.js (renamed from html/display-panel.mjs) | 8 | ||||
-rw-r--r-- | html/options.html | 7 | ||||
-rw-r--r-- | html/options_main.js | 399 | ||||
-rw-r--r-- | html/options_main.mjs | 398 |
5 files changed, 412 insertions, 403 deletions
diff --git a/html/display-panel.html b/html/display-panel.html index 9c8de5e..4adeb53 100644 --- a/html/display-panel.html +++ b/html/display-panel.html @@ -6,6 +6,7 @@ </head> <body> <button id="settings_but" type="button">Settings</button> - <script src="./display-panel.mjs" type="module"></script> + <script src="/common/browser.js"></script> + <script src="./display-panel.js"></script> </body> </html> diff --git a/html/display-panel.mjs b/html/display-panel.js index 38f2a42..91b0df7 100644 --- a/html/display-panel.mjs +++ b/html/display-panel.js @@ -10,7 +10,9 @@ "use strict"; -import browser from '/common/browser.mjs'; +(() => { + const browser = window.browser; -document.getElementById("settings_but") - .addEventListener("click", (e) => browser.runtime.openOptionsPage()); + document.getElementById("settings_but") + .addEventListener("click", (e) => browser.runtime.openOptionsPage()); +})(); diff --git a/html/options.html b/html/options.html index 921b423..0bce6fc 100644 --- a/html/options.html +++ b/html/options.html @@ -170,6 +170,11 @@ </div> </div> - <script src="./options_main.mjs" type="module"></script> + <script src="/common/connection_types.js"></script> + <script src="/common/stored_types.js"></script> + <script src="/common/once.js"></script> + <script src="/common/browser.js"></script> + <script src="/common/storage_client.js"></script> + <script src="./options_main.js"></script> </body> </html> diff --git a/html/options_main.js b/html/options_main.js new file mode 100644 index 0000000..979fb44 --- /dev/null +++ b/html/options_main.js @@ -0,0 +1,399 @@ +/** + * Myext HTML options page main script + * + * Copyright (C) 2021 Wojtek Kosior + * + * Dual-licensed under: + * - 0BSD license + * - GPLv3 or (at your option) any later version + */ + +"use strict"; + +(() => { + const get_storage = window.get_storage; + const TYPE_PREFIX = window.TYPE_PREFIX; + const TYPE_NAME = window.TYPE_NAME; + const list_prefixes = window.list_prefixes; + + var storage; + function by_id(id) + { + return document.getElementById(id); + } + + const item_li_template = by_id("item_li_template"); + const component_li_template = by_id("component_li_template"); + const selectable_component_li_template = + by_id("selectable_component_li_template"); + /* Make sure they are later cloned without id. */ + item_li_template.removeAttribute("id"); + component_li_template.removeAttribute("id"); + selectable_component_li_template.removeAttribute("id"); + + function item_li_id(prefix, item) + { + return `li_${prefix}_${item}`; + } + + function add_li(prefix, item, at_the_end=false) + { + let ul = ul_by_prefix[prefix]; + let li = item_li_template.cloneNode(true); + li.id = item_li_id(prefix, item); + + let span = li.firstElementChild; + span.textContent = item; + + let edit_button = span.nextElementSibling; + edit_button.addEventListener("click", () => edit_item(prefix, item)); + + let remove_button = edit_button.nextElementSibling; + remove_button.addEventListener("click", + () => storage.remove(prefix, item)); + + if (!at_the_end) { + for (let element of ul.ul.children) { + if (element.id < li.id || element.id.startsWith("work_")) + continue; + + ul.ul.insertBefore(li, element); + return; + } + } + + ul.ul.appendChild(li); + } + + const selectable_components_ul = by_id("selectable_components_ul"); + + function selectable_li_id(prefix, item) + { + return `sli_${prefix}_${item}`; + } + + function add_selectable(prefix, name) + { + if (prefix === TYPE_PREFIX.PAGE) + return; + + let li = selectable_component_li_template.cloneNode(true); + li.id = selectable_li_id(prefix, name); + li.setAttribute("data-prefix", prefix); + li.setAttribute("data-name", name); + + let chbx = li.firstElementChild; + let span = chbx.nextElementSibling; + + span.textContent = `${name} (${TYPE_NAME[prefix]})`; + + selectable_components_ul.appendChild(li); + } + + /* + * Used to construct and update components list of edited + * bundle as well as edited page. + */ + function add_components(ul, components) + { + let components_ul = ul.work_name_input.nextElementSibling; + + for (let component of components) { + let [prefix, name] = component; + let li = component_li_template.cloneNode(true); + li.setAttribute("data-prefix", prefix); + li.setAttribute("data-name", name); + let span = li.firstElementChild; + span.textContent = `${name} (${TYPE_NAME[prefix]})`; + let remove_but = span.nextElementSibling; + remove_but.addEventListener("click", () => + components_ul.removeChild(li)); + components_ul.appendChild(li); + } + + components_ul.appendChild(ul.work_empty_component_li); + } + + /* Used to reset edited bundle as well as edited page. */ + function generic_reset_work_li(ul, item, components) + { + if (item === undefined) { + item = ""; + components = []; + }; + + ul.work_name_input.value = item; + let old_components_ul = ul.work_name_input.nextElementSibling; + let components_ul = old_components_ul.cloneNode(false); + + ul.work_li.insertBefore(components_ul, old_components_ul); + ul.work_li.removeChild(old_components_ul); + + add_components(ul, components); + } + + function reset_work_page_li(ul, item, settings) + { + ul.work_page_allow_chbx.checked = !!settings?.allow; + generic_reset_work_li(ul, item, settings?.components); + } + + /* Used to get edited bundle as well as edited page data for saving. */ + function generic_work_li_data(ul) + { + let components_ul = ul.work_name_input.nextElementSibling; + let component_li = components_ul.firstElementChild; + + let components = []; + + /* Last list element is empty li with id set. */ + while (component_li.id === '') { + components.push([component_li.getAttribute("data-prefix"), + component_li.getAttribute("data-name")]); + component_li = component_li.nextElementSibling; + } + + return [ul.work_name_input.value, components]; + } + + function work_page_li_data(ul) + { + let [url, components] = generic_work_li_data(ul); + let settings = {components, allow : !!ul.work_page_allow_chbx.checked}; + + return [url, settings]; + } + + const script_url_input = by_id("script_url_field"); + const script_sha256_input = by_id("script_sha256_field"); + const script_contents_field = by_id("script_contents_field"); + + function maybe_string(maybe_defined) + { + return maybe_defined === undefined ? "" : maybe_defined + ""; + } + + function reset_work_script_li(ul, name, data) + { + ul.work_name_input.value = maybe_string(name); + script_url_input.value = maybe_string(data?.url); + script_sha256_input.value = maybe_string(data?.hash); + script_contents_field.value = maybe_string(data?.text); + } + + function work_script_li_data(ul) + { + return [ul.work_name_input.value, { + url : script_url_input.value, + hash : script_sha256_input.value, + text : script_contents_field.value + }]; + } + + function cancel_work(prefix) + { + let ul = ul_by_prefix[prefix]; + + if (ul.state === UL_STATE.IDLE) + return; + + if (ul.state === UL_STATE.EDITING_ENTRY) { + add_li(prefix, ul.edited_item); + } + + ul.work_li.classList.add("hide"); + ul.state = UL_STATE.IDLE; + } + + function save_work(prefix) + { + let ul = ul_by_prefix[prefix]; + + if (ul.state === UL_STATE.IDLE) + return; + + let [item, data] = ul.get_work_li_data(ul); + + if (prefix == TYPE_PREFIX.PAGE) + + /* Here we fire promises and return without waiting. */ + + if (ul.state === UL_STATE.EDITING_ENTRY) + storage.replace(prefix, ul.edited_item, item, data); + + if (ul.state === UL_STATE.ADDING_ENTRY) + storage.set(prefix, item, data); + + cancel_work(prefix); + } + + function edit_item(prefix, item) + { + cancel_work(prefix); + + let ul = ul_by_prefix[prefix]; + let li = by_id(item_li_id(prefix, item)); + ul.reset_work_li(ul, item, storage.get(prefix, item)); + ul.ul.insertBefore(ul.work_li, li); + ul.ul.removeChild(li); + ul.work_li.classList.remove("hide"); + + ul.state = UL_STATE.EDITING_ENTRY; + ul.edited_item = item; + } + + function add_new_item(prefix) + { + cancel_work(prefix); + + let ul = ul_by_prefix[prefix]; + ul.reset_work_li(ul); + ul.work_li.classList.remove("hide"); + ul.ul.appendChild(ul.work_li); + + ul.state = UL_STATE.ADDING_ENTRY; + } + + const select_components_window = by_id("select_components_window"); + var select_prefix; + + function select_components(prefix) + { + select_prefix = prefix; + select_components_window.classList.remove("hide"); + + for (let li of selectable_components_ul.children) { + let chbx = li.firstElementChild; + chbx.checked = false; + } + } + + function commit_components() + { + let selected = []; + + for (let li of selectable_components_ul.children) { + let chbx = li.firstElementChild; + if (!chbx.checked) + continue; + + selected.push([li.getAttribute("data-prefix"), + li.getAttribute("data-name")]); + } + + add_components(ul_by_prefix[select_prefix], selected); + cancel_components(); + } + + function cancel_components() + { + select_components_window.classList.add("hide"); + } + + const UL_STATE = { + EDITING_ENTRY : 0, + ADDING_ENTRY : 1, + IDLE : 2 + }; + + const ul_by_prefix = { + [TYPE_PREFIX.PAGE] : { + ul : by_id("pages_ul"), + work_li : by_id("work_page_li"), + work_name_input : by_id("page_url_field"), + work_empty_component_li : by_id("empty_page_component_li"), + work_page_allow_chbx : by_id("page_allow_chbx"), + reset_work_li : reset_work_page_li, + get_work_li_data : work_page_li_data, + state : UL_STATE.IDLE, + edited_item : undefined, + }, + [TYPE_PREFIX.BUNDLE] : { + ul : by_id("bundles_ul"), + work_li : by_id("work_bundle_li"), + work_name_input : by_id("bundle_name_field"), + work_empty_component_li : by_id("empty_bundle_component_li"), + reset_work_li : generic_reset_work_li, + get_work_li_data : generic_work_li_data, + state : UL_STATE.IDLE, + edited_item : undefined, + }, + [TYPE_PREFIX.SCRIPT] : { + ul : by_id("scripts_ul"), + work_li : by_id("work_script_li"), + work_name_input : by_id("script_name_field"), + reset_work_li : reset_work_script_li, + get_work_li_data : work_script_li_data, + state : UL_STATE.IDLE, + edited_item : undefined, + } + } + + async function main() + { + storage = await get_storage(); + + for (let prefix of list_prefixes) { + for (let item of storage.get_all_names(prefix).sort()) { + add_li(prefix, item, true); + add_selectable(prefix, item); + } + } + + storage.add_change_listener(handle_change); + + let commit_components_but = by_id("commit_components_but"); + let cancel_components_but = by_id("cancel_components_but"); + commit_components_but.addEventListener("click", commit_components); + cancel_components_but.addEventListener("click", cancel_components); + + for (let prefix of list_prefixes) { + let add_but = by_id(`add_${TYPE_NAME[prefix]}_but`); + let discard_but = by_id(`${TYPE_NAME[prefix]}_discard_but`); + let save_but = by_id(`${TYPE_NAME[prefix]}_save_but`); + let select_components_but = + by_id(`${TYPE_NAME[prefix]}_select_components_but`); + + add_but.addEventListener("click", () => add_new_item(prefix)); + discard_but.addEventListener("click", () => cancel_work(prefix)); + save_but.addEventListener("click", () => save_work(prefix)); + if (select_components_but === null) + continue; + + select_components_but.addEventListener( + "click", + () => select_components(prefix) + ); + } + } + + function handle_change(change) + { + if (change.old_val === undefined) { + add_li(change.prefix, change.item); + add_selectable(change.prefix, change.item); + return; + } + + if (change.new_val !== undefined) + return; + + let ul = ul_by_prefix[change.prefix]; + if (ul.state === UL_STATE.EDITING_ENTRY && + ul.edited_item === change.item) { + ul.state = UL_STATE.ADDING_ENTRY; + return; + } + + let li = by_id(item_li_id(change.prefix, change.item)); + ul.ul.removeChild(li); + + if (change.prefix === TYPE_PREFIX.PAGE) + return; + + let sli = by_id(selectable_li_id(change.prefix, change.item)); + selectable_components_ul.removeChild(sli); + } + + main(); +})(); diff --git a/html/options_main.mjs b/html/options_main.mjs deleted file mode 100644 index f288971..0000000 --- a/html/options_main.mjs +++ /dev/null @@ -1,398 +0,0 @@ -/** -* Myext HTML options page main script -* -* Copyright (C) 2021 Wojtek Kosior -* -* Dual-licensed under: -* - 0BSD license -* - GPLv3 or (at your option) any later version -*/ - -"use strict"; - -import get_storage from '/common/storage_client.mjs'; -import {TYPE_PREFIX, TYPE_NAME, list_prefixes} from '/common/stored_types.mjs'; - -var storage; - -const item_li_template = document.getElementById("item_li_template"); -const component_li_template = document.getElementById("component_li_template"); -const selectable_component_li_template = - document.getElementById("selectable_component_li_template"); -/* Make sure they are later cloned without id. */ -item_li_template.removeAttribute("id"); -component_li_template.removeAttribute("id"); -selectable_component_li_template.removeAttribute("id"); - -function item_li_id(prefix, item) -{ - return `li_${prefix}_${item}`; -} - -function add_li(prefix, item, at_the_end=false) -{ - let ul = ul_by_prefix[prefix]; - let li = item_li_template.cloneNode(true); - li.id = item_li_id(prefix, item); - - let span = li.firstElementChild; - span.textContent = item; - - let edit_button = span.nextElementSibling; - edit_button.addEventListener("click", () => edit_item(prefix, item)); - - let remove_button = edit_button.nextElementSibling; - remove_button.addEventListener("click", () => storage.remove(prefix, item)); - - if (!at_the_end) { - for (let element of ul.ul.children) { - if (element.id < li.id || element.id.startsWith("work_")) - continue; - - ul.ul.insertBefore(li, element); - return; - } - } - - ul.ul.appendChild(li); -} - -const selectable_components_ul = - document.getElementById("selectable_components_ul"); - -function selectable_li_id(prefix, item) -{ - return `sli_${prefix}_${item}`; -} - -function add_selectable(prefix, name) -{ - if (prefix === TYPE_PREFIX.PAGE) - return; - - let li = selectable_component_li_template.cloneNode(true); - li.id = selectable_li_id(prefix, name); - li.setAttribute("data-prefix", prefix); - li.setAttribute("data-name", name); - - let chbx = li.firstElementChild; - let span = chbx.nextElementSibling; - - span.textContent = `${name} (${TYPE_NAME[prefix]})`; - - selectable_components_ul.appendChild(li); -} - -/* - * Used to construct and update components list of edited - * bundle as well as edited page. - */ -function add_components(ul, components) -{ - let components_ul = ul.work_name_input.nextElementSibling; - - for (let component of components) { - let [prefix, name] = component; - let li = component_li_template.cloneNode(true); - li.setAttribute("data-prefix", prefix); - li.setAttribute("data-name", name); - let span = li.firstElementChild; - span.textContent = `${name} (${TYPE_NAME[prefix]})`; - let remove_but = span.nextElementSibling; - remove_but.addEventListener("click", () => - components_ul.removeChild(li)); - components_ul.appendChild(li); - } - - components_ul.appendChild(ul.work_empty_component_li); -} - -/* Used to reset edited bundle as well as edited page. */ -function generic_reset_work_li(ul, item, components) -{ - if (item === undefined) { - item = ""; - components = []; - }; - - ul.work_name_input.value = item; - let old_components_ul = ul.work_name_input.nextElementSibling; - let components_ul = old_components_ul.cloneNode(false); - - ul.work_li.insertBefore(components_ul, old_components_ul); - ul.work_li.removeChild(old_components_ul); - - add_components(ul, components); -} - -function reset_work_page_li(ul, item, settings) -{ - ul.work_page_allow_chbx.checked = !!settings?.allow; - generic_reset_work_li(ul, item, settings?.components); -} - -/* Used to get edited bundle as well as edited page data for saving. */ -function generic_work_li_data(ul) -{ - let components_ul = ul.work_name_input.nextElementSibling; - let component_li = components_ul.firstElementChild; - - let components = []; - - /* Last list element is empty li with id set. */ - while (component_li.id === '') { - components.push([component_li.getAttribute("data-prefix"), - component_li.getAttribute("data-name")]); - component_li = component_li.nextElementSibling; - } - - return [ul.work_name_input.value, components]; -} - -function work_page_li_data(ul) -{ - let [url, components] = generic_work_li_data(ul); - let settings = {components, allow : !!ul.work_page_allow_chbx.checked}; - - return [url, settings]; -} - -const script_url_input = document.getElementById("script_url_field"); -const script_sha256_input = document.getElementById("script_sha256_field"); -const script_contents_field = document.getElementById("script_contents_field"); - -function maybe_string(maybe_defined) -{ - return maybe_defined === undefined ? "" : maybe_defined + ""; -} - -function reset_work_script_li(ul, name, data) -{ - ul.work_name_input.value = maybe_string(name); - script_url_input.value = maybe_string(data?.url); - script_sha256_input.value = maybe_string(data?.hash); - script_contents_field.value = maybe_string(data?.text); -} - -function work_script_li_data(ul) -{ - return [ul.work_name_input.value, { - url : script_url_input.value, - hash : script_sha256_input.value, - text : script_contents_field.value - }]; -} - -function cancel_work(prefix) -{ - let ul = ul_by_prefix[prefix]; - - if (ul.state === UL_STATE.IDLE) - return; - - if (ul.state === UL_STATE.EDITING_ENTRY) { - add_li(prefix, ul.edited_item); - } - - ul.work_li.classList.add("hide"); - ul.state = UL_STATE.IDLE; -} - -function save_work(prefix) -{ - let ul = ul_by_prefix[prefix]; - - if (ul.state === UL_STATE.IDLE) - return; - - let [item, data] = ul.get_work_li_data(ul); - - if (prefix == TYPE_PREFIX.PAGE) - - /* Here we fire promises and return without waiting. */ - - if (ul.state === UL_STATE.EDITING_ENTRY) - storage.replace(prefix, ul.edited_item, item, data); - - if (ul.state === UL_STATE.ADDING_ENTRY) - storage.set(prefix, item, data); - - cancel_work(prefix); -} - -function edit_item(prefix, item) -{ - cancel_work(prefix); - - let ul = ul_by_prefix[prefix]; - let li = document.getElementById(item_li_id(prefix, item)); - ul.reset_work_li(ul, item, storage.get(prefix, item)); - ul.ul.insertBefore(ul.work_li, li); - ul.ul.removeChild(li); - ul.work_li.classList.remove("hide"); - - ul.state = UL_STATE.EDITING_ENTRY; - ul.edited_item = item; -} - -function add_new_item(prefix) -{ - cancel_work(prefix); - - let ul = ul_by_prefix[prefix]; - ul.reset_work_li(ul); - ul.work_li.classList.remove("hide"); - ul.ul.appendChild(ul.work_li); - - ul.state = UL_STATE.ADDING_ENTRY; -} - -const select_components_window = - document.getElementById("select_components_window"); -var select_prefix; - -function select_components(prefix) -{ - select_prefix = prefix; - select_components_window.classList.remove("hide"); - - for (let li of selectable_components_ul.children) { - let chbx = li.firstElementChild; - chbx.checked = false; - } -} - -function commit_components() -{ - let selected = []; - - for (let li of selectable_components_ul.children) { - let chbx = li.firstElementChild; - if (!chbx.checked) - continue; - - selected.push([li.getAttribute("data-prefix"), - li.getAttribute("data-name")]); - } - - add_components(ul_by_prefix[select_prefix], selected); - cancel_components(); -} - -function cancel_components() -{ - select_components_window.classList.add("hide"); -} - -const UL_STATE = { - EDITING_ENTRY : 0, - ADDING_ENTRY : 1, - IDLE : 2 -}; - -const ul_by_prefix = { - [TYPE_PREFIX.PAGE] : { - ul : document.getElementById("pages_ul"), - work_li : document.getElementById("work_page_li"), - work_name_input : document.getElementById("page_url_field"), - work_empty_component_li : - document.getElementById("empty_page_component_li"), - work_page_allow_chbx : document.getElementById("page_allow_chbx"), - reset_work_li : reset_work_page_li, - get_work_li_data : work_page_li_data, - state : UL_STATE.IDLE, - edited_item : undefined, - }, - [TYPE_PREFIX.BUNDLE] : { - ul : document.getElementById("bundles_ul"), - work_li : document.getElementById("work_bundle_li"), - work_name_input : document.getElementById("bundle_name_field"), - work_empty_component_li : - document.getElementById("empty_bundle_component_li"), - reset_work_li : generic_reset_work_li, - get_work_li_data : generic_work_li_data, - state : UL_STATE.IDLE, - edited_item : undefined, - }, - [TYPE_PREFIX.SCRIPT] : { - ul : document.getElementById("scripts_ul"), - work_li : document.getElementById("work_script_li"), - work_name_input : document.getElementById("script_name_field"), - reset_work_li : reset_work_script_li, - get_work_li_data : work_script_li_data, - state : UL_STATE.IDLE, - edited_item : undefined, - } -} - -async function main() -{ - storage = await get_storage(); - - for (let prefix of list_prefixes) { - for (let item of storage.get_all_names(prefix).sort()) { - add_li(prefix, item, true); - add_selectable(prefix, item); - } - } - - storage.add_change_listener(handle_change); - - let commit_components_but = - document.getElementById("commit_components_but"); - let cancel_components_but = - document.getElementById("cancel_components_but"); - commit_components_but.addEventListener("click", commit_components); - cancel_components_but.addEventListener("click", cancel_components); - - for (let prefix of list_prefixes) { - let add_but = document.getElementById(`add_${TYPE_NAME[prefix]}_but`); - let discard_but = - document.getElementById(`${TYPE_NAME[prefix]}_discard_but`); - let save_but = document.getElementById(`${TYPE_NAME[prefix]}_save_but`); - let select_components_but = document.getElementById( - `${TYPE_NAME[prefix]}_select_components_but` - ); - - add_but.addEventListener("click", () => add_new_item(prefix)); - discard_but.addEventListener("click", () => cancel_work(prefix)); - save_but.addEventListener("click", () => save_work(prefix)); - if (select_components_but === null) - continue; - - select_components_but.addEventListener( - "click", - () => select_components(prefix) - ); - } -} - -function handle_change(change) -{ - if (change.old_val === undefined) { - add_li(change.prefix, change.item); - add_selectable(change.prefix, change.item); - return; - } - - if (change.new_val !== undefined) - return; - - let ul = ul_by_prefix[change.prefix]; - if (ul.state === UL_STATE.EDITING_ENTRY && ul.edited_item === change.item) { - ul.state = UL_STATE.ADDING_ENTRY; - return; - } - - let li = document.getElementById(item_li_id(change.prefix, change.item)); - ul.ul.removeChild(li); - - if (change.prefix === TYPE_PREFIX.PAGE) - return; - - let sli = document.getElementById(selectable_li_id(change.prefix, - change.item)); - selectable_components_ul.removeChild(sli); -} - -main(); |