Add content for extension
This commit is contained in:
commit
3d7e640d4e
|
@ -0,0 +1,2 @@
|
|||
# Firefox: Second Extension Tutorial
|
||||
Following Mozilla's [Your second extension](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_second_WebExtension).
|
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
|
@ -0,0 +1,47 @@
|
|||
(() => {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
removeExistingBeasts();
|
||||
const beastImage = document.createElement("img");
|
||||
beastImage.setAttribute("src", beastURL);
|
||||
beastImage.style.height = "100vh";
|
||||
beastImage.className = "beastify-image";
|
||||
document.body.appendChild(beastImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove every beast from the page.
|
||||
*/
|
||||
function removeExistingBeasts() {
|
||||
const existingBeasts = document.querySelectorAll(".beastify-image");
|
||||
for (const beast of existingBeasts) {
|
||||
beast.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for messages from the background script.
|
||||
* Call "insertBeast()" or "removeExistingBeasts()".
|
||||
*/
|
||||
browser.runtime.onMessage.addListener((message) => {
|
||||
if (message.command === "beastify") {
|
||||
insertBeast(message.beastURL);
|
||||
} else if (message.command === "reset") {
|
||||
removeExistingBeasts();
|
||||
}
|
||||
});
|
||||
})();
|
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Beastify",
|
||||
"version": "1.0",
|
||||
|
||||
"description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify",
|
||||
"homepage_url": "https://git.ebacher-skemp.com/testing/firefox-extension-second-beastify",
|
||||
"icons": {
|
||||
"48": "icons/beasts-48.png"
|
||||
},
|
||||
|
||||
"permissions": ["activeTab"],
|
||||
|
||||
"browser_action": {
|
||||
"default_icon": "icons/beasts-32.png",
|
||||
"default_title": "Beastify",
|
||||
"default_popup": "popup/choose_beast.html"
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
"beasts/frog.jpg",
|
||||
"beasts/turtle.jpg",
|
||||
"beasts/snake.jpg"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
html,
|
||||
body {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
width: 100%;
|
||||
margin: 3% auto;
|
||||
padding: 4px;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
background-color: #e5f2f2;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #cff2f2;
|
||||
}
|
||||
|
||||
button[type="reset"] {
|
||||
background-color: #fbfbc9;
|
||||
}
|
||||
|
||||
button[type="reset"]:hover {
|
||||
background-color: #eaea9d;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="choose_beast.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="popup-content">
|
||||
<button>Frog</button>
|
||||
<button>Turtle</button>
|
||||
<button>Snake</button>
|
||||
<button type="reset">Reset</button>
|
||||
</div>
|
||||
<div id="error-content" class="hidden">
|
||||
<p>Can't beastify this web page.</p>
|
||||
<p>Try a different page.</p>
|
||||
</div>
|
||||
<script src="choose_beast.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* 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 on the buttons, and send the appropriate message to
|
||||
* the content script in the page.
|
||||
*/
|
||||
function listenForClicks() {
|
||||
document.addEventListener("click", (e) => {
|
||||
/**
|
||||
* Given the name of a beast, get the URL to the corresponding image.
|
||||
*/
|
||||
function beastNameToURL(beastName) {
|
||||
switch (beastName) {
|
||||
case "Frog":
|
||||
return browser.runtime.getURL("beasts/frog.jpg");
|
||||
case "Snake":
|
||||
return browser.runtime.getURL("beasts/snake.jpg");
|
||||
case "Turtle":
|
||||
return browser.runtime.getURL("beasts/turtle.jpg");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(() => {
|
||||
const url = beastNameToURL(e.target.textContent);
|
||||
browser.tabs.sendMessage(tabs[0].id, {
|
||||
command: "beastify",
|
||||
beastURL: url,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Just log the error to the console.
|
||||
*/
|
||||
function reportError(error) {
|
||||
console.error(`Could not beastify: ${error}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active tab,
|
||||
* then call "beastify()" or "reset()" as appropriate.
|
||||
*/
|
||||
if (e.target.tagName !== "BUTTON" || !e.target.closest("#popup-content")) {
|
||||
// Ignore when click is not on a button within <div id="popup-content">.
|
||||
return;
|
||||
}
|
||||
if (e.target.type === "reset") {
|
||||
browser.tabs
|
||||
.query({ active: true, currentWindow: true })
|
||||
.then(reset)
|
||||
.catch(reportError);
|
||||
} else {
|
||||
browser.tabs
|
||||
.query({ active: true, currentWindow: true })
|
||||
.then(beastify)
|
||||
.catch(reportError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* There was an error executing the script.
|
||||
* Display the popup's error message, and hide the normal UI.
|
||||
*/
|
||||
function reportExecuteScriptError(error) {
|
||||
document.querySelector("#popup-content").classList.add("hidden");
|
||||
document.querySelector("#error-content").classList.remove("hidden");
|
||||
console.error(`Failed to execute beastify content script: ${error.message}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the popup loads, inject a content script into the active tab,
|
||||
* and add a click handler.
|
||||
* If we couldn't inject the script, handle the error.
|
||||
*/
|
||||
browser.tabs
|
||||
.executeScript({ file: "/content_scripts/beastify.js" })
|
||||
.then(listenForClicks)
|
||||
.catch(reportExecuteScriptError);
|
Loading…
Reference in New Issue