Every known way to get references to windows, in javascript

One of the biggest challenges in building zoid and post-robot was figuring out how to get a handle on different windows. A big part of both of these modules is post-messaging between windows and frames, and rendering to different windows.

To get all of that to work across each major browser, quite a few tricks were needed to get a handle on the right window. Getting the window object for the popup or frame you want to reference is the literally the only way you can hope to send a message to it, using the window.postMessage api.

For anyone who’s interested in building cross-window or cross-domain javascript, this reference should be helpful getting a reference to the window you want to message.

Window Group

  • Popup windows that were opened by my window, or a child of my window
  • Frames that were opened by my window, or a child of my window
  • Ancestors of my window

So if you’re in a window/tab opened by a user, and you want to get a reference to another window that the user opened (like say they opened another tab), you probably aren’t going to be able to get a handle on it.

That said, here are the windows you can get.

Current Window

New Popup Window

var newWin = window.open('https://www.google.com', 'windowName');

Existing Popup Window

var existingWin = window.open('', 'windowName');

This will even work if the popup window was opened from a different frame on the same domain.

In modern browsers, this will even work if the window was opened from a different frame on a different domain. But be warned — this can cause some strange behavior in IE.

Popup Windows as they open

var windows = [];var winOpen = window.open;window.open = function() {
var win = winOpen.apply(this, arguments);
windows.push(win);
return win;
};

Just bear in mind, if anyone opens a popup window before your code loads, you’re not going to catch it, after which the only recourse is to get the window by name.

Window Opener

This property is accessible cross domain, so even if you have a window reference for a window on a different domain, you can still access crossDomainWindow.opener

Frame Parent

This property is accessible cross domain, so even if you have a frame reference for a window on a different domain, you can still access crossDomainFrame.parent

Frame Top Window

All Frames in a window

for (var i = 0; i < window.frames.length; i++) {
console.log(window.frames[i]);
}

This property is accessible cross domain, so even if you have a popup or frame reference for a window on a different domain, you can still access crossDomainWindow.frames.

Fun fact: window.frames is actually just an alias for window, so window.frames === window, window.frames.length === window.length, and window.frames[0] === window[0].

Named frames in a window

<iframe name="myIframeName" src="https://www.google.com" />

You can access it by name by referencing window.frames['myIframeName'] or window.frames.myIframeName — or even just window.myIframeName.

These properties are accessible cross domain, so even if you have a popup or frame reference for a window on a different domain, you can still access crossDomainWindow.myIframeName.

Receive a postMessage

In the first window:

window.addEventListener('message', function(event) {
if (event.data === 'identify_me') {
console.log(event.source, 'is saying hello!');
}
});

In the second window:

firstWindow.postMessage('identify_me', '*');

This will work for popups and frames in most modern browsers. The exception to this rule is IE, which steadfastly prevents you from sending post-messages between a window and a popup window.

Iframe Element Window

<iframe id="myframe" src="https://www.google.com" />

You can get a handle on its window by using document.getElementById('myframe').contentWindow providing the frame has already been inserted into the DOM.

Obviously you can not do this cross-domain.

Same Domain Global

In the first window:

window.winRef = window.open('https://www.google.com', 'windowName');

And in the second window:

console.log(firstWindow.winRef);

Alternatively, a window could pass itself, or another window, to a global function in another window.

In the first window:

function identifyMe(win) {
console.log(win, 'said hello');
}

And in the second window:

window.opener.identifyMe(window);

This could be useful if the opener didn’t get a chance to get a handle on the window as it was being opened.

Chaining

Impossible Window References

  • I’m in IE
  • I render a cross-domain iframe
  • That iframe opens a popup window

There’s literally no way for me to get a handle on the popup window from the original parent window. Even if the window wants me to have a reference, it can’t send me a post-message, because of the IE restriction on post-messages between popups.

If you can think of a way to do this, please let me know!

One thing I’d really like is for there to be some browser api to get a reference to any window, from any other window, perhaps by name — like window.getWindowHandle(name). That would negate a lot of the above hacks.

Others?

works for PayPal, as a lead engineer in Checkout. Opinions expressed herein belong to him and not his employer. daniel@bluesuncorp.co.uk

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store