From 847f83460dece7ba8c65f1dc64526655d5f3a32d Mon Sep 17 00:00:00 2001 From: Will Bamberg Date: Thu, 21 Sep 2017 15:41:28 -0700 Subject: [PATCH] Only inject script once; use CSS to hide page --- beastify/content_scripts/beastify.js | 65 +++++++------- beastify/popup/choose_beast.css | 4 +- beastify/popup/choose_beast.html | 2 +- beastify/popup/choose_beast.js | 121 ++++++++++++++++----------- 4 files changed, 110 insertions(+), 82 deletions(-) diff --git a/beastify/content_scripts/beastify.js b/beastify/content_scripts/beastify.js index 240512e..26985e5 100644 --- a/beastify/content_scripts/beastify.js +++ b/beastify/content_scripts/beastify.js @@ -1,47 +1,48 @@ (function() { - /* - Check and set a global guard variable. - If this content script is injected into the same page again, - it will do nothing next time. - */ + /** + * Check and set a global guard variable. + * If this content script is injected into the same page again, + * it will do nothing next time. + */ if (window.hasRun) { return; } window.hasRun = true; - /* - beastify(): - * removes every node in the document.body, - * then inserts the chosen beast - */ - function beastify(request, sender, sendResponse) { - removeEverything(); - insertBeast(request.beastURL); - } - - /* - Remove every node under document.body - */ - function removeEverything() { - while (document.body.firstChild) { - document.body.firstChild.remove(); - } - } - - /* - Given a URL to a beast image, create and style an IMG node pointing to - that image, then insert the node into the document. - */ + /** + * Given a URL to a beast image, remove all existing beasts, then + * create and style an IMG node pointing to + * that image, then insert the node into the document. + */ function insertBeast(beastURL) { - var beastImage = document.createElement("img"); + removeExistingBeasts(); + let beastImage = document.createElement("img"); beastImage.setAttribute("src", beastURL); beastImage.style.height = "100vh"; + beastImage.className = "beastify-image"; document.body.appendChild(beastImage); } - /* - Assign beastify() as a listener for messages from the extension. + /** + * Remove every beast from the page. + */ + function removeExistingBeasts() { + let existingBeasts = document.querySelectorAll(".beastify-image"); + for (let beast of existingBeasts) { + beast.remove(); + } + } + + /** + * Listen for messages from the background script. + * Call "beastify()" or "reset()". */ - browser.runtime.onMessage.addListener(beastify); + browser.runtime.onMessage.addListener((message) => { + if (message.command === "beastify") { + insertBeast(message.beastURL); + } else if (message.command === "reset") { + removeExistingBeasts(); + } + }); })(); diff --git a/beastify/popup/choose_beast.css b/beastify/popup/choose_beast.css index 36c1068..e35ca25 100644 --- a/beastify/popup/choose_beast.css +++ b/beastify/popup/choose_beast.css @@ -18,10 +18,10 @@ html, body { background-color: #E5F2F2; } -.clear { +.reset { background-color: #FBFBC9; } -.clear:hover { +.reset:hover { background-color: #EAEA9D; } diff --git a/beastify/popup/choose_beast.html b/beastify/popup/choose_beast.html index 5984a4e..83b49f4 100644 --- a/beastify/popup/choose_beast.html +++ b/beastify/popup/choose_beast.html @@ -10,7 +10,7 @@
Frog
Turtle
Snake
-
Reset
+
Reset
diff --git a/beastify/popup/choose_beast.js b/beastify/popup/choose_beast.js index d9d4f9f..2401edc 100644 --- a/beastify/popup/choose_beast.js +++ b/beastify/popup/choose_beast.js @@ -1,54 +1,81 @@ -/* -Given the name of a beast, get the URL to the corresponding image. -*/ -function beastNameToURL(beastName) { - switch (beastName) { - case "Frog": - return browser.extension.getURL("beasts/frog.jpg"); - case "Snake": - return browser.extension.getURL("beasts/snake.jpg"); - case "Turtle": - return browser.extension.getURL("beasts/turtle.jpg"); - } -} +/** + * CSS to hide everything on the page, + * except for elements that have the "beastify-image" class. + */ +const hidePage = `body > :not(.beastify-image) { + display: none; + }`; -/* -Listen for clicks in the popup. +/** + * When the popup loads, inject a content script into the active tab, + * and add a clck handler. + */ +browser.tabs.executeScript({file: "/content_scripts/beastify.js"}) +.then(() => { + document.addEventListener("click", (e) => { -If the click is on one of the beasts: - (1) inject the beastify.js content script. + /** + * Given the name of a beast, get the URL to the corresponding image. + */ + function beastNameToURL(beastName) { + switch (beastName) { + case "Frog": + return browser.extension.getURL("beasts/frog.jpg"); + case "Snake": + return browser.extension.getURL("beasts/snake.jpg"); + case "Turtle": + return browser.extension.getURL("beasts/turtle.jpg"); + } + } - (2) send a message to "beastify.js" that contains the URL to - the chosen beast's image. + /** + * Insert the page-hiding CSS into the active tab, + * then get the beast URL and + * send a "beastify" message to the content script in the active tab. + */ + function beastify(tabs) { + browser.tabs.insertCSS({code: hidePage}).then(() => { + let url = beastNameToURL(e.target.textContent); + browser.tabs.sendMessage(tabs[0].id, { + command: "beastify", + beastURL: url + }); + }); + } -If it's on a button which contains class "clear": - Reload the page. - Close the popup. This is needed, as the content script malfunctions after page reloads. -*/ -document.addEventListener("click", (e) => { + /** + * Remove the page-hiding CSS from the active tab, + * send a "reset" message to the content script in the active tab. + */ + function reset(tabs) { + browser.tabs.removeCSS({code: hidePage}).then(() => { + browser.tabs.sendMessage(tabs[0].id, { + command: "reset", + }); + }); + } - function reportError(error) { - console.error(`Could not beastify: ${error}`); - } + /** + * Just log the error to the console. + */ + function reportError(error) { + console.error(`Could not beastify: ${error}`); + } - function beastify(tabs) { - browser.tabs.executeScript(tabs[0].id, { - file: "/content_scripts/beastify.js" - }).then(() => { - var chosenBeast = e.target.textContent; - var url = beastNameToURL(chosenBeast); - browser.tabs.sendMessage(tabs[0].id, {beastURL: url}); - }); - } - - if (e.target.classList.contains("beast")) { - browser.tabs.query({active: true, currentWindow: true}) - .then(beastify) - .catch(reportError); - } - else if (e.target.classList.contains("clear")) { - browser.tabs.reload(); - window.close(); - return; - } + /** + * Get the active tab, + * then call "beastify()" or "reset()" as appropriate. + */ + if (e.target.classList.contains("beast")) { + browser.tabs.query({active: true, currentWindow: true}) + .then(beastify) + .catch(reportError); + } + else if (e.target.classList.contains("reset")) { + browser.tabs.query({active: true, currentWindow: true}) + .then(reset) + .catch(reportError); + } + }); + });