@spectra/window-day-care
Version:
A library to help you create popup windows and iframes. It makes communication between parent and child window a breeze.
111 lines (94 loc) • 3.5 kB
text/typescript
import 'rxjs/add/operator/filter';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
/** Represents an instance of child window like an iframe or a pop-up */
export abstract class ChildWindow {
private _message$ = new Subject<any>();
public get message$(): Observable<any> { return this._message$.filter(x => !x.childWindowMessageType); }
private _messageListener = (e: any): void => this._message$.next(e.data);
protected constructor(protected _window: Window) {
window.addEventListener('message', this._messageListener);
}
/**
* Sends a message to the parent window
* @param message A simple JSON-object
*/
public sendMessage(message: any): void {
this._window.postMessage(message, window.location.origin);
}
/** Closes the window */
public close(): void {
this._message$.complete();
this._window.removeEventListener('message', this._messageListener);
this._cleanUp();
}
/**
* Sets the new location of the child window. Returns a promise that is resolved when the page is loaded.
* @param uri the location the child window will go to
*/
public setLocation(uri: string): Promise<void> {
return new Promise(resolve => {
const subscription = this._message$.subscribe(x => {
if (x.childWindowMessageType === ChildWindowMessageType.Loaded) {
subscription.unsubscribe();
resolve();
}
});
this._window.location.href = uri;
});
}
protected abstract _cleanUp(): void;
}
/** Checks whether we're in an iframe at the moment. */
export function isIframe(): boolean {
return window.parent !== window;
}
/** Checks whether we're in a pop up at the moment. */
export function isPopUp(): boolean {
return !!window.opener;
}
/** Checks whether we're in a child window at the moment. */
export function isChildWindow(): boolean {
return isIframe() || isPopUp();
}
/** Helps you communicating from inside a child window */
export class ChildWindowHost {
private get _parent(): Window {
console.log(window.parent);
console.log(window.opener);
console.log(isIframe());
if (isIframe()) {
return window.parent;
} else if (isPopUp) {
return window.opener;
}
}
/** Sends a message to this child window */
public sendMessage(message: any, targetOrigin: string = '*') {
this._parent.postMessage(message, targetOrigin);
}
}
/**
* Returns the current child window host. This method should only be called when you are in a child window.
* Use the {@link isChildWindow}-method to check whether this is the case.
*/
export function getChildWindowHost(): ChildWindowHost {
if (!isIframe() && !isPopUp()) {
throw new Error('Can\'t create iframe-host in a window without parent');
}
return new ChildWindowHost();
}
export enum ChildWindowMessageType {
None = 0,
Loaded
}
if (isChildWindow()) {
const domContentLoadedHandler = (e: Event) => {
const message = {
childWindowMessageType: ChildWindowMessageType.Loaded
};
window.parent.postMessage(message, '*');
window.document.removeEventListener('DOMContentLoaded', domContentLoadedHandler);
};
window.document.addEventListener('DOMContentLoaded', domContentLoadedHandler);
}