You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



Popup Content (Context Menus and Tooltips)

Feature Owners
Dave Hyatt (Content Model Work, Arbitrary XUL Popups)
Chris Saari (Popup Menus and Context Menus)
Mike Pinkerton (Tooltips, Making Things Suck Less)

The XUL language provides a way for developers to declare that a XUL subtree is popup content, meaning that the content is displayed in its own window when a certain event occurs (e.g., a right mouse click to bring up a context menu, or a left click to bring up a popup color picker on a toolbar).

There are two kinds of popup content: menus and windows. Popup menus use the native menus on each platform and are described using menu and menuitem elements (See Menus and Menu Bars for details). Popup windows can contain arbitrary XUL, and are full-fledged XUL windows, declared using the window tag (See Windows and Dialogs for details).

Popup content is placed inside a popup tag, which prevents it from being displayed in the main document. The popup tag always has an identifier attached to it (using the id attribute) that is used when attaching the popup content to a UI element.

<popup id="replyMenu">
  <menu>
    <menuitem name="Reply to Sender">
    <menuitem name="Reply to All">
  </menu>
</popup>

There are three different ways of automatically attaching a popup to content. All three methods involve setting attributes on the content node that should have the popup content attached to it. The attributes are popup, context, and tooltip. The value of one of these attributes is the id of the popup element that should be used to build the popup content.

<titledbutton value="Reply" popup="replyMenu"/>

The popup attribute is used to attach popup content that will be invoked on a "left mouse down". The context attribute is used to attach popup content that will be invoked on a context menu event (with the cross-platform abstraction being taken care of for you). The tooltip attribute is used to attach popup content that will be invoked after a time-delay hover over the node that has the popup content attached. (Note that tooltips may only be used with popup window content and never with popup menu content.)

By default the popup content appears with its top left point located directly underneath the point at which the user's mouse goes down (on tooltips the content is displaced by the height of the mouse cursor). This placement can be controlled using the popupanchor and popupalign attributes.

The popupanchor and popupalign attributes have four possible values: topleft, topright, bottomleft and bottomright. The popupanchor attribute can be used to specify that the popup content should come up anchored to one of the four corners of the content object (e.g., the button popping up the content). If omitted, no anchoring occurs. Instead the popup content comes up directly underneath the mouse event coordinates. This point (either directly under the mouse or attached to one of the four corners) is called the originating point.

The popupalign attribute can be used to specify which corner of the popup content is tied to the originating point. If omitted, the default is topleft. The example below shows how to create the traditional buttons with attached left mouse menus that exist in the 4.x Communicator product.

<titledbutton value="Reply" popup="replyMenu" popupanchor="bottomleft"/>

On Windows 98, anchored menus will animate (unless the property is turned off) to the opposite corner of the value specified in the popupalign attribute. In the above example, since the attribute is omitted, the default is topleft, and the menu will therefore animate to the bottomright corner.

The popup content can have attached event handlers just as regular content might. In these event handlers, the element that the popup was invoked upon can be retrieved by examining the popupNode property of the document. This property is set only when the popup is currently open.

<popup id="toolbarContextMenu">
  <menu>
        ...
    <menuitem name="Delete" onclick="mailNewsCore.deleteButton(document.popupNode)">
        ...
  </menu>
</popup>

A similar property, tooltipNode, is set for the element that has a tooltip displayed over it.

Arbitrary XUL windows that are created as popups have their own document, and any namespaces must be declared again on the new window tag. Style sheets, however, are inherited from the parent document. A popup XUL window is linked to the parent window that spawned it using the opener property, and thus can get back to the originating document to invoke functions or to examine data.

Arbitrary XUL popups can be closed or repositioned just as normal windows can using the methods of the window object. The most relevant method is window.close(), which can be used to discard the popup.

