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.



Toolbars and Toolboxes

Feature Owner
Mike Pinkerton

A toolbar is a strip that contains a set of widgets called toolbar items. The toolbar can lay out its components either horizontally or vertically, and it can optionally wrap to multiple rows/columns. (In fact, a toolbar is really just an extension of the box element. See The Box System for details.)

The toolbar is specified using the toolbar tag. The attribute align is used to specify whether or not the toolbar is a horizontal toolbar or a vertical toolbar. If this attribute is omitted, the toolbar will lay out its children horizontally.

The align attribute should be moved into CSS, but for now it must be specified as an attribute on the toolbar.

<toolbar align="vertical">
  <html:button>Button One</html:button>
  <html:button>Button Two</html:button>
  <html:button>Button Three</html:button>   
</toolbar>

Toolbars are capable of supporting drag and drop operations by manipulating its DOM subtree. The drag and drop code for toolbars can also provide feedback for insertion before, after, or on other items on the toolbar. In order for this code to work, the contents of the toolbar (e.g., buttons and input fields) must be grouped into a single container within the toolbar, but that container can be an arbitrary child of the toolbar. See below for more details on drag and drop.

A toolbar item is also an extension of a box and it can therefore contain arbitrary HTML and XUL content that is treated as a single toolbar item for the purposes of drag and drop, deletion operations on the toolbar, cut and paste of toolbar items, and context/popup menus on toolbar items.

The toolbar item can lay out its contents horizontally or vertically (with horizontal being the default) using the align attribute.

<toolbar>
  <toolbaritem>
    <html:button>Button One</html:button>
  </toolbaritem>
  <toolbaritem>
    <html:button>Button Two</html:button>
  </toolbaritem>
  <toolbaritem>
    <html:img src="icon.gif"/>Input Label: <html:input/>
  </toolbaritem>
</toolbar>

A toolbar's contents can be marked as unmodifiable by setting the readonly attribute on the toolbar. Toolbars with this attribute set will disallow any drops into their content area, and they will not allow their contents to be altered in any way.

Although toolbars can be embedded directly in the window, they are commonly placed inside another object called the toolbox. The toolbox is represented using the toolbox tag. A toolbox contains one or more toolbars as children, and it surfaces the UI that allows the toolbars within the toolbox to be reordered and collapsed.

When a toolbar is placed inside of a toolbox, it acquires a stripe on its left hand side (if the toolbox stacks its components) or on its top side (if the toolbox is horizontal). This stripe is affectionately referred to as the grippy, and it is the object that the user manipulates in order to move the toolbar around or to collapse it.

Collapsed toolbars appear in a thin strip at the bottom of the toolbox (if vertical) or the right of the toolbox (if horizontal). This strip is only shown if at least one of the toolbars in the toolbox is collapsed.

<toolbox>
  <toolbar id="Command Toolbar">
    <html:button>Button One</html:button>
  </toolbar>
  <toolbar id="Personal Toolbar>
    <html:button>Button Two</html:button>
  </toolbar>
  <toolbar id="Location Toolbar>
    <html:img src="icon.gif"/>URL: <html:input/>
  </toolbar>
</toolbox>

When a toolbar is collapsed, an attribute called collapsed is set to true on the toolbar element. When the toolbar is shown again, this attribute is unset. If this attribute is specified in the XUL file, it indicates that the initial state of the toolbar is to be collapsed inside the toolbox, although a new state may be stored persistently in order for the user's visibility preferences to be retained. (See Persistence and Sharing for details.)

The collapsed attribute is ignored if the toolbar is not contained in a toolbox.

The toolbar or toolbox can also be hidden using the standard mechanism (in both HTML and XUL) for hiding content elements: myToolbar.style.display = none. Showing the toolbar requires setting it back to its original display type (which for toolbars is block).

The look of the toolbox grippies can be customized using the pseudo elements :toolbox-normal and :toolbox-rollover. The former is used by default for the grippies, and the latter is used when the user mouses over the grippies.

:toolbox-rollover {
    background-color: #ccccff;
    background-image: url("resource:/res/toolbar/TB_Tab_mo.gif");
    background-repeat: no-repeat;
    color: green;
    border-bottom: solid darkGray 1px;
    border-top: solid white 0px;
    border-left: solid white 0px;
    border-right: solid darkGray 1px;
}

Toolbar Drag & Drop

Tracking During The Drag

The toolbars make use of a DOM event capturer to annotate the toolbar's content node with information about where the drag will go in order to draw the correct drop feedback. Since toolbars can be arbitrarily complicated, however, the capturer needs a little help figuring out which child frame contains the drop area. This is done by setting the dragdroparea attribute on the toolbar. If this attribute is not specified, the tracking code assumes the toolbar frame is the drop area.

Here's an example of a toolbar with nested boxes for some complicated layout. The buttons that can be dragged around live within one of these nested boxes.

<toolbar id="PersonalToolbar" dragdroparea="innermostBox">                 
  <box align="horizontal" flex="1" style="min-width: 1px">
    <!-- button area of personal toolbar -->
    <box align="horizontal" flex="1" style="min-width: 1px; overflow: hidden"
      datasources="rdf:bookmarks" ref="NC:PersonalToolbarFolder">
      <titledbutton> ...
    </box>
  </box>
</toolbar>

The toolbar also needs a little help from the ondragover event handler to trigger the drop feedback magic. The capturer always annotates the toolbar with various attributes, but it might not be valid to drop on the toolbar based on the contents of the drag. When the event handler determines that a drag is valid, it needs to touch the dd-triggerrepaint attribute on the toolbar which triggers a repaint with the correct drop feedback. By not touching this attribute, the toolbar will not redraw and this prevents the feedback from appearing. If you don't want drop feedback at all, this is how you'd accomplish it.

function DragOverPersonalToolbar ( event )
{
  var validFlavor = false;
  var dragSession = null;
                  
  var dragService = 
    Components.classes["component://netscape/widget/dragservice"].getService(Components.interfaces.nsIDragService);
  if ( dragService ) {
    dragSession = dragService.getCurrentSession();
    if ( dragSession ) {
      if ( dragSession.isDataFlavorSupported("moz/toolbaritem") )
        validFlavor = true;
      else if ( dragSession.isDataFlavorSupported("text/plain") )
        validFlavor = true;
      //XXX other flavors here...
                  
      // touch the attribute to trigger the repaint with the drop feedback.
      if ( validFlavor ) {
        var toolbar = document.getElementById("PersonalToolbar");
        toolbar.setAttribute ( "dd-triggerrepaint", 0 );
        dragSession.canDrop = true;
        event.preventBubble();
      }
    }
  }
} // DragOverPersonalToolbar

Determining Where To Drop

The event capturer sets two attributes on the toolbar during the drag tracking which are useful when the user finally releases the mouse over the toolbar. The first is dd-droplocation which is an integer index of the item before which the newly dropped items should be inserted. This index is zero-based. The second attribute, dd-dropon, tells if the drop should go on (or into) a container on the toolbar. When this is true, dd-droplocation is the item index of the container.

The toolbar determines if something is a container by checking the container attribute of the content node.

Customizing Drop Feedback

The drop feedback marker bar is normally black, but can be customized on a particular toolbar via CSS. To do this, use the :-moz-drop-marker pseudoelement.

For example:

toolbar#PersonalToolbar:-moz-drop-marker {
   color: white;
}