# 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](#hotkey-definition). 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](#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 as `Control+G`) E.g. following hotkeys are **NOT** valid: - `Alt+o`: **alt** is neither a valid modifier nor a valid single key - `o+d`: combining two or more single keys is not valid - `Shift-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](ui.md)). ## 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 ```js class MyComponent extends Component { setup() { useHotkey("a", this.onAHotkey.bind(this)); useHotkey("Home", () => this.onHomeHotkey()); } onAHotkey() { ... } onHomeHotkey() { ... } } ``` ### `[data-hotkey]` attribute ```js 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`
`; ``` ### manual usage of the service ```js 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); } } ```