<popup id="justifierPopup">
  <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    width="40" height="100">
     <titledbutton id="left"
       onclick="opener.setJustification('left'); window.close();"/>
     <titledbutton id="center"
       onclick="opener.setJustification('center'); window.close();"/>
     <titledbutton id="right"
       onclick="opener.setJustification('right'); window.close();"/>
  </window>
</popup>
...
<titledbutton popup="justifierPopup" popupanchor="bottomleft"/>
...

Popup content can also be created in response to any event (and not just the predefined popup, context and tooltip events. There are two new methods on the window object that allow popup content to be instantiated programmatically.

createPopup takes six arguments: the DOM element to attach the popup to, the DOM element that represents the popup content, the x screen coordinate of the popup, the y screen coordinate of the popup, the popup type (context, popup, or tooltip), and the popup alignment (topleft, bottomright, bottomleft, topright).

The createAnchoredPopup method can be used to create popup content at a specific anchor point on a content object. It takes five arguments: the element to attach the popup to, the popup content element, the anchor position for the content (topleft, bottomright, bottomleft, topright), the popup type, and the popup alignment.

Using these methods, fine-grained control of popup instantiation is possible, e.g., a popup can be brought up after a time-delay or in response to keyboard events.

Popups can also be built dynamically or be modified just prior to being displayed. The create and destroy events are fired on a popup element just prior to it being displayed and just after it has lost the focus, respectively. Event listeners can be attached using the oncreate and ondestroy attributes or by using the DOM addEventListener function.

Due to how the menubar and dynamic menus are implemented on MacOS, the ondestroy handler is not guaranteed to be called at any particular time. On MacOS only, it will be called at one of the following times:

  • just before the next menu is to be displayed (which could be hours after the menu actually leaves the screen or when a different menubar is active)
  • when the app quits

The window associated with this menubar may be long gone by the time the handler is executed. Do not put anything time-critical or anything that relies on a window being present in this handler.

Tooltips

Tooltips are basically timed xul popups. You have full control over the appearance of these popups, or you may use a combination of JS and a standard "template" tooltip to get up and running quickly.

The easy way:

<!-- this popup is in globaloverlay.xul. you don't need to duplicate it
     it is included here as an example. -->
<popupset>
  <popup id="aTooltip" oncreate="return FillInTooltip(document.tooltipNode);">
   <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
     width="200" height="20" style="border: thin solid black">
        <titledbutton id = "replaceMe" align="left" class="borderless paneltitle"/>
   </window>
  </popup>
</popupset>

...
<toolbar tooltip="aTooltip">
  <titledbutton tooltiptext="Tip for Button One"/>
  <titledbutton tooltiptext="Tip for Button Two"/>
  <titledbutton tooltiptext="Tip for Button Three"/>
</toolbar>
...

The tooltiptext attribute specifies the text displayed in the tooltip for this item. If you need more control over the tooltip for a particular button, you can specify the tooltip attribute directly on that item and set its id to a different popup where the new content lives.

You can use the JS convenience routine FillInTooltip() (available from globaloverlay.js) anywhere you want as long as you have one node within the popup whose name is "replaceMe". This way you keep the convenience of only having to specify the tooltip text on the button but can use any popup you like.

To prevent tooltips from showing up based on content, return false from the oncreate event handler. Actually, this is true for any xul popup, but most useful for tooltips.

Tooltips will automatically time out after 5 seconds or so and go away on their own. If you have a lot of information in your tooltip and would prefer that it didn't, set the noautohide attribute to true on the tooltip's <popup> tag. Tooltips will also go away when the mouse leaves the Gecko frame corresponding to the DOM node that was the event target that spawned the tip.

Known Issues

  • HTML Elements - Popups can only be attached to XUL elements right now and not to HTML elements.
  • Anchoring - Don't try to use the popupanchor attribute yet. It will cause the popups to not even show up at all. Also, the createAnchoredPopup method doesn't do anything yet.
  • Arbitrary XUL Popup Issues

    • The destruct event doesn't fire when an arbitrary XUL popup is closed.