Xbl Module construction



Making xbl widgets portable across xul applications

An xbl module is a self contained widget tree which contains xbl bindings and methods, css bindings and basic style information, images and icons, Overlays and js, documentation and working code examples. The widget tree is implemented as a directory structure. Everthing here is already available in the mozilla AOM. What is presented here is a method of use.

Introduction

The examples below use the xbutton xbl module as a reference. The principle of how to make an xbl module portable is what is being documented. The xbutton is the first xbl module that can be 'dropped in' to multiple xul applications and is implemented in the XPTK toolkit and the kiosk browser. This method relies heavily on css and how style rules get applied in mozilla as does xbl. Under this scheme you can copy the xbutton module directory into your projects /content directory and include the WidgetName.css in your applications main stylesheet or in the top of your xul application or Overlay. Here is a snippet from one of the kiosk browser chromes that is using the xbutton xbl module:
 <?xml-stylesheet href="chrome://kiosk/skin" type="text/css"?>
<?xml-stylesheet href="chrome://kiosk/content/toolkit/xbutton/style/xbutton.css" type="text/css"?>
<?xml-stylesheet href="chrome://kiosk/content/toolkit/xbutton/style/button.css" type="text/css"?>
Above we have the style sheet calls, we're bringing in the kiosk.css, xbutton.css that contains the button binding, button.css that is a copy of the mozilla modern skin button and later in the xul document we use the widget binding we just created:
  <button label="" orient="horizontal" 
src="chrome://kiosk/content/toolkit/xbutton/images/message-mail.png"
id="mailBtn"
onclick='window.openDialog("chrome://messenger/content/");'
tooltiptext="Messenger Mail">
</button>
I know that I have a button widget provided by the xbutton.css only because the module developer said so in his documentation. The widget bindings are defined in the WidgetName-bindings.css, so you also look there to see what tags the module is providing. Documenting the widget is a must. A developer should not have to read and understand your xbl code to use your widget.

Thats all that is needed to include the xbutton xbl widget in an xul document. The documentation you provide tells the xul developer the name of the xbl widget that your module is providing, in the case of xbutton it is <button>. You must expect that your css rules will be overloaded by the xul developer, as we will see later in this doc.

XBL modules should include usage documentation in their main directories so if someone lifts a module for their project the documentation goes with the module. Also include good working examples that demonstrate all attributes of your widget. You are going to write good documentation, right?

Organization of Module

XBL modules should have a widget tree directory structure as in any mozilla project:

/WidgetName directory

This is the root of your module. In this root you would have your WidgetName.xul demonstrating the propper use of your widget.Also here is where you keep your widget documentation in html format All paths used in your css and xbl should be relative to this directory. A demonstration is the xbutton-bindings.css which points to the /xbl directory from inside the /style directory:
  /* **** xbutton-binding.css
Binding stylesheet for the extended button */

  button {
-moz-binding: url("../xbl/xbutton.xml#button");
}

  menu-button {
-moz-binding: url("../xbl/xbutton.xml#button");
}

/xbl directory

In the xbl directory you would have the xml document(s) containing the bindings for the custom widget. All paths used should be relative to the widget directory so that the widget is not tied to one directory or project. The resource definition points to the style directory, as in:
    <resources>
<stylesheet src="../style/button.css"/>
</resources>
which points to the ./style directory from inside the ./xbl directory. The key to making you xbl widget portable is the use of relative paths.

/style diectory

In the style directory you would have a /WidgetName-bindings.css that could be imported into an applications main stylesheet to obtain the widgets bindings. Also in the style directory there should be a widget specific WidgetName.css that imports the WidgetName-bindings.css and basic widgetName.css. The widgetName.css contains the basic style rules for the xbl widget, these should be enough to display your widget in the absence of any other style rules for your xbl widget. Here is a css binding for the xbutton.xml button:

  1. button {
  2. -moz-binding: url("chrome://xptk/content/modules/xbutton/xbl/xbutton.xml#button");
  3. }
This binding shows that the xbutton is being used from the XPTK chrome directory but the path could point to where it's installed into your project, as shown above. It should be noted that the standard, cannonical, place to drop the widget directory in your project is the /content directory so the chrome path would be chrome://myproject/content/xbutton/xbutton.xml. Also note that in line 1 above the button could be xbutton and you would have an <xbutton> widget to use in your app with all the attributes of the xbutton.xml button. You could have <button> and <xbutton> tags in the same application. Another method of obtaining a binding, while not as clean but css2 syntax, is:
  1. button[module="xbutton"] {
  2. -moz-binding: url("chrome://xptk/content/modules/xbutton/xbl/xbutton.xml#button");
  3. }

In the xul document you would then do:

 <button module="xbutton" label="xbutton" orient="horizontal"
src="chrome://xptk/content/modules/xbutton/images/message-mail.png"
color="darkred" bgcolor="#cccccc" />

Notice the attribute selector module="xbutton" in the css matches the attribute definiton in the xul button definition. This method also lets you have multiple button bindings.

/content directory

The content directory contains any xul Overlays that implement your widget(s). Any javascript used by your widget or Overlay should be here. Also any stringbundles needed by your widgets or Overlays will be here.

/images directory

The images directory contains any images or icons that are needed for your widget.

/locale directory

The locale directory contains any locale information needed by your widget or Overlay