6.0 KiB
Hotkey Service
Technical name | Dependencies |
---|---|
hotkey |
ui |
Overview
The hotkey
service offers an easy way to react to a
fine bounded subset of keyboard inputs: hotkeys.
It provides some very special features:
-
awareness of the UI active element: no need to worry about that from your side.
-
a clean subset of listenable hotkeys: it ensures a consistent experience through different OSes or browsers.
-
a
useHotkey
hook: it ensures your JS code executes only when your component is alive and present in the DOM. -
a
[data-hotkey]
attribute: it gives a JS-free way to make any HTML element "clickable" through an hotkey press. -
a single key to display overlays over all HTML elements having
[data-hotkey]
attributes.
Good To Know - ALT is required
By default, to trigger an hotkey, it is required to also press the ALT
key:
e.g. ALT+C would trigger the C hotkey.
An option is available to make it optional in some cases. See the API section.
Good To Know - MAC users
To ensure a similar experience to Mac users some keys had to get swapped :
Standard Key is... | MacOS Corresponding Key is... |
---|---|
alt |
control |
control |
meta (known as Command by mac users) |
Hotkey Definition
An hotkey represents as a string a single keyboard input from a single key combined or not with modifiers.
Authorized Single Keys |
---|
a-z |
0-9 |
ArrowUp, ArrowLeft, ArrowDown and ArrowRight |
PageUp, PageDown, Home and End |
Backspace, Enter and Escape |
Authorized Modifiers |
---|
Control |
Shift |
Hotkeys must be written following these rules:
- they are not case sensitive.
- the composition character is the plus sign: "+".
- each hotkey can have none or any modifier in the authorized subset.
- order of their parts is important:
- modifiers must come first
- modifiers must get alphabetically sorted (Control is always before Shift)
- single key part must come last
E.g. following hotkeys are valid:
Control+Shift+5
g
Control+g
(same asControl+G
)
E.g. following hotkeys are NOT valid:
Alt+o
: alt is neither a valid modifier nor a valid single keyo+d
: combining two or more single keys is not validShift-p
: the composition character must be "+" and not "-"Tab
: it is not part of the list of valid single keys, nor modifiers
Hotkey Activation
Hotkeys are activated through keyboard inputs.
By default, to activate an hotkey, ALT
key should get pressed simultaneously.
It is also possible to register an hotkey that will be fireable, even without pressing ALT key.
When the service detects an hotkey activation, it will:
- execute all matching registrations callbacks.
- click on all visible elements having a matching
[data-hotkey]
attribute.
The hotkey
service will also make sure that those
registrations and elements belong to the correct UI active element (see ui
service).
API
The hotkey
service provides the following API:
-
registerHotkey(hotkey: string, callback: ()=>void, options: { altIsOptional?: boolean, allowRepeat?: boolean }): number
it asks the service to call the given callback when a matching hotkey is pressed.
options.altIsOptional
: default is false.options.allowRepeat
: default is false.This method returns a token you can use to unsubscribe later on.
-
unregisterHotkey(token: number): void
it asks the service to forget about the token matching registration.
In addition to that, you have access to some development helpers which are greatly recommended:
-
useHotkey(hotkey: string, callback: ()=>void, options: { altIsOptional?: boolean, allowRepeat?: boolean }): void
a hook that ensures your registration exists only when your component is mounted.
-
[data-hotkey]
an HTML attribute taking an hotkey definition.
When the defined hotkey is pressed, the element gets clicked.
Examples
useHotkey
hook
class MyComponent extends Component {
setup() {
useHotkey("a", this.onAHotkey.bind(this));
useHotkey("Home", () => this.onHomeHotkey());
}
onAHotkey() { ... }
onHomeHotkey() { ... }
}
[data-hotkey]
attribute
class MyComponent extends Component {
setup() {
this.variableHotkey = "control+j";
}
onButton1Clicked() {
console.log("clicked either with the mouse or with hotkey 'Shift+o'");
}
onButton2Clicked() {
console.log(`clicked either with the mouse or with hotkey '${this.variableHotkey}'`);
}
}
MyComponent.template = xml`
<div>
<button t-on-click="onButton1Clicked" data-hotkey="Shift+o">
One!
</button>
<button t-on-click="onButton2Clicked" t-att-data-hotkey="variableHotkey">
Two!
</button>
</div>
`;
manual usage of the service
class MyComponent extends Component {
setup() {
this.hotkey = useService("hotkey");
}
mounted() {
this.hotkeyToken1 = this.hotkey.registerHotkey("backspace", () =>
console.log("backspace has been pressed")
);
this.hotkeyToken2 = this.hotkey.registerHotkey("Shift+P", () =>
console.log('Someone pressed on "shift+p"!')
);
}
willUnmount() {
// You need to manually unregister your registrations when needed!
this.hotkey.unregisterHotkey(this.hotkeyToken1);
this.hotkey.unregisterHotkey(this.hotkeyToken2);
}
}