-
-
Notifications
You must be signed in to change notification settings - Fork 260
/
Copy pathfocus.js
67 lines (53 loc) · 1.85 KB
/
focus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import isFocusable from './-is-focusable';
import { nextTickPromise } from '../-utils';
/**
@private
@param {Element} element the element to trigger events on
*/
export function __focus__(element) {
let browserIsNotFocused = document.hasFocus && !document.hasFocus();
// makes `document.activeElement` be `element`. If the browser is focused, it also fires a focus event
element.focus();
// Firefox does not trigger the `focusin` event if the window
// does not have focus. If the document does not have focus then
// fire `focusin` event as well.
if (browserIsNotFocused) {
// if the browser is not focused the previous `el.focus()` didn't fire an event, so we simulate it
fireEvent(element, 'focus', {
bubbles: false,
});
fireEvent(element, 'focusin');
}
}
/**
Focus the specified target.
Sends a number of events intending to simulate a "real" user focusing an
element.
The following events are triggered (in order):
- `focus`
- `focusin`
The exact listing of events that are triggered may change over time as needed
to continue to emulate how actual browsers handle focusing a given element.
@public
@param {string|Element} target the element or selector to focus
@return {Promise<void>} resolves when the application is settled
*/
export default function focus(target) {
return nextTickPromise().then(() => {
if (!target) {
throw new Error('Must pass an element or selector to `focus`.');
}
let element = getElement(target);
if (!element) {
throw new Error(`Element not found when calling \`focus('${target}')\`.`);
}
if (!isFocusable(element)) {
throw new Error(`${target} is not focusable`);
}
__focus__(element);
return settled();
});
}