Firefox Add-on SDK code set that creates a context (right-click) menu item allowing the user to select any text and download it to a file on the desktop. The filename is fixed (“OnlineNotes.html), but you as Super Developer can change that functionality! Please note that this idea is mostly lifted from the FF tutorials; most changes I made were to fit it to my purposes, with little creative addition beyond that.
This is specialized code for a small project, so would need some work to be universally capable. You will need to know or learn how to create and install a script to make this work.
Main code, stored in {your addon dir}/lib/main.js
exports.main = function (options, callbacks) { // load the context menu script. (Is part of the Firefox SDK.) var contextMenu = require("context-menu"); // reference and store the local directory "data" // element-getter.js is stored in this directory var data = require("self").data; var fileMgr = require("fileMgr-test.js"); contextMenu.Item({ // name that appears in the right-click menu label: "Take a note.", // only show this menu item when something is selected context: contextMenu.SelectionContext(), // show this menu item after the entire page is loaded. // This may take a while at times, and may make the user wonder where the menu item is. contentScriptWhen : "ready", // load this script onto the page (stored in the {local}/data directory). contentScriptFile : [data.url('element-getter.js')], // when a message is sent (from the page to the menu item), run this // elementContent = a JSON object with image name, URL, author, and copyright data onMessage: function (elementContent) { // record some info to the console -- run this script from the command line to see this data // console.log( elementContent ); // save the image info fileMgr.saveText( elementContent, "OnlineNotes.html" ); } }); }
.
Context menu functions, stored in {your addon dir}/lib/fileMgr-test.js
'use strict'; // super powerful Component script. Allows access to everything a browser can access. // As noted by Firefox, this is experimental, and may change or be removed in the future. var {Cc, Ci, Cm, Cr, Cu} = require("chrome"); // joins an array with a single-quote and comma var joinQuoted = function(arr){ return arr.map(function(elem){ // This will wrap each element of the array with quotes return "'" + elem + "'"; }).join(","); // This puts a comma in between every element }; // make joinQuoted a public function that other scripts can use exports.joinQuoted = joinQuoted; // save (create, else append) textJSON to the outFile // This function is public to other scripts. // NOTE: The text in the file is an array of arrays, but it will not have a closing bracket. This will have to be added manually. exports.saveText = function(textJSON, outFile) { // netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); // load file stuff Cu.import("resource://gre/modules/FileUtils.jsm"); // join textJSON array with quotes // var joinedText = ",[" + joinQuoted(textJSON) + "]"; var joinedText = textJSON; // console.log("saveText.text = " + joinedText); // create a new file reference to the OS's current desktop directory var file = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties). get("Desk", Ci.nsIFile); // reference a specific file for appending data file.append(outFile); console.log("intended file.path: " + file.path); // create the file if it doesn't exist if ( file.exists() == false ) { // console.log( "Creating file: " + file.path ); file.create( Ci.nsIFile.NORMAL_FILE_TYPE, 420 ); // fix joinedText for the first entry // replace initial comma with opening bracket // NOTE: The file will not have a closing bracket. This will have to be added manually. // joinedText = "[" + joinedText.substring(1,joinedText.length); joinedText = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\"><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><title>Notes</title></head><body >" + joinedText; } // create an output stream var outputStream = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance( Ci.nsIFileOutputStream ); // flags found here: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/FileUtils.jsm?redirectlocale=en-US&redirectslug=JavaScript_code_modules%2FFileUtils.jsm // initalize/start the output stream. // write only, create if non-existent (redundant), append (instead of overwriting) outputStream.init( file, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_APPEND, 420, 0 ); // write joinedText to file var result = outputStream.write( joinedText, joinedText.length ); // close the stream outputStream.close(); };
.
Code added to the page content, stored in {your addon dir}/data/element-getter.js
// Get the text selected on the webpage. // This javascript file is _not_ connected to the context (right-click) menu. They are in two separate code areas. // The only way this file can communicate with the context menu is "self.postMessage(info)", // where "info" is a JSON object. self.on('click', function (node, data) { var text = window.getSelection().toString(); console.log("saving text = " + text); text = "<div style=\"width: 515px; margin: 8px;\">\n\"" + text + "\"\n<br /> <a href=\"" + document.URL + "\" target=\"_blank\">" + document.URL + "</a></div><p />\n" ; self.postMessage(text); });