diff --git a/background.js b/background.js
new file mode 100644
index 0000000..ad5dc1c
--- /dev/null
+++ b/background.js
@@ -0,0 +1,10 @@
+chrome.runtime.onInstalled.addListener(() => {
+ chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
+ chrome.declarativeContent.onPageChanged.addRules([{
+ conditions: [ new chrome.declarativeContent.PageStateMatcher({
+ pageUrl: { },
+ })
+ ], actions: [ new chrome.declarativeContent.ShowPageAction() ]
+ }]);
+ });
+});
\ No newline at end of file
diff --git a/fonts/fa-light-300.ttf b/fonts/fa-light-300.ttf
new file mode 100644
index 0000000..a433f45
Binary files /dev/null and b/fonts/fa-light-300.ttf differ
diff --git a/fonts/fa-regular-400.ttf b/fonts/fa-regular-400.ttf
new file mode 100644
index 0000000..b2599e0
Binary files /dev/null and b/fonts/fa-regular-400.ttf differ
diff --git a/fonts/fa-solid-900.ttf b/fonts/fa-solid-900.ttf
new file mode 100644
index 0000000..58c9a9f
Binary files /dev/null and b/fonts/fa-solid-900.ttf differ
diff --git a/fonts/font-awesome.css b/fonts/font-awesome.css
new file mode 100644
index 0000000..664cfe2
--- /dev/null
+++ b/fonts/font-awesome.css
@@ -0,0 +1,25 @@
+/****************/
+/* FONT AWESOME */
+/****************/
+
+@font-face {
+ font-family: 'Font Awesome';
+ src: url('fa-light-300.ttf') format('truetype');
+ font-weight: 300;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Font Awesome';
+ src: url('fa-regular-400.ttf') format('truetype');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Font Awesome';
+ src: url('fa-solid-900.ttf') format('truetype');
+ font-weight: 900;
+ font-style: normal;
+}
+
diff --git a/manifest.json b/manifest.json
index d0d9119..235be9a 100644
--- a/manifest.json
+++ b/manifest.json
@@ -4,16 +4,22 @@
"version": "0.3",
"description": "Get rid of sticky elements on websites - permanently!",
"author": "Said Achmiz",
- "homepage_url": "https://wiki.obormot.net/Main/AlwaysKillSticky",
- "permissions": [ "activeTab", "storage" ],
+ "homepage_url": "https://git.sr.ht/~achmizs/AlwaysKillSticky.git",
+ "permissions": [ "declarativeContent", "activeTab", "storage" ],
+ "background": {
+ "scripts": ["background.js"],
+ "persistent": false
+ },
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_end",
- "js": [ "contentScript.js" ]
+ "js": [ "functions.js", "contentScript.js" ]
}
],
"page_action": {
+ "default_popup": "popup.html",
+ "default_title": "AlwaysKillSticky - Click the icon to control sticky-killing on this site!",
"default_icon": {
"16": "images/ASK16.png",
"32": "images/ASK32.png",
diff --git a/options.css b/options.css
new file mode 100644
index 0000000..010e7c6
--- /dev/null
+++ b/options.css
@@ -0,0 +1,173 @@
+html {
+ box-sizing: border-box;
+ font-size: 16px;
+}
+*, *::before, *::after {
+ box-sizing: inherit;
+}
+body {
+ margin: 0 auto;
+ display: flex;
+ flex-flow: column;
+ max-width: 640px;
+ min-height: 100vh;
+ padding: 10px;
+ font-size: 1rem;
+}
+body > div {
+ border: 1px solid #ddd;
+ padding: 30px 15px 15px 15px;
+ position: relative;
+}
+body > div + div {
+ margin: 2.5em 0 0 0;
+}
+h1 {
+ border-bottom: 1px solid #ddd;
+ margin: 0.5em 0;
+}
+h2 {
+ margin: 0;
+ background-color: #fff;
+ padding: 10px 15px;
+ position: absolute;
+ top: calc(-1 * (0.625em + 10px));
+ left: 10px;
+ border: inherit;
+}
+textarea {
+ border: 1px solid #aaa;
+ font-family: Inconsolata, Courier, monospace;
+ font-size: 1.125rem;
+ width: 100%;
+ display: block;
+}
+#matchingPatterns textarea {
+ min-height: 300px;
+}
+#exclusionPatterns textarea {
+ min-height: 150px;
+}
+form {
+ text-align: right;
+ margin: 0 0 2.5em 0;
+ display: flex;
+ align-items: center;
+}
+form .buttons {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ flex: 1 1 0;
+}
+button {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ border: 1px solid #bbb;
+ color: #fff;
+ padding: 10px 16px;
+ cursor: default;
+ margin: 0 0 0 0.5em;
+}
+button.save-button {
+ background-color: #16e;
+ font-size: 1.5rem;
+}
+button.reset-button {
+ background-color: #d3453d;
+ font-size: 1rem;
+}
+button:active {
+ transform: scale(0.95);
+}
+button:focus:active {
+ outline: none;
+}
+button:disabled {
+ background-color: #777;
+ opacity: 0.3;
+}
+input#whitelist-mode {
+ display: block;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ border: 1px solid #000;
+ font-size: 1rem;
+ height: 2em;
+ width: 4em;
+ margin: 0 6px;
+ background-color: #000;
+ box-shadow:
+ -2em 0 0 1px #fff inset,
+ 0 0 0 3px #fff inset;
+}
+input#whitelist-mode:checked {
+ border: 1px solid #fff;
+ background-color: #fff;
+ box-shadow:
+ 2em 0 0 1px #000 inset,
+ 0 0 0 3px #000 inset;
+}
+input#whitelist-mode,
+.mode-select-container span {
+ cursor: pointer;
+}
+.mode-select-container {
+ white-space: nowrap;
+ display: flex;
+ align-items: center;
+ align-self: flex-start;
+ border: 1px solid #ddd;
+ padding: 8px 10px;
+ cursor: default;
+ background-color: #fff;
+}
+.mode-select-container.whitelist {
+ background-color: #000;
+ color: #fff;
+}
+.mode-select-container:not(.whitelist) .blacklist-mode-label,
+.mode-select-container.whitelist .whitelist-mode-label {
+ border-bottom: 1px dotted currentColor;
+}
+.mode-select-container span::selection {
+ background-color: transparent;
+}
+.mode-select-container span.disabled {
+ pointer-events: none;
+}
+.mode-select-container span:not(.disabled):hover {
+ border-bottom: 1px solid currentColor;
+}
+form button:not(:disabled):hover {
+ text-shadow:
+ 0 0 1px #fff,
+ 0 0 3px #fff,
+ 0 0 5px #fff;
+ cursor: pointer;
+}
+#matchingPatterns.disabled h2 {
+ color: rgba(0,0,0,0.15);
+}
+#matchingPatterns.disabled p {
+ opacity: 0.2;
+}
+#matchingPatterns.disabled .textarea-container {
+ position: relative;
+}
+#matchingPatterns.disabled .textarea-container::before {
+ content: ".*";
+ display: flex;
+ position: absolute;
+ background-color: rgba(232,232,232,0.9);
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+ justify-content: center;
+ align-items: center;
+ font-family: Inconsolata, Courier, monospace;
+ font-size: 4em;
+}
+body > p {
+ padding: 0 15px;
+}
diff --git a/options.html b/options.html
index f22dfac..94ab02b 100644
--- a/options.html
+++ b/options.html
@@ -3,181 +3,7 @@
Always Kill Sticky - Options
-
+
Always Kill Sticky
diff --git a/popup.css b/popup.css
new file mode 100644
index 0000000..b1f6796
--- /dev/null
+++ b/popup.css
@@ -0,0 +1,93 @@
+html {
+ font-size: 16px;
+ box-sizing: border-box;
+}
+*, *::before, *::after {
+ box-sizing: inherit;
+}
+body {
+ margin: 0;
+ padding: 0;
+}
+button {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background-color: #fff;
+ border: none;
+ cursor: pointer;
+}
+button:active {
+ transform: scale(0.95);
+}
+button:focus {
+ outline: none;
+}
+button::selection {
+ background-color: transparent;
+}
+#main-button-container {
+ display: flex;
+ flex-flow: column;
+}
+#main-button-container button {
+ padding: 10px;
+ font-size: 6rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 150px;
+ width: 150px;
+ color: #ccc;
+ font-family: Font Awesome, sans-serif;
+}
+#main-button-container button.active {
+ color: #000;
+}
+#main-button-container button:hover {
+ text-shadow:
+ 0 0 1px #fff,
+ 0 0 3px #fff,
+ 0 0 5px #fff;
+}
+#main-button-container button:hover {
+ color: #999;
+}
+#main-button-container button::before {
+ content: "\F08D";
+ font-weight: 900;
+ position: relative;
+ top: 3px;
+}
+#main-button-container button::after {
+ content: "\F05E";
+ position: absolute;
+ font-weight: 300;
+ color: #c00;
+ opacity: 0.0;
+ transform: scaleX(-1) scale(1.5);
+}
+#main-button-container button.active::after {
+ opacity: 1.0;
+}
+#aux-button-container {
+ display: flex;
+ border-top: 1px solid #ddd;
+}
+.options-button {
+ font-size: 1.125rem;
+ padding: 10px;
+ color: #777;
+ width: 100%;
+}
+.options-button:hover {
+ color: #000;
+}
+.options-button::before {
+ content: "\F1DE";
+ font-family: Font Awesome;
+ font-size: 0.875em;
+ margin: 0 5px 0 0;
+}
+.options-button::after {
+ content: "Options";
+}
diff --git a/popup.html b/popup.html
new file mode 100644
index 0000000..e00c9d1
--- /dev/null
+++ b/popup.html
@@ -0,0 +1,17 @@
+
+
+ AlwaysKillSticky
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/popup.js b/popup.js
new file mode 100644
index 0000000..3e54e81
--- /dev/null
+++ b/popup.js
@@ -0,0 +1,147 @@
+/*******************/
+/* EVENT LISTENERS */
+/*******************/
+
+
+/***********/
+/* HELPERS */
+/***********/
+
+/* Toggle the current state, as represented in the ASK object. (Nothing actually
+ happens until the UI state is updated, killSticky() is called (if needed),
+ and the new settings are saved in storage.)
+
+ What “toggle the current state” actually means depends on the current mode.
+
+ [1] In blacklist mode, toggleState() does one of the following:
+
+ (a) (if stickies are not being killed on the current page) adds a matching
+ pattern (if one is not already there), and removes all applicable
+ exclusion patterns; or,
+ (b) (if stickies are being killed on the current page) removes all
+ applicable matching patterns.
+
+ [2] In whitelist mode, toggleState() does one of the following:
+
+ (a) (if stickies are not being killed on the current page) removes all
+ applicable exclusion patterns; or,
+ (b) (if stickies are being killed on the current page) adds an exclusion
+ pattern.
+ */
+function toggleState() {
+ if (ASK.mode == "blacklist") {
+ if (!ASK.pageMatched || ASK.pageExcluded) {
+ /* In this case, stickies are NOT being killed. We must add a matching
+ pattern, and remove all applicable exclusion patterns. */
+ if (!ASK.pageMatched) {
+ ASK.matchingPatterns.push(regExpForCurrentTab());
+ }
+ if (ASK.pageExcluded) {
+ ASK.exclusionPatterns = ASK.exclusionPatterns.filter(pattern =>
+ !ASK.activeTabLocation.match(new RegExp(pattern))
+ );
+ }
+ } else {
+ /* In this case, stickies ARE being killed. We must remove all
+ applicable matching patterns. */
+ ASK.matchingPatterns = ASK.matchingPatterns.filter(pattern =>
+ !ASK.activeTabLocation.match(new RegExp(pattern))
+ );
+ }
+ } else { // if whitelist mode
+ // TODO: code this!
+ }
+ recalculatePatternEffects();
+}
+
+function regExpForCurrentTab() {
+ let a = document.createElement("A");
+ a.href = ASK.activeTabLocation;
+ return ".*" + a.host.replace(/\./g, "\\.") + ".*";
+}
+
+function recalculatePatternEffects() {
+ ASK.pageMatched = false;
+ ASK.pageExcluded = false;
+ for (let pattern of ASK.matchingPatterns) {
+ if (ASK.activeTabLocation.match(new RegExp(pattern))) {
+ ASK.pageMatched = true;
+ break;
+ }
+ }
+ for (let pattern of ASK.exclusionPatterns) {
+ if (ASK.activeTabLocation.match(new RegExp(pattern))) {
+ ASK.pageExcluded = true;
+ break;
+ }
+ }
+}
+
+function updateState(result) {
+ ASK.mode = result.mode || "blacklist";
+ ASK.matchingPatterns = (ASK.mode == "whitelist") ?
+ [ ".*" ] :
+ result.matchingPatterns.split("\n");
+ ASK.exclusionPatterns = (typeof result.exclusionPatterns != "undefined" &&
+ result.exclusionPatterns != "") ?
+ result.exclusionPatterns.split("\n") :
+ [ ];
+ recalculatePatternEffects();
+}
+
+function updateUIState() {
+ let button = document.querySelector("#main-button-container button");
+ if (ASK.mode == "blacklist" && ASK.pageMatched && !ASK.pageExcluded) {
+ button.classList.toggle("active", true);
+// button.innerHTML = "X";
+ } else if (ASK.mode == "blacklist" && (!ASK.pageMatched || ASK.pageExcluded)) {
+ button.classList.toggle("active", false);
+// button.innerHTML = "O";
+ } else if (ASK.mode == "whitelist" && !ASK.pageExcluded) {
+ button.classList.toggle("active", false);
+// button.innerHTML = "X";
+ } else if (ASK.mode == "whitelist" && ASK.pageExcluded) {
+ button.classList.toggle("active", true);
+// button.innerHTML = "O";
+ }
+}
+
+/******************/
+/* INITIALIZATION */
+/******************/
+
+function initialize() {
+ window.ASK = { };
+
+ chrome.tabs.query({currentWindow: true, active: true}, (tabs) => {
+ ASK.activeTabLocation = tabs[0].url;
+ chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode" ], (result) => {
+ updateState(result);
+ updateUIState();
+ });
+ });
+
+ document.querySelector("#main-button-container button").addActivateEvent((event) => {
+ toggleState();
+
+ let matchingPatterns = ASK.matchingPatterns.join("\n");
+ let exclusionPatterns = ASK.exclusionPatterns.join("\n");
+ let mode = ASK.mode;
+ chrome.storage.sync.set({
+ "matchingPatterns": matchingPatterns,
+ "exclusionPatterns": exclusionPatterns,
+ "mode": mode
+ }, () => {
+ updateUIState();
+ if (ASK.pageMatched && !ASK.pageExcluded)
+ chrome.tabs.executeScript(null, { code: 'killSticky()' });
+ });
+ });
+
+
+ document.querySelector("#aux-button-container button").addActivateEvent((event) => {
+ chrome.runtime.openOptionsPage(null);
+ });
+}
+
+initialize();
\ No newline at end of file