About Custom Buttons add-on

Custom Buttons allows you to create custom toolbarbuttons that can perform almost any task within your application. The language used in this buttons is JavaScript.

People who have never used or seen this scripting language, at the end of this documentation will find a basic guide to JavaScript.

About this documentation

  • You can double click on code blocks to select all code.
  • Code blocks highlighted in green are from the official Custom Buttons documentation.
  • Code blocks highlighted in red are modified/added by me (Odyseus).
  • Code blocks highlighted in orange are extracted from the Russian forum.
  • Code blocks not highlighted have not been reviewed or tested. Which means that the code could be non-functional (due to its possible deprecation) or its just bad translated by me (due to the use of an automatic translator).
  • I've made very minor changes to the examples of the original documentation. Like replacing all instances of "Components.classes" for the variable "Cc", etc.
  • I have also added examples that were removed from the original documentation, like "menu-button" and "menu" buttons examples.

Getting started


  1. Button URL: By entering a button URI into this field, a currently installed button can be updated with code from said URI. Or install a new button.
  2. Name: Name of the button.
  3. Image: Image for the button. An image can be:
    • An URL containing an online image, e.g., "https://duckduckgo.com/favicon.ico".
    • A "chrome" URL, e.g., "chrome://branding/content/icon32.png".
    • A "file:///" URI, e.g., "file:///C:/Users/UserName/Desktop/Image.png", "file:///home/UserName/ Pictures/ Image.png".
    • A data URI, e.g., "data:image/png;base64,...base64 code...".
    • A "moz-icon", e.g., "moz-icon://.png?size=16".
  4. Browse: It allows you to browse for a local image.
  5. => base64: It converts any image from any source to Base64 format. This facilitates sharing the button without worrying about the source of the image.
  6. Tabs

    The code inside this tab is executed every time the button is clicked with left mouse button.

    The code inside this tab is executed every time the button is initialized.

    A button is initialized when:

    • The application starts.
    • The button is edited and saved, either by pressing the "OK" or the "Save" buttons.
    • Leaving the applications customize mode. In applications using CustomizableUI. jsm (Australis), the button also is initialized each time is moved from toolbar to toolbar while in customize mode.
    • Can also be programmatically initialized with this.init(); and/or self.init();

    The content of this tab is diplayed when the menuitem "Button Help" from the Custom Buttons context menu is clicked. The Help tab of a Custom Buttons button can also be used in several usefull ways.

    By default, there is a "separator" [,] that can be used to "divide" the Help tab content.

    Example:


    The "Button Help" menu item from the button shown in the image above will display...


    ...and the rest of the content can be called as follow...

    /*Code*/
    var usefulCode = this.Help.split("[,]")[1];
    
    alert(usefulCode);

    or...

    /*Code*/
    var usefulCode = self.getAttribute("Help").split("[,]")[1];
    
    alert(usefulCode);

    ...whose result will be...


    Using the same "separator" [,] as in the previous example, the content of the Help tab can be "divided" into several parts in order to use these parts separately.


    The different parts can be called like this...

    var usefulCodePartOne = this.Help.split("[,]")[1];
    
    var usefulCodePartTwo = this.Help.split("[,]")[2];
    
    var usefulCodePartThree = this.Help.split("[,]")[3];

    ...or like this...

    var usefulCodePartOne = self.getAttribute("Help").split("[,]")[1];
    
    var usefulCodePartTwo = self.getAttribute("Help").split("[,]")[2];
    
    var usefulCodePartThree = self.getAttribute("Help").split("[,]")[3];

    This procedure is the one I like and use in my buttons. I like it because I do not have to remember nor pay attention to the index in which the code I want is, which would be necessary to recall in the example number one.

    /*Initialization*/
    var usefulCodeOne = getHelp("MarkerOne");
    
    var usefulCodeTwo = getHelp("MarkerTwo");
    
    var usefulCodeThree = getHelp("MarkerThree");
    
    function getHelp(aMarker) { // Get specific data from the Help tab.
      return document.getElementById(self.id).getAttribute("Help").split("<!--" + aMarker + "-->")[1];
    }
    IMPORTANT!!! Markers should ALWAYS exist in pairs and be unique.
    
    <!--MarkerThree-->
    Usefull code that can be called from JavaScript.
    <!--MarkerThree-->
    
    <!--MarkerOne-->
    Usefull code that can be called from JavaScript.
    <!--MarkerOne-->
    
    <!--MarkerTwo-->
    Usefull code that can be called from JavaScript.
    <!--MarkerTwo-->

    In this tab a hotkey can be configured to execute the button. To delete an already configured hotkey, focus/click the "Hotkey" textbox and press Esc.

  7. Save: By pressing "Save", all changes made to the button are saved and the button is re-initialized.
  8. OK: By pressing "OK", the edit window is closed, all changes made to the button are saved and the button is re-initialized.
  9. Edit external...: It allows to edit the content of the current selected tab in an external editor.
  10. How to use this feature without losing your mind

    Every time you press the "Edit external..." button to edit a button, a temporary file is created inside your profile folder (inside a folder called Temp_ExternalEditor) and opened with the text editor of your choice. While you are editing this file, DO NOT re-focus the edit window of the button you are editing. Once you've made all changes you needed/wanted, SAVE the file and THEN re-focus the edit window of the button and save the button. The instant the edit window is focused, that temporary file no longer exists/is deleted.

    Notes
    • To avoid headaches, use a text editor that deserves to be called as such. That is, anything but the Windows Notepad!
    • To change the text editor, reset the preference called "extensions.custombuttons.external_editor". When you press again the "Edit external..." button, you will be able to choose another editor.
  11. Cancel: By pressing "Cancel", the edit window is closed, all changes to the button are discarded and the button is not re-initialized.
  • Left click View → Add new button… in the Menu Bar - or right click a toolbar and left click Add new button…
  • Type Hello World in the "Name" field.
  • Type http://www.mozilla.org/favicon.ico in the "Image" field.
  • Type alert("Hello world"); on a blank line in the "Code" section.
  • Left click OK to close the Edit button dialog.
  • Left click View → Toolbars → Customize… in the Menu Bar - or right click a toolbar and left click Customize….
  • Find the button and drag it to a toolbar.
  • Left click Done to close the Customize Toolbar window.
  • Left click the button to show the alert.
  • Right click the button to show the context popup.
ImageActionComments
Edit button...
Delete button
Clone buttonMiddle click to add new blank button.
Copy to clipboard
Update ButtonHidden unless clipboard has a button URL.
Bookmark Button
Button HelpHidden unless "Help" section has text.
Customize...
Add new button...
ShortcutAction
Ctrl + FOpen search dialog in forward direction.
Ctrl + Shift + FOpen search dialog in backward direction.
F3Find next.
Shift + F3Find previous.
Ctrl + /Incremental search.
Ctrl + HOpen replace dialog in forward direction.
Ctrl + Shift + HOpen replace dialog in backward direction.
Ctrl + Shift + AComment or uncomment selected lines.
TabIndent selected lines.
Shift + TabUnindent selected lines.
Ctrl + WToggle word wrapping.
Ctrl + GGoto line number.
F9Execute code from "Code" section.
F11Maximize or restore editor window.
Ctrl + EnterSave changes and close editor.

OptionComments
Show "Save" button in code editor
Disable buttons initializationFor debug purposes.
Enable install buttons from mail messagesOnly on Thunderbird/SeaMonkey.
Save size and position of editor windows separately for each custom button
firefox.exe
-custombuttons disable-buttons-initialization
seamonkey.exe
-custombuttons disable-buttons-initialization
thunderbird.exe
-custombuttons disable-buttons-initialization
sunbird.exe
-custombuttons disable-buttons-initialization
kompozer.exe
-custombuttons disable-buttons-initialization
flock.exe
-custombuttons disable-buttons-initialization
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
var Cr = Components.results;
var self = this; // "this" is the button itself.
var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; // Namespace for XUL elements.
var xhtmlns = "http://www.w3.org/1999/xhtml"; // Namespace for HTML elements inside XUL elements.
var _id = this.id; // The id of the button.
var _doc = document;
var _uri = buttonURI; // The button URI.
var cbu = custombuttonsUtils;

All middle click events with modifiers are "broken". Web browsers nowadays do not allow the use of modifier keys (Alt, Ctrl, etc.) in conjunction with the middle mouse button.

/*Initialization code*/
// right click button and shift - open custom button context popup
this.buttonClick = function (event) {
  event.preventDefault();
  if (event.button == 0 && !event.altKey && !event.ctrlKey && !event.shiftKey)
    alert("left click");
  if (event.button == 1 && !event.altKey && !event.ctrlKey && !event.shiftKey)
    alert("middle click");
  if (event.button == 2 && !event.altKey && !event.ctrlKey && !event.shiftKey)
    alert(" right click");
  if (event.button == 2 && !event.altKey && !event.ctrlKey && event.shiftKey)
    gShowPopup(this);
}
this.setAttribute("onclick", "this.buttonClick(event)");
/*Initialization code*/
this.   leftclick = function(event) { alert("   leftclick"); }
this.  aleftclick = function(event) { alert("  aleftclick"); } // a for alt
this.  cleftclick = function(event) { alert("  cleftclick"); } // c for ctrl
this.  sleftclick = function(event) { alert("  sleftclick"); } // s for shift
this.    midclick = function(event) { alert("    midclick"); }
this.   amidclick = function(event) { alert("   amidclick"); }
this.   cmidclick = function(event) { alert("   cmidclick"); }
this.   smidclick = function(event) { alert("   smidclick"); }
this.  rightclick = function(event) { alert("  rightclick");   gShowPopup(this); }
this. arightclick = function(event) { alert(" arightclick"); }
this. crightclick = function(event) { alert(" crightclick"); }
this. srightclick = function(event) { alert(" srightclick"); } // not available
this.  leftDclick = function(event) { alert("  leftDclick"); } // capital d for double
this. aleftDclick = function(event) { alert(" aleftDclick"); }
this. cleftDclick = function(event) { alert(" cleftDclick"); }
this. sleftDclick = function(event) { alert(" sleftDclick"); }
this.   midDclick = function(event) { alert("   midDclick"); }
this.  amidDclick = function(event) { alert("  amidDclick"); }
this.  cmidDclick = function(event) { alert("  cmidDclick"); }
this.  smidDclick = function(event) { alert("  smidDclick"); }
this. rightDclick = function(event) { alert(" rightDclick"); }
this.arightDclick = function(event) { alert("arightDclick"); }
this.crightDclick = function(event) { alert("crightDclick"); }
this.srightDclick = function(event) { alert("srightDclick"); } // not available
this.setAttribute("onclick", "custombuttons.gQuot.mHandler(event, this)");
this.setAttribute("ondblclick", "custombuttons.gQuot.mHandler(event, this)");
/*Initialization code*/
this.acsleftDclick = function (event) {
  alert("alt ctrl shift left double click");
}
this.setAttribute("ondblclick", "custombuttons.gQuot.mHandler(event, this)");
/*Initialization code*/
this.image = "http://www.mozilla.org/favicon.ico";
this.setAttribute("onmouseup", "this.image = 'chrome://custombuttons/skin/button.png'");
this.setAttribute("onmousedown", "this.image = 'chrome://custombuttons/skin/stdicons/rbutton.png'");
this.setAttribute("onmouseout", "this.image = 'chrome://custombuttons/skin/stdicons/gbutton.png'");
this.setAttribute("onmouseover", "this.image = 'chrome://custombuttons/skin/stdicons/bbutton.png'");
/*Initialization code*/
this.style.opacity = "0.65";
this.setAttribute("onmouseout", "custombuttons.ButtonDim(event)");
this.setAttribute("onmouseover", "custombuttons.ButtonBrt(event)");
/*Initialization code*/
// click "Save" or "OK" in the editor initializes one button
// close the customize toolbar window initializes all buttons
var uid = "__unique_identifier_" + this.id;
if (!(uid in window)) {
  alert("test");
  window[uid] = true;
}
// comment in the next line to re-execute
// delete window[uid];
/*Code*/
if (typeof(inspectDOMDocument) == "undefined") {
  alert("DOM Inspector is not enabled or installed.");
  return;
}
function runInspector(node) {
  if (node instanceof Document) {
    inspectDOMDocument(node);
  } else if (node instanceof Node) {
    inspectDOMNode(node);
  } else if (node !== null && typeof(node) != "undefined") {
    inspectObject(node);
  }
}
runInspector(document);
runInspector(content.document);
runInspector(document.getElementsByTagName("toolbar")[0]);
runInspector(document.getElementById("custombuttons-button0"));
runInspector(navigator);
runInspector(Cc["@mozilla.org/xre/app-info;1"].
  getService(Ci.nsIXULAppInfo));
