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.
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 and F (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>
<menu id="file-menu" value="File" accesskey="f">
<menupopup id="file-popup">
<menuitem id="close-command" value="Close" accesskey="c"/>
</menupopup>
</menu>
</menubar>
|
You can also use the accesskey 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 Contol+C to copy text to the clipboard. Although shortcuts such as this might not always be valid, they will usally 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. However, we don't need to disable Control+C when text isn't selected. Instead, we check to see if any text is selected when the keys are pressed and do nothing if no text is selected. (or perhaps beep instead.)
XUL provides an element, key, 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 Control) need to be pressed. An example is shown below:
<key id="sample-key" shift="true" key="R"/> |
This sample defines a keyboard shortcut that is activated when the user presses the Shift key and R. The key 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 a number of attributes, as listed below.
Your keyboard won't necessary have all of the keys, in which case they will be mapped to modifier keys that you do have.
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 attribute xulkey refers to the special platform-specific key used for shortcuts. If works just like the other attributes.
All of the modifier key attributes listed above can be set to true, if you require the user to press the key or false if the key must not be pressed. You can also leave the attribute off entirely, which means you don't care whether the key is pressed or not. Note that leaving the attribute out is not the same as using a value of false.
<key id="copy-key" control="true" key="C"/> <key id="copy-key" control="true" alt="false" key="C"/> |
The above two lines do not mean the same thing. The first line creates a keyboard shortcut which is activated when the user presses Control and C. It does not matter what other keys are pressed, nor whether Alt is pressed. The second example is activated when the user presses Control and C. In addition, Alt must not be pressed. This is an important distinction if you are creating keyboard shortcuts that require two modifiers to be pressed.
You can add two or more modifier keys if you want. In addition, you don't have to use any.
The key 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 typed (such as the Enter key or the function keys). The key attribute can only be used for printable characters. Another attribute, keycode can be used for non-printable characters.
The keycode 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.
| VK_CANCEL | VK_BACK | VK_TAB | VK_CLEAR |
| VK_RETURN | VK_ENTER | VK_SHIFT | VK_CONTROL |
| VK_ALT | VK_PAUSE | VK_CAPS_LOCK | VK_ESCAPE |
| VK_SPACE | VK_PAGE_UP | VK_PAGE_DOWN | VK_END |
| VK_HOME | VK_LEFT | VK_UP | VK_RIGHT |
| VK_DOWN | VK_PRINTSCREEN | VK_INSERT | VK_DELETE |
| VK_0 | VK_1 | VK_2 | VK_3 |
| VK_4 | VK_5 | VK_6 | VK_7 |
| VK_8 | VK_9 | VK_SEMICOLON | VK_EQUALS |
| VK_A | VK_B | VK_C | VK_D |
| VK_E | VK_F | VK_G | VK_H |
| VK_I | VK_J | VK_K | VK_L |
| VK_M | VK_N | VK_O | VK_P |
| VK_Q | VK_R | VK_S | VK_T |
| VK_U | VK_V | VK_W | VK_X |
| VK_Y | VK_Z | VK_NUMPAD0 | VK_NUMPAD1 |
| VK_NUMPAD2 | VK_NUMPAD3 | VK_NUMPAD4 | VK_NUMPAD5 |
| VK_NUMPAD6 | VK_NUMPAD7 | VK_NUMPAD8 | VK_NUMPAD9 |
| VK_MULTIPLY | VK_ADD | VK_SEPARATOR | VK_SUBTRACT |
| VK_DECIMAL | VK_DIVIDE | VK_F1 | VK_F2 |
| VK_F3 | VK_F4 | VK_F5 | VK_F6 |
| VK_F7 | VK_F8 | VK_F9 | VK_F10 |
| VK_F11 | VK_F12 | VK_F13 | VK_F14 |
| VK_F15 | VK_F16 | VK_F17 | VK_F18 |
| VK_F19 | VK_F20 | VK_F21 | VK_F22 |
| VK_F23 | VK_F24 | VK_NUM_LOCK | VK_SCROLL_LOCK |
| VK_COMMA | VK_PERIOD | VK_SLASH | VK_BACK_QUOTE |
| VK_OPEN_BRACKET | VK_BACK_SLASH | VK_CLOSE_BRACKET | VK_QUOTE |
For example, to create a shortcut that is activated when the user presses Alt and F5, do the following:
<key id="test-key" alt="true" keycode="VK_F5"/> |
You add the key element wherever you want in a XUL window declaration, although it should be should be inside a keyset element. This element is designed for holding a set of key elements. This also serves to group all the key definitions in one place in a file. The example below demonstrates some keyboard shortcuts:
<keyset> <key id="copy-key" xulkey="true" key="C"/> <key id="find-key" keycode="VK_F3"/> <key id="switch-key" control="true" alt="true" 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 Control 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).
Now that we know how to define keyboard shortcuts, we'll find out how we can use them. There are two ways. The first is the simplest and just requires that you use the regular key event handlers on the key element. When the user presses the key, the script will be invoked. An example is shown below:
<keyset> <key id="copy-key" xulkey="true" key="C" onkeypress="DoCopy();"/> </keyset> |
The function DoCopy will be called when the user presses the keys specified by the key 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.
You can also use the keyup and keydown event handlers.
If you are assigning a keyboard shortcut that performs a command that also exists on a menu, you can associate the key element directly with the menu command. To do this, add a key attribute on the menuitem. Set its value to the id of the key that you want to use. The example below demonstrates this.
Example 7.3.1
<keyset>
<key id="paste-key" xulkey="true" key="V"/>
</keyset>
<menubar>
<menu id="edit-menu" value="Edit" accesskey="e">
<menupopup id="edit-popup">
<menuitem id="paste-command" accesskey="p" key="paste-key" value="Close"
oncommand="alert('Paste invoked')"/>
</menupopup>
</menu>
</menubar>
|
The menuitem's key 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 Alt 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 disabled 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.
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 Escape.
<keyset>
<key id="cut_cmd" xulkey="true" key="X"/>
<key id="copy_cmd" xulkey="true" key="C"/>
<key id="paste_cmd" xulkey="true" key="V"/>
<key id="close_cmd" keycode="VK_ESCAPE"/>
</keyset>
<box orient="vertical" flex="1">
<toolbox>
<menubar>
<menu id="file-menu" value="File" accesskey="f">
<menupopup id="file-popup">
<menuitem value="Open Search..." accesskey="o"/>
<menuitem value="Save Search..." accesskey="s"/>
<menuseparator/>
<menuitem value="Close" accesskey="c" key="close_cmd"
oncommand="window.close();"/>
</menupopup>
</menu>
<menu id="edit-menu" value="Edit" accesskey="e">
<menupopup id="edit-popup">
<menuitem value="Cut" accesskey="t" key="cut_cmd"/>
<menuitem value="Copy" accesskey="c" key="copy_cmd"/>
<menuitem value="Paste" accesskey="p" key="paste_cmd" disabled="true"/>
</menupopup>
</menu>
|
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.
(Next) Next, we'll find out how to handle focus and selection.
Examples: 7.3.1