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)
  - Chris Saari (Popup Menus and Context Menus)
 
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.