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

Implement: Contextualmenu gets window from target element. #387

Merged
merged 2 commits into from
Oct 6, 2016
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
23 changes: 15 additions & 8 deletions src/components/Callout/CalloutContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class CalloutContent extends BaseComponent<ICalloutProps, ICalloutState>
private _didSetInitialFocus: boolean;
private _hostElement: HTMLDivElement;
private _calloutElement: HTMLDivElement;
private _targetWindow: Window;

constructor(props: ICalloutProps) {
super(props);
Expand All @@ -47,6 +48,12 @@ export class CalloutContent extends BaseComponent<ICalloutProps, ICalloutState>
slideDirectionalClassName: null,
calloutElementRect: null
};
// This is used to allow the Callout to appear on a window other than the one the javascript is running in.
if (props.targetElement && props.targetElement.ownerDocument && props.targetElement.ownerDocument.defaultView) {
this._targetWindow = props.targetElement.ownerDocument.defaultView;
} else {
this._targetWindow = window;
}
}

public componentDidUpdate() {
Expand Down Expand Up @@ -90,11 +97,11 @@ export class CalloutContent extends BaseComponent<ICalloutProps, ICalloutState>
}
}

private _dismissOnLostFocus(ev: Event) {
protected _dismissOnLostFocus(ev: Event) {
let { targetElement } = this.props;
let target = ev.target as HTMLElement;

if (ev.target !== window &&
if (ev.target !== this._targetWindow &&
this._hostElement &&
!elementContains(this._hostElement, target) &&
(!targetElement || !elementContains(targetElement, target))) {
Expand All @@ -103,21 +110,21 @@ export class CalloutContent extends BaseComponent<ICalloutProps, ICalloutState>
}

@autobind
private _setInitialFocus() {
protected _setInitialFocus() {
if (this.props.setInitialFocus && !this._didSetInitialFocus && this.state.positions) {
this._didSetInitialFocus = true;
focusFirstChild(this._calloutElement);
}
}

@autobind
private _onComponentDidMount() {
protected _onComponentDidMount() {
// This is added so the callout will dismiss when the window is scrolled
// but not when something inside the callout is scrolled.
this._events.on(window, 'scroll', this._dismissOnLostFocus, true);
this._events.on(window, 'resize', this.dismiss, true);
this._events.on(window, 'focus', this._dismissOnLostFocus, true);
this._events.on(window, 'click', this._dismissOnLostFocus, true);
this._events.on(this._targetWindow , 'scroll', this._dismissOnLostFocus, true);
this._events.on(this._targetWindow , 'resize', this.dismiss, true);
this._events.on(this._targetWindow , 'focus', this._dismissOnLostFocus, true);
this._events.on(this._targetWindow , 'click', this._dismissOnLostFocus, true);

if (this.props.onLayerMounted) {
this.props.onLayerMounted();
Expand Down
9 changes: 8 additions & 1 deletion src/components/ContextualMenu/ContextualMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export class ContextualMenu extends React.Component<IContextualMenuProps, IConte
private _events: EventGroup;
private _async: Async;
private _focusZone: FocusZone;
private _targetWindow: Window;

constructor(props: IContextualMenuProps) {
super(props);
Expand All @@ -100,6 +101,12 @@ export class ContextualMenu extends React.Component<IContextualMenuProps, IConte
this._enterTimerId = 0;
this._events = new EventGroup(this);
this._async = new Async(this);
// This is used to allow the ContextualMenu to appear on a window other than the one the javascript is running in.
if (props.targetElement && props.targetElement.ownerDocument && props.targetElement.ownerDocument.defaultView) {
this._targetWindow = props.targetElement.ownerDocument.defaultView;
} else {
this._targetWindow = window;
}

}

Expand All @@ -119,7 +126,7 @@ export class ContextualMenu extends React.Component<IContextualMenuProps, IConte

// Invoked once, only on the client (not on the server), immediately after the initial rendering occurs.
public componentDidMount() {
this._events.on(window, 'resize', this.dismiss);
this._events.on(this._targetWindow, 'resize', this.dismiss);
}

// Invoked when a component is receiving new props.
Expand Down