/*Initialization code*/
// constructor example - change button type property
// destructor  example - close window
// update      example - edit button
// delete      example - delete button
LOG("test 2");
this.onDestroy = function (reason) {
  LOG("test 1");
  if (reason == "constructor")
    LOG("constructor");
  if (reason == "destructor")
    LOG("destructor");
  if (reason == "update")
    LOG("update");
  if (reason == "delete")
    LOG("delete");
}
/*Code*/
// some commands are only legal when there is a selection or when the focus is on a text field
var cmd;
cmd = "cmd_paste"; // cmd_paste command is implemented by a controller
cmd = "cmd_close";
var controller = document.commandDispatcher.getControllerForCommand(cmd);
if (controller) {
  if (controller.isCommandEnabled(cmd)) {
    controller.doCommand(cmd);
  }
} else {
  var element = document.getElementById(cmd);
  if (element) {
    element.doCommand();
  }
}
/*Code*/
goDoCommand("cmd_paste");
/*Code*/
document.getElementById("cmd_close").doCommand();

Example 1

/*Initialization code*/
// #000000 black
// #0000FF blue
// #00FF00 lime
// #00FFFF aqua
// #FF0000 red
// #FF00FF fuchsia
// #FFFF00 yellow
// #FFFFFF white
var ios = Cc["@mozilla.org/network/io-service;1"].
  getService(Ci.nsIIOService);
var sss = Cc["@mozilla.org/content/style-sheet-service;1"].
  getService(Ci.nsIStyleSheetService);
var css = "menubar             { background: #00FF00 !important; }";
css += "#" + this.id + "       { background: #000000 !important; }";
css += "#" + this.id + ":hover { background: #FFFFFF !important; }";
var uss = ios.newURI("data:text/css," + encodeURIComponent(css), null, null);
// comment out the next line to disable style
if (!sss.sheetRegistered(uss, sss.USER_SHEET))
  sss.loadAndRegisterSheet(uss, sss.USER_SHEET);
this.onDestroy = function (reason) {
  if (reason == "update") {
    var uss = ios.newURI("data:text/css," + encodeURIComponent(css), null, null);
    if (sss.sheetRegistered(uss, sss.USER_SHEET))
      sss.unregisterSheet(uss, sss.USER_SHEET);
  }
  if (reason == "delete") {
    var uss = ios.newURI("data:text/css," + encodeURIComponent(css), null, null);
    if (sss.sheetRegistered(uss, sss.USER_SHEET))
      sss.unregisterSheet(uss, sss.USER_SHEET);
    alert("style sheet unregistered");
  }
}

Example 2

/*Code*/
var browser = gBrowser.getBrowserForTab(gBrowser.addTab("about:logo"));
browser.addEventListener("load", function (event) {
  browser.removeEventListener("load", arguments.callee, true);
  alert("test");
}, true);
/*Code*/
// custom button event listener is deleted automatically when a button is destroyed
var browser = gBrowser.getBrowserForTab(gBrowser.addTab("about:logo"));
addEventListener("load", function (event) {
  removeEventListener("load", arguments.callee, true, browser);
  alert("test" + "\n" + "handlers length: " + this._handlers.length);
}, true, browser);
/*Code*/
var consoleService = Cc["@mozilla.org/consoleservice;1"].
  getService(Ci.nsIConsoleService);
consoleService.logStringMessage("test 1");
LOG("test 2");
alert(LOG(2 + 2));
try {
  toErrorConsole(); // console2.mozdev.org
} catch (e) {
  toJavaScriptConsole();
}
/*Code*/
// left click entry in error console to go directly to the error
this.is.an.error;
Error : this.is is undefined
Source File : chrome : //custombuttons/content/button.js?windowId=Firefox&amp;id=custombuttons-button0@code
Line : 3
/*Code*/
var element = content.document.getElementById("blackify");
if (element) {
  element.parentNode.removeChild(element);
} else {
  var style = content.document.createElement("style");
  style.setAttribute("type", "text/css");
  style.setAttribute("id", "blackify");
  style.innerHTML = "*         { background: #000000 !important; }" +
    "*         {      color: #CCCCCC !important; }" +
    "a         {      color: #FFCC66 !important; }" +
    "a:hover   {      color: #FFFFCC !important; }" +
    "a:visited {      color: #FFB720 !important; }";
  content.document.getElementsByTagName("head")[0].appendChild(style);
}

Working with buttons, mouse, menus, etc

The following three examples create the exact same button. The difference lies in the way the menu for this button is created. In the first example, the menu is created by parsing a variable that stores an XML string. In the second example, the menu is created with pure JavaScript. And in the third example, the menu is stored indide the "Help" tab of the button.

/*Initialization code*/
/**
 *   left click on button    - Open menu popup
 *  right click on button    - Open custom button context popup
 *   left click on menuitems - Open page in the current tab
 * middle click on menuitems - Open page in a new tab in the background
 *  right click on menuitems - Open page in a new tab in the foreground
 */

const cbNS = "http://xsms.nm.ru/custombuttons/";

// xulns = http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul.
// Is a global variable defined by Custom Buttons.
var menu =  "<menupopup xmlns=\"" + xulns + "\" xmlns:cb=\"" + cbNS + "\"" +
  " onclick=\"this.parentNode.menuClick(event);\">" +
  "<menu" +
  " class=\"menu-iconic\"" +
  " image=\"chrome://global/skin/dirListing/folder.png\"" +
  " label=\"Search\">" +
  "<menupopup>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://www.google.com/favicon.ico\"" +
  " label=\"Google\"" +
  " cb:url=\"http://www.google.com/\"/>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://search.yahoo.com/favicon.ico\"" +
  " label=\"Yahoo\"" +
  " cb:url=\"http://search.yahoo.com/\"/>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://www.bing.com/favicon.ico\"" +
  " label=\"Bing\"" +
  " cb:url=\"http://www.bing.com/\"/>" +
  "<menuseparator/>" +
  "<menuitem" +
  " label=\"Open All in Tabs\"" +
  " onclick=\"document.getElementById(\'" + this.id + "\').openAllInTabs(event);\"/>" +
  "</menupopup>" +
  "</menu>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://en.wikipedia.org/favicon.ico\"" +
  " label=\"Wikipedia\"" +
  " cb:url=\"http://en.wikipedia.org/\"/>" +
  "</menupopup>";

this.appendChild($XML(menu)); // This appends the menu itself to the button.

var nodeList = this.getElementsByTagName("menuitem"); // Gets all menuitems in this button.

for (var i = 0; i < nodeList.length; i++) { // This loop sets the tooltip for each menuitem.
  var label = nodeList[i].getAttribute("label");
  var url = nodeList[i].getAttributeNS(cbNS, "url");
  if (label && url)
    nodeList[i].setAttribute("tooltiptext", label + "\n" + url);
}

this.type = "menu";

this.orient = "horizontal";

this.menuClick = function (event) {
  event.preventDefault();
  event.stopPropagation();
  this.open = false; // This closes the popup after middle/right clicks on menuitems.
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url && event.button == 0) // Left click
    loadURI(url);
  if (url && event.button == 1) // Middle click
    gBrowser.addTab(url);
  if (url && event.button == 2) // Right click
    gBrowser.selectedTab = gBrowser.addTab(url);
};

this.openAllInTabs = function (event) {
  var nodeList = event.target.parentNode.childNodes;
  for (var i = 0; i < nodeList.length; i++) {
    var url = nodeList[i].getAttributeNS(cbNS, "url");
    if (url)
      gBrowser.addTab(url);
  }
};

function $XML(aXML) { // Return parsed XML
  aXML = aXML.replace(/>\s+</g, "><"); // Linearize XML
  return (new DOMParser).parseFromString(aXML, "application/xml").documentElement;
}
/*Initialization code*/
/**
 *   left click on button    - Open menu popup
 *  right click on button    - Open custom button context popup
 *   left click on menuitems - Open page in the current tab
 * middle click on menuitems - Open page in a new tab in the background
 *  right click on menuitems - Open page in a new tab in the foreground
 */

const cbNS = "http://xsms.nm.ru/custombuttons/";

// xulns = http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul.
// Is a global variable defined by Custom Buttons.
var mainPopup = document.createElementNS(xulns, "menupopup");
mainPopup.setAttribute("xmlns:cb", cbNS);
mainPopup.setAttribute("onclick", "this.parentNode.menuClick(event);");

var subMenu = mainPopup.appendChild(document.createElementNS(xulns, "menu"));
subMenu.setAttribute("class", "menu-iconic");
subMenu.setAttribute("label", "Search");
subMenu.setAttribute("image", "chrome://global/skin/dirListing/folder.png");

var subPopup = subMenu.appendChild(document.createElementNS(xulns, "menupopup"));

