Focus and Selection

The section will describe how to handle the focus and selection of elements.

Focused Elements

The focused element refers to the element which currently receives input events. If there are three textboxes on a window, the one that has the focus is the one that the user can currently enter text into. Only one element per window has the focus at a time.

The user can change the focus by clicking an element with the mouse or by pressing the TAB key. When the TAB key is pressed, the next element is given the focus. To step backwards, the Shift key and Tab key can be pressed.

Rearranging the tab order

You can change the order in which elements are focused when the user presses the TAB key by adding a tabindex attribute to an element. This attribute should be set to a number. When the user presses TAB, the focus will shift to the element with the next highest tab index. That means that you can order the elements by setting indices on elements in sequence. Usually, however, you would not set the tabindex attribute. If you do not, pressing TAB will set the focus to the next displayed element. You only need to set tab indices if you wish to use a different order. Here is an example:

var el = env.locale; Example 1 : Source View

<button label="Button 1" tabindex="2"/>
<button label="Button 2" tabindex="1"/>
<button label="Button 3" tabindex="3"/>

The focus event

The focus event is used to respond when the focus is given to an element. The blur event is used to respond when the focus is removed from an element. You can respond to focus changes by adding an onfocus or onblur attribute on an element. They work just like their HTML counterparts. You might use these event handlers to highlight the element or display text on a status bar. The following example can be used to apply a function to handle a focus event.

var el = env.locale; Example 2 : Source View

<script>
function displayFocus(){
  var elem=document.getElementById('sbar');
  elem.setAttribute('value','Enter your phone number.');
}
</script>
<textbox id="tbox1"/>
<textbox id="tbox2" onfocus="displayFocus();"/>
<description id="sbar" value=""/>

The focus event, when it occurs, will call the displayFocus function. This function will change the value of the text label. We could extend this example to remove the text when the blur event occurs. Typically, you will use focus and blur events to update parts of the interface as the user selects elements. For instance, you might update a total as the user enters values in other fields, or use focus events to validate certain values. Don't display an alert during a focus or blur event as this will be distracting for the user and is poor user interface design.

You can also add event handlers dynamically using the DOM function addEventListener. You can use it for any element and event type. It takes three parameters, the event type, a function to execute when the event occurs and a boolean indicating whether to capture or not.

Getting the currently focused element

The currently focused element is held by an object called a command dispatcher, of which there is only one for the window. The command dispatcher is responsible for keeping track of the focused element as the user uses the interface. The command dispatcher has other roles, which will be discussed in a later section on commands. For now, we'll look at some of the focus related features of the command dispatcher.

You can retrieve the command dispatcher from a window using the document's commandDispatcher property. From there, you can get the focused element with the dispatcher's focusedElement property. The example below shows this.

var el = env.locale; Example 3 : Source View

<window id="focus-example" title="Focus Example"
        onload="init();"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script>
function init(){
  addEventListener("focus",setFocusedElement,true);
}
function setFocusedElement(){
  var focused = document.commandDispatcher.focusedElement;
  document.getElementById("focused").value = focused.tagName;
}
</script>
<hbox>
  <label control="username" value="User Name:"/>
  <textbox id="username"/>
</hbox>
<button label="Hello"/>
<checkbox label="Remember This Decision"/>
<label id="focused" value="-No focus-"/>
</window>

In this example, a focus event handler is attached the window. We want to use a capturing event handler, so the addEventListener method needs to be used. It registers a capturing event handler with the window which will call the setFocusedElement method. This method gets the focused element from the command dispatcher and sets a label to its tag name. As the focused element is changed, the label will show the tagname of the element.

A few things to note.

  • First, when the textbox is focused, the tag name is 'html:input', not 'textbox' as we might expect. This is because XUL text boxes are implemented using the HTML input widget, so the focus event is received for that element instead.
  • Second, clicking the textbox's label changes the focus to the textbox. This is because the label has a control attribute pointing to the id of the textbox.
  • Finally, the other label which displays the tag name has no control attribute, so clicking it has no effect on the focused element. Only focusable elements can be focused.

