From 716ace2d41d979a7389ee929b740eb72b6be8933 Mon Sep 17 00:00:00 2001 From: rebloor Date: Fri, 21 Jul 2017 09:54:33 +1200 Subject: [PATCH] Selfify example (#251) * Selfify example for how to access files article * Restored selfify.js and updated choose_file.js as suggested by Luca * Updated comments * Updates for feedback from Will * Updates from the second round of feedback * removed activetab from manifest, removed document.body.appendChild(info);, renamed the content script (selfify > content), renamed the listener (selfify > injectImage) and moved example to imagify folder. * Correctly renamed folder and update manifest.json --- imagify/README.md | 26 ++++++++++++ imagify/content_scripts/content.js | 47 ++++++++++++++++++++++ imagify/manifest.json | 22 +++++++++++ imagify/sidebar/choose_file.js | 63 ++++++++++++++++++++++++++++++ imagify/sidebar/sidebar.css | 15 +++++++ imagify/sidebar/sidebar.html | 24 ++++++++++++ imagify/viewer.css | 8 ++++ imagify/viewer.html | 17 ++++++++ imagify/viewer.js | 3 ++ 9 files changed, 225 insertions(+) create mode 100644 imagify/README.md create mode 100644 imagify/content_scripts/content.js create mode 100644 imagify/manifest.json create mode 100644 imagify/sidebar/choose_file.js create mode 100644 imagify/sidebar/sidebar.css create mode 100644 imagify/sidebar/sidebar.html create mode 100644 imagify/viewer.css create mode 100644 imagify/viewer.html create mode 100644 imagify/viewer.js diff --git a/imagify/README.md b/imagify/README.md new file mode 100644 index 0000000..b5e0359 --- /dev/null +++ b/imagify/README.md @@ -0,0 +1,26 @@ +# imagify + +**This add-on injects JavaScript into web pages. The `addons.mozilla.org` domain disallows this operation, so this add-on will not work properly when it's run on pages in the `addons.mozilla.org` domain.** + +## What it does ## + +The extension includes: + +* a sidebar including HTML, CSS, and JavaScript +* a content script +* a web page template, packaged as web accessible resources + +When the extension loads the user is offered a file picker and drop zone as methods to choose an image file. + +Once an image file has been chosen, the extension injects the content script into the active tab, and sends the content script a message containing the URL of the chosen image. + +When the content script receives this message, it replaces the current page content with the chosen image file. + +## What it shows ## + +How to: +* write a sidebar +* implement a file picker and drag and drop zone +* give a sidebar style and behavior using CSS and JavaScript +* inject a content script programmatically using `tabs.executeScript()` +* send a message from the main extension to a content script diff --git a/imagify/content_scripts/content.js b/imagify/content_scripts/content.js new file mode 100644 index 0000000..1c83760 --- /dev/null +++ b/imagify/content_scripts/content.js @@ -0,0 +1,47 @@ +(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. + */ + if (window.hasRun) { + return; + } + window.hasRun = true; + + /* + Add the image to the web page by: + * Removing every node in the document.body + * Inserting the selected image + */ + function injectImage(request, sender, sendResponse) { + removeEverything(); + insertImage(request.imageURL); + } + + /* + Remove every node under document.body + */ + function removeEverything() { + while (document.body.firstChild) { + document.body.firstChild.remove(); + } + } + + /* + Given a URL to an image, create and style an iframe containing an + IMG node pointing to that image, then insert the node into the document. + */ + function insertImage(imageURL) { + const insertImage = document.createElement("iframe"); + insertImage.setAttribute("src", browser.extension.getURL(`/viewer.html?blobURL=${imageURL}`)); + insertImage.setAttribute("style", "width: 100vw; height: 100vh;"); + document.body.appendChild(insertImage); + } + + /* + Assign injectImage() as a listener for messages from the extension. + */ + browser.runtime.onMessage.addListener(injectImage); + +})(); \ No newline at end of file diff --git a/imagify/manifest.json b/imagify/manifest.json new file mode 100644 index 0000000..93fcd5a --- /dev/null +++ b/imagify/manifest.json @@ -0,0 +1,22 @@ +{ + + "description": "Adds a sidebar offerin a file picker and drap and drop zone. When an image file is chosen the active tab's body content is replaced with file selected. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#imagify", + "manifest_version": 2, + "name": "Imagify", + "version": "1.0", + "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/imagify", + + "permissions": [ + "tabs", + "" + ], + + "sidebar_action": { + "default_title": "Imagify", + "default_panel": "sidebar/sidebar.html" + }, + + "web_accessible_resources": [ + "/viewer.html" + ] +} diff --git a/imagify/sidebar/choose_file.js b/imagify/sidebar/choose_file.js new file mode 100644 index 0000000..12780ea --- /dev/null +++ b/imagify/sidebar/choose_file.js @@ -0,0 +1,63 @@ +/* +Listens for a file being selected, creates a ObjectURL for the chosen file, injects a +content script into the active tab then passes the image URL through a message to the +active tab ID. +*/ + +// Listen for a file being selected through the file picker +const inputElement = document.getElementById("input"); +inputElement.addEventListener("change", handlePicked, false); + +// Listen for a file being dropped into the drop zone +const dropbox = document.getElementById("drop_zone"); +dropbox.addEventListener("dragenter", dragenter, false); +dropbox.addEventListener("dragover", dragover, false); +dropbox.addEventListener("drop", drop, false); + +// Get the image file if it was chosen from the pick list +function handlePicked() { + displayFile(this.files); +} + +// Get the image file if it was dragged into the sidebar drop zone +function drop(e) { + e.stopPropagation(); + e.preventDefault(); + displayFile(e.dataTransfer.files); +} + +/* +Insert the content script and send the image file ObjectURL to the content script using a +message. +*/ +function displayFile(fileList) { + const imageURL = window.URL.createObjectURL(fileList[0]); + + browser.tabs.executeScript({ + file: "/content_scripts/content.js" + }).then(messageContent) + .catch(reportError); + + function messageContent() { + const gettingActiveTab = browser.tabs.query({active: true, currentWindow: true}); + gettingActiveTab.then((tabs) => { + browser.tabs.sendMessage(tabs[0].id, {imageURL}); + }); + } + + function reportError(error) { + console.error(`Could not inject content script: ${error}`); + } +} + +// Ignore the drag enter event - not used in this extension +function dragenter(e) { + e.stopPropagation(); + e.preventDefault(); +} + +// Ignore the drag over event - not used in this extension +function dragover(e) { + e.stopPropagation(); + e.preventDefault(); +} \ No newline at end of file diff --git a/imagify/sidebar/sidebar.css b/imagify/sidebar/sidebar.css new file mode 100644 index 0000000..27f3ca7 --- /dev/null +++ b/imagify/sidebar/sidebar.css @@ -0,0 +1,15 @@ +html, body { + width: 100%; + height: 100%; +} + +#drop_zone { + border: 5px solid blue; + width: 100%; + height: 100%; +} + +#drop_zone_label { + margin: 1em; + display: block; +} \ No newline at end of file diff --git a/imagify/sidebar/sidebar.html b/imagify/sidebar/sidebar.html new file mode 100644 index 0000000..c15ef7f --- /dev/null +++ b/imagify/sidebar/sidebar.html @@ -0,0 +1,24 @@ + + + + + + + + + + + +
+ +
+ +
+ Drag an image file into this Drop Zone ... +
+ + + + + + diff --git a/imagify/viewer.css b/imagify/viewer.css new file mode 100644 index 0000000..00c0af5 --- /dev/null +++ b/imagify/viewer.css @@ -0,0 +1,8 @@ +html, body { + margin: 0; + padding: 0; +} + +img { + width: 100%; +} diff --git a/imagify/viewer.html b/imagify/viewer.html new file mode 100644 index 0000000..e48614f --- /dev/null +++ b/imagify/viewer.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/imagify/viewer.js b/imagify/viewer.js new file mode 100644 index 0000000..50d15cd --- /dev/null +++ b/imagify/viewer.js @@ -0,0 +1,3 @@ +const params = new URLSearchParams(window.location.search); +const imageBlobURL = params.get("blobURL"); +document.querySelector("img").setAttribute("src", imageBlobURL);