var mItem1 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem1.setAttribute("class", "menuitem-iconic");
mItem1.setAttribute("label", "Google");
mItem1.setAttribute("image", "http://www.google.com/favicon.ico");
mItem1.setAttributeNS(cbNS, "cb:url", "https://www.google.com");

var mItem2 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem2.setAttribute("class", "menuitem-iconic");
mItem2.setAttribute("label", "Yahoo");
mItem2.setAttribute("image", "http://search.yahoo.com/favicon.ico");
mItem2.setAttributeNS(cbNS, "cb:url", "https://search.yahoo.com");

var mItem3 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem3.setAttribute("class", "menuitem-iconic");
mItem3.setAttribute("label", "Bing");
mItem3.setAttribute("image", "http://www.bing.com/favicon.ico");
mItem3.setAttributeNS(cbNS, "cb:url", "https://www.bing.com");

subPopup.appendChild(document.createElementNS(xulns, "menuseparator"));

var mItem4 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem4.setAttribute("label", "Open All in Tabs");
mItem4.setAttribute("onclick", "document.getElementById('" + this.id + "').openAllInTabs(event);");

var mItem5 = mainPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem5.setAttribute("class", "menuitem-iconic");
mItem5.setAttribute("label", "Wikipedia");
mItem5.setAttribute("image", "http://en.wikipedia.org/favicon.ico");
mItem5.setAttributeNS(cbNS, "cb:url", "http://en.wikipedia.org");

this.appendChild(mainPopup); // This appends the menu itself to the button.

var nodeList = this.getElementsByTagName("menuitem"); // Gets all menuitems in this button.

for (var i = 0; i < nodeList.length; i++) { // This loop sets the tooltip for each menuitem.
  var label = nodeList[i].getAttribute("label");
  var url = nodeList[i].getAttributeNS(cbNS, "url");
  if (label && url)
    nodeList[i].setAttribute("tooltiptext", label + "\n" + url);
}

this.type = "menu";

this.orient = "horizontal";

this.menuClick = function (event) {
  event.preventDefault();
  event.stopPropagation();
  this.open = false; // This closes the popup after middle/right clicks on menuitems.
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url && event.button == 0) // Left click
    loadURI(url);
  if (url && event.button == 1) // Middle click
    gBrowser.addTab(url);
  if (url && event.button == 2) // Right click
    gBrowser.selectedTab = gBrowser.addTab(url);
};

this.openAllInTabs = function (event) {
  var nodeList = event.target.parentNode.childNodes;
  for (var i = 0; i < nodeList.length; i++) {
    var url = nodeList[i].getAttributeNS(cbNS, "url");
    if (url)
      gBrowser.addTab(url);
  }
};

The following three examples create the exact same button. The difference lies in the way the menu for this button is created. In the first example, the menu is created by parsing a variable that stores an XML string. In the second example, the menu is created with pure JavaScript. And in the third example, the menu is stored indide the "Help" tab of the button.

/*Initialization code*/
/**
 *   Left click on button               - Open page in a new window
 *   Left click on           dropmarker - Open menu popup
 *  Right click on button or dropmarker - Open custom button context popup
 *   Left click on menuitems            - Open page in the current tab
 * Middle click on menuitems            - Open page in a new tab in the background
 *  Right click on menuitems            - Open page in a new tab in the foreground
 */

const cbNS = "http://xsms.nm.ru/custombuttons/";

// xulns = http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul.
// Is a global variable defined by Custom Buttons.
var menu = "<menupopup xmlns=\"" + xulns + "\" xmlns:cb=\"" + cbNS + "\"" +
  " onclick=\"this.parentNode.menuClick(event)\"" +
  " oncommand=\"this.parentNode.menuCommand(event)\">" +
  "<menu class=\"menu-iconic\"" +
  " image=\"chrome://global/skin/dirListing/folder.png\" label=\"Search\">" +
  "<menupopup>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://www.google.com/favicon.ico\"" +
  " label = \"Google\"" +
  " cb:url=\"https://www.google.com/\"/>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://search.yahoo.com/favicon.ico\"" +
  " label=\"Yahoo\"" +
  " cb:url=\"https://search.yahoo.com/\"/>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://www.bing.com/favicon.ico\"" +
  " label=\"Bing\"" +
  " cb:url=\"https://www.bing.com/\"/>" +
  "<menuseparator/>" +
  "<menuitem" +
  " label=\"Open All in Tabs\"" +
  " onclick=\"document.getElementById('" + this.id + "').openAllInTabs(event);\"/>" +
  "</menupopup>" +
  "</menu>" +
  "<menuitem" +
  " class=\"menuitem-iconic\"" +
  " image=\"http://en.wikipedia.org/favicon.ico\"" +
  " label=\"Wikipedia\"" +
  " cb:url=\"http://en.wikipedia.org/\"/>" +
  "</menupopup>";

this.appendChild($XML(menu)); // This appends the menu itself to the button.

var nodeList = this.getElementsByTagName("menuitem"); // Gets all menuitems in this button.

for (var i = 0; i < nodeList.length; i++) { // This loop sets the tooltip for each menuitem.
  var label = nodeList[i].getAttribute("label");
  var url = nodeList[i].getAttributeNS(cbNS, "url");
  if (label && url)
    nodeList[i].setAttribute("tooltiptext", label + "\n" + url);
}

this.type = "menu-button";

this.orient = "horizontal";

this.menuClick = function (event) {
  event.preventDefault();
  event.stopPropagation();
  this.open = false; // This closes the popup after middle/right clicks on menuitems.
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url && event.button == 1) // Middle click
    gBrowser.addTab(url);
  if (url && event.button == 2) // Right click
    gBrowser.selectedTab = gBrowser.addTab(url);
};

this.menuCommand = function (event) { // Left click
  event.stopPropagation();
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url)
    loadURI(url);
};

this.buttonCommand = function (event) { // Left click on button, not dropmarker
  var url = "about:config";
  window.open(url, "_blank", "chrome,centerscreen,width=640,height=480");
};

this.openAllInTabs = function (event) {
  var nodeList = event.target.parentNode.childNodes;
  for (var i = 0; i < nodeList.length; i++) {
    var url = nodeList[i].getAttributeNS(cbNS, "url");
    if (url)
      gBrowser.addTab(url);
  }
};

this.setAttribute("oncommand", "this.buttonCommand(event)");

function $XML(aXML) { // Return parsed XML
  aXML = aXML.replace(/>\s+</g, "><"); // Linearize XML
  return (new DOMParser).parseFromString(aXML, "application/xml").documentElement;
}
/*Initialization code*/
/**
 *   Left click on button               - Open page in a new window
 *   Left click on           dropmarker - Open menu popup
 *  Right click on button or dropmarker - Open custom button context popup
 *   Left click on menuitems            - Open page in the current tab
 * Middle click on menuitems            - Open page in a new tab in the background
 *  Right click on menuitems            - Open page in a new tab in the foreground
 */

const cbNS = "http://xsms.nm.ru/custombuttons/";

// xulns = http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul.
// Is a global variable defined by Custom Buttons.
var mainPopup = document.createElementNS(xulns, "menupopup");
mainPopup.setAttribute("xmlns:cb", cbNS);
mainPopup.setAttribute("onclick", "this.parentNode.menuClick(event);");
mainPopup.setAttribute("oncommand", "this.parentNode.menuCommand(event);");

var subMenu = mainPopup.appendChild(document.createElementNS(xulns, "menu"));
subMenu.setAttribute("class", "menu-iconic");
subMenu.setAttribute("label", "Search");
subMenu.setAttribute("image", "chrome://global/skin/dirListing/folder.png");

var subPopup = subMenu.appendChild(document.createElementNS(xulns, "menupopup"));

var mItem1 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem1.setAttribute("class", "menuitem-iconic");
mItem1.setAttribute("label", "Google");
mItem1.setAttribute("image", "http://www.google.com/favicon.ico");
mItem1.setAttributeNS(cbNS, "cb:url", "https://www.google.com");

var mItem2 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem2.setAttribute("class", "menuitem-iconic");
mItem2.setAttribute("label", "Yahoo");
mItem2.setAttribute("image", "http://search.yahoo.com/favicon.ico");
mItem2.setAttributeNS(cbNS, "cb:url", "https://search.yahoo.com");

var mItem3 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem3.setAttribute("class", "menuitem-iconic");
mItem3.setAttribute("label", "Bing");
mItem3.setAttribute("image", "http://www.bing.com/favicon.ico");
mItem3.setAttributeNS(cbNS, "cb:url", "https://www.bing.com");

subPopup.appendChild(document.createElementNS(xulns, "menuseparator"));

var mItem4 = subPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem4.setAttribute("label", "Open All in Tabs");
mItem4.setAttribute("onclick", "document.getElementById('" + this.id + "').openAllInTabs(event);");

var mItem5 = mainPopup.appendChild(document.createElementNS(xulns, "menuitem"));
mItem5.setAttribute("class", "menuitem-iconic");
mItem5.setAttribute("label", "Wikipedia");
mItem5.setAttribute("image", "http://en.wikipedia.org/favicon.ico");
mItem5.setAttributeNS(cbNS, "cb:url", "http://en.wikipedia.org");

this.appendChild(mainPopup); // This appends the menu itself to the button.

var nodeList = this.getElementsByTagName("menuitem"); // Gets all menuitems in this button.

for (var i = 0; i < nodeList.length; i++) { // This loop sets the tooltip for each menuitem.
  var label = nodeList[i].getAttribute("label");
  var url = nodeList[i].getAttributeNS(cbNS, "url");
  if (label && url)
    nodeList[i].setAttribute("tooltiptext", label + "\n" + url);
}

this.type = "menu-button";

this.orient = "horizontal";

this.menuClick = function (event) {
  event.preventDefault();
  event.stopPropagation();
  this.open = false; // This closes the popup after middle/right clicks on menuitems.
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url && event.button == 1) // Middle click
    gBrowser.addTab(url);
  if (url && event.button == 2) // Right click
    gBrowser.selectedTab = gBrowser.addTab(url);
};

this.menuCommand = function (event) { // Left click
  event.stopPropagation();
  var url = event.target.getAttributeNS(cbNS, "url");
  if (url)
    loadURI(url);
};

this.buttonCommand = function (event) { // Left click on button, not dropmarker
  var url = "about:config";
  window.open(url, "_blank", "chrome,centerscreen,width=640,height=480");
};

this.openAllInTabs = function (event) {
  var nodeList = event.target.parentNode.childNodes;
  for (var i = 0; i < nodeList.length; i++) {
    var url = nodeList[i].getAttributeNS(cbNS, "url");
    if (url)
      gBrowser.addTab(url);
  }
};

this.setAttribute("oncommand", "this.buttonCommand(event)");

Example 1

/*Initialization code*/
this.dragAndDropHandler = {
  handleEvent : function (aEvt) {
    var types = aEvt.dataTransfer.types; // All data types found in the dragged data.
    switch (aEvt.type) {
    case "dragover":
      // Warning!!! The dragover event is triggered "every few hundred milliseconds".
      // That's what MDN docs says. https://developer.mozilla.org/en-US/docs/Web/Events/dragover
      // In the past, I think to remember that said every 100 milliseconds.
      // So be carefull what you put in here because it will run several times per second.
      aEvt.preventDefault();
      break;
    case "drop":
      if (types.contains("text/html") || types.contains("text/plain") ||
        types.contains("text/x-moz-text-internal")) {
        let data = aEvt.dataTransfer.getData('text/html');
        var urlArr = /href="?([^"\s]+)"?\s*/.exec(data); // Check if what is been dragged contains a link.
        if (!urlArr)                                               // If it's not a link...
          urlArr = aEvt.dataTransfer.getData('text/plain') ||
            aEvt.dataTransfer.getData('text/x-moz-text-internal'); // ...treat it as plain text.
        if (urlArr) {
          if (typeof urlArr === "object")                // If an URL was found, log the URL...
            LOG(urlArr[1]);
          else                                           // ...else, log plain text.
            LOG(urlArr);
        }
      }
      aEvt.preventDefault();
      break;
    }
  }
};

this.dragAndDropHandler can be used by setting attributes...

/*Initialization code*/
// The "drop" event will not trigger if the "dragover" event is not declared.
this.setAttribute("ondragover", "this.dragAndDropHandler.handleEvent(event);");

this.setAttribute("ondrop", "this.dragAndDropHandler.handleEvent(event);");

...or by adding event listeners.

/*Initialization code*/
var uid = "__unique_identifier_" + this.id;
if (!(uid in window)) { // Ensures that event listeners are added just once.
  window[uid] = true;
  // The "drop" event will not trigger if the "dragover" event is not declared.
  this.addEventListener("dragover", this.dragAndDropHandler, false);
  this.addEventListener("drop", this.dragAndDropHandler, false);
}

Example 2 - Simpler examples

By setting attributes

/*Initialization code*/
// The "drop" event will not trigger if the "dragover" event is not declared.
this.ondragover = function (aEvt) {
  aEvt.preventDefault();
};

// This will log to the console all data types found in the droped data.
this.ondrop = function (aEvt) {
  var listOfTypes = [];
  for (var type = 0; type < aEvt.dataTransfer.types.length; type++)
    listOfTypes.push(aEvt.dataTransfer.types[type]);
  LOG(listOfTypes.join("\n"));
  aEvt.preventDefault();
};

By adding event listeners

/*Initialization code*/
var uid = "__unique_identifier_" + this.id;
if (!(uid in window)) { // Ensures that event listeners are added just once.
  window[uid] = true;
  // The "drop" event will not trigger if the "dragover" event is not declared.
  this.addEventListener("dragover", function (aEvt) {
    aEvt.preventDefault();
  }, false);

  // This will log to the console all data types found in the droped data.
  this.addEventListener("drop", function (aEvt) {
    var listOfTypes = [];
    for (var type = 0; type < aEvt.dataTransfer.types.length; type++)
      listOfTypes.push(aEvt.dataTransfer.types[type]);
    LOG(listOfTypes.join("\n"));
    aEvt.preventDefault();
  }, false);

}

Hide dropmarker - for "menu" and/or "menu-button" types

Example 1

/*Initialization*/
this.hideDropMarker = function () {
  var dropMarker = document.getAnonymousElementByAttribute(self, "class", "toolbarbutton-menu-dropmarker");
  if (dropMarker) {
    dropMarker.setAttribute("hidden", "true");
  } else {
    setTimeout(self.hideDropMarker, 10);
  }
}
this.hideDropMarker();

Example 2

/*Initialization*/
(function dropmarkerVisibility() {
  let dropMarker = document.getAnonymousElementByAttribute(self, "class", "toolbarbutton-menu-dropmarker");
  if (dropMarker)
    dropMarker.setAttribute("hidden", true);
  else
    setTimeout(function () {
      dropmarkerVisibility();
    }, 50);
})();

Open menu on mouse over and hide on mouse out

Example 1

/*Initialization*/
this.timer = 0;

// Opens de menu on mouse over.
this.onmouseover = function (event) {
  this.open = true;
  clearTimeout(this.timer);
};

// Closes de menu on mouse out.
this.onmouseout = function (event) {
  if (!event.relatedTarget || Array.indexOf(this.getElementsByTagName("*"), event.relatedTarget) === -1) {
    clearTimeout(this.timer);
    this.timer = setTimeout(function () {
        self.open = false;
      }, 200); // 200 - delay for closing the menu in milliseconds.
  }
};

Example 2 - variation with open delay

/*Initialization*/
this.timer = 0;

// Opens de menu on mouse over.
this.onmouseover = function () {
  clearTimeout(this.timer);
  this.timer = setTimeout(function () {
      self.open = true;
    }, 200); // 200 - delay for open the menu in milliseconds.
};

// Closes de menu on mouse out.
this.onmouseout = function () {
  clearTimeout(this.timer);
  this.timer = setTimeout(function () {
      self.open = false;
    }, 200); // 200 - delay for closing the menu in milliseconds.
};

Example 3 - variation targeting the menu popup

/*Initialization*/
let thisMenupopup = this.getElementsByTagName("menupopup")[0];

if (thisMenupopup) {
  this.timer = 0;

  // Opens de menu on mouse over.
  this.onmouseover = function () {
    clearTimeout(this.timer);
    this.timer = setTimeout(function () {
        thisMenupopup.openPopup(self, "after_start", 0, 0, false, false);
      }, 200); // 200 - delay for open the menu in milliseconds.
  };

  // Closes de menu on mouse out.
  this.onmouseout = function () {
    clearTimeout(this.timer);
    this.timer = setTimeout(function () {
        thisMenupopup.hidePopup();
      }, 200); // 200 - delay for closing the menu in milliseconds.
  };
}

Prompts, alerts, etc

Examples of the various output messages, examples of data requests from the user and so forth

/*Code*/
createMsg("title").aMsg("message");
/*Code*/
custombuttons.alertBox("title", "description");
/*Code*/
custombuttons.alertSlide("title", "description");
/*Code*/
// close window or click cancel alerts "false,default,false"
var box = custombuttons.promptBox("title", "description", "default");
if (box[0]) {
  alert(box[0] + "," + box[1] + "," + box[2]);
} else {
  alert(box[0] + "," + box[1] + "," + box[2]);
}
/*Code*/
// close window or click cancel alerts "false,default,true"
var box = custombuttons.promptBox("title", "description", "default", {
    value : true,
    prompt : "option"
  });
if (box[0]) {
  alert(box[0] + "," + box[1] + "," + box[2]);
} else {
  alert(box[0] + "," + box[1] + "," + box[2]);
}
/*Code*/
// close window alerts "option b"
var box = custombuttons.confirmBox("title", "description", "option a", "option b");
if (box) {
  alert("option a");
} else {
  alert("option b");
}
/*Code*/
// close window alerts "option c"
var box = custombuttons.confirmBox3("title", "description", "option a", "option c", "option b");
if (box == 0)
  alert("option a");
if (box == 1)
  alert("option c");
if (box == 2)
  alert("option b");
/*Code*/
// close window or click cancel alerts "false,option a"
var arr = ["option a", "option b", "option c"];
var box = custombuttons.selectBox("title", "description", arr);
if (box[0]) {
  alert(box[0] + "," + arr[box[1].value]);
} else {
  alert(box[0] + "," + arr[box[1].value]);
}
/*Code*/
// close window or click no alerts "option a,true,option b,true,option c,true"
var arr = new Array();
arr[0] = ["option a", true];
arr[1] = ["option b", true];
arr[2] = ["option c", true];
var dialog = custombuttons.checkboxDialog(this, arr,
    "title", "group", "header", "description", "yes", "no",
    "help", "help message", "disclosure", "disclosure message");
if (dialog) {
  alert(arr);
  for (var i = 0; i < dialog.chosen.length; i++)
    alert(dialog.chosen[i].index + "," + dialog.chosen[i].label);
} else {
  alert(arr);
}
/*Code*/
// close window or click no alerts "option a,true,option b,false,option c,false"
var arr = new Array();
arr[0] = ["option a", true];
arr[1] = ["option b", false];
arr[2] = ["option c", false];
var dialog = custombuttons.radioboxDialog(this, arr,
    "title", "group", "header", "description", "yes", "no",
    "help", "help message", "disclosure", "disclosure message");
if (dialog) {
  alert(arr);
  for (var i = 0; i < dialog.chosen.length; i++)
    alert(dialog.chosen[i].index + "," + dialog.chosen[i].label);
} else {
  alert(arr);
}

This function is similar to the custombuttons.alertSlide function, but this one allows you to use a custom image. It also works (should) on platforms that don't implement nsIAlertsService.

function notifyme(aImg, aTitle, aMsg) {
  let notFeature = custombuttons.getPrefs("notification.feature.enabled");
  try {
    let nsIAlertsService = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService);
    if (!notFeature) {
      custombuttons.setPrefs("notification.feature.enabled", true);
      setTimeout(function () {
        nsIAlertsService.showAlertNotification(aImg, aTitle, aMsg, false, "", null);
        custombuttons.setPrefs("notification.feature.enabled", false);
      }, 100);
    } else
      nsIAlertsService.showAlertNotification(aImg, aTitle, aMsg, false, "", null);
  } catch (aEr) {
    let win = Cc['@mozilla.org/embedcomp/window-watcher;1']
      .getService(Ci.nsIWindowWatcher)
      .openWindow(null, 'chrome://global/content/alerts/alert.xul',
        '_blank', 'chrome,titlebar=no,popup=yes', null);
    win.arguments = [aImg, aTitle, aMsg, false, ''];
  }
}

// Usage
notifyme("chrome://branding/content/icon32.png", "Title", "Message");

This is a very basic example of usage of the PopupNotifications.jsm module.

function notify(aMsg, aDel) {
  let nt = PopupNotifications.show(gBrowser.selectedBrowser, self.id +
      "-Door-Hanger", aMsg, self.id, null, null, null);
  (aDel) && nt.remove();
}

// Usage
notify("Message");          // Show door hanger notification
setTimeout(function () {
  notify("", true);         // Remove after...
}, 5000);                   // ...5 seconds.
var soundFile = "C:\\WINDOWS\\Media\\notify.wav";
var sound = Cc["@mozilla.org/sound;1"].createInstance(Ci.nsISound);
sound.playSystemSound(soundFile);

Working with files

/*Code*/
var localFile = Cc["@mozilla.org/file/local;1"].
  createInstance(Ci.nsILocalFile);
localFile.initWithPath("C:\\WINDOWS\\system32\\notepad.exe");
localFile.launch();
/*Code*/
var localFile = Cc["@mozilla.org/file/local;1"].
  createInstance(Ci.nsILocalFile);
var process = Cc["@mozilla.org/process/util;1"].
  createInstance(Ci.nsIProcess);
var args = ["C:\\Program Files\\Mozilla Firefox\\README.txt"];
localFile.initWithPath("C:\\WINDOWS\\system32\\notepad.exe");
process.init(localFile);
process.run(false, args, args.length);
/*Code*/
// chrome folder does not exist by default
var file = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties).
  get("UChrm", Ci.nsIFile);
file.append("userChrome.css");
var localFile = Cc["@mozilla.org/file/local;1"].
  createInstance(Ci.nsILocalFile);
var process = Cc["@mozilla.org/process/util;1"].
  createInstance(Ci.nsIProcess);
var args = [file.path];
localFile.initWithPath("C:\\WINDOWS\\system32\\notepad.exe");
process.init(localFile);
process.run(false, args, args.length);
/*Code*/
// single pane
var localFile = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties).
  get("Home", Ci.nsILocalFile);
localFile.reveal();
/*Code*/
// default view
var file = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties).
  get("Home", Ci.nsIFile);
var localFile = Cc["@mozilla.org/file/local;1"].
  createInstance(Ci.nsILocalFile);
var process = Cc["@mozilla.org/process/util;1"].
  createInstance(Ci.nsIProcess);
var args = ["/e,", file.path];
localFile.initWithPath("C:\\WINDOWS\\explorer.exe");
process.init(localFile);
process.run(false, args, args.length);
/*Code*/
var file = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties).
  get("ProfD", Ci.nsIFile);
file.append("custombuttons");
var environment = Cc["@mozilla.org/process/environment;1"].
  getService(Ci.nsIEnvironment);
var localFile = Cc["@mozilla.org/file/local;1"].
  createInstance(Ci.nsILocalFile);
var process = Cc["@mozilla.org/process/util;1"].
  createInstance(Ci.nsIProcess);
var args = ["/k", "cd /d " + file.path + " & title Custom Buttons & dir"];
localFile.initWithPath(environment.get("ComSpec"));
process.init(localFile);
process.run(false, args, args.length);
function openPath(aPath, aArgs) {
  var nsIFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  nsIFile.initWithPath(aPath);
  try {
    if (nsIFile.isDirectory())                                   // If aPath is a Directory...
      nsIFile.reveal();                                          // ...try to open it.
    else if (!nsIFile.isDirectory() && !nsIFile.isExecutable())  // If aPath is not a Directory nor an executable...
      nsIFile.launch();                                          // ...try to launch it.
    else if (!nsIFile.isDirectory() && nsIFile.isExecutable()) { // If aPath is an executable, try to execute it.
      var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
      try {
        process.init(nsIFile);                               // Initialize nsIProcess.
        (aArgs === undefined || aArgs[0] === "")             // Check if there are arguments.
         ? process.runw(false, null, null)                   // Run nsIFile WITHOUT arguments...
         : process.runw(false, aArgs, aArgs.length);         // ...or run nsIFile WITH arguments.
      } catch (aError) {
        Cu.reportError(aError);
      }
    }
  } catch (aError) {
    Cu.reportError(aError);
  }
}

Usage

Usage:openPath(aPath, aArgs);
  • aPath: Any valid and existent path. Absolute or "constructed".
    • Path examples absolute:
      "C:\\Windows\\notepad.exe" // Windows path
      "/usr/bin/kwrite" // "Linux" path
    • Path example from OS.File API:
      OS.Constants.Path.desktopDir // Desktop path in all platforms
    • Path example from "Directory service":
      Services.dirsvc.get("Desk", Ci.nsIFile) // Desktop path in all platforms
    • Path example "constructed" with OS.File API:
      OS.Path.join(OS.Constants.Path.libDir, "seamonkey.exe")
    • Path example "constructed" with "Directory service":
      let baseDir = Services.dirsvc.get("CurProcD", Ci.nsIFile);
      baseDir.append("seamonkey.exe");
  • aArgs: An array of arguments. ONLY for executable files.
    • Example with one argument:
      ["arg"]
    • Example with n arguments:
      ["arg-1", "arg-2", "arg-n"]
Note: it's MANDATORY to use double backslashes "\\" in all Windows paths.
/**
 * Practical examples
 */

// Open Desktop directory on any platform
// Option 1
openPath(OS.Constants.Path.desktopDir);
// Option 2
openPath(Services.dirsvc.get("Desk", Ci.nsIFile));

// Open Home directory on any platform
// Option 1
openPath(OS.Constants.Path.homeDir);
// Option 2
openPath(Services.dirsvc.get("Home", Ci.nsIFile));

// Execute a new instace of Firefox with profile selector.
// Short version
openPath(OS.Path.join(OS.Constants.Path.libDir, "firefox.exe"), ["-no-remote", "-p"]);
// or long version...
let profDir = Services.dirsvc.get("CurProcD", Ci.nsIFile);
profDir.append("firefox.exe");
openPath(profDir, ["-no-remote", "-p"]);

// Execute a new instace of SeaMonkey with profile selector.
// Short version
openPath(OS.Path.join(OS.Constants.Path.libDir, "seamonkey.exe"), ["-no-remote", "-p"]);
// or long version...
let profDir = Services.dirsvc.get("CurProcD", Ci.nsIFile);
profDir.append("seamonkey.exe");
openPath(profDir, ["-no-remote", "-p"]);

// Execute Notepad in Windows.
openPath("C:\\Windows\\notepad.exe");

// Execute KWrite in Linux.
openPath("/usr/bin/kwrite");

// Open a Firefox profile called "default" in Linux.
openPath("/usr/bin/firefox", ["-no-remote", "-p", "default"]);

File creation function


function addfile(parentpath, filename) {
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  file.initWithPath(parentpath);
  file.append(filename);
  if (!file.exists() || !file.isFile()) { // if it doesn't exist, create
    file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
  }
}

Folder add function


function adddir(parentpath, newdir) {
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  file.initWithPath(parentpath);
  file.append(newdir);
  if (!file.exists() || !file.isDirectory()) { // if it doesn't exist, create
    file.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
  }
}

Profile address

var currProfD = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
var profileDir = currProfD.path;

Doubling slashes in the path.

function slashdouble(path) {
  var path = path.replace(/\\/g, "\\")
    return (path)
}

Function of reading from file

function readfile(parentdir, filename, fileout) {
  var filefullpath = parentdir + "\\" + filename;
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  file.initWithPath(filefullpath);
  Cu.import("resource://gre/modules/NetUtil.jsm");
  NetUtil.asyncFetch(file, function (inputStream, status) {
    if (!Components.isSuccessCode(status)) {
      data = "An error occured"; // To notify Interval func on error
      return;
    }
    data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
    if (!data) {
      data = "File contains no data";
    } // To notify Interval func on empty file
  });
}
readfile(feedsdir, "myfeeds.txt");
var xInterval = setInterval(function () {
    if (typeof(data) == "undefined") {
      return;
    } else {
      alert(data);
      clearInterval(xInterval);
      // Parser code here, data is valid
    }
  }, 1101);

Open folder

var Dir = "C:\\windows\\Media"; // the path to a folder, do not forget about the double slashes in the path
var nsLocalFile = Components.Constructor("@mozilla.org/file/local;1", "nsILocalFile", "initWithPath");
new nsLocalFile(Dir).reveal();

Save the file with a choice

MyFile = "test"; //the contents of the file
MyFilename = "test.txt"; // the file name
var nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"]
  .createInstance(nsIFilePicker);
fp.init(window, "", fp.modeSave);
fp.defaultString = MyFilename;
fp.appendFilters(fp.filterHTML);
fp.appendFilters(fp.filterAll);
if (fp.show() == fp.returnCancel)
  return;
var stream = Cc['@mozilla.org/network/file-output-stream;1']
  .createInstance(Ci.nsIFileOutputStream);
stream.init(fp.file, 0x02 | 0x20 | 0x08, 0666, 0);
stream.write(MyFile, MyFile.length);
stream.close();

Converting strings to unicode

var mytext = "Text"
  var uc = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
uc.charset = "utf-8";
unicodetext = uc.ConvertFromUnicode(mytext);

To create a new resource resource:rootc

//icon
// data:image/png;base64,CODE

Cu.import("resource://gre/modules/FileUtils.jsm");
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath("C:\\");

var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var rph = ios.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
var uri = ios.newFileURI(file);
rph.setSubstitution("rootc", uri);

alert("resource:rootc")
getBrowser().selectedTab = getBrowser().addTab("resource:rootc");

Start external program with arguments

var prgpath = "C:\\windows\\ping.exe"; // the path to the executable file, do not forget about the double slashes in the path
var args = ['-n', '6', 'google.com']; // arguments are separated by a space. i.e. string bla.exe -open "c:\program files\ololo\ololo.txt" will have arguments var args = ['-open','"c:\program', 'files\ololo\ololo.txt"'];
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
file.initWithPath(prgpath);
var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, args, args.length);

Function writes to the file, overwriting

function data2fileoverwrite(filepath, data) {
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  file.initWithPath(filepath);
  Cu.import("resource://gre/modules/NetUtil.jsm");
  Cu.import("resource://gre/modules/FileUtils.jsm");

  var ostream = FileUtils.openSafeFileOutputStream(file)
    var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
  converter.charset = "UTF-8";
  var istream = converter.convertToInputStream(data);

  // The last argument (the callback) is optional.
  NetUtil.asyncCopy(istream, ostream, function (status) {
    if (!Components.isSuccessCode(status)) {
      // Handle error!
      return;
    }
    // Data has been written to the file.
  });
};

Feature writing to a file by adding at the end

function append2file(filepath, text) {
  var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  file.initWithPath(filepath);
  var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
  var converter = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream);
  stream.init(file, 0x02 | 0x10, 0664, 0);
  converter.init(stream, "UTF-8", 0, 0x1010);
  converter.writeString("\u101D\u101A"); //If you want to add a new row
  converter.writeString(text);
  converter.close();
  stream.close();
}
append2file("C:\\testfile.txt", "ololololololo!");

Select the file and getting his path

const nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(window, "Select any file!", nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText);

var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
  var file = fp.file;
  // Get the path as string. Note that you usually won't
  // need to work with the string paths.
  var path = fp.file.path;
  alert("You have chosen a file:\n" + path);
  // work with returned nsILocalFile...
}

Working with clipboard, text data, etc

/*Code*/
// copy string to system clipboard
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
  getService(Ci.nsIClipboardHelper);
clipboard.copyString("test");
/*Code*/
// internal clipboard - uppercase write, read, clear
gClipboard.Write(document.location.href);
alert(gClipboard.Read());
gClipboard.Clear();
alert(gClipboard.Read());
/*Code*/
// system clipboard - lowercase write, read, clear
gClipboard.write(content.document.location.href);
alert(gClipboard.read());
gClipboard.clear();
alert(gClipboard.read());
/*Code*/
var commands = document.getElementsByTagName("command");
var out = new Array();
var info = Cc["@mozilla.org/xre/app-info;1"].
  getService(Ci.nsIXULAppInfo);
out.push(info.name + " " + info.version, "");
out.push('windowtype="' + document.documentElement.getAttribute("windowtype") + '"', "");
for (var i = 0; i < commands.length; i++) {
  var id = commands[i].getAttribute("id");
  var oncommand = commands[i].getAttribute("oncommand");
  if (id && oncommand)
    out.push(id);
}
var req = new XMLHttpRequest();
req.open("GET", "chrome://global/content/platformHTMLBindings.xml", false);
req.send(null);
var doc = req.responseXML;
var handlers = doc.getElementsByTagName("handler");
for (var i = 0; i < handlers.length; i++) {
  var command = handlers[i].getAttribute("command");
  if (command && out.indexOf(command) == -1)
    out.push(command);
}
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
  getService(Ci.nsIClipboardHelper);
clipboard.copyString(out.join("\r\n"));
/*Code*/
var file = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties).
  get("Home", Ci.nsIFile);
alert(file.path);
var uri = Cc["@mozilla.org/network/io-service;1"].
  getService(Ci.nsIIOService).
  newFileURI(file);
alert(uri.spec);
var localFile = file.QueryInterface(Ci.nsILocalFile);
localFile.reveal();
/*Code*/
var ds = Cc["@mozilla.org/file/directory_service;1"].
  getService(Ci.nsIProperties);
var nsDirectoryServiceDefs = ["AppData", "ApplMenu", "Buckt", "CmDeskP", "CmPrgs", "CmStrt",
  "CntlPnl", "Cntls", "CookD", "CurProcD", "CurWorkD", "Desk", "DeskP", "DeskV", "DfltDwnld",
  "Docs", "Drivs", "DrvD", "Exts", "Favs", "Fnts", "GreD", "Home", "IntrntSts", "ISrch", "LibD",
  "LocalAppData", "LocApp", "LocDocs", "LocDsk", "LocFrmwrks", "Locl", "LoclIntrntPlgn", "LocPrfs",
  "Mov", "Music", "netH", "NetW", "OS2Dir", "Pct", "Pers", "Prfs", "PrntHd", "Prnts", "ProgF",
  "Progs", "Rcnt", "Shdwn", "SndTo", "Strt", "SysD", "TmpD", "Tmpls","Trsh", "ULibDir", "UsrApp",
  "UsrDocs", "UsrDsk", "UsrFrmwrks", "UsrIntrntPlgn", "UsrPrfs", "WinD", "XCurProcD", "XDGDesk",
  "XDGDocs", "XDGDwnld", "XDGMusic", "XDGPict", "XDGPubSh", "XDGTempl", "XDGVids", "XpcomLib"];
var nsAppDirectoryServiceDefs = ["AChrom", "AChromDL", "APluginsDL", "APlugns", "AppRegD",
  "AppRegF", "ARes", "BMarks", "cachePDir", "DefProfLRt", "DefProfRt", "DefRt", "DLoads",
  "ExtPrefDL", "LclSt", "PrefD", "PrefDL", "PrefDOverride", "PrefF", "PrfDef", "ProfD", "profDef",
  "ProfDefNoLoc", "ProfLD", "SHARED", "SrchF", "SrchPluginsDL", "SrchPlugns", "UChrm", "UHist",
  "UMimTyp", "UPnls", "UsrSrchPlugns", "UStor", "XPIClnupD"];
var nsBrowserDirectoryServiceDefs = ["ExistingPrefOverride"];
var nsXULAppAPI = ["ProfDS", "ProfLDS", "UAppData", "XREAppDist", "XREExeF", "XREExtDL",
  "XRESysLExtPD", "XRESysSExtPD", "XREUSysExt"];
var props = new Array();
var out = new Array();
props = props.concat(nsDirectoryServiceDefs);
props = props.concat(nsAppDirectoryServiceDefs);
props = props.concat(nsBrowserDirectoryServiceDefs);
props = props.concat(nsXULAppAPI);
for (var i = 0; i < props.length; i++) {
  if (ds.has(props[i])) {
    var file = ds.get(props[i], Ci.nsIFile);
    if (file && file.path) {
      out.push([props[i], file.path]);
    }
  }
}
out.sort(function (a, b) {
  return a[1] > b[1]
});
var width = out.reduce(function (a, b) {
    return a[0].length > b[0].length ? a : b
  })[0].length;
for (var i = 0; i < out.length; i++) {
  out[i] = out[i][0] + Array(width + 2 - out[i][0].length).join(" ") + out[i][1];
}
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
  getService(Ci.nsIClipboardHelper);
clipboard.copyString(out.join("\r\n"));

Obtain the value from the Clipboard

var text = custombuttonsUtils.gClipboard.read();

Write the value to the Clipboard

var text = "This text will be placed into the Clipboard";
const gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].
  getService(Ci.nsIClipboardHelper);
gClipboardHelper.copyString(text);

Attention!! If you add one of the components of the string (for example, if you enter through the prompt):

Add it with a numeric variable is like adding rows to it around, use the following option:

var a = prompt("Enter the number of:");
var b = 5;
var n = a + b;
var m = (+a) + (+b);
alert("a=" + a + "\nb=5\na+b=" + n + "\n(+a)+(+b)=" + m);
// do not forget about this feature of javascript

Break a line into pieces at a delimiter

var stroka = "123=43*44o=lol*=rm8658oo*=uenrnk7n*=4upa6m";
var chkpoint = "*="; // This separator
var arrayOfStrings = stroka.split(chkpoint);
pervyi_element = arrayOfStrings[0]; //is 123 = 43 * 44o = lol
vtoroi_element = arrayOfStrings[1]; //equal to rm8658oo
//etc

The length of the string

var stroka = "envosnvrohnorhnsonhoisd";
alert(stroka + "=" + stroka.length + " characters");

Get a piece of string

var stroka = "1234567890";
alert(stroka.substring(4, 7)); // 567
alert(stroka.substring(5)); // 67890

Converting strings to unicode

var mytext = "sdlgsdlgsdlvnlsfndn";
var uc = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
uc.charset = "utf-8";
unicodetext = uc.ConvertFromUnicode(mytext);

URL decoding with (unescape)

var nn = unescape('%64%6f%63%75%6d%65%6e');
alert(nn);

Insert text into the text area on page option 1.

var text = "Pasted text";
var cmd = "cmd_insertText";
var controller = document.commandDispatcher.getControllerForCommand(cmd);
if (controller && controller.isCommandEnabled(cmd)) {
  controller = controller.QueryInterface(Ci.nsICommandController);
  var params = Cc["@mozilla.org/embedcomp/command-params;1"]
    .createInstance(Ci.nsICommandParams);
  params.setStringValue("state_data", text);
  controller.doCommandWithParams(cmd, params);
}

Insert text into the text field on page option 2.

var intext = "The pasted text";
var theBox = document.commandDispatcher.focusedElement;
var pos = theBox.selectionStart;
var text = theBox.value.substring(0, pos) + intext + theBox.value.substring(pos, theBox.value.length);
theBox.value = text;
theBox.setSelectionRange(pos, pos + intext.length);

Paste the code into the current page version 1.

vnachalo = "< b>This bold text and a line at the top of the page< b>< hr>";
vkonec = "< br>< u>The underlined text and picture < img src='http://www.mozilla.org/favicon.ico'> at the end of the page</ u>";
content.document.body.innerHTML = vnachalo + content.document.body.innerHTML + vkonec; // remove spaces from HTML tags for it to work

Paste the code into the current page version 2.


var begin = "< b>This bold text and a line at the top of the page< b>< hr>";
var end = "< br >< u >The underlined text and picture < img src='http://www.mozilla.org/favicon.ico'> at the end of the page<					/ u >";
var doc = content.document; // remove spaces from HTML tags for it to work
var body = doc.body || doc.documentElement;
body.insertBefore(createDocumentFragment(begin), body.firstChild);
body.appendChild(createDocumentFragment(end));
function createDocumentFragment(html) {
  var tmp = doc.createElementNS("http://www.w3.org/1999/xhtml", "div");
  tmp.innerHTML = html;
  var df = doc.createDocumentFragment();
  while (tmp.hasChildNodes())
    df.appendChild(tmp.firstChild);
  return df;
}

Paste the code into the current page option 3.


  var begin = "< b >This bold text and a line at the top of the page< b >< hr >";
  var end = "< br >< u >The underlined text and picture < img src='http://www.mozilla.org/favicon.ico'> at the end of the page</ u >";
  var doc = content.document; // remove spaces from HTML tags for it to work
  var body = doc.body || doc.documentElement;
  body.insertBefore(createDiv(begin), body.firstChild);
  body.appendChild(createDiv(end));
  function createDiv(html) {
    var div = doc.createElementNS("http://www.w3.org/1999/xhtml", "div");
    div.innerHTML = html;
    return div;
  }

Getting the date 1.


  var t=new Date();
  var y=1900+t.getYear();
  var min=t.getMinutes(); if (min<10){min="0"+min};
  var h=t.getHours();
  var m=t.getMonth();switch(m){case 0: m="Jan";break;case 1: m="Feb";break;case 2: m="Mar";break;case 3: m="Apr";break;case 4: m="May";break;case 5: m="Jun";break;case 6: m="Jul";break;case 7: m="Aug";break;case 8: m="Sep";break;case 9: m="Oct";break;case 10: m="Nov";break;default: m="Dec";}
  var d=t.getDate();
  var curdate=y+"-"+d+"-"+m+"_"+h+":"+min;
  alert(curdate)

Getting the date 2.


  var t=new Date();
  var y=1900+t.getYear();
  var min=t.getMinutes(); if (min<10){min="0"+min};
  var h=t.getHours();
  var m = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][t.getMonth()];
  var d=t.getDate();
  var curdate=y+"-"+d+"-"+m+"_"+h+":"+min;
  alert(curdate)

Working with URLs, tabs, UI elements and so on

/*Code*/
// open page in the current tab
loadURI("http://www.google.com/");
/*Code*/
// open page in a new tab in the background
gBrowser.addTab("http://www.google.com/");
/*Code*/
// open page in a new tab in the foreground
gBrowser.selectedTab = gBrowser.addTab("http://www.google.com/");
/*Code*/
// open page in a new window
window.open("http://www.google.com/");
/*Code*/
// open page in the side panel
openWebPanel("Firefox", "about:logo");
/*Code*/
// open and close a page in the side panel
if (document.getElementById("sidebar-title").value) {
toggleSidebar();
} else {
openWebPanel("Firefox", "about:logo");
}
javascript:(function(){alert('test');})();
/*Code*/
loadURI("javascript:(function(){alert('test');})();");
javascript:(function(){alert("test");})();
/*Code*/
loadURI('javascript:(function(){alert("test");})();');
/*Code*/
// google "greasemonkey location hack" for more information
content.document.location.href = "javascript:(" + function() {
alert("test");
} + ")()";
/*Code*/
// next tab
gBrowser.tabContainer.advanceSelectedTab(1, true);
/*Code*/
// previous tab
gBrowser.tabContainer.advanceSelectedTab(-1, true);
/*Code*/
// move tab forward
if (gBrowser.selectedTab.nextSibling) gBrowser.moveTabForward();
else gBrowser.moveTabToStart();
/*Code*/
// move tab backward
if (gBrowser.selectedTab.previousSibling) gBrowser.moveTabBackward();
else gBrowser.moveTabToEnd();
/*Code*/
gBrowser.reloadTab(gBrowser.selectedTab);
/*Code*/
gBrowser.reloadAllTabs();
/*Code*/
gBrowser.removeTab(gBrowser.selectedTab);
/*Code*/
gBrowser.removeAllTabsBut(gBrowser.selectedTab);

Navigate History - Firefox and SeaMonkey

/*Code*/
// go back to the first page
gBrowser.webNavigation.gotoIndex(0);
/*Code*/
// go forward to the last page
gBrowser.webNavigation.gotoIndex(gBrowser.webNavigation.sessionHistory.count - 1);
/*Code*/
var toolbar = document.getElementById("toolbar-menubar");
var visibility = toolbar.getAttribute("autohide") == "true";
setToolbarVisibility(toolbar, visibility);
/*Code*/
var toolbar = document.getElementById("nav-bar");
var visibility = toolbar.collapsed;
setToolbarVisibility(toolbar, visibility);
/*Code*/
var toolbar = document.getElementById("PersonalToolbar");
var visibility = toolbar.collapsed;
setToolbarVisibility(toolbar, visibility);
/*Code*/
var toolbar = document.getElementById("addon-bar");
var visibility = toolbar.collapsed;
setToolbarVisibility(toolbar, visibility);
/*Code*/
var toolbar = document.getElementById("FindToolbar");
toolbar.hidden ? toolbar.onFindCommand() : toolbar.close();
/*Code*/
gBrowser.setStripVisibilityTo(!gBrowser.getStripVisibility());
/*Code*/
document.getElementsByAttribute("label", "Troubleshooting Information")[0].doCommand();
/*Code*/
// unicode hexadecimal 2026 - horizontal ellipsis character
document.getElementsByAttribute("label", "Add new button\u2026")[0].doCommand();
/*Initialization code*/
// toggle attribute in customize toolbar window
var info = Cc["@mozilla.org/xre/app-info;1"].
getService(Ci.nsIXULAppInfo);
var toolbox;
if (info.name == "Firefox" || info.name == "SeaMonkey") {
toolbox = document.getElementById("navigator-toolbox");
}
if (info.name == "Thunderbird") {
toolbox = document.getElementById("mail-toolbox");
}
var ob = <observes
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
element={toolbox.id}
attribute="iconsize"
onbroadcast={"document.getElementById('" + this.id + "').change()"}/>;
this.appendChild(custombuttonsUtils.makeXML(ob));
this.change = function() {
if (toolbox.getAttribute("iconsize") == "small") {
this.image = "chrome://global/skin/icons/information-16.png";
alert('attribute for the "Use Small Icons" option is checked');
}
if (toolbox.getAttribute("iconsize") == "large") {
this.image = "chrome://global/skin/icons/information-24.png";
alert('attribute for the "Use Small Icons" option is not checked');
}
}
this.change();

Management of the browser window.

window.restore(); // Restore
  window.maximize(); // Expand
  window.minimize() // Collapse
  window.close(); // Close
  goQuitApplication();// Close all windows
  window.moveTo(0,0);// Move the window to the specified coordinates (upper left corner)
  window.resizeTo(1024,738);// Resize the window

OPEN a new window size half the screen with the address or arbitrary html code.

var urla = "http://custombuttons.mozdev.org/"//---set the address or write code as in the line below
  var urlb = "data:text/html,ololo!"; //just text ololo!
  // 2 lines below to clear 1-HTML code of the page 2-collect the entire address
  var pagecode='<html><head><title>The title of the page</title><meta http-equiv="content-type" content="text		/html; charset=UTF-8"></head><body><hr><font size=+2 color=#ff1010><b>TEST</b></font><hr>		</body></html>';
  var urlc = "data:text/html,"+pagecode;

  var sizex = screen.width/2; //------screen width/2
  var sizey = screen.height/2; //-----screen height/2

Setup window: resizable - changing dimensions scrollbars - Show scroll bars menubar - the menu bar toolbar - browser panel location - Panel with the address bar personalbar - custom panels status - status bar

var winfeatures='resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes,location=yes,personalbar=yes,status=yes,width=' + sizex + ',height=' +sizey;
  var wnd = window.open(url, this.name,winfeatures ); // actually open the window with the address url and settings winfeatures
  if (wnd.focus) wnd.focus();

Add the current page to a specified folder in bookmarks

var folderName = "test";
  var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Ci.nsINavBookmarksService);
  var menuFolder = bmsvc. bookmarksMenuFolder;
  var f = bmsvc. getChildFolder (menuFolder, folderName);
  if (f == 0){ bmsvc. createFolder (menuFolder, folderName, bmsvc. DEFAULT_INDEX);
  f = bmsvc. getChildFolder (menuFolder, folderName);}
  PlacesCommandHook. bookmarkCurrentPage (false, f);

Open the url in a new tab without validation

var url="http://custombuttons.mozdev.org/";
  getBrowser (). selectedTab = getBrowser (). addTab (url);

Open the url in a new tab if it is not empty, if empty then the current

var url="http://custombuttons.mozdev.org/";
  if (getBrowser().currentURI.spec == "about:blank") loadURI (url);
  else{ getBrowser (). selectedTab = getBrowser (). addTab (url);

Open the url in a new tab if it is not empty, if empty then the current option 2. for FF 4+

var url = "http://custombuttons.mozdev.org/";
  if (
  (
  gBrowser.currentURI.spec == "about:blank"
  || gBrowser.currentURI.spec == cbu.getPrefs("browser.newtab.url")
  )
  && !gBrowser.selectedBrowser.webProgress.isLoadingDocument
  )
  loadURI(url);
  else
  gBrowser.selectedTab = gBrowser.addTab(url);

Open a url in the current tab

var url="http://custombuttons.mozdev.org/";
  loadURI (url);

Get the address of the current page

var url=getBrowser().currentURI.spec;

Listener to load the page.

var appcontent = document.getElementById("appcontent");
  appcontent.removeEventListener("DOMContentLoaded", pageloadedok, true);
  appcontent.addEventListener("DOMContentLoaded", pageloadedok, true);
  function pageloadedok(){custombuttons.alertSlide("Page loaded","Page loaded")}

Listener values change URL bar

var myExt_urlBarListener = {
    QueryInterface: function (aIID)
    {
      if (aIID.equals(Ci.nsIWebProgressListener) ||
      aIID.equals(Ci.nsISupportsWeakReference) ||
      aIID.equals(Ci.nsISupports))
      return this;
      throw Cr.NS_NOINTERFACE;
    },

    onLocationChange: function (aProgress, aRequest, aURI)
    {
      setTimeout(urlbarvaluechanged, 300);
    },

    onStateChange: function (a, b, c, d) {},
    onProgressChange: function (a, b, c, d, e, f) {},
    onStatusChange: function (a, b, c, d) {},
    onSecurityChange: function (a, b, c) {}
  };

  gBrowser.addProgressListener(myExt_urlBarListener,Ci.nsIWebProgress.NOTIFY_LOCATION);
  function urlbarvaluechanged(){custombuttons.alertSlide("urlbar value changed", "on "+gURLBar.value);}

Getting the current IP with duplicate in case the first server is unavailable.

var xmlhttp = new XMLHttpRequest();
  xmlhttp.open('GET', 'http://ip.xss.ru/', true);
  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4) {
      if (xmlhttp.status == 200) {
        var ip = xmlhttp.responseText;
        ipok = ip. match (/\d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d/) [0];
        alert("1="+ipok);
        return ipok;
      } else { getipalt(); }
    }
  };
  xmlhttp.send(null);

  function getipalt(){
    xmlhttp.open('GET', 'http://www.myip.ru/ru-RU/index.php', true);
    xmlhttp.onreadystatechange = function () {
      if (xmlhttp.readyState == 4) {
        if (xmlhttp.status == 200) {
          var ip = xmlhttp.responseText;

          ipok = ip. match (/\d?\d?\d\.\d?\d?\d\.\d?\d?\d\.\d?\d?\d/) [0];
          alert("2="+ipok);
          return ipok;
        }
      }
    };
    xmlhttp.send(null);
  }

Working with preferences (about:config)

/*Code*/
toOpenWindowByType("Preferences:ConfigManager", "chrome://global/content/config.xul");

Custom Buttons' built-in

/*Code*/
// test whether a preference exists
alert(custombuttons.isPref("dom.disable_open_during_load"));
// Will alert "true" if the preference exists or "false" if it doesn't.

Native code - Using "Services" module

var prefType = Services.prefs.getPrefType("preference.name");

if (prefType === 0) // Inexistent
  alert("Preference doesn't exists.");
else if (prefType === 32) // String
  alert("Preference type is 'string'.");
else if (prefType === 64) // Integer
  alert("Preference type is 'integer'.");
else if (prefType === 128) // Boolean
  alert("Preference type is 'boolean'.");
	h3#nav_f-2-pref-get-value Get preference value
	h4 Custom Buttons' built-in
/*Code*/
// get preference
alert(custombuttons.getPrefs("dom.disable_open_during_load"));

Native code - Using "Services" module

Services.prefs.getBoolPref("preference.name"); // Get "boolean" type preference

Services.prefs.getIntPref("preference.name"); // Get "integer" type preference

Services.prefs.getCharPref("preference.name"); // Get "string" type preference

Services.prefs.getComplexValue("preference.name",
    Ci.nsISupportsString).data; // Get "string" type preference with UNICODE support

Given a "string" type preference with the value C:\Folder\папка\フォルダ\夹 (It's a Windows path with words in Russian, Japanese and Chinese).

Using getCharPref will output...


And using getComplexValue will output...


Custom Buttons' built-in

/*Code*/
// set preference
custombuttons.setPrefs("dom.disable_open_during_load", false);
/*Code*/
// toggle preference
var s = "dom.disable_open_during_load";
custombuttons.setPrefs(s, !custombuttons.getPrefs(s));

Native code - Using "Services" module


Services.prefs.setBoolPref("preference.name", true); // Set "boolean" type preference

Services.prefs.setBoolPref("preference.name",
  !Services.prefs.getBoolPref("preference.name")); // Toggle "boolean" type preference

Services.prefs.setIntPref("preference.name", 100); // Set "integer" type preference

Services.prefs.setCharPref("preference.name", "Preference Value"); // Set "string" type preference

// Set "string" type preference with UNICODE support
var str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
str.data = "Preference 值";
Services.prefs.setComplexValue("preference.name", Ci.nsISupportsString, str);

Clear preference - Custom Buttons' built-in

/*Code*/
// clear preference
custombuttons.clearPrefs("dom.disable_open_during_load");

Clear preference - Native code using "Services" module

Called to clear a user set value from a specific preference. This will, in effect, reset the value to the default value. If no default value exists the preference will cease to exist.

Services.prefs.clearUserPref("preference.name");

Observe Preferences - Firefox, SeaMonkey and Thunderbird

/*Initialization code*/
// toggle preference in about:config
var prefs = Cc["@mozilla.org/preferences-service;1"]
  .getService(Ci.nsIPrefBranch);
var pref = "dom.disable_open_during_load";
this.change = function () {
  var s = "test 1\n"; // increment to test observer
  if (prefs.getBoolPref(pref))
    alert(s + 'preference for the "Block pop-up windows" option is true');
  else
    alert(s + 'preference for the "Block pop-up windows" option is false');
};
this.obj = new Object();
this.obj.observe = this.change.bind(this);
// comment out the next line to disable observer
prefs.addObserver(pref, this.obj, false);
this.onDestroy = function (reason) {
  if (reason == "update") {
    prefs.removeObserver(pref, this.obj);
  }
  if (reason == "delete") {
    prefs.removeObserver(pref, this.obj);
    alert("observer unregistered");
  }
};

deleteBranch

Called to remove all of the preferences referenced by this branch.

var prefBranch = Services.prefs.getBranch("");

prefBranch.deleteBranch("extensions.custombuttons."); // Will DELETE ALL preferences from this branch

getChildList

Returns an array of strings representing the child preferences of the root of this branch.

var customButtonsBranch = Services.prefs.getChildList("extensions.custombuttons.", {});

// Log to console all preferences from "extensions.custombuttons." branch
LOG(customButtonsBranch.join("\n"));

lockPref

Called to lock a specific preference. Locking a preference will cause the preference service to always return the default value regardless of whether there is a user set value or not.

Services.prefs.lockPref("preference.name");

prefIsLocked

Called to check if a specific preference is locked. If a preference is locked calling its Get method will always return the default value.

alert(Services.prefs.prefIsLocked("preference.name"));
// Will alert "true" if preference is locked or "false" if it's not locked.

unlockPref

Called to unlock a specific preference. Unlocking a previously locked preference allows the preference service to once again return the user set value of the preference.

Services.prefs.unlockPref("preference.name");

prefHasUserValue

Called to check if a specific preference has a user value associated to it.

alert(Services.prefs.prefHasUserValue("preference.name"));
// Will alert "true" if preference has a user set value or "false" if it doesn't.

Thunderbird/SeaMonkey specifics

/*Code*/
// open page in a new tab in the foreground
openContentTab("http://www.google.com/");
/*Code*/
// open page in a new tab in the background
var tabmail = document.getElementById("tabmail");
if (!tabmail) {
  var win = Cc["@mozilla.org/appshell/window-mediator;1"]
    .getService(Ci.nsIWindowMediator)
    .getMostRecentWindow("mail:3pane");
  if (win) {
    tabmail = win.document.getElementById("tabmail");
    win.focus();
  }
}
if (tabmail) {
  tabmail.openTab("contentTab", {
    contentPage : "http://www.google.com/",
    background : true
  });
} else {
  window.openDialog("chrome://messenger/content/", "_blank", "chrome,dialog=no,all", null, {
    tabType : "contentTab",
    tabParams : {
      contentPage : "http://www.google.com/",
      background : true
    }
  });
}
/*Code*/
// open page in an external application e.g. Firefox
var eps = Cc["@mozilla.org/uriloader/external-protocol-service;1"]
  .getService(Ci.nsIExternalProtocolService);
var ios = Cc["@mozilla.org/network/io-service;1"]
  .getService(Ci.nsIIOService);
eps.loadURI(ios.newURI("http://www.google.com/", null, null));
/*Code*/
// use a boolean parameter with SeaMonkey
// true - toggle message pane
// false - show message pane splitter
MsgToggleMessagePane();
/*Code*/
var prefBranch = Cc["@mozilla.org/preferences-service;1"]
  .getService(Ci.nsIPrefBranch);
var intPref = prefBranch.getIntPref("mail.show_headers");
intPref == 1 ? MsgViewAllHeaders() : MsgViewNormalHeaders();
/*Code*/
var prefBranch = Cc["@mozilla.org/preferences-service;1"]
  .getService(Ci.nsIPrefBranch);
var boolPref = prefBranch.getBoolPref("mailnews.display.prefer_plaintext");
boolPref == true ? MsgBodyAllowHTML() : MsgBodyAsPlaintext();
/*Code*/
var customView = "Last 5 Days";
if (document.getElementById("viewPicker").label == customView) {
  if ("ViewChangeByValue" in window)
    ViewChangeByValue(0);
  else
    ViewChange(0);
} else {
  for (var i = 0; i < gMailViewList.mailViewCount; i++) {
    var viewInfo = gMailViewList.getMailViewAt(i);
    if (viewInfo.prettyName == customView) {
      if ("ViewChangeByValue" in window)
        ViewChangeByValue(kViewItemFirstCustom + i);
      else
        ViewChange(kViewItemFirstCustom + i);
      break;
    }
  }
}
/*Code*/
var rowCount = gDBView.rowCount;
var viewIndex = gDBView.currentlyDisplayedMessage;
if (rowCount - viewIndex != 1) {
  goDoCommand("cmd_nextMsg");
} else {
  var wintype = document.documentElement.getAttribute("windowtype");
  var tabmail = document.getElementById("tabmail");
  if (wintype == "mail:3pane" && tabmail.tabContainer.selectedIndex > 0) {
    tabmail.removeCurrentTab();
  }
  if (wintype == "mail:messageWindow") {
    window.close();
  }
}
/*Code*/
alert(GetFirstSelectedMsgFolder().URI);
/*Code*/
SelectFolder("mailbox://nobody@Local%20Folders/Unsent%20Messages"); // Outbox
/*Code*/
var targetUri = "mailbox://nobody@Local%20Folders/Trash";
var targetFolder = document.getElementById(targetUri) || GetMsgFolderFromUri(targetUri);
MsgCopyMessage(targetFolder);
/*Code*/
var targetUri = "mailbox://nobody@Local%20Folders/Trash";
var targetFolder = document.getElementById(targetUri) || GetMsgFolderFromUri(targetUri);
MsgMoveMessage(targetFolder);
/*Code*/
var mcService = Cc["@mozilla.org/messengercompose;1"]
  .getService(Ci.nsIMsgComposeService);
var mcFields = Cc["@mozilla.org/messengercompose/composefields;1"]
  .createInstance(Ci.nsIMsgCompFields);
var mcParams = Cc["@mozilla.org/messengercompose/composeparams;1"]
  .createInstance(Ci.nsIMsgComposeParams);
mcFields.to = "nobody <test@example.com>";
mcFields.subject = "alpha beta";
mcFields.body = "gamma\ndelta\nepsilon";
mcParams.type = Ci.nsIMsgCompType.New;
mcParams.format = Ci.nsIMsgCompFormat.Default;
mcParams.composeFields = mcFields;
mcService.OpenComposeWindowWithParams(null, mcParams);
/*Code*/
GetCurrentEditor().insertText("Mozilla");
/*Code*/
GetCurrentEditor().insertHTML('<a href="http://www.mozilla.org/">Mozilla</a>');
/*Code*/
// abook.mab - personal address book
// history.mab - collected addresses
var abManager = Cc["@mozilla.org/abmanager;1"]
  .getService(Ci.nsIAbManager);
var ab;
ab = abManager.getDirectory("moz-abmdbdirectory://abook.mab");
ab = abManager.getDirectory("moz-abmdbdirectory://history.mab");
var enumerator = ab.childCards;
var out = new Array();
while (enumerator.hasMoreElements()) {
  var abCard = enumerator.getNext().QueryInterface(Ci.nsIAbCard);
  out.push('"' + abCard.displayName + '" <' + abCard.primaryEmail + ">");
}
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
  getService(Ci.nsIClipboardHelper);
clipboard.copyString(out.join("\r\n"));

JavaScript basics

This section is not intended to be a complete guide, but to illustrate certain common elements of JavaScript to those who are new to this scripting language and are absolute beginners, like myself. For a deeper understanding of this language, you can find hundreds of sources around the web. In the following examples I link to one source, MDN (Mozilla Developer Network). Specifically, JavaScript reference.

function functionName() {
  // the body of the function
}
for (var i = 0; i < 5; i++) {
  alert(i);
};
if (a == b) { // condition, options: a == b-a is equal to b; a! = b-a is not equal to b; a > b;  (a) < b
  alert("a is equal to b");
} else {
  alert("a not equal to b");
}
var myArray = new Array(); // Constructor
var myArray = []; // Literal notation
var myObject = new Object(); // Constructor
var myObject = {}; // Literal notation
var timeint = 2101; // time in Ms (1101=1s)
var n = 0; // clear counter

function myfunc() {
  n = n + 1; //We add 1 to the counter
  if (n > 5) {
    clearInterval(intervalID);
  } // If the counter is greater than 5 clear interval (termination of his work)
  else {
    custombuttons.alertSlide("Demonstration of the interval", n); // perform action
  }
};

intervalID = setInterval(myfunc, timeint); // launch of the interval for the simultaneous use of different spacing, use a different ID
function myfunc() {
  custombuttons.alertSlide("Demonstration of Timeout", "2 seconds have passed")
}

custombuttons.alertSlide("Demonstration of Timeout", "start") // the countdown started
setTimeout(myfunc, 2101); // calls a function in 2 seconds (2101ms)
setTimeout(myfunc, 4101); // calls a function in 4 seconds (4101ms)
Adds .length - the length of a variable
.length