Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use getDocument in FocusZone and FocusTrapZone #10187

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "Use getDocument instead document in FocusZone and FocusTrapZone",
"packageName": "office-ui-fabric-react",
"email": "sohuts@microsoft.com",
"commit": "c4766bf28c3c6fe6021e2a0f277524bcc64064b4",
"date": "2019-08-19T15:03:13.879Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getFirstTabbable,
getLastTabbable,
getNextElement,
getDocument,
focusAsync,
initializeComponentRef,
on
Expand Down Expand Up @@ -67,7 +68,7 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
if (
!this.props.disabled ||
this.props.forceFocusInsideTrap ||
!elementContains(this._root.current, document.activeElement as HTMLElement)
!elementContains(this._root.current, this._getDocument().activeElement as HTMLElement)
) {
this._returnFocusToInitiator();
}
Expand Down Expand Up @@ -162,7 +163,7 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
// even when it's not. Using document.activeElement is another way
// for us to be able to get what the relatedTarget without relying
// on the event
relatedTarget = document.activeElement as Element;
relatedTarget = this._getDocument().activeElement as Element;
}

if (!elementContains(this._root.current, relatedTarget as HTMLElement)) {
Expand Down Expand Up @@ -213,7 +214,7 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl

this._previouslyFocusedElementOutsideTrapZone = elementToFocusOnDismiss
? elementToFocusOnDismiss
: (document.activeElement as HTMLElement);
: (this._getDocument().activeElement as HTMLElement);
if (!disableFirstFocus && !elementContains(this._root.current, this._previouslyFocusedElementOutsideTrapZone)) {
this.focus();
}
Expand All @@ -226,12 +227,13 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
return this !== value;
});

const activeElement = document.activeElement as HTMLElement;
const doc = this._getDocument();
const activeElement = doc.activeElement as HTMLElement;
if (
!ignoreExternalFocusing &&
this._previouslyFocusedElementOutsideTrapZone &&
typeof this._previouslyFocusedElementOutsideTrapZone.focus === 'function' &&
(elementContains(this._root.current, activeElement) || activeElement === document.body)
(elementContains(this._root.current, activeElement) || activeElement === doc.body)
) {
this._focusAsync(this._previouslyFocusedElementOutsideTrapZone);
}
Expand Down Expand Up @@ -277,7 +279,7 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
}

if (FocusTrapZone._focusStack.length && this === FocusTrapZone._focusStack[FocusTrapZone._focusStack.length - 1]) {
const focusedElement = document.activeElement as HTMLElement;
const focusedElement = this._getDocument().activeElement as HTMLElement;

if (!elementContains(this._root.current, focusedElement)) {
this.focus();
Expand All @@ -304,4 +306,8 @@ export class FocusTrapZone extends React.Component<IFocusTrapZoneProps, {}> impl
}
}
};

private _getDocument(): Document {
return getDocument(this._root.current)!;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu

let parentElement = getParent(root, ALLOW_VIRTUAL_ELEMENTS);

while (parentElement && parentElement !== document.body && parentElement.nodeType === 1) {
while (parentElement && parentElement !== this._getDocument().body && parentElement.nodeType === 1) {
if (isElementFocusZone(parentElement)) {
this._isInnerZone = true;
break;
Expand All @@ -160,15 +160,15 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
this._updateTabIndexes();

if (this.props.defaultActiveElement) {
this._activeElement = getDocument()!.querySelector(this.props.defaultActiveElement) as HTMLElement;
this._activeElement = this._getDocument().querySelector(this.props.defaultActiveElement) as HTMLElement;
this.focus();
}
}
}

public componentDidUpdate(): void {
const { current: root } = this._root;
const doc = getDocument(root);
const doc = this._getDocument();

if (doc && this._lastIndexPath && (doc.activeElement === doc.body || doc.activeElement === root)) {
// The element has been removed after the render, attempt to restore focus.
Expand Down Expand Up @@ -309,16 +309,15 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu

private _evaluateFocusBeforeRender(): void {
const { current: root } = this._root;
const doc = getDocument(root);

const doc = this._getDocument();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is important, otherwise, SSR tests will fail

if (doc) {
const focusedElement = doc.activeElement as HTMLElement;

// Only update the index path if we are not parked on the root.
if (focusedElement !== root) {
const shouldRestoreFocus = elementContains(root, focusedElement, false);

this._lastIndexPath = shouldRestoreFocus ? getElementIndexPath(root as HTMLElement, doc.activeElement as HTMLElement) : undefined;
this._lastIndexPath = shouldRestoreFocus ? getElementIndexPath(root as HTMLElement, focusedElement) : undefined;
}
}
}
Expand Down Expand Up @@ -500,7 +499,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
return;
}

if (document.activeElement === this._root.current && this._isInnerZone) {
if (this._getDocument().activeElement === this._root.current && this._isInnerZone) {
// If this element has focus, it is being controlled by a parent.
// Ignore the keystroke.
return;
Expand Down Expand Up @@ -948,7 +947,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
private _getOwnerZone(element?: HTMLElement): HTMLElement | null {
let parentElement = getParent(element as HTMLElement, ALLOW_VIRTUAL_ELEMENTS);

while (parentElement && parentElement !== this._root.current && parentElement !== document.body) {
while (parentElement && parentElement !== this._root.current && parentElement !== this._getDocument().body) {
if (isElementFocusZone(parentElement)) {
return parentElement;
}
Expand Down Expand Up @@ -1060,4 +1059,8 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
private _portalContainsElement(element: HTMLElement): boolean {
return element && !!this._root.current && portalContainsElement(element, this._root.current);
}

private _getDocument(): Document {
return getDocument(this._root.current)!;
}
}