/**********/ /* EVENTS */ /**********/ /* Triggered when a click is received by the mode selector switch, or by either of the two labels ("Blacklist" and "Whitelist"). */ function modeSelectorInputReceived() { toggleModeSelectorState(); // Activate the "Reset" and "Save" buttons, since changes have been made. setButtonsActive(true); } /* * Triggered when a click is received by the kill count display switch */ function hideKillCountInputReceived() { setButtonsActive(true); } /***********/ /* HELPERS */ /***********/ /* Toggles all UI state associated with mode selection. Called on input to the mode selector (see modeSelectorInputReceived()), OR when changes are reset (see resetChanges()). */ function toggleModeSelectorState(newMode) { /* Update state of the checkbox itself, and the container div. */ let container = document.querySelector(".mode-select-container"); let checkbox = document.querySelector("input#whitelist-mode"); newMode = newMode || (container.classList.contains("whitelist") ? "blacklist" : "whitelist"); container.classList.toggle("whitelist", (newMode == "whitelist")); checkbox.checked = (newMode == "whitelist"); /* Enable both spans (the "Blacklist" and "Whitelist" labels, then disable just the label associated with the now-enabled mode. */ container.querySelectorAll("span").forEach(span => { span.classList.toggle("disabled", false); }); document.querySelector(`.${newMode}-mode-label`).classList.toggle("disabled", true); /* In whitelist mode, the matching patterns textarea must be disabled, since the matching patterns list is treated as containing only the single pattern ".*". An overlay is shown, to indicate this. */ document.querySelector("div#matchingPatterns").classList.toggle("disabled", (newMode == "whitelist")); document.querySelector("div#matchingPatterns textarea").disabled = (newMode == "whitelist"); } /* * Sets the kill count selector state * Used by resetChanges() */ function setHideKillCountSelectorState(hideKillCount) { let checkbox = document.querySelector("input#hide-kill-count"); checkbox.checked = hideKillCount; } /* Saves the entered state in storage. De-activate the "Reset" and "Save" buttons. */ 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 hideKillCount = document.querySelector("input#hide-kill-count").checked ? true : false; console.log("In saveChanges, hideKillCount: " + hideKillCount); //DEBUG chrome.storage.local.set({ "matchingPatterns": matchingPatterns, "exclusionPatterns": exclusionPatterns, "mode": mode, "hideKillCount": hideKillCount }, () => { let error = chrome.runtime.lastError; if (error) { alert(error.message); } else { setButtonsActive(false); } }); } /* Retrieves the saved state from storage and reset the UI to reflect it, discarding the user's changes. */ function resetChanges(callback) { chrome.storage.local.get([ "matchingPatterns", "exclusionPatterns", "mode", "hideKillCount" ], (result) => { AKS.matchingPatterns = result.matchingPatterns || ""; AKS.exclusionPatterns = result.exclusionPatterns || "" AKS.mode = result.mode || "blacklist"; AKS.hideKillCount = result.hideKillCount || false; document.querySelector("#matchingPatterns textarea").value = AKS.matchingPatterns; document.querySelector("#exclusionPatterns textarea").value = AKS.exclusionPatterns; toggleModeSelectorState(AKS.mode); setHideKillCountSelectorState(AKS.hideKillCount); // De-activate the "Reset" and "Save" buttons. setButtonsActive(false); // Expand all textareas. document.querySelectorAll("textarea").forEach(textarea => { expandTextarea(textarea); }); // Trigger provided callback, if any. if (callback) callback(); }); } /* Activates or de-activates the "Reset" and "Save" buttons. Called when changes are made (to activate) or when changes are saved or reset (to de-activate). */ function setButtonsActive(active) { document.querySelectorAll(".top-controls button").forEach(button => { button.disabled = !active; }); } /* Enables or disables scrolling on the page body, depending on whether the help overlay is visible. */ function setBodyScrollState() { document.querySelector("body").classList.toggle("noscroll", location.hash == "#help"); } /* Expands a textarea to show all its contents (up to a maximum height which is set via CSS). */ function expandTextarea(textarea) { let totalBorderHeight = 2; if (textarea.clientHeight == textarea.scrollHeight + totalBorderHeight) return; requestAnimationFrame(() => { textarea.style.height = 'auto'; textarea.style.height = textarea.scrollHeight + totalBorderHeight + 'px'; }); } function setHelpOverlayVisible(visible) { location.hash = visible ? "help" : ""; setBodyScrollState(); } /******************/ /* INITIALIZATION */ /******************/ function initialize() { window.AKS = { }; /* Retrieve saved settings from storage, and set all UI elements to their proper state. Then, focus the first active textarea. */ resetChanges(() => { let divToFocus = (AKS.mode == "whitelist") ? "#exclusionPatterns" : "#matchingPatterns"; document.querySelector(`${divToFocus} textarea`).focus(); }); // Update version. document.querySelector(".bottom-info .version").innerText = chrome.runtime.getManifest().version; // Listeners for Reset and Save buttons. document.querySelectorAll("button").forEach(button => { button.addActivateEvent((event) => { event.target.blur(); if (button.classList.contains("save-button")) saveChanges(); else resetChanges(); }); }); // Listeners to activate Reset/Save buttons when textareas get input. document.querySelectorAll("textarea").forEach(textarea => { textarea.addEventListener("input", (event) => { setButtonsActive(true); }); }); // Listeners to auto-expand textareas on input. document.querySelectorAll("textarea").forEach(textarea => { textarea.addEventListener("input", (event) => { expandTextarea(textarea); }); }); // Listeners for mode select switch. document.querySelector("input#whitelist-mode").addEventListener("change", (event) => { modeSelectorInputReceived(); }); document.querySelectorAll(".mode-select-container span").forEach(span => { span.addActivateEvent((event) => { modeSelectorInputReceived(); }); }); //Listener for killcount display switch document.querySelector("input#hide-kill-count").addEventListener("change", (event) => { hideKillCountInputReceived(); }); // Listener for open help button. document.querySelector(".open-help-button").addActivateEvent((event) => { setHelpOverlayVisible(true); }); // Listener for close help button. document.querySelector(".help-overlay .close-button").addActivateEvent((event) => { setHelpOverlayVisible(false); }); // Disable scrolling on the document body, if need be (if help is open). setBodyScrollState(); // Listener for Escape key (closes the help overlay). document.addEventListener("keyup", (event) => { if (event.keyCode == 27 && location.hash == "#help") { setHelpOverlayVisible(false); } }); } initialize();