aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2021-09-01 11:45:06 +0200
committerWojtek Kosior <koszko@koszko.org>2021-09-01 11:45:06 +0200
commit453ba03962ececcdff9264bea606b7bc488c1803 (patch)
tree169d81bb94e2c2849d1756c65ad3a528a9d944db
parent544c6df3ab1e331c6b6779b76ad33180a06b0b4d (diff)
downloadbrowser-extension-453ba03962ececcdff9264bea606b7bc488c1803.tar.gz
browser-extension-453ba03962ececcdff9264bea606b7bc488c1803.zip
add styling for popup page\n\nThis does not include styling for contents of the import dialog
-rw-r--r--copyright4
-rw-r--r--html/DOM_helpers.js2
-rw-r--r--html/back_button.css50
-rw-r--r--html/base.css22
-rw-r--r--html/display-panel.html365
-rw-r--r--html/display-panel.js174
-rw-r--r--html/import_frame.html1
-rw-r--r--html/options.html95
-rw-r--r--html/options_main.js8
-rw-r--r--html/table.css46
10 files changed, 532 insertions, 235 deletions
diff --git a/copyright b/copyright
index 75be239..58993a6 100644
--- a/copyright
+++ b/copyright
@@ -31,6 +31,10 @@ Files: *.html README.txt copyright
Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
License: GPL-3+ or Alicense-1.0 or CC-BY-SA-4.0
+Files: html/*.css
+Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
+License: GPL-3+ or Alicense-1.0 or CC-BY-SA-4.0
+
Files: html/base.css
Copyright: 2021 Wojtek Kosior <koszko@koszko.org>
2021 Nicholas Johnson <nicholasjohnson@posteo.org>
diff --git a/html/DOM_helpers.js b/html/DOM_helpers.js
index 392299f..01e2be9 100644
--- a/html/DOM_helpers.js
+++ b/html/DOM_helpers.js
@@ -42,7 +42,7 @@ function clone_template(template_id)
result_object[template_key] = element;
element.removeAttribute("id");
- element.removeAttribute("template_key");
+ element.removeAttribute("data-template");
for (const child of element.children)
to_process.push(child);
diff --git a/html/back_button.css b/html/back_button.css
new file mode 100644
index 0000000..1ddc5da
--- /dev/null
+++ b/html/back_button.css
@@ -0,0 +1,50 @@
+/**
+ * part of Hachette
+ * Style for a "back" button with a CSS arrow image.
+ *
+ * Copyright (C) 2021 Wojtek Kosior
+ * Redistribution terms are gathered in the `copyright' file.
+ */
+
+.back_button {
+ display: block;
+ width: auto;
+ height: auto;
+ background-color: white;
+ border: solid #454 0.4em;
+ border-left: none;
+ border-radius: 0 1.5em 1.5em 0;
+ cursor: pointer;
+}
+
+.back_button:hover {
+ box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19);
+}
+
+.back_button>div, .back_arrow {
+ width: 2em;
+ height: 0.5em;
+ background-color: #4CAF50;
+ border-radius: 0.3em;
+ margin: 1.15em 0.4em;
+}
+
+.back_button>div::after, .back_arrow::after,
+.back_button>div::before, .back_arrow::before {
+ content: "";
+ display: block;
+ position: relative;
+ background-color: inherit;
+ width: 1.3em;
+ height: 0.5em;
+ transform: rotate(45deg);
+ border-radius: 0.3em;
+ top: 0.3em;
+ right: 0.2em;
+ margin: 0 -1.3em -0.5em 0;
+}
+
+.back_button>div::before, .back_arrow::before {
+ transform: rotate(-45deg);
+ top: -0.3em;
+}
diff --git a/html/base.css b/html/base.css
index 91fd953..0b9c7d3 100644
--- a/html/base.css
+++ b/html/base.css
@@ -6,8 +6,11 @@
* Redistribution terms are gathered in the `copyright' file.
*/
-html {
+body {
font-family: sans-serif;
+ background-color: #f0f0f0;
+ color: #555;
+ overflow: auto;
}
textarea {
@@ -18,6 +21,10 @@ input[type="checkbox"], input[type="radio"], .hide {
display: none;
}
+.camouflage {
+ visibility: hidden;
+}
+
.show_next:not(:checked)+* {
display: none;
}
@@ -42,6 +49,8 @@ button, .button {
margin: 2px 0px;
-moz-user-select: none;
user-select: none;
+ cursor: pointer;
+ font: 400 15px sans-serif;
}
button.slimbutton, .button.slimbutton {
@@ -64,3 +73,14 @@ aside {
textarea: {
resize: none;
}
+
+.has_bottom_line::after, .has_upper_line::before {
+ content: "";
+ display: block;
+ height: 8px;
+ background: linear-gradient(transparent, #555);
+}
+
+.has_bottom_line::after {
+ background: linear-gradient(#555, transparent);
+}
diff --git a/html/display-panel.html b/html/display-panel.html
index cbd7dc8..4121c30 100644
--- a/html/display-panel.html
+++ b/html/display-panel.html
@@ -9,117 +9,336 @@
<title>Hachette - page settings</title>
<link type="text/css" rel="stylesheet" href="reset.css" />
<link type="text/css" rel="stylesheet" href="base.css" />
+ <link type="text/css" rel="stylesheet" href="back_button.css" />
+ <link type="text/css" rel="stylesheet" href="table.css" />
<style>
body {
- width: 300px;
- height: 300px;
+ width: max-content;
+ width: -moz-max-content;
}
- ul {
- padding-inline-start: 15px;
+ .bold, h2 {
+ font-weight: bold;
}
- .bold {
- font-weight: bold;
+ h2 {
+ margin: 8px;
+ font-size: 120%;
+ }
+
+ .top>h2 {
+ padding-left: calc(0.8*3.2em - 8px);
+ }
+
+ .top {
+ line-height: calc(0.8*3.6em - 16px);
}
- .unroll_chbx:not(:checked)+*+label span.triangle:first-child+span.triangle,
- .unroll_chbx:checked+*+label span.triangle:first-child,
- .unroll_chbx:not(:checked)+*,
- .unroll_chbx:not(:checked)+*+label+* {
+ #main_view>.top>h2 {
+ padding-left: 0;
+ }
+
+ h3 {
+ padding: 5px;
+ font-size: 108%;
+ text-shadow: 0 0 0 #454;
+ }
+
+ .unroll_chbx:not(:checked)+div>:not(:first-child) {
display: none;
}
+ .unroll_triangle {
+ height: 1em;
+ width: 1em;
+ display: inline-block;
+ }
+
+ .unroll_triangle::after {
+ content: "";
+ width: 0.6em;
+ height: 0.6em;
+ background: linear-gradient(-45deg, currentColor 50%, transparent 50%);
+ display: block;
+ position: relative;
+ transform: rotate(-45deg);
+ top: 0.3em;
+ }
+
+ .unroll_chbx:checked+div>:first-child .unroll_triangle::after {
+ transform: rotate(45deg);
+ left: 0.2em;
+ top: 0.2em;
+ }
+
+ .unroll_chbx:checked+div>:first-child .unroll_block {
+ display: block;
+ }
+
+ .unroll_chbx:checked+div>:first-child {
+ line-height: 1.4em;
+ }
+
+ .l2_ul {
+ border-left: solid #454 5px;
+ }
+
+ .l1_li {
+ margin-top: 0.3em;
+ margin-bottom: 0.3em;
+ }
+
+ .l1_li>div {
+ padding: 0.3em 0.3em 0.3em 0;
+ }
+
+ .l2_li {
+ padding: 0.3em;
+ }
+
+ #container_for_injected>*:nth-child(odd),
+ .l2_li:nth-child(odd) {
+ background-color: #e5e5e5;
+ }
+
#container_for_injected>#none_injected:not(:last-child) {
display: none;
}
+
+ #page_url_heading>span {
+ display: inline-block;
+ }
+
+ .back_button {
+ position: fixed;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ /* The following scales the entire button. */
+ font-size: 80%;
+ }
+
+ #show_main_view_radio:checked~.back_button {
+ margin-left: -3.2em;
+ }
+
+ #show_main_view_radio:not(:checked)~.back_button {
+ transition: all 0.2s ease-out;
+ }
+
+ pre {
+ font-family: monospace;
+ background-color: white;
+ border-top: dashed #4CAF50 1px;
+ border-bottom: dashed #4CAF50 1px;
+ padding: 1px 5px;
+ }
+
+ .matched_pattern {
+ font-weight: bold;
+ }
+
+ tr.matched_pattern~tr {
+ color: #777;
+ font-size: 90%;
+ }
+
+ .padding_inline {
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ .header {
+ border-bottom: dashed #4CAF50 1px;
+ padding-bottom: 0.3em;
+ margin-bottom: 0.5em;
+ text-align: center;
+ }
+
+ .middle {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+
+ .footer {
+ border-top: dashed #4CAF50 1px;
+ padding-top: 0.3em;
+ margin-top: 0.5em;
+ text-align: center;
+ }
+
+ .active_setting_table {
+ margin-bottom: 0.5em;
+ }
+
+ .active_setting_table td {
+ padding: 5px;
+ vertical-align: middle;
+ }
</style>
</head>
<body>
<template>
- <li id="pattern_li">
- <span></span>
- <button>View in settings</button>
- </li>
- <li id="query_match_li" class="queried_pattern_match" data-template="li">
+ <tr id="pattern_entry" data-template="entry">
+ <td data-template="name"></td>
+ <td>
+ <div class="button" data-template="button">Add setting</div>
+ </td>
+ </tr>
+
+ <li id="query_match_li" class="l2_li" data-template="li">
<div>
<span>pattern:</span>
<span class="bold" data-template="pattern"></span>
- <button data-template="btn">Install</button>
+ <label class="button slimbutton" for="show_install_view_radio" data-template="btn">
+ Install
+ </label>
</div>
<div id="unrollable_component" data-template="unroll_container">
- <span data-template="component_label">payload:</span>
<input type="checkbox" class="unroll_chbx" data-template="chbx"></input>
- <br data-template="br"/>
- <label class="bold" data-template="lbl">
- <span data-template="triangle">
- <span class="triangle">&#x23F5;</span>
- <span class="triangle">&#x23F7;</span>
+ <div>
+ <span>payload:
+ <label class="bold unroll_block" data-template="lbl">
+ <div data-template="triangle" class="unroll_triangle"></div>
+ <span data-template="payload"></span>
+ </label>
</span>
- <span data-template="component"></span>
+ <div data-template="unroll"></div>
+ </div>
+ </div>
+ </li>
+
+ <div id="injected_script" data-template="div">
+ <input type="checkbox" class="unroll_chbx" data-template="chbx"></input>
+ <div>
+ <label data-template="lbl">
+ <h3><div class="unroll_triangle"></div> script</h3>
</label>
- <div data-template="unroll"></div>
+ <pre data-template="script_contents"></pre>
+ </div>
+ </div>
+
+ <div id="multi_repos_query_result" data-template="div">
+ Results for <span class="bold" data-template="url_span"></span>
+ <ul class="l1_ul" data-template="ul"></ul>
+ </div>
+
+ <li id="single_repo_query_result" class="l1_li" data-template="li">
+ <div>
+ From <span class="bold" data-template="repo_url"></span>
</div>
</li>
+
+ <ul id="result_patterns_list" class="l2_ul" data-template="ul">
+ </ul>
</template>
- <input id="show_install_view_chbx" type="checkbox" class="show_hide_next2"></input>
+ <input id="show_install_view_radio" type="radio" class="show_next" name="current_view"></input>
<div id="install_view">
+ <div class="top has_bottom_line"><h2> Site modifiers install </h2></div>
<IMPORT html/import_frame.html />
- <!--
- <div id="install_status"></div>
- <label for="show_install_chbx" class="bold">Cancel install</label>
- <button id="commit_install_but">Commit install</button>
- -->
</div>
- <div id="main_view">
- <h2 id="page_url_heading"></h2>
-
- <input id="show_privileged_notice_chbx" type="checkbox" class="show_next"></input>
- <h3>Privileged page</h3>
-
- <input id="show_page_state_chbx" type="checkbox" class="show_next"></input>
- <div>
- <input id="possible_patterns_chbx" type="checkbox" class="unroll_chbx"></input>
- <span></span>
- <label for="possible_patterns_chbx">
- <h3>
- <span class="triangle">&#x23F5;</span>
- <span class="triangle">&#x23F7;</span>
- Possible patterns
- </h3>
- </label>
- <ul id="possible_patterns"></ul>
-
- <input id="connected_chbx" type="checkbox" class="show_hide_next2"></input>
+
+ <input id="show_injected_view_radio" type="radio" class="show_next" name="current_view"></input>
+ <div id="injected_view">
+ <div class="top has_bottom_line"><h2>Injected scripts</h2></div>
+ <div id="container_for_injected">
+ <span id="none_injected">None</span>
+ </div>
+ </div>
+
+ <input id="show_patterns_view_radio" type="radio" class="show_next" name="current_view"></input>
+ <div>
+ <div class="top has_bottom_line"><h2>Possible patterns for this page</h2></div>
+ <div class="padding_inline">
+ <aside>
+ Patterns higher are more specific and override the ones below.
+ </aside>
+ </div>
+ <div class="table_wrapper">
<div>
- Matched pattern: <span id="pattern" class="bold">...</span>
- <button id="view_pattern" class="hide">
- View in settings
- </button>
- <br/>
- Blocked: <span id="blocked" class="bold">...</span>
- <br/>
- Payload: <span id="payload" class="bold">...</span>
- <button id="view_payload" class="hide">
- View in settings
- </button>
- <h3>Injected</h3>
- <div id="container_for_injected">
- <span id="none_injected">None</span>
+ <table>
+ <tbody id="possible_patterns">
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+
+ <input id="show_queried_view_radio" type="radio" class="show_next" name="current_view"></input>
+ <div>
+ <div class="top has_bottom_line"><h2>Queried from repositories</h2></div>
+ <div id="container_for_repo_responses" class="padding_inline">
+ </div>
+ </div>
+
+ <input id="show_main_view_radio" type="radio" class="show_next" name="current_view" checked></input>
+ <div id="main_view">
+ <div class="top has_bottom_line"><h2 id="page_url_heading"></h2></div>
+ <h3 id="privileged_notice" class="middle hide">Privileged page</h3>
+
+ <div id="page_state" class="hide">
+ <div class="header padding_inline">
+ <label for="show_patterns_view_radio" class="button">
+ Edit settings for this page
+ </label>
+ </div>
+ <div class="middle padding_inline">
+ <input id="connected_chbx" type="checkbox" class="show_hide_next2"></input>
+ <div>
+ <table class="active_setting_table">
+ <tbody>
+ <tr>
+ <td>Matched pattern:</td>
+ <td id="pattern" class="bold">...</td>
+ <td>
+ <button id="view_pattern" class="hide">
+ View in settings
+ </button>
+ </td>
+ </tr>
+ <tr>
+ <td>Scripts blocked:</td>
+ <td id="blocked" class="bold">...</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Injected payload:</td>
+ <td id="payload" class="bold">...</td>
+ <td id="payload_buttons" class="hide">
+ <button id="view_payload"> View in settings </button>
+ <br/>
+ <label id="view_injected" class="button" for="show_injected_view_radio">
+ View injected scripts
+ </label>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <label id="query_pattern" for="show_queried_view_radio" class="button">
+ Install scripts for this page
+ </label>
</div>
- <input id="query_started_chbx" type="checkbox" class="show_hide_next2"></input>
- <div id="container_for_repo_responses">
- <h3>Queried from repositories</h3>
+ <div>
+ <h3>
+ Connecting to content script..<span id="loading_point">.</span>
+ </h3>
+ <aside id="reload_notice">
+ Try reloading the page.
+ </aside>
</div>
- <button id="query_pattern">
- Search for matching patterns
- </button>
</div>
- <h3>Trying to connect..<input id="loading_chbx" type="checkbox" class="show_next"></input><span>.</span></h3>
</div>
- <button id="settings_but" type="button" style="margin-top: 20px;">Settings</button>
- </div>_POPUPSCRIPTS_
+ <div class="footer padding_inline">
+ <button id="settings_but" type="button">
+ Open Hachette settings
+ </button>
+ </div>
+ </div>
+
+ <div class="has_upper_line"></div>
+
+ <label for="show_main_view_radio" class="back_button"><div></div></label>_POPUPSCRIPTS_
</body>
</html>
diff --git a/html/display-panel.js b/html/display-panel.js
index 54b5578..0c89864 100644
--- a/html/display-panel.js
+++ b/html/display-panel.js
@@ -20,6 +20,7 @@
* IMPORT TYPE_PREFIX
* IMPORT nice_name
* IMPORT open_in_settings
+ * IMPORT url_matches
* IMPORT each_url_pattern
* IMPORT by_id
* IMPORT get_template
@@ -30,6 +31,16 @@
let storage;
let tab_url;
+/* Force popup <html>'s reflow on stupid Firefox. */
+if (is_mozilla) {
+ const reflow_forcer =
+ () => document.documentElement.style.width = "-moz-fit-content";
+ for (const radio of document.querySelectorAll('[name="current_view"]'))
+ radio.addEventListener("change", reflow_forcer);
+}
+
+const show_queried_view_radio = by_id("show_queried_view_radio");
+
const tab_query = {currentWindow: true, active: true};
async function get_current_tab()
@@ -48,8 +59,21 @@ async function get_current_tab()
}
const page_url_heading = by_id("page_url_heading");
-const show_privileged_notice_chbx = by_id("show_privileged_notice_chbx");
-const show_page_state_chbx = by_id("show_page_state_chbx");
+const privileged_notice = by_id("privileged_notice");
+const page_state = by_id("page_state");
+
+/* Helper functions to convert string into a list of one-letter <span>'s. */
+function char_to_span(char, doc)
+{
+ const span = document.createElement("span");
+ span.textContent = char;
+ return span;
+}
+
+function to_spans(string, doc=document)
+{
+ return string.split("").map(c => char_to_span(c, doc));
+}
async function show_page_activity_info()
{
@@ -61,69 +85,65 @@ async function show_page_activity_info()
}
tab_url = /^([^?#]*)/.exec(tab.url)[1];
- page_url_heading.textContent = tab_url;
+ to_spans(tab_url).forEach(s => page_url_heading.append(s));
if (is_privileged_url(tab_url)) {
- show_privileged_notice_chbx.checked = true;
+ privileged_notice.classList.remove("hide");
return;
}
populate_possible_patterns_list(tab_url);
- show_page_state_chbx.checked = true;
+ page_state.classList.remove("hide");
try_to_connect(tab.id);
}
-const possible_patterns_ul = by_id("possible_patterns");
-const pattern_li_template = get_template("pattern_li");
-pattern_li_template.removeAttribute("id");
+const possible_patterns_list = by_id("possible_patterns");
const known_patterns = new Map();
function add_pattern_to_list(pattern)
{
- const li = pattern_li_template.cloneNode(true);
- li.id = `pattern_li_${known_patterns.size}`;
- known_patterns.set(pattern, li.id);
+ const template = clone_template("pattern_entry");
+ template.name.textContent = pattern;
- const span = li.firstElementChild;
- span.textContent = pattern;
-
- const button = span.nextElementSibling;
const settings_opener = () => open_in_settings(TYPE_PREFIX.PAGE, pattern);
- button.addEventListener("click", settings_opener);
+ template.button.addEventListener("click", settings_opener);
- possible_patterns_ul.appendChild(li)
+ known_patterns.set(pattern, template);
+ possible_patterns_list.append(template.entry);
- return li.id;
+ return template;
}
function ensure_pattern_exists(pattern)
{
- let id = known_patterns.get(pattern);
+ let entry_object = known_patterns.get(pattern);
/*
* As long as pattern computation works well, we should never get into this
* conditional block. This is just a safety measure. To be removed as part
* of a bigger rework when we start taking iframes into account.
*/
- if (id === undefined) {
+ if (entry_object === undefined) {
console.log(`unknown pattern: ${pattern}`);
- id = add_pattern_to_list(pattern);
+ entry_object = add_pattern_to_list(pattern);
}
- return id;
+ return entry_object;
}
-function set_pattern_li_button_text(li_id, text)
+function style_possible_pattern_entry(pattern, exists_in_settings)
{
- by_id(li_id).firstElementChild.nextElementSibling.textContent = text;
+ const [text, class_action] = exists_in_settings ?
+ ["Edit", "add"] : ["Add", "remove"];
+ const entry_object = ensure_pattern_exists(pattern);
+
+ entry_object.button.textContent = `${text} setting`;
+ entry_object.entry.classList[class_action]("matched_pattern");
}
function handle_page_change(change)
{
- const li_id = ensure_pattern_exists(change.item);
- if (change.old_val === undefined)
- set_pattern_li_button_text(li_id, "Edit in settings");
- if (change.new_val === undefined)
- set_pattern_li_button_text(li_id, "Add setting");
+ if (url_matches(tab_url, change.item))
+ style_possible_pattern_entry(change.item, change.new_val !== undefined);
}
function populate_possible_patterns_list(url)
@@ -131,10 +151,8 @@ function populate_possible_patterns_list(url)
for (const pattern of each_url_pattern(url))
add_pattern_to_list(pattern);
- for (const [pattern, settings] of query_all(storage, url)) {
- set_pattern_li_button_text(ensure_pattern_exists(pattern),
- "Edit in settings");
- }
+ for (const [pattern, settings] of query_all(storage, url))
+ style_possible_pattern_entry(pattern, true);
storage.add_change_listener(handle_page_change, [TYPE_PREFIX.PAGE]);
}
@@ -160,17 +178,16 @@ function try_to_connect(tab_id)
setTimeout(() => monitor_connecting(tab_id), 1000);
}
-const query_started_chbx = by_id("query_started_chbx");
-
-function start_querying_repos(port)
+function start_querying_repos()
{
+ query_pattern_but.removeEventListener("click", start_querying_repos);
const repo_urls = storage.get_all_names(TYPE_PREFIX.REPO);
if (content_script_port)
content_script_port.postMessage([TYPE_PREFIX.URL, tab_url, repo_urls]);
- query_started_chbx.checked = true;
}
-const loading_chbx = by_id("loading_chbx");
+const loading_point = by_id("loading_point");
+const reload_notice = by_id("reload_notice");
function handle_disconnect(tab_id, button_cb)
{
@@ -184,7 +201,9 @@ function handle_disconnect(tab_id, button_cb)
if (connected_chbx.checked)
return;
- loading_chbx.checked = !loading_chbx.checked;
+ loading_point.classList.toggle("camouflage");
+ reload_notice.classList.remove("hide");
+
setTimeout(() => try_to_connect(tab_id), 1000);
}
@@ -198,7 +217,8 @@ function monitor_connecting(tab_id)
else
return;
- loading_chbx.checked = !loading_chbx.checked;
+ loading_point.classList.toggle("camouflage");
+ reload_notice.classList.remove("hide");
try_to_connect(tab_id);
}
@@ -206,11 +226,15 @@ const pattern_span = by_id("pattern");
const view_pattern_but = by_id("view_pattern");
const blocked_span = by_id("blocked");
const payload_span = by_id("payload");
+const payload_buttons_div = by_id("payload_buttons");
const view_payload_but = by_id("view_payload");
+const view_injected_but = by_id("view_injected");
const container_for_injected = by_id("container_for_injected");
const queried_items = new Map();
+let max_injected_script_id = 0;
+
function handle_activity_report(message)
{
connected_chbx.checked = true;
@@ -236,25 +260,22 @@ function handle_activity_report(message)
const components = settings.components;
if (components) {
payload_span.textContent = nice_name(...components);
+ payload_buttons_div.classList.remove("hide");
const settings_opener = () => open_in_settings(...components);
- view_payload_but.classList.remove("hide");
view_payload_but.addEventListener("click", settings_opener);
} else {
payload_span.textContent = "none";
}
}
if (type === "script") {
- const h4 = document.createElement("h4");
- const pre = document.createElement("pre");
- h4.textContent = "script";
- pre.textContent = data;
-
- container_for_injected.appendChild(h4);
- container_for_injected.appendChild(pre);
+ const template = clone_template("injected_script");
+ const chbx_id = `injected_script_${max_injected_script_id++}`;
+ template.chbx.id = chbx_id;
+ template.lbl.setAttribute("for", chbx_id);
+ template.script_contents.textContent = data;
+ container_for_injected.appendChild(template.div);
}
if (type === "repo_query_action") {
- query_started_chbx.checked = true;
-
const key = data.prefix + data.item;
const results = queried_items.get(key) || {};
Object.assign(results, data.results);
@@ -274,35 +295,26 @@ const results_lists = new Map();
function create_results_list(url)
{
- const list_div = document.createElement("div");
- const list_head = document.createElement("h4");
- const list = document.createElement("ul");
+ const cloned_template = clone_template("multi_repos_query_result");
+ cloned_template.url_span.textContent = url;
+ container_for_repo_responses.appendChild(cloned_template.div);
- list_head.textContent = url;
- list_div.appendChild(list_head);
- list_div.appendChild(list);
- container_for_repo_responses.appendChild(list_div);
+ cloned_template.by_repo = new Map();
+ results_lists.set(url, cloned_template);
- const list_object = {list, by_repo: new Map()};
-
- results_lists.set(url, list_object);
-
- return list_object;
+ return cloned_template;
}
function create_result_item(list_object, repo_url, result)
{
- const result_li = document.createElement("li");
- const repo_url_span = document.createElement("span");
- const result_item = {result_li, appended: null};
-
- repo_url_span.textContent = repo_url;
- result_li.appendChild(repo_url_span);
+ const cloned_template = clone_template("single_repo_query_result");
+ cloned_template.repo_url.textContent = repo_url;
+ cloned_template.appended = null;
- list_object.list.appendChild(result_li);
- list_object.by_repo.set(repo_url, result_item);
+ list_object.ul.appendChild(cloned_template.li);
+ list_object.by_repo.set(repo_url, cloned_template);
- return result_item;
+ return cloned_template;
}
function set_appended(result_item, element)
@@ -310,7 +322,7 @@ function set_appended(result_item, element)
if (result_item.appended)
result_item.appended.remove();
result_item.appended = element;
- result_item.result_li.appendChild(element);
+ result_item.li.appendChild(element);
}
function show_message(result_item, text)
@@ -333,11 +345,9 @@ function unroll_chbx_first_checked(entry_object)
entry_object.chbx.removeEventListener("change", entry_object.unroll_cb);
delete entry_object.unroll_cb;
- entry_object.unroll.textContent = "preview not implemented...";
+ entry_object.unroll.innerHTML = "preview not implemented...<br />(consider contributing)";
}
-const show_install_chbx = by_id("show_install_view_chbx");
-
let import_frame;
let install_target = null;
@@ -463,7 +473,6 @@ function record_fetched_install_dep(prefix, item, repo_url, result)
function install_clicked(entry_object)
{
- show_install_chbx.checked = true;
import_frame.show_loading();
install_target = {
@@ -483,25 +492,24 @@ var max_query_result_id = 0;
function show_query_successful_result(result_item, repo_url, result)
{
- const ul = document.createElement("ul");
-
- set_appended(result_item, ul);
+ const cloned_ul_template = clone_template("result_patterns_list");
+ set_appended(result_item, cloned_ul_template.ul);
for (const match of result) {
const entry_object = clone_template("query_match_li");
entry_object.pattern.textContent = match.pattern;
- ul.appendChild(entry_object.li);
+ cloned_ul_template.ul.appendChild(entry_object.li);
if (!match.payload) {
entry_object.payload.textContent = "(none)";
- for (const key of ["chbx", "br", "triangle", "unroll"])
+ for (const key of ["chbx", "triangle", "unroll"])
entry_object[key].remove();
continue;
}
- entry_object.component.textContent = nice_name(...match.payload);
+ entry_object.payload.textContent = nice_name(...match.payload);
const install_cb = () => install_clicked(entry_object);
entry_object.btn.addEventListener("click", install_cb);
@@ -544,7 +552,7 @@ async function main()
{
storage = await get_remote_storage();
import_frame = await get_import_frame();
- import_frame.onclose = () => show_install_chbx.checked = false;
+ import_frame.onclose = () => show_queried_view_radio.checked = true;
show_page_activity_info();
}
diff --git a/html/import_frame.html b/html/import_frame.html
index 0511e6c..835977d 100644
--- a/html/import_frame.html
+++ b/html/import_frame.html
@@ -5,7 +5,6 @@
<span></span>
</li>
</template>
-<h2> Settings import </h2>
<input id="import_loading_radio" type="radio" name="import_window_content" class="show_next"></input>
<span> Loading... </span>
<input id="import_failed_radio" type="radio" name="import_window_content" class="show_next"></input>
diff --git a/html/options.html b/html/options.html
index e0c3c23..13a8973 100644
--- a/html/options.html
+++ b/html/options.html
@@ -9,11 +9,9 @@
<title>Hachette options</title>
<link type="text/css" rel="stylesheet" href="reset.css" />
<link type="text/css" rel="stylesheet" href="base.css" />
+ <link type="text/css" rel="stylesheet" href="table.css" />
<style>
body {
- background-color: #f0f0f0;
- color: #555;
- overflow: auto;
width: 100%;
}
@@ -37,6 +35,10 @@
font-size: 130%;
padding: 10px;
display: inline-block;
+ cursor: pointer;
+ }
+
+ #tab_heads {
-moz-user-select: none;
user-select: none;
}
@@ -49,13 +51,6 @@
border-radius: 0;
}
- #tab_heads::after {
- display: block;
- height: 8px;
- content: "";
- background: linear-gradient(#555, transparent);
- }
-
div.tab {
min-width: 50vw;
width: fit-content;
@@ -86,77 +81,36 @@
width: fit-content;
}
- div.ul_container {
- background-color: #f0f0f0;
- width: -moz-fit-content;
- width: fit-content;
- margin: 6px 0;
- }
-
- div.ul_container::after, div.ul_container::before {
- display: block;
- height: 6px;
- content: "";
- background: linear-gradient(transparent, #555);
- }
-
- div.ul_container::after {
- background: linear-gradient(#555, transparent);
- }
-
- .work_li div.ul_container::before {
+ .work_li .table_wrapper::before {
background: linear-gradient(#e0f0f0, #555);
}
- .work_li div.ul_container::after {
+ .work_li .table_wrapper::after {
background: linear-gradient(#555, #e0f0f0);
}
- div.ul_container>.always_scrollbar{
+ .table_wrapper>.always_scrollbar{
border-left: solid #454 8px;
max-height: 80vh;
overflow-y: scroll;
}
- div.ul_container table {
- border-collapse: unset;
- }
-
- div.ul_container, div.ul_container>*, div.ul_container table>tbody {
- width: -moz-min-content;
- width: min-content;
- }
-
- div.ul_container div.ul_container>.always_scrollbar,
- .popup_frame div.ul_container>.always_scrollbar {
+ .table_wrapper .table_wrapper>.always_scrollbar,
+ .popup_frame .table_wrapper>.always_scrollbar {
max-height: 60vh;
}
- .popup_frame div.ul_container table {
+ .popup_frame .table_wrapper table {
min-width: 30vw;
}
- .popup_frame div.ul_container {
+ .popup_frame .table_wrapper {
margin: 0 auto;
}
- tr:nth-child(odd) {
- background-color: #e5e5e5;
- }
-
- td {
- vertical-align: middle;
- min-width: fit-content;
- min-width: -moz-fit-content;
- width: 1%;
- }
-
tr>td:first-child {
- padding: 3px 10px 6px;
max-width: 70vw;
overflow: hidden;
- width: 100%;
- white-space: nowrap;
}
tr.work_li>td:first-child {
@@ -198,14 +152,6 @@
min-width: 70vw;
resize: none;
}
-
- td>div.button {
- margin-right: 4px;
- }
-
- input[type="radio"]:not(:checked)+.import_window_content {
- display: none;
- }
</style>
</head>
<body>
@@ -239,7 +185,7 @@
<input type="radio" name="tabs" id="show_pages" checked></input>
<input type="radio" name="tabs" id="show_bags"></input>
<input type="radio" name="tabs" id="show_scripts"></input>
- <div id="tab_heads">
+ <div id="tab_heads" class="has_bottom_line">
<label for="show_repos" id="repos_lbl"> Repos </label>
<label for="show_pages" id="pages_lbl"> Pages </label>
<label for="show_bags" id="bags_lbl"> Bags </label>
@@ -247,7 +193,7 @@
<button id="import_but" style="margin-left: 40px;"> Import </button>
</div>
<div id="repos" class="tab">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="repos_ul">
@@ -270,7 +216,7 @@
<button id="add_repo_but" type="button"> Add repository </button>
</div>
<div id="pages" class="tab">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="pages_ul">
@@ -304,7 +250,7 @@
<button id="add_page_but" type="button"> Add page </button>
</div>
<div id="bags" class="tab">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="bags_ul">
@@ -313,7 +259,7 @@
<div class="form_grid">
<label for="bag_name_field"> Name: </label>
<input id="bag_name_field"></input>
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="bag_components_ul">
@@ -341,7 +287,7 @@
<button id="add_bag_but" type="button"> Add bag </button>
</div>
<div id="scripts" class="tab">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="scripts_ul">
@@ -375,7 +321,7 @@
<div id="chbx_components_window" class="hide popup" position="absolute">
<div class="popup_frame">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div>
<table>
<tbody id="chbx_components_ul">
@@ -390,7 +336,7 @@
<div id="radio_components_window" class="hide popup" position="absolute">
<div class="popup_frame">
- <div class="ul_container">
+ <div class="table_wrapper tight_table has_bottom_line has_upper_line">
<div class="always_scrollbar">
<table>
<tbody id="radio_components_ul">
@@ -411,6 +357,7 @@
<div id="import_window" class="hide popup" position="absolute">
<div class="popup_frame">
+ <h2> Settings import </h2>
<IMPORT html/import_frame.html />
</div>
</div>
diff --git a/html/options_main.js b/html/options_main.js
index 8067fe7..03505a5 100644
--- a/html/options_main.js
+++ b/html/options_main.js
@@ -77,8 +77,12 @@ function add_li(prefix, item, at_the_end=false)
break;
}
}
- if (!li.parentElement)
- ul.ul.appendChild(li);
+ if (!li.parentElement) {
+ if (ul.work_li !== ul.ul.lastElementChild)
+ ul.ul.appendChild(li);
+ else
+ ul.work_li.before(li);
+ }
list_set_scrollbar(ul.ul);
}
diff --git a/html/table.css b/html/table.css
new file mode 100644
index 0000000..6296f83
--- /dev/null
+++ b/html/table.css
@@ -0,0 +1,46 @@
+.table_wrapper {
+ display: block;
+ background-color: #f0f0f0;
+ margin: 6px 0;
+}
+
+.table_wrapper table {
+ border-collapse: unset;
+ width: 100%;
+}
+
+.table_wrapper.tight_table,
+.table_wrapper.tight_table>*,
+.table_wrapper.tight_table>*>table {
+ width: -moz-min-content;
+ width: min-content;
+}
+
+tr:nth-child(odd) {
+ background-color: #e5e5e5;
+}
+
+td {
+ vertical-align: middle;
+ min-width: fit-content;
+ min-width: -moz-fit-content;
+}
+
+.tight_table td {
+ width: 1%;
+}
+
+td:first-child {
+ padding: 3px 10px 6px;
+ white-space: nowrap;
+}
+
+.tight_table td:first-child {
+ width: 100%;
+}
+
+td>div.button {
+ margin-right: 4px;
+ white-space: nowrap;
+ float: right;
+}