| return shouldKillSticky; | 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 */ | /* INITIALIZATION */ | ||||
| /******************/ | /******************/ | ||||
| function initialize() { | function initialize() { | ||||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode" ], | |||||
| chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode", "constantVigilance" ], | |||||
| (result) => { | (result) => { | ||||
| let shouldKillSticky = checkForShouldKillSticky(result); | let shouldKillSticky = checkForShouldKillSticky(result); | ||||
| updateIcon(shouldKillSticky); | updateIcon(shouldKillSticky); | ||||
| let constantVigilance = (result.constantVigilance == "false") ? false : true; | |||||
| window.onload = () => { | window.onload = () => { | ||||
| if (shouldKillSticky) killSticky(); | |||||
| if (shouldKillSticky) { | |||||
| killSticky(); | |||||
| if (constantVigilance) startConstantVigilance(); | |||||
| } | |||||
| }; | }; | ||||
| }); | }); | ||||
| } | } |
| display: flex; | display: flex; | ||||
| flex-flow: row wrap; | flex-flow: row wrap; | ||||
| align-items: center; | align-items: center; | ||||
| max-width: 640px; | |||||
| max-width: 750px; | |||||
| } | } | ||||
| .top-controls .buttons { | .top-controls .buttons { | ||||
| display: flex; | display: flex; | ||||
| background-color: #777; | background-color: #777; | ||||
| opacity: 0.3; | 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 { | input#whitelist-mode { | ||||
| display: block; | display: block; | ||||
| -webkit-appearance: none; | -webkit-appearance: none; | ||||
| align-self: flex-start; | align-self: flex-start; | ||||
| border: 1px solid #ddd; | border: 1px solid #ddd; | ||||
| padding: 8px 10px; | padding: 8px 10px; | ||||
| margin | |||||
| cursor: default; | cursor: default; | ||||
| background-color: #fff; | background-color: #fff; | ||||
| } | } | ||||
| .mode-select-container span:not(.disabled):hover { | .mode-select-container span:not(.disabled):hover { | ||||
| border-bottom: 1px solid currentColor; | 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; | 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; | |||||
| } | } | ||||
| /******************/ | /******************/ | ||||
| .fa-heavy { | .fa-heavy { | ||||
| font-weight: 900; | font-weight: 900; | ||||
| } | } | ||||
| p.note { | |||||
| font-size: 0.875em; | |||||
| } |
| <input type='checkbox' id='whitelist-mode'></input> | <input type='checkbox' id='whitelist-mode'></input> | ||||
| <span class='whitelist-mode-label'>Whitelist mode</span> | <span class='whitelist-mode-label'>Whitelist mode</span> | ||||
| </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'> | <span class='buttons'> | ||||
| <button disabled type='button' class='reset-button'>Reset</button> | <button disabled type='button' class='reset-button'>Reset</button> | ||||
| <button disabled type='button' class='save-button'>Save</button> | <button disabled type='button' class='save-button'>Save</button> |
| let matchingPatterns = document.querySelector("#matchingPatterns textarea").value; | let matchingPatterns = document.querySelector("#matchingPatterns textarea").value; | ||||
| let exclusionPatterns = document.querySelector("#exclusionPatterns textarea").value; | let exclusionPatterns = document.querySelector("#exclusionPatterns textarea").value; | ||||
| let mode = document.querySelector("input#whitelist-mode").checked ? "whitelist" : "blacklist"; | let mode = document.querySelector("input#whitelist-mode").checked ? "whitelist" : "blacklist"; | ||||
| let constantVigilance = document.querySelector("input#constant-vigilance").checked ? "true" : "false"; | |||||
| chrome.storage.sync.set({ | chrome.storage.sync.set({ | ||||
| "matchingPatterns": matchingPatterns, | "matchingPatterns": matchingPatterns, | ||||
| "exclusionPatterns": exclusionPatterns, | "exclusionPatterns": exclusionPatterns, | ||||
| "mode": mode | |||||
| "mode": mode, | |||||
| "constantVigilance": constantVigilance | |||||
| }, () => { setButtonsActive(false); }); | }, () => { setButtonsActive(false); }); | ||||
| } | } | ||||
| discarding the user's changes. | discarding the user's changes. | ||||
| */ | */ | ||||
| function resetChanges(callback) { | 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.matchingPatterns = result.matchingPatterns || ""; | ||||
| AKS.exclusionPatterns = result.exclusionPatterns || "" | AKS.exclusionPatterns = result.exclusionPatterns || "" | ||||
| AKS.mode = result.mode || "blacklist"; | AKS.mode = result.mode || "blacklist"; | ||||
| AKS.constantVigilance = result.constantVigilance || "true"; | |||||
| document.querySelector("#matchingPatterns textarea").value = AKS.matchingPatterns; | document.querySelector("#matchingPatterns textarea").value = AKS.matchingPatterns; | ||||
| document.querySelector("#exclusionPatterns textarea").value = AKS.exclusionPatterns; | document.querySelector("#exclusionPatterns textarea").value = AKS.exclusionPatterns; | ||||
| toggleModeSelectorState(AKS.mode); | toggleModeSelectorState(AKS.mode); | ||||
| // Set CONSTANT VIGILANCE! checkbox state. | |||||
| document.querySelector("input#constant-vigilance").checked = AKS.constantVigilance == "true"; | |||||
| // De-activate the "Reset" and "Save" buttons. | // De-activate the "Reset" and "Save" buttons. | ||||
| setButtonsActive(false); | setButtonsActive(false); | ||||
| }); | }); | ||||
| // Listeners for mode select switch. | // Listeners for mode select switch. | ||||
| document.querySelector("input[type='checkbox']").addEventListener("change", (event) => { | |||||
| document.querySelector("input#whitelist-mode").addEventListener("change", (event) => { | |||||
| modeSelectorInputReceived(); | modeSelectorInputReceived(); | ||||
| }); | }); | ||||
| document.querySelectorAll(".mode-select-container span").forEach(span => { | document.querySelectorAll(".mode-select-container span").forEach(span => { | ||||
| }); | }); | ||||
| }); | }); | ||||
| /* 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. | // Listener for open help button. | ||||
| document.querySelector(".open-help-button").addActivateEvent((event) => { | document.querySelector(".open-help-button").addActivateEvent((event) => { | ||||
| setHelpOverlayVisible(true); | setHelpOverlayVisible(true); |