Search code examples
javascriptwindow.openpostmessagewindow.opener

How to communicate with popup after reload


My page opens a popup and communicates with it using window.postMessage. To know when it is ready, one of the first things in the popup-script is:

window.opener.postMessage("initialize")

and then I reply and give the data and so on. However if I have two instances of the same page open I'm running into a few problems. In Chrome and Firefox it actually opens individual popups even when the windowName is set. Setting focus using myPopup.focus() doesn't even seem to bring them up to the top. In IE however it reuses the same window, which I initially thought was a great improvement.

As stated in the spec, the window.opener reference is however never updated, even when another parent reopened it. Meaning the initial code will communicate with my first instance. I've tried in various ways to change the behavior, but I can't seem to communicate between these in any way.

Then I found a clever way of detecting this, storing the dimensions and position, then closing and reopening it. It looks like this:

const createPopup = (dimensions) => {
  let features = "menubar=0,toolbar=0,status=0,personalbar=0,location=0,resizable=1,scrollbars=1";
  const myPopup = window.open("/imageViewer.html", "ImageViewer", features);
  if (myPopup.opener !== window) {
    dimensions = { height: myPopup.outerHeight, width: myPopup.outerWidth, X: myPopup.screenX, Y: myPopup.screenY };
    myPopup.close();
    return createPopup(dimensions);
  }
  if (dimensions) {
    myPopup.moveTo(dimensions.X, dimensions.Y);
    myPopup.resizeTo(dimensions.width, dimensions.height);
  } else {
    myPopup.focus();
  }

  return myPopup;
};

The problem is that the main use I have for this is when the popup is located on a secondary monitor, and it doesn't seem to be allowed to neither move the popup outside the dimensions of the primary screen.

Is there anyway to solve this problem with using postMessage? My only other alternative which comes to mind is using localstorage to put information and look this up on intervals, but I'm not very happy with such a solution.

So to sum up I need to have a function (createPopup) which will create or bring a secondary window/popup to the front. The main window needs to be able to communicate with it, and it must work when using different instances of the same main page. (but running the function again when switching instances is OK.)


Solution

  • While setting in JavaScript failed, it works when setting directly when opening the window in the features-parameter:

    export const createPopup = (dim) => {
      let features = "menubar=0,toolbar=0,status=0,personalbar=0,location=0,resizable=1,scrollbars=1";
      if (dim) {
        features += ",left=" + dim.X + ",top=" + dim.Y + ",width=" + dim.width + ",height=" + dim.height;
      }
      const myPopup = window.open("/imageViewer.html", "ImageViewer", features);
      try {
        if (myPopup.opener !== window) {
          throw Error("just trying to read opener will throw exception in IE if the opening window has been closed");
        }
      } catch {
        dim = { height: myPopup.outerHeight, width: myPopup.outerWidth, X: myPopup.screenX, Y: myPopup.screenY };
        myPopup.close();
        return createPopup(dim);
      }
      myPopup.focus();
    
      return myPopup;
    };
    

    Focus still doesn't seem to work in chrome-based browsers, but that is a very different bug indeed.