You could use keyboard event handlers to respond to the keyboard. However, it would be tedious to do that for every button and menu item (though it could be necessary when one's key commands are only triggered when the user is focused on a particular element).
XUL provides methods in which you can define keyboard shortcuts. We've already seen in the section on menus that we can define an attribute called
accesskey which specifies the key which a user can press to activate the menu or menu item. In the example below, the File menu can be selected by pressing Alt + F together (or some other key combination for a specific platform). Once the File menu is open, the Close menu item can be selected by pressing C.
<menubar id="sample-menubar"> <menu id="file-menu" label="File" accesskey="f"> <menupopup id="file-popup"> <menuitem id="close-command" label="Close" accesskey="c"/> </menupopup> </menu> </menubar>
You can also use the
attribute on buttons. When the key is pressed in this case, the button is selected.
You might want to set up more general keyboard shortcuts however. For example, pressing Ctrl + C to copy text to the clipboard. Although shortcuts such as this might not always be valid, they will usually work any time the window is open. Usually, a keyboard shortcut will be allowed at any time and you can check to see whether it should do something using a script. For example, copying text to the clipboard should only work when some text is selected.
XUL provides an element,
, which lets you define a keyboard shortcut for a window. It has attributes to specify the key that should be pressed and what modifier keys (such as Shift or Ctrl) need to be pressed. An example is shown below:
<keyset> <key id="sample-key" modifiers="shift" key="R"/> </keyset>
This sample defines a keyboard shortcut that is activated when the user presses the Shift key and R. The
attribute (note that it has the same name as the element itself) can be used to indicate which key should be pressed, in this case R. You could add any character for this attribute to require that key to be pressed. The modifiers that must be pressed are indicated with the
attribute. It is a space-separated list of modifier keys, which are listed below.
- The user must press the Alt key. On the Macintosh, this is the Option key.
- The user must press the Ctrl key.
- The user must press the Meta key. This is the Command key on the Macintosh.
- The user must press the Shift key.
- The user must press the Win key. This is the Super key or the Hyper key on Linux. If this value is used, typically the key combination conflicts with system wide shortcut keys. So, you shouldn't use this value as far as possible.
- The user must press the special accelerator key. The key used for keyboard shortcuts on the user's platform. Usually, this would be the value you would use.
- The user must press the special access key. The key used for access keys on the user's platform.
Your keyboard won't necessarily have all of the keys, in which case they will be mapped to modifier keys that you do have.
element must be placed inside a
element. This element is designed for holding a set of
key elements, which serves to group all of the key definitions in one place in a file. Any
key elements outside of a
keyset element will not work.
Each platform generally uses a different key for keyboard shortcuts. For example, Windows uses the Control key and the Macintosh uses the Command key. It would be inconvenient to define separate
key elements for each platform. Luckily, there is a solution. The modifier
accel refers to the special platform-specific key used for shortcuts. It works just like the other modifiers, but won't be the same on every platform.
Here are some additional examples:
<keyset> <key id="copy-key" modifiers="control" key="C"/> <key id="explore-key" modifiers="control alt" key="E"/> <key id="paste-key" modifiers="accel" key="V"/> </keyset>
attribute is used to specify the key that must be pressed. However, there will also be cases where you want to refer to keys that cannot be specified with a character (such as the Enter key or the function keys). The
key attribute can only be used for printable characters. Another attribute,
can be used for non-printable characters.
attribute should be set to a special code which represents the key you want. A table of the keys is listed below. Not all of the keys are available on all keyboards.
For example, to create a shortcut that is activated when the user presses Alt and F5, do the following:
<keyset> <key id="test-key" modifiers="alt" keycode="VK_F5"/> </keyset>
The example below demonstrates some more keyboard shortcuts:
<keyset> <key id="copy-key" modifiers="accel" key="C"/> <key id="find-key" keycode="VK_F3"/> <key id="switch-key" modifiers="control alt" key="1"/> </keyset>
The first key is invoked when the user presses their platform-specific shortcut key and C. The second is invoked when the user presses F3. The third is invoked on a press of the Ctrl key, the Alt key and 1. If you wanted to distinguish between keys on the main part of the keyboard and the numeric keypad, use the VK_NUMPAD keys (such as VK_NUMPAD1).
Refer to the Mozilla Keyboard Planning FAQ and Cross Reference for more information about selecting keyboard shortcuts to use in applications.
Now that we know how to define keyboard shortcuts, we'll find out how we can use them. There are two ways.
The first way is the simplest and just requires that you use the command event handler on the
element. When the user presses the key, the script will be invoked. An example is shown below:
<keyset> <key id="copy-key" modifiers="accel" key="C" oncommand="DoCopy();"/> </keyset>
DoCopy will be called when the user presses the keys specified by the
element, which in this example, are the keys for copying to the clipboard (such as Control + C). This will work as long as the window is open. The
DoCopy function should check to see if text is selected and then copy the text to the clipboard. Note that textboxes have the clipboard shortcuts built-in so you don't have to implement them yourself.
Assigning a keyboard shortcut on a menu
The second way is: If you are assigning a keyboard shortcut that performs a command that also exists on a menu, you can associate the
element directly with the menu command. To do this, also add a
attribute on the
. Set its value to the
of the key that you want to use. The example below demonstrates this.
<keyset> <key id="paste-key" modifiers="accel" key="V" oncommand="alert('Paste invoked')"/> </keyset> <menubar id="sample-menubar"> <menu id="edit-menu" label="Edit" accesskey="e"> <menupopup id="edit-popup"> <menuitem id="paste-command" accesskey="p" key="paste-key" label="Paste" oncommand="alert('Paste invoked')"/> </menupopup> </menu> </menubar>
attribute, which here is
paste-key is equal to the
id of the defined key. You can use this for additional keys as well to define keyboard shortcuts for any number of menu items.
You'll also notice in the image that text has been placed next to the Paste menu command to indicate that Ctrl and the V key can be pressed to invoke the menu command. This is added for you based on the modifiers on the
key element. Keyboard shortcuts attached to menus will work even if the menu is not open.
One additional feature of key definitions is that you can disable them easily. To do this add a
attribute to the
key element and set it to the value
true. This disables the keyboard shortcut so that it cannot be invoked. It is useful to change the
disabled attribute using a script.
Our find files example
Let's add keyboard shortcuts to the find files dialog. We'll add four of them, one for each of the Cut, Copy, and Paste commands and also one for the Close command when the user presses Esc.
<?xml version="1.0" encoding="utf-8"?> <window xmlns="http://www.mozilla.org/keymaster/gat...re.is.only.xul"> <keyset> <key id="cut_cmd" modifiers="accel" key="X"/> <key id="copy_cmd" modifiers="accel" key="C"/> <key id="paste_cmd" modifiers="accel" key="V"/> <key id="close_cmd" keycode="VK_ESCAPE" oncommand="window.close();"/> </keyset> <vbox flex="1"> <toolbox> <menubar id="findfiles-menubar"> <menu id="file-menu" label="File" accesskey="f"> <menupopup id="file-popup"> <menuitem label="Open Search..." accesskey="o"/> <menuitem label="Save Search..." accesskey="s"/> <menuseparator/> <menuitem label="Close" accesskey="c" key="close_cmd" oncommand="window.close();"/> </menupopup> </menu> <menu id="edit-menu" label="Edit" accesskey="e"> <menupopup id="edit-popup"> <menuitem label="Cut" accesskey="t" key="cut_cmd"/> <menuitem label="Copy" accesskey="c" key="copy_cmd"/> <menuitem label="Paste" accesskey="p" key="paste_cmd" disabled="true"/> </menupopup> </menu> </menubar> </toolbox> </vbox> </window>
Now we can use those shortcuts to activate the commands. Of course, the clipboard commands don't do anything anyway, as we haven't written those scripts.
There are three keyboard events that may be used if the key related features described above aren't suitable. These events are:
- Called when a key is pressed and released when an element has the focus. You might use this to check for allowed characters in a field.
- Called when a key is pressed down while an element has the focus. Note that the event will be called as soon as the key is pressed, even if it hasn't been released yet.
- Called when a key is released while an element has the focus.
Key events are only sent to the element that has the focus. Typically, this will include textboxes, buttons, checkboxes and so forth. If no element is focused, the key event will instead be targeted at the XUL document itself. In this case, you can add an event listener to the
tag. Normally though, if you want to respond to keys globally, you will use a keyboard shortcut as described earlier.
The key event object has two properties which hold the key that was pressed. The
keyCode property holds the key code and may be compared to one of the constants from the key table earlier in this section. The
charCode is used for printable characters and will hold the numeric Unicode character code value for the key that was pressed.
Next, we'll find out how to handle focus and the selection.