Making a label focusable

If you were creating custom elements, you might have a need to change whether an element can have the focus or not. For this, you can use a special style property -moz-user-focus. This property controls whether an element can be focused. For instance, you could make a label focusable, as in the example below.

var el = env.locale; Example 4 : Source View

<label id="focused" style="-moz-user-focus: normal;"
          onkeypress="alert('Label Focused');" value="Focus Me"/>

The style property is set to normal. You can also set it to ignore to turn off the focus for an element. This shouldn't be used for disabling an element, however; the disabled attribute or property should be used instead, since that is what it is designed for. Once the label in the example is focused, it can respond to key presses. Naturally, the label gives no indication that it is focused, since it isn't normally expected to ever be focused.

Changing the focus

There are several ways to change the currently focused element. The simplest is to call the focus method of a the XUL element that you wish to set the focus to. The blur method can be used to remove the focus from an element. The following example demonstrates this:

var el = env.locale; Example 5 : Source View

<textbox id="addr"/>
<button label="Focus" oncommand="document.getElementById('addr').focus()"/>

Or, you can use the methods advanceFocus and rewindFocus on the command dispatcher. These methods move the focus to the next element in sequence or the previous element respectively. This is what happens when the user presses TAB or Shift+Tab.

For textboxes, a special attribute, focused is added whenever the element has the focus. You can check for the presence of this attribute to determine if the element has the focus, either from a script or within a style sheet. It will have the value true if the textbox has the focus and, if the textbox does not have the focus, the attribute will not be present.

Suppose you wanted to move the focus from where it currently is, to the next place the browser thinks it should be. A user typically does this by hitting the "Tab" key. You can do this anywhere you have a XUL browser document by simply:

      document.commandDispatcher.advanceFocus();

In fact, the commandDispatcher simply implements the nsIDOMXULCommandDispatcher interface. This interface also provides a number of other methods which may be useful.

Platform Specific Behaviors

Mac OS X
There is a preference called "Full Keyboard Access" (FKA). Note that XUL adheres to this. This means that when the FKA preference is off, only textboxes and lists/trees are focusable with the keyboard, as well as from your code using focus().

Handling Text Changes

There are two events that can be used when the user changes the value of a textbox. Naturally, these events will only be sent to the textbox that has the focus.

  • The input event is fired whenever the text is modified in the field. The new value will be different than the old value. You may want to use this event instead of using key events, as some keys such as the shift key don't change the value. Also, the input event would not fire if a letter key was pressed and there were already more characters than will fit in the textbox.
  • The change event is similar in that it fires only when the field is changed. However it only fires once the textbox loses the focus, thus, only once per set of changes.

Text Selection

When working with a textbox, you may wish to retrieve not the entire contents of a field but only what the user has selected. Or, you may wish to change the current selection.

XUL textboxes support a way to retrieve and modify the selection. The simplest one is to select all of the text in a textbox. This involves using the select method of the textbox.

tbox.select();

However, you may wish to select only part of the text. To do this you can use the setSelectionRange function. It takes two parameters, the first is the starting character and the second is the character after the last one that you want to have selected. Values are zero-based, so the first character is 0, the second is 1 and so on.

tbox.setSelectionRange(4,8);

This example will select the fifth character displayed, as well as the sixth, seventh and eighth. If there were only six characters entered into the field, only the fifth and sixth characters would be selected. No error would occur.

If you use the same value for both parameters, the start and end of the selection changes to the same position. This results in changing the cursor position within the textbox. For example, the line below can be used to move the cursor to the beginning of the text.

tbox.setSelectionRange(0,0);

You can retrieve the current selection by using the selectionStart and selectionEnd properties. These properties are set to the starting and ending positions of the current selection respectively. If both are set to the same value no text is selected, and the cursor is moved to that position. Once you have the start and end positions, you can pull out the substring from the whole text.

You can retrieve and modify the contents of the textbox by using the value property.

One additional useful property of textboxes is the textLength property, which holds the total number of characters in the field.

Next, we'll find out how to use commands.

Document Tags and Contributors

 Last updated by: Sheppy,