Skip to content

Commit

Permalink
Implement: Contextualmenu gets window from target element. (#387)
Browse files Browse the repository at this point in the history
* added in the ability for contextualmenu projection.

* fixed lint problems
  • Loading branch information
joschect authored and dzearing committed Oct 6, 2016
1 parent 3f73a1f commit 8dcf417
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
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

0 comments on commit 8dcf417

Please sign in to comment.