]> git.gir.st - VimFx.git/blob - documentation/api.md
Save the focusType instead of getting it on every keydown
[VimFx.git] / documentation / api.md
1 <!--
2 This is part of the VimFx documentation.
3 Copyright Simon Lydell 2015, 2016.
4 See the file README.md for copying conditions.
5 -->
6
7 # API
8
9 This file documents VimFx’s [config file] API.
10
11 Both `config.js` and `frame.js` have access to a variable called `vimfx`. Note
12 that while the variables have the same name, they are different and provide
13 different API methods.
14
15
16 ## `config.js` API
17
18 In `config.js`, the following API is available as the variable `vimfx`.
19
20 ### `vimfx.get(...)`, `vimfx.getDefault(...)` and `vimfx.set(...)`
21
22 Gets or sets the (default) value of a VimFx pref.
23
24 You can see all prefs in [defaults.coffee], or by opening [about:config] and
25 filtering by `extensions.vimfx`. Note that you can also access the [special
26 options], which may not be accessed in [about:config], using `vimfx.get(...)`
27 and `vimfx.set(...)`—in fact, this is the _only_ way of accessing those options.
28
29 #### `vimfx.get(pref)`
30
31 Gets the value of the VimFx pref `pref`.
32
33 ```js
34 // Get the value of the Hint chars option:
35 vimfx.get('hint_chars')
36 // Get all keyboard shortcuts (as a string) for the `f` command:
37 vimfx.get('mode.normal.follow')
38 ```
39
40 #### `vimfx.getDefault(pref)`
41
42 Gets the default value of the VimFx pref `pref`.
43
44 Useful when you wish to extend a default, rather than replacing it. See below.
45
46 #### `vimfx.set(pref, value)`
47
48 Sets the value of the VimFx pref `pref` to `value`.
49
50 ```js
51 // Set the value of the Hint chars option:
52 vimfx.set('hint_chars', 'abcdefghijklmnopqrstuvwxyz')
53 // Add yet a keyboard shortcut for the `f` command:
54 vimfx.set('mode.normal.follow', vimfx.getDefault('mode.normal.follow') + ' e')
55 ```
56
57 When extending a pref (as in the second example above), be sure to use
58 `vimfx.getDefault` rather than `vimfx.get`. Otherwise you get a multiplying
59 effect. In the above example, after starting Firefox a few times the pref would
60 be `f e e e e`. Also, if you find that example very verbose: Remember that
61 you’re using a programming language! Write a small helper function that suits
62 your needs.
63
64 Note: If you produce conflicting keyboard shortcuts, the order of your code does
65 not matter. The command that comes first in VimFx’s settings page in the Add-ons
66 Manager (and in the Keyboard Shortcuts help dialog) gets the shortcut; the other
67 one(s) do(es) not. See the notes about order in [mode object], [category object]
68 and [command object] for more information about order.
69
70 ```js
71 // Even though we set the shortcut for focusing the search bar last, the command
72 // for focusing the location bar “wins”, because it comes first in VimFx’s
73 // settings page in the Add-ons Manager.
74 vimfx.set('mode.normal.focus_location_bar', 'ö')
75 vimfx.set('mode.normal.focus_search_bar', 'ö')
76
77 // Swapping their orders also swaps the “winner”.
78 let {commands} = vimfx.modes.normal
79 ;[commands.focus_location_bar.order, commands.focus_search_bar.order] =
80 [commands.focus_search_bar.order, commands.focus_location_bar.order]
81 ```
82
83 ### `vimfx.addCommand(options, fn)`
84
85 Creates a new command.
86
87 `options`:
88
89 - name: `String`. The name used when accessing the command via
90 `vimfx.modes[options.mode].commands[options.name]`. It is also used for the
91 pref used to store the shortcuts for the command:
92 `` `custom.mode.${options.mode}.${options.name}` ``.
93 - description: `String`. Shown in the Keyboard Shortcuts help dialog and VimFx’s
94 settings page in the Add-ons Manager.
95 - mode: `String`. Defaults to `'normal'`. The mode to add the command to. The
96 value has to be one of the keys of [`vimfx.modes`].
97 - category: `String`. Defaults to `'misc'` for Normal mode and `''`
98 (uncategorized) otherwise. The category to add the command to. The
99 value has to be one of the keys of [`vimfx.get('categories')`][categories].
100 - order: `Number`. Defaults to putting the command at the end of the category.
101 The first of the default commands has the order `100` and then they increase
102 by `100` per command. This allows to put new commands between two already
103 existing ones.
104
105 `fn` is called when the command is activated. See the [onInput] documentation
106 below for more information.
107
108 <strong id="custom-command-shortcuts">Note</strong> that you have to give the
109 new command a shortcut in VimFx’s settings page in the Add-ons Manager or set
110 one using `vimfx.set(...)` to able to use the new command.
111
112 ```js
113 vimfx.addCommand({
114 name: 'hello',
115 description: 'Log Hello World',
116 }, => {
117 console.log('Hello World!')
118 })
119 // Optional:
120 vimfx.set('custom.mode.normal.hello', 'gö')
121 ```
122
123 ### `vimfx.addOptionOverrides(...)` and `vimfx.addKeyOverrides(...)`
124
125 These methods take any number of arguments. Each argument is a rule. The rules
126 are added in order. The methods may be run multiple times.
127
128 A rule is an `Array` of length 2:
129
130 1. The first item is a function that returns `true` if the rule should be
131 applied and `false` if not. This is called the matching function.
132 2. The second item is the value that should be used if the rule is applied. This
133 is called the override.
134
135 The rules are tried in the same order they were added. When a matching rule is
136 found it is applied. No more rules will be applied.
137
138 #### `vimfx.addOptionOverrides(...rules)`
139
140 The rules are matched any time the value of a VimFx pref is needed.
141
142 The matching function receives a [location object].
143
144 The override is an object whose keys are VimFx pref names and whose values
145 override the pref in question. The values should be formatted as in an [options
146 object].
147
148 ```js
149 vimfx.addOptionOverrides(
150 [ ({hostname, pathname, hash}) =>
151 `${hostname}${pathname}${hash}` === 'google.com/',
152 {prevent_autofocus: false}
153 ]
154 )
155 ```
156
157 #### `vimfx.addKeyOverrides(...rules)`
158
159 The rules are matched any time you press a key that is not part of the tail of a
160 multi-key shortcut.
161
162 The matching function receives a [location object] as well as the current
163 mode name (one of the keys of [`vimfx.modes`]).
164
165 The override is an array of keys which should not activate VimFx commands but be
166 sent to the page.
167
168 This allows to disable commands on specific sites. To _add_ commands on specific
169 sites, add them globally and then disable them on all _other_ sites.
170
171 ```js
172 vimfx.addKeyOverrides(
173 [ location => location.hostname === 'facebook.com',
174 ['j', 'k']
175 ]
176 )
177 ```
178
179 ### `vimfx.send(vim, message, data = null, callback = null)`
180
181 Send `message` (a string) to the instance of `frame.js` in the tab managed by
182 [`vim`][vim object], and pass it `data`. If provided, `callback` must be a
183 function that takes a single argument, which is the data that `frame.js`
184 responds with. `frame.js` uses its [`vimfx.listen(...)`] method to listen for
185 (and optionally respond to) `message`.
186
187 Here is an example:
188
189 ```js
190 // config.js
191 // You get a `vim` instance by using `vimfx.addCommand(...)` or `vimfx.on(...)`.
192 vimfx.send(vim, 'getSelection', {example: 5}, selection => {
193 console.log('Currently selected text:', selection)
194 })
195 ```
196
197 ```js
198 // frame.js
199 vimfx.listen('getSelection', ({example}, callback) => {
200 console.log('`example` should be 5:', example)
201 let selection = content.getSelection().toString()
202 callback(selection)
203 })
204 ```
205
206 What if you want to do it the other way around: Send a message _from_ `frame.js`
207 and listen for it in `config.js`? That’s not the common use case, so VimFx does
208 not provide convenience functions for it. Yes, `vimfx.send(...)`, and
209 `vimfx.listen(...)` in `frame.js`, are just light wrappers around the standard
210 Firefox [Message Manager] to make it easier to create custom commands that ask
211 `frame.js` for information about the current web page (as in the above example).
212 If you want to send messages any other way, you’ll need to use the Message
213 Manager directly. See [the `shutdown` event] for an example.
214
215 (While it would have made sense to provide `vim.send(message, data, callback)`
216 instead of `vimfx.send(vim, message, data, callback)`, the latter was chosen for
217 symmetry between `config.js` and `frame.js`. Use `vimfx.send()` to send
218 messages, and `vimfx.listen()` to listen for them.)
219
220 ### `vimfx.on(eventName, listener)` and `vimfx.off(eventName, listener)`
221
222 After calling `vimfx.on(eventName, listener)`, `listener(data)` will be called
223 when `eventName` is fired.
224
225 You may use `vimfx.off(eventName, listener)` if you’d like to remove your
226 added listener for some reason.
227
228 While [`vimfx.send(...)`] and [`vimfx.listen(...)`] are all about passing
229 messages between `config.js` and `frame.js`, `vimfx.on(...)` is all about doing
230 something whenever VimFx emits internal events.
231
232 #### The `locationChange` event
233
234 Occurs when opening a new tab, navigating to a new URL or refreshing the page,
235 causing a full page load. The data passed to listeners is an object with the
236 following properties:
237
238 - vim: The current [vim object].
239 - location: A [location object].
240
241 This can be used to enter a different mode by default on some pages (which can
242 be used to replace the blacklist option).
243
244 ```js
245 vimfx.on('locationChange', ({vim, location}) => {
246 if (location.hostname === 'example.com') {
247 vim.enterMode('ignore', {type: 'blacklist'})
248 }
249 })
250 ```
251
252 #### The `notification` and `hideNotification` events
253
254 The `notification` event occurs when `vim.notify(message)` is called, and means
255 that `message` should be displayed to the user.
256
257 The `hideNotification` event occurs when the `vim.hideNotification()` is called,
258 and means that the current notification is requested to be hidden.
259
260 The data passed to listeners is an object with the following properties:
261
262 - vim: The current [vim object].
263 - message: The message that should be notified. Only for the `notification`
264 event.
265
266 Both of these events are emitted even if the [`notifications_enabled`] option is
267 disabled, allowing you to display notifications in any way you want.
268
269 #### The `modeChange` event
270
271 Occurs whenever the current mode in any tab changes. The initial entering of the
272 default mode in new tabs also counts as a mode change. The data passed to
273 listeners is the current [vim object].
274
275 ```js
276 vimfx.on('modeChange', vim => {
277 let mode = vimfx.modes[vim.mode].name
278 vim.notify(`Entering mode: ${mode}`)
279 })
280 ```
281
282 #### The `TabSelect` event
283
284 Occurs whenever any tab in any window is selected. This is also fired when
285 Firefox starts for the currently selected tab. The data passed to listeners is
286 the `event` object passed to the standard Firefox [TabSelect] event.
287
288 #### The `modeDisplayChange` event
289
290 This is basically a combination of the `modeChange` and the `TabSelect` events.
291 The event is useful for knowing when to update UI showing the current mode. The
292 data passed to listeners is the current [vim object].
293
294 (VimFx itself uses this event to update the toolbar [button], by setting
295 `#main-window[vimfx-mode]` to the current mode. You may use this with custom
296 [styling].)
297
298 #### The `focusTypeChange` event
299
300 Occurs when focusing or blurring any element. The data passed to listeners is
301 the current [vim object].
302
303 `vim.focusType` has been updated just before this event fires.
304
305 (VimFx itself uses this event to update the toolbar [button], by setting
306 `#main-window[vimfx-focus-type]` to the current focus type. You may use this
307 with custom [styling].)
308
309 #### The `shutdown` event
310
311 Occurs when:
312
313 - VimFx shuts down: When Firefox shuts down, when VimFx is disabled or when
314 VimFx is updated.
315 - When the config file is reloaded using the `zr` command.
316
317 If you care about that things you do in `config.js` and `frame.js` are undone
318 when any of the above happens, read on.
319
320 If all you do is using the methods of the `vimfx` object, you shouldn’t need to
321 care about this event.
322
323 The following methods don’t need any undoing:
324
325 - `vimfx.get(...)`
326 - `vimfx.getDefault(...)`
327 - `vimfx.send(...)`
328 - `vimfx.off(...)`
329
330 The following methods are automatically undone when the `shutdown` event fires.
331 This means that if you, for example, add a custom command in `config.js` but
332 then remove it from `config.js` and hit `zr`, the custom command will be gone in
333 VimFx.
334
335 - `vimfx.set(...)`
336 - `vimfx.addCommand(...)`
337 - `vimfx.addOptionOverrides(...)`
338 - `vimfx.addKeyOverrides(...)`
339 - `vimfx.on(...)`
340
341 The following require manual undoing:
342
343 - `vimfx.mode`. Any changes you do here must be manually undone.
344
345 If you add event listeners in `frame.js`, here’s an example of how to remove
346 them on `shutdown`:
347
348 ```js
349 // config.js
350 vimfx.on('shutdown', () => {
351 Components.classes['@mozilla.org/globalmessagemanager;1']
352 .getService(Components.interfaces.nsIMessageListenerManager)
353 // Send this message to _all_ frame scripts.
354 .broadcastAsyncMessage('VimFx-config:shutdown')
355 })
356 ```
357
358 ```js
359 // frame.js
360 let listeners = []
361 function listen(eventName, listener) {
362 addEventListener(eventName, listener, true)
363 listeners.push([eventName, listener])
364 }
365
366 listen('focus', event => {
367 console.log('focused element', event.target)
368 })
369
370 addMessageListener('VimFx-config:shutdown', () => {
371 listeners.forEach(([eventName, listener]) => {
372 removeMessageListener(eventName, listener, true)
373 })
374 })
375 ```
376
377 ### `vimfx.modes`
378
379 An object whose keys are mode names and whose values are [mode object]s.
380
381 This is a very low-level part of the API. It allows to:
382
383 - Access all commands and run them. This is the most common thing that a config
384 file user needs it for.
385
386 ```js
387 let {commands} = vimfx.modes.normal
388 // Inside a custom command:
389 commands.tab_new.run(args)
390 ```
391
392 - Adding new commands. It is recommended to use the `vimfx.addCommand(...)`
393 helper instead. It’s easier.
394
395 ```js
396 vimfx.modes.normal.commands.new_command = {
397 pref: 'extensions.my_extension.mode.normal.new_command',
398 category: 'misc',
399 order: 10000,
400 description: translate('mode.normal.new_command'),
401 run: args => console.log('New command! args:', args)
402 }
403 ```
404
405 - Adding new modes. This is the most advanced customization you can do to VimFx.
406 Expect having to read VimFx’s source code to figure it all out.
407
408 ```js
409 vimfx.modes.new_mode = {
410 name: translate('mode.new_mode'),
411 order: 10000,
412 commands: {},
413 onEnter(args) {},
414 onLeave(args) {},
415 onInput(args, match) {
416 if (match.type === 'full') {
417 match.command.run(args)
418 }
419 return (match.type !== 'none')
420 },
421 }
422 ```
423
424 Have a look at [modes.coffee] and [commands.coffee] for more information.
425
426 ### `vimfx.get('categories')`
427
428 An object whose keys are category names and whose values are [category object]s.
429
430 ```js
431 let categories = vimfx.get('categories')
432
433 // Add a new category.
434 categories.custom = {
435 name: 'Custom commands',
436 order: 10000,
437 }
438
439 // Swap the order of the Location and Tabs categories.
440 ;[commands.focus_location_bar.order, categories.tabs.order] =
441 [categories.tabs.order, commands.focus_location_bar.order]
442 ```
443
444 ### Mode object
445
446 A mode is an object with the following properties:
447
448 - name: `String`. A human readable name of the mode used in the Keyboard
449 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
450 file users adding custom modes could simply use a hard-coded string; extension
451 authors are encouraged to look up the name from a locale file.
452 - order: `Number`. The first of the default modes has the order `100` and then
453 they increase by `100` per mode. This allows to put new modes between two
454 already existing ones.
455 - commands: `Object`. The keys are command names and the values are [command
456 object]s.
457 - onEnter(data, ...args): `Function`. Called when the mode is entered.
458 - onLeave(data): `Function`. Called when the mode is left.
459 - onInput(data, match): `Function`. Called when a key is pressed.
460
461 #### onEnter, onLeave and onInput
462
463 These methods are called with an object (called `data` above) with the following
464 properties:
465
466 - vim: The current [vim object].
467 - storage: An object unique to the current [vim object] and to the current mode.
468 Allows to share things between commands of the same mode by getting and
469 setting keys on it.
470
471 ##### onEnter
472
473 This method is called with an object as mentioned above, and after that there
474 may be any number of arguments (`args` in `vim.enterMode(modeName, ...args)`)
475 that the mode is free to do whatever it wants with.
476
477 Whatever is returned from `onEnter` will be returned from
478 `vim.enterMode(modeName, ...args)`.
479
480 ##### onInput
481
482 The object passed to this method (see above) also has the following properties:
483
484 - uiEvent: `Event` or `false`. The keydown event object if the event occurred in
485 the browser UI, `false` otherwise (if the event occurred in web page content).
486 - count: `Number`. The count for the command. `undefined` if no count. (This is
487 simply a copy of `match.count`. `match` is defined below.)
488
489 The above object should be passed to commands when running them. The mode is
490 free to do whatever it wants with the return value (if any) of the commands it
491 runs.
492
493 It also receives a [match object] as the second argument.
494
495 `onInput` should return `true` if the current keypress should not be passed on
496 to the browser and web pages, and `false` otherwise.
497
498 ### Category object
499
500 A category is an object with the following properties:
501
502 - name: `String`. A human readable name of the category used in the Keyboard
503 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
504 file users adding custom categories could simply a use hard-coded string;
505 extension authors are encouraged to look up the name from a locale file.
506 - order: `Number`. The first of the default categories is the “uncategorized”
507 category. It has the order `100` and then they increase by `100` per category.
508 This allows to put new categories between two already existing ones.
509
510 ### Command object
511
512 A command is an object with the following properties:
513
514 - pref: `String`. The pref used to store the shortcuts for the command.
515 - run(args): `Function`. Called when the command is activated.
516 - description: `String`. A description of the command, shown in the Keyboard
517 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
518 file users adding custom commands could simply use a hard-coded string;
519 extension authors are encouraged to look up the name from a locale file.
520 - category: `String`. The category to add the command to. The value has to be
521 one of the keys of [`vimfx.get('categories')`][categories].
522 - order: `Number`. The first of the default commands has the order `100` and
523 then they increase by `100` per command. This allows to put new commands
524 between two already existing ones.
525
526 ### Match object
527
528 A `match` object has the following properties:
529
530 - type: `String`. It has one of the following values:
531
532 - `'full'`: The current keypress, together with previous keypresses, fully
533 matches a command shortcut.
534 - `'partial'`: The current keypress, together with previous keypresses,
535 partially matches a command shortcut.
536 - `'count'`: The current keypress is not part of a command shortcut, but is a
537 digit and contributes to the count of a future matched command.
538 - `'none'`: The current keypress is not part of a command shortcut and does
539 not contribute to a count.
540
541 - likelyConflict: `Boolean`. This is `true` if the current keypress is likely to
542 cause conflicts with default Firefox behavior of that key, and `false`
543 otherwise. A mode might not want to run commands and suppress the event if
544 this value is `true`. VimFx uses the current keypress and `vim.focusType` of
545 the current [vim object] to decide if the current keypress is a likely
546 conflict:
547
548 1. If the key is part of the tail of a shortcut, it is never a conflict.
549 2. If `vim.focusType` is `'activatable'` or `'adjustable'` and the key is
550 present in [`activatable_element_keys`] or [`adjustable_element_keys`]
551 (respectively), then it is a likely conflict.
552 3. Finally, unless `vim.focusType` is `'none'`, then it is a likely conflict.
553 This most commonly means that a text input is focused.
554
555 Note that any VimFx shortcut starting with a keypress involving a modifier is
556 _very_ likely to conflict with either a Firefox default shortcut or a shortcut
557 from some other add-on. This is _not_ attempted to be detected in any way.
558 Instead, VimFx uses no modifiers in any default Normal mode shortcuts, leaving
559 it up to you to choose modifier-shortcuts that work out for you if you want
560 such shortcuts. In other words, for modifier-shortcuts the point of VimFx _is_
561 to conflict (overriding default shortcuts).
562
563 - command: `null` unless `type` is `'full'`. Then it is the matched command (a
564 [command object]).
565
566 The matched command should usually be run at this point. It is suitable to
567 pass on the object passed to [onInput] to the command. Some modes might choose
568 to add extra properties to the object first. (That is favored over passing
569 several arguments, since it makes it easier for the command to in turn pass
570 the same data it got on to another command, if needed.)
571
572 Usually the return value of the command isn’t used, but that’s up to the mode.
573
574 - count: `Number`. The count for the command. `undefined` if no count.
575
576 - specialKeys: `Object`. The keys may be any of the following:
577
578 - `<force>`
579 - `<late>`
580
581 If a key exists, its value is always `true`. The keys that exist indicate the
582 [special keys] for the sequence used for the matched command (if any).
583
584 - keyStr: `String`. The current keypress represented as a string.
585
586 - unmodifiedKey: `String`. `keyStr` without modifiers.
587
588 - toplevel: `Boolean`. Whether or not the match was a toplevel match in the
589 shortcut key tree. This is `true` unless the match is part of the tail of a
590 multi-key shortcut.
591
592 - discard(): `Function`. Discards keys pressed so far: If `type` is `'partial'`
593 or `'count'`. For example, if you have typed `12g`, run `match.discard()` and
594 then press `$`, the `$` command will be run instead of `12g$`.
595
596 ### Vim object
597
598 There is one `vim` object per tab.
599
600 A `vim` object has the following properties:
601
602 - window: [`Window`]. The current Firefox window object. Most commands
603 interacting with Firefox’s UI use this.
604
605 - browser: [`Browser`]. The `browser` that this vim object handles.
606
607 - options: `Object`. Provides access to all of VimFx’s options. It is an
608 [options object].
609
610 - mode: `String`. The current mode name.
611
612 - focusType: `String`. The type of currently focused element. VimFx decides the
613 type based on how it responds to keystorkes. It has one of the following
614 values:
615
616 - `'ignore'`: Some kind of Vim-style editor. VimFx automatically
617 enters Ignore mode when this focus type is encountered.
618 - `'editable'`: Some kind of text input, a `<select>` element or a
619 “contenteditable” element.
620 - `'activatable'`: An “activatable” element (link or button).
621 (See also the [`activatable_element_keys`] option.)
622 - `'adjustable'`: An “adjustable” element (form control or video
623 player). (See also the [`adjustable_element_keys`] option.)
624 - `'other'`: Some other kind of element that can receive keystrokes.
625 (Deprecated.)
626 - `'none'`: The currently focused element does not appear to respond to
627 keystrokes in any special way.
628
629 [The `focusTypeChange` event] is fired whenever `focusType` is updated.
630
631 `match.likelyConflict` of [match object]s depend on `focusType`.
632
633 - enterMode(modeName, ...args): `Function`. Enter mode `modeName`, passing
634 `...args` to the mode. It is up to every mode to do whatever it wants to with
635 `...args`. If `modeName` was already the current mode, nothing is done and
636 `undefined` is returned. Otherwise it us up to the mode to return whatever it
637 wants to.
638
639 - isUIEvent(event): `Function`. Returns `true` if `event` occurred in the
640 browser UI, and `false` otherwise (if it occurred in web page content).
641
642 - notify(message): `Function`. Display a notification with the text `message`.
643
644 - hideNotification(): `Function`. Hide the current notification (if any).
645
646 - markPageInteraction(value=true): `Function`. When `value` is `true` (as it is
647 by default when the argument is omitted), marks that the user has interacted
648 with the page. After that [autofocus prevention] is not done anymore. Commands
649 interacting with web page content might want to do this. If `value` is
650 `false`, the state is reset and autofocus prevention _will_ be done again.
651
652 **Warning:** There are also properties starting with an underscore on `vim`
653 objects. They are private, and not supposed to be used outside of VimFx’s own
654 source code. They may change at any time.
655
656 ### Options object
657
658 An `options` object provides access to all of VimFx’s options. It is an object
659 whose keys are VimFx pref names.
660
661 Note that the values are not just simply `vimfx.get(pref)` for the `pref` in
662 question; they are _parsed_ (`parse(vimfx.get(pref))`):
663
664 - Space-separated prefs are parsed into arrays of strings.
665
666 - `black_list` and `{prev,next}_patterns` are parsed into arrays of regular
667 expressions.
668
669 (See [parse-prefs.coffee] for all details.)
670
671 Any [option overrides] are automatically taken into account when getting an
672 option value.
673
674 The [special options] are also available on this object.
675
676
677 ### Location object
678
679 A location object is very similar to [`window.location`] in web pages.
680 Technically, it is a [`URL`] instance. You can experiment with the current
681 location object by opening the [web console] and entering `location`.
682
683
684 ## `frame.js` API
685
686 In `frame.js`, the following API is available as the variable `vimfx`.
687
688 ### `vimfx.listen(message, listener)`
689
690 Listen for `message` (a string) from `config.js`. `listener` will be called with
691 the data sent from `config.js` (if any), and optionally a callback function if
692 `config.js` wants you to respond. If so, call the callback function, optionally
693 with some data to send back to `config.js.` `config.js` uses its
694 [`vimfx.send(...)`] method to send `message` (and optionally some data along
695 with it).
696
697 See the [`vimfx.send(...)`] method in `config.js` for more information and
698 examples.
699
700 ### `vimfx.setHintMatcher(hintMatcher)`
701
702 `hintMatcher` is a function that lets you customize which elements do and don’t
703 get hints. It might help to read about [the `f` commands] first.
704
705 If you call `vimfx.setHintMatcher(hintMatcher)` more than once, only the
706 `hintMatcher` provided the last time will be used.
707
708 ```js
709 vimfx.setHintMatcher((id, element, {type, semantic}) => {
710 // Inspect `element` and change `type` and `semantic` if needed.
711 return {type, semantic}
712 })
713 ```
714
715 The arguments passed to the `hintMatcher` function are:
716
717 - id: `String`. A string identifying which command is used:
718
719 - `'normal'`: `f` or `af`.
720 - `'tab'`: `F`, `gf` or `gF`.
721 - `'copy'`: `yf`.
722 - `'focus'`: `zf`.
723
724 - element: `Element`. One out of all elements currently inside the viewport.
725
726 - info: `Object`. It has the following properties:
727
728 - type: `String` or `null`. If a string, it means that `element` should get a
729 hint. If `null`, it won’t. See the available strings below. When a marker
730 is matched, `type` decides what happens to `element`.
731 - semantic: `Boolean`. Indicates whether or not the element is “semantic.”
732 Semantic elements get better hints.
733
734 This object contains information on how VimFx has matched `element`. You have
735 the opportunity to change this.
736
737 The available type strings depend on `id`:
738
739 - normal:
740
741 - link: A “proper” link (not used as a button with the help of JavaScript),
742 with an `href` attribute.
743 - text: An element that can you can type in, such as text inputs.
744 - clickable: Some clickable element not falling into another category.
745 - clickable-special: Like “clickable,” but uses a different technique to
746 simulate a click on the element. If “clickable” doesn’t work, try this one.
747 - scrollable: A scrollable element.
748
749 - tab:
750
751 - link: Like “link” when `id` is “normal” (see above).
752
753 - copy:
754
755 - link: Like “link” when `id` is “normal” (see above).
756 - text: Like “text” when `id` is “normal” (see above), except that in this
757 case “contenteditable” elements are not included.
758 - contenteditable: Elements with “contenteditable” turned on.
759
760 - focus:
761
762 - focusable: Any focusable element not falling into another category.
763 - scrollable: Like “scrollable” when `id` is “normal” (see above).
764
765 The function must return an object like the `info` parameter (with the `type`
766 and `semantic` properties).
767
768
769 ## Stability
770
771 The API is currently **experimental** and therefore **unstable.** Things might
772 break with new VimFx versions. However, no breaking changes are planned, and
773 will be avoided if feasible.
774
775 As soon as VimFx 1.0.0 (which does not seem to be too far away) is released
776 backwards compatibility will be a priority and won’t be broken until VimFx
777 2.0.0.
778
779 [option overrides]: #vimfxaddoptionoverridesrules
780 [`vimfx.send(...)`]: #vimfxsendvim-message-data--null-callback--null
781 [`vimfx.listen(...)`]: #vimfxlistenmessage-listener
782 [categories]: #vimfxgetcategories
783 [`vimfx.modes`]: #vimfxmodes
784 [onInput]: #oninput
785 [mode object]: #mode-object
786 [category object]: #category-object
787 [command object]: #command-object
788 [match object]: #match-object
789 [vim object]: #vim-object
790 [options object]: #options-object
791 [location object]: #location-object
792 [The `focusTypeChange` event]: #the-focustypechange-event
793 [the `shutdown` event]: #the-shutdown-event
794
795 [blacklisted]: options.md#blacklist
796 [special options]: options.md#special-options
797 [config file]: config-file.md
798 [bootstrap.js]: config-file.md#bootstrapjs
799 [autofocus prevention]: options.md#prevent-autofocus
800 [`activatable_element_keys`]: options.md#activatable_element_keys
801 [`adjustable_element_keys`]: options.md#adjustable_element_keys
802 [`notifications_enabled`]: options.md#notifications_enabled
803
804 [button]: button.md
805 [the `f` commands]: commands.md#the-f-commands--hints-mode
806 [special keys]: shortcuts.md#special-keys
807 [styling]: styling.md
808
809 [defaults.coffee]: ../extension/lib/defaults.coffee
810 [parse-prefs.coffee]: ../extension/lib/parse-prefs.coffee
811 [modes.coffee]: ../extension/lib/modes.coffee
812 [commands.coffee]: ../extension/lib/commands.coffee
813 [vim.coffee]: ../extension/lib/vim.coffee
814
815 [`Window`]: https://developer.mozilla.org/en-US/docs/Web/API/Window
816 [`Browser`]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
817 [`window.location`]: https://developer.mozilla.org/en-US/docs/Web/API/Location
818 [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
819 [Message Manager]: https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager
820 [TabSelect]: https://developer.mozilla.org/en-US/docs/Web/Events/TabSelect
821 [web console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console
822 [about:config]: http://kb.mozillazine.org/About:config
Imprint / Impressum