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
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:tabindex
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
attribute pointing to the id of the textbox.control
- Finally, the other label which displays the tag name has no
attribute, so clicking it has no effect on the focused element. Only focusable elements can be focused.control
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
method of the select
.textbox
tbox.select();
However, you may wish to select only part of the text. To do this you can use the
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.setSelectionRange
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
and selectionStart
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.selectionEnd
You can retrieve and modify the contents of the textbox by using the
property.value
One additional useful property of textboxes is the
property, which holds the total number of characters in the field.textLength
Next, we'll find out how to use commands.