XUL Tutorial - 10.6 - Adding Event Handlers
Previous Contents Reference Next

XUL Tutorial - Adding Event Handlers

Next, we'll find out how to add event handlers to XBL-defined elements.

Event Handlers

As you might expect, mouse clicks, key presses and other events are passed to each of the elements inside the content. However, you may wish to trap the events and handle them in a special way. You can add event handlers to the elements inside the content if needed. The last example in the previous section demonstrated this. In that example, onclick handlers were added to some buttons.

However, you may want to add an event handler to the entire contents, that is, all the elements defined in the content tag. This could be useful when trapping the focus and blur events. To define an event handler, use the handler element. Each will describe the action taken for a single event handler. You can use more than one handler if necessary. If an event does not match any of the handler events, it is simply passed to the inner content as usual.

The general handler syntax is as follows:

<binding id="binding-name">
  <handlers>
    <handler event="event-name" action="script"/>
  </handlers>
</binding>

Place all of your handlers with-in the handlers element. Each handler element defines the action taken for a particular event specified by its event attribute. Valid event types are those supported by XUL and JavaScript, such as click and focus. Use the event name without the 'on' in front of it. For example, the event type of the 'onmousedown' event is 'mousedown'.

A common reason to set handlers is to modify the custom properties when an event occurs. For example, a custom checkbox might have a checked property which needs to be changed when the user clicks the checkbox:

<handlers>
  <handler event="mouseup" action="this.checked=!this.checked"/>
</handlers>

When the user clicks and releases the mouse button over the check box, the mouseup event is send to it, and the handler defined here is called, causing the state of the checked property to be reversed.

You will need to add handlers to adjust the properties whenever input from the mouse or keyboard would require it. Similarly, you may wish to change a property when the element is focused.

The following attribute is not currently implemented

For mouse events, you can use the button attribute to have the handler only trap events that occur from a certain button. Without this attribute, the handler traps all events regardless of the button that was pressed. The button attribute should be set to either left, right or middle, depending on which button you want to check.

<handlers>
  <handler event="click" button="left" action="alert('Left button pressed');"/>
  <handler event="click" button="right" action="alert('Right button pressed');"/>
  <handler event="mouseup" button="middle" action="alert('Middle button pressed')"/>
</handler>

For key events, you can use a number of attributes similar to those for the charcode element to match a specific key and match only when certain modifer keys are pressed. The previous example could be extended so that the checked property of the check box is changed when the space bar is pressed.

<handlers>
  <handler event="keypress" key=" " action="this.checked=!checked"/>
</handlers>

You can also use the keycode attribute to check for non-printable keys. The section on keyboard shortcuts provides more information. The modifier keys can be checked by adding one of the attributes below. If set one to true, then the modifier key must be pressed to trigger the event.

The following alternate syntax can be used when the code in a handler is more complex:

<binding id="binding-name">
  <handlers>
    <handler event="event-name">
      -- handler code goes here --
    </handler>
  </handlers>
</binding>

Handlers Example

The following example adds a very primitive form of clipboard operation to a textfield.

Example 10.6.1
<binding id="clipfield">
  <content>
    <xul:textfield/>
  </content>
  <implementation>
    <property name="clipboard"/>
  </implementation>
  <handlers>
    <handler event="keypress" key="x" primary="true"
      action="this.clipboard=document.getAnonymousNodes(this)[0].value; document.getAnonymousNodes(this)[0].value='';"/>
    <handler event="keypress" key="c" primary="true"
      action="this.clipboard=document.getAnonymousNodes(this)[0].value;"/>
    <handler event="keypress" key="v" primary="true"
      action="document.getAnonymousNodes(this)[0].value=this.clipboard ? this.clipboard : '';"/>
  </handlers>
</binding>

The content is a single text field. A property clipboard has been added to it to store the clipboard contents. This does mean that the clipboard operations are limited to this single text field. However, each one will have its own buffer.

Three handlers have been added, one for cut, one for copy and the other for paste. Each has its own keystroke that invokes it. The first handler is the cut operation and is invoked when the x key is pressed along with the primary modifer key (this key is platform-specific). The script with-in the action attribute is used to cut the text from the text field and put it into the clipboard property. For simplicity, the entire text is cut and not just the selected text. The code works as follows:

  1. this.clipboard=document.getAnonymousNodes(this)[0].value;
    The first element of the anonymous content array is retreived which gives a reference to the textfield element, which happens to be the first (and only) element with-in the content element. The value property is retrieved which will provide the text with-in the field. This is then assigned to the clipboard property. The result is copying the text in the field into this special clipboard.
  2. document.getAnonymousNodes(this)[0].value=''
    The text of the textfield is then assigned a value of a null string. This effectively clears the text in the field.

A copy operation is similar but does not the clear the text afterwards. Pasting is the opposite where the value of the field is assigned from the clipboard property. If we were creating a real implementation of these clipboard keyboard shortcuts, we would probably use the real clipboard interface and handle the current selection as well.

Binding Attach and Detach Events

XBL supports two additional events that you can use in a handler tag. The first is the bindingattached event which is called whenever the binding is attached to an element. The reverse, bindingdetached is called when a binding is removed from an element. The primary purpose of these event handlers is to initialize a bound element.

There are two points when a binding is attached to an element. The first occurs when a window is displayed. All elements that have XBL-bound content will have their bindingattached handlers invoked. The order that they are called in should not be relied upon, as they are loaded from various files. The window's onload handler is not called until after all the bindings have been attached. The second point a binding is attached is if you change the -moz-binding style property of an element. The existing binding will be removed, after its bindingdetached handler is called. Then, the new binding will be added in its place and its bindingattached handler invoked.


(Next) In the next section, we'll look at how to style XBL-defined widgets.

Examples: 10.6.1

XUL Tutorial - 10.6 - Adding Event Handlers
Previous Contents Reference Next