Skip to content

Commit

Permalink
Refactor focus to be always async.
Browse files Browse the repository at this point in the history
  • Loading branch information
rwjblue committed Dec 6, 2017
1 parent b995867 commit a587f73
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 24 deletions.
4 changes: 3 additions & 1 deletion addon-test-support/@ember/test-helpers/dom/click.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export default function click(selector) {

nextTick(() => {
fireEvent(element, 'mousedown');
_focus(element);
if (isFocusable(element)) {
_focus(element);
}
fireEvent(element, 'mouseup');
fireEvent(element, 'click');
});
Expand Down
42 changes: 19 additions & 23 deletions addon-test-support/@ember/test-helpers/dom/focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,25 @@ import fireEvent from './fire-event';
import settled from '../settled';
import isFocusable from './-is-focusable';

// Use Symbol here #someday...
const FOCUS_SUCCESSFUL = Object.freeze({});
const FOCUS_UNSUCCESSFUL = Object.freeze({});
const nextTick = setTimeout;

export function _focus(element) {
if (isFocusable(element)) {
let browserIsNotFocused = document.hasFocus && !document.hasFocus();
let browserIsNotFocused = document.hasFocus && !document.hasFocus();

// makes `document.activeElement` be `element`. If the browser is focused, it also fires a focus event
element.focus();
// 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,
});
// 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');
}

return FOCUS_SUCCESSFUL;
fireEvent(element, 'focusin');
}

return FOCUS_UNSUCCESSFUL;
}

/**
Expand All @@ -44,11 +36,15 @@ export default function focus(selectorOrElement) {
}

let element = getElement(selectorOrElement);
let focusResult = _focus(element);
if (!element) {
throw new Error(`Element not found when calling \`focus('${selectorOrElement}')\`.`);
}

if (focusResult !== FOCUS_SUCCESSFUL) {
if (!isFocusable(element)) {
throw new Error(`${selectorOrElement} is not focusable`);
}

nextTick(() => _focus(element));

return settled();
}

0 comments on commit a587f73

Please sign in to comment.