| @@ -51,17 +51,45 @@ function checkForShouldKillSticky(result) { | |||
| return shouldKillSticky; | |||
| } | |||
| /* Some websites add sticky elements after loading, or make existing elements | |||
| sticky (either on a timer, or based on user actions). CONSTANT VIGILANCE | |||
| counteracts this behavior, by watching the DOM for mutations, and, if | |||
| necessary, killing any newly-formed stickies. | |||
| */ | |||
| function startConstantVigilance() { | |||
| var observer = new MutationObserver((mutationsList, observer) => { | |||
| var shouldKillSticky = false; | |||
| for (var mutation of mutationsList) { | |||
| if (mutation.target.style.position == 'fixed' || | |||
| mutation.target.style.position == 'sticky') | |||
| shouldKillSticky = true; | |||
| } | |||
| if (shouldKillSticky) | |||
| requestAnimationFrame(() => { killSticky(); }); | |||
| }); | |||
| observer.observe(document.querySelector("body"), { | |||
| attributes: true, | |||
| childList: true, | |||
| subtree: true | |||
| }); | |||
| } | |||
| /******************/ | |||
| /* INITIALIZATION */ | |||
| /******************/ | |||
| function initialize() { | |||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode" ], | |||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode", "constantVigilance" ], | |||
| (result) => { | |||
| let shouldKillSticky = checkForShouldKillSticky(result); | |||
| updateIcon(shouldKillSticky); | |||
| let constantVigilance = (result.constantVigilance == "false") ? false : true; | |||
| window.onload = () => { | |||
| if (shouldKillSticky) killSticky(); | |||
| if (shouldKillSticky) { | |||
| killSticky(); | |||
| if (constantVigilance) startConstantVigilance(); | |||
| } | |||
| }; | |||
| }); | |||
| } | |||
| @@ -81,7 +81,7 @@ textarea { | |||
| display: flex; | |||
| flex-flow: row wrap; | |||
| align-items: center; | |||
| max-width: 640px; | |||
| max-width: 750px; | |||
| } | |||
| .top-controls .buttons { | |||
| display: flex; | |||
| @@ -121,6 +121,18 @@ button:focus:active { | |||
| background-color: #777; | |||
| opacity: 0.3; | |||
| } | |||
| .top-controls button:not(:disabled):hover { | |||
| text-shadow: | |||
| 0 0 1px #fff, | |||
| 0 0 3px #fff, | |||
| 0 0 5px #fff; | |||
| cursor: pointer; | |||
| } | |||
| /******************/ | |||
| /* MODE SELECTION */ | |||
| /******************/ | |||
| input#whitelist-mode { | |||
| display: block; | |||
| -webkit-appearance: none; | |||
| @@ -153,6 +165,7 @@ input#whitelist-mode, | |||
| align-self: flex-start; | |||
| border: 1px solid #ddd; | |||
| padding: 8px 10px; | |||
| margin | |||
| cursor: default; | |||
| background-color: #fff; | |||
| } | |||
| @@ -173,15 +186,59 @@ input#whitelist-mode, | |||
| .mode-select-container span:not(.disabled):hover { | |||
| border-bottom: 1px solid currentColor; | |||
| } | |||
| .top-controls button:not(:disabled):hover { | |||
| text-shadow: | |||
| 0 0 1px #fff, | |||
| 0 0 3px #fff, | |||
| 0 0 5px #fff; | |||
| /**********************/ | |||
| /* CONSTANT VIGILANCE */ | |||
| /**********************/ | |||
| .constant-vigilance-container { | |||
| border: 1px solid #ddd; | |||
| padding: 9px 13px 12px 11px; | |||
| display: flex; | |||
| align-items: center; | |||
| margin: 0 0 0 10px; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox'] { | |||
| -webkit-appearance: none; | |||
| -moz-appearance: none; | |||
| border: 1px solid #000; | |||
| width: 15px; | |||
| height: 15px; | |||
| position: relative; | |||
| top: 1px; | |||
| margin: 3px 5px 0 0; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox'], | |||
| .constant-vigilance-container label { | |||
| cursor: pointer; | |||
| } | |||
| p.note { | |||
| font-size: 0.875em; | |||
| .constant-vigilance-container label { | |||
| line-height: 1; | |||
| padding: 8px 0 0 0; | |||
| border-bottom: 1px solid transparent; | |||
| font-size: 0.875rem; | |||
| } | |||
| .constant-vigilance-container label::selection { | |||
| background-color: transparent; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox']:focus { | |||
| outline: none; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox']:focus + label, | |||
| .constant-vigilance-container input[type='checkbox']:hover + label, | |||
| .constant-vigilance-container input[type='checkbox'] + label:hover { | |||
| border-bottom: 1px dotted #000; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox']:checked, | |||
| .constant-vigilance-container input[type='checkbox']:hover { | |||
| box-shadow: 0 0 0 2px #fff inset; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox']:hover { | |||
| background-color: #ccc; | |||
| } | |||
| .constant-vigilance-container input[type='checkbox']:checked { | |||
| background-color: #000; | |||
| } | |||
| /******************/ | |||
| @@ -341,3 +398,6 @@ code { | |||
| .fa-heavy { | |||
| font-weight: 900; | |||
| } | |||
| p.note { | |||
| font-size: 0.875em; | |||
| } | |||
| @@ -16,6 +16,10 @@ | |||
| <input type='checkbox' id='whitelist-mode'></input> | |||
| <span class='whitelist-mode-label'>Whitelist mode</span> | |||
| </span> | |||
| <span class='constant-vigilance-container'> | |||
| <input type='checkbox' name='constant-vigilance' id='constant-vigilance' checked></input> | |||
| <label for='constant-vigilance' title='Continue monitoring the page for sticky elements added after page load. (See help for more info.)'>CONSTANT VIGILANCE!</label> | |||
| </span> | |||
| <span class='buttons'> | |||
| <button disabled type='button' class='reset-button'>Reset</button> | |||
| <button disabled type='button' class='save-button'>Save</button> | |||
| @@ -49,10 +49,12 @@ function saveChanges() { | |||
| let matchingPatterns = document.querySelector("#matchingPatterns textarea").value; | |||
| let exclusionPatterns = document.querySelector("#exclusionPatterns textarea").value; | |||
| let mode = document.querySelector("input#whitelist-mode").checked ? "whitelist" : "blacklist"; | |||
| let constantVigilance = document.querySelector("input#constant-vigilance").checked ? "true" : "false"; | |||
| chrome.storage.sync.set({ | |||
| "matchingPatterns": matchingPatterns, | |||
| "exclusionPatterns": exclusionPatterns, | |||
| "mode": mode | |||
| "mode": mode, | |||
| "constantVigilance": constantVigilance | |||
| }, () => { setButtonsActive(false); }); | |||
| } | |||
| @@ -60,16 +62,20 @@ function saveChanges() { | |||
| discarding the user's changes. | |||
| */ | |||
| function resetChanges(callback) { | |||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode" ], (result) => { | |||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode", "constantVigilance" ], (result) => { | |||
| AKS.matchingPatterns = result.matchingPatterns || ""; | |||
| AKS.exclusionPatterns = result.exclusionPatterns || "" | |||
| AKS.mode = result.mode || "blacklist"; | |||
| AKS.constantVigilance = result.constantVigilance || "true"; | |||
| document.querySelector("#matchingPatterns textarea").value = AKS.matchingPatterns; | |||
| document.querySelector("#exclusionPatterns textarea").value = AKS.exclusionPatterns; | |||
| toggleModeSelectorState(AKS.mode); | |||
| // Set CONSTANT VIGILANCE! checkbox state. | |||
| document.querySelector("input#constant-vigilance").checked = AKS.constantVigilance == "true"; | |||
| // De-activate the "Reset" and "Save" buttons. | |||
| setButtonsActive(false); | |||
| @@ -160,7 +166,7 @@ function initialize() { | |||
| }); | |||
| // Listeners for mode select switch. | |||
| document.querySelector("input[type='checkbox']").addEventListener("change", (event) => { | |||
| document.querySelector("input#whitelist-mode").addEventListener("change", (event) => { | |||
| modeSelectorInputReceived(); | |||
| }); | |||
| document.querySelectorAll(".mode-select-container span").forEach(span => { | |||
| @@ -169,6 +175,12 @@ function initialize() { | |||
| }); | |||
| }); | |||
| /* Listener to activate Reset/Save buttons when the CONSTANT VIGILANCE | |||
| checkbox is toggled. */ | |||
| document.querySelector("input#constant-vigilance").addEventListener("change", (event) => { | |||
| setButtonsActive(true); | |||
| }); | |||
| // Listener for open help button. | |||
| document.querySelector(".open-help-button").addActivateEvent((event) => { | |||
| setHelpOverlayVisible(true); | |||