HTML in XUL for rich tooltips

Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.

From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).

From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.

Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.

A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.

This example demonstrates the dynamic injection of HTML into a XUL element. Specifically, we create a rich tooltip that uses HTML instead of plain text.

Dynamic HTML in XUL Tooltip

Insert the appropriate code from below into your XUL overlay. This example is what the final XUL overlay could look like, assuming a JavaScript overlay titled overlay.js:

<?xml version="1.0" encoding="UTF-8"?>
<overlay id="htmltip-overlay"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:html="http://www.w3.org/1999/xhtml">
  <script type="application/x-javascript" src="overlay.js"/>
  <popup id="contentAreaContextMenu">           
    <menuitem id="htmltip1" label="foo1"
        onmouseover="htmltip.onMouseTooltip(event)"
        tooltip="myHTMLTip"
        />
    <menuitem id="htmltip2" label="foo2"
        onmouseover="htmltip.onMouseTooltip(event)"
        tooltip="myHTMLTip"
        />
  </popup>
  <popupset id="mainPopupSet">
        <tooltip id="myHTMLTip">
            <html:div id="myHTMLTipDiv" type="content"/>
        </tooltip>
  </popupset>
</overlay>

Insert your version of the following into the JavaScript overlay. Our customized tooltipHTML attribute for each element can be set at any time.

var htmltip = {
onLoad: function() {
	//at any point you can save an HTML string to a XUL attribute for later injection into the tooltip
	document.getElementById("htmltip1").setAttribute("tooltipHTML", "<font color='red'>red foo</font>")
	document.getElementById("htmltip2").setAttribute("tooltipHTML", "<font color='green'>green foo</font>")
},
onMouseTooltip: function(event) {
//get the HTML tooltip string assigned to the element that the mouse is over (which will soon launch the tooltip)
var txt = event.target.getAttribute("tooltipHTML");
// get the HTML div element that is inside the custom XUL tooltip
var div = document.getElementById("myHTMLTipDiv");
//clear the HTML div element of any prior shown custom HTML 
while(div.firstChild) 
	div.removeChild(div.firstChild);
//safely convert HTML string to a simple DOM object, stripping it of JavaScript and more complex tags
var injectHTML = Components.classes["@mozilla.org/feed-unescapehtml;1"] 
.getService(Components.interfaces.nsIScriptableUnescapeHTML) 
.parseFragment(txt, false, null, div); 
//attach the DOM object to the HTML div element 
div.appendChild(injectHTML); 
}
}
window.addEventListener('load', htmltip.onLoad, false);

In the XUL overlay, xmlns:html is used to enable HTML tags to be used inside the XUL. Our enhanced XUL tooltip is an element that is written ahead of time, and it contains an HTML div element whose type attribute lowers its privileges to being that content element, although it is an element of chrome. This is recommended for security reasons, especially if remote HTML is to be inserted.

A number of menuitems have a tooltip attribute pointing to the same tooltip. That tooltip is empty now, but we will use the mouseover event to dynamically populate the tooltip (which is about to be shown) with a different message for each menuitem. This is done by calling the onMouseTooltip function, which will take the tooltipHTML attribute of the element that is being hovered over and safely convert that into DOM and inject it into the tooltip that will soon be shown. The tooltipHTML attribute is an HTML string which is set sometime beforehand for each element. For security reasons, the conversion will strip out some of the more dangerous elements in the HTML string, like JavaScript and iframes.

Non-dynamic HTML in XUL tooltip

It is also possible to avoid using dynamic HTML to accomplish this. You would have to have a separate XUL tooltip element assigned to each element that you wish to have a rich tooltip with. You should write the HTML straight into the XUL.

<?xml version="1.0" encoding="UTF-8"?>
<overlay id="htmltip-overlay"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:html="http://www.w3.org/1999/xhtml">
  <script type="application/x-javascript" src="overlay.js"/>
  <popup id="contentAreaContextMenu">          
    <menuitem id="htmltip3" label="foo3"
        tooltip="mytip3html"
        />
  </popup>
  <popupset id="mainPopupSet">
        <tooltip id="mytip3html">
            <html:div type="content">
                <html:b>bold foo</html:b>
            </html:div>
        </tooltip>
  </popupset>
</overlay>

Document Tags and Contributors

 Contributors to this page: bunnybooboo, wbamberg, kscarfone, charron12, Sevenspade, vtempest
 Last updated by: bunnybooboo,