Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve child window reference after refresh

I have an HTML5 offline app (i.e. there's no server-side component/code).

It basically has two windows (parent and child). However, in some instances I need to programmatically refresh the parent window. When this happens, it loses its reference to the child, and the child's reference to window.opener is no longer valid. So my thinking was that I'd serialize the child window and store that in localStorage. Then when the parent refreshed it could pick up the window reference from localStorage and still interact with the child.

The problem is that this doesn't work (as per my previous question here Stringify DOMWindow object). I can't serialize a DOM window like any other object.

So how can I have my newly refreshed window pick up a reference to its predecessor's child?

Edit: Stressed the fact that it's an offline app. There's no server-side component.

I should also add that the reason I need to refresh the parent is to check for application updates (changes in the cache manifest). Since the parent is the first page in the application that loads, it basically manages the caching (in fact as an aside, in Safari if this window is closed during any of the caching process the entire browser crashes). So "parent" is essentially "first page that the user loads". This means that I can't have the "parent" in a frame, as the topmost window would then manage the caching, and require the refresh in order to look for updates. Actually, it appears that I can use the frame method, as refreshing any of the pages in the application will trigger the update check. Cumbersome though.

like image 845
ggutenberg Avatar asked Nov 02 '10 17:11

ggutenberg


People also ask

How do I stop refreshing parent page when child opens window?

Set a flag once child window is open and unset it once its closed. In ShowPopup use event. preventdefault() if child window is open!

How do I know if my child window is closed?

If you store a reference to the child window when you call window. open() , then you can poll using setInterval() to see whether the window is still open using the window.

How to return value from child window to parent window using window open in JavaScript?

From a child window or a small window once opened, we can transfer any user entered value to main or parent window by using JavaScript. You can see the demo of this here. Here the parent window is known as opener. So the value we enter in a child window we can pass to main by using opener.

How to pass value from child page to parent page using JavaScript?

Inside the SetName JavaScript function, the reference of the parent window txtName TextBox is obtained from window. opener instance using document. getElementById method of JavaScript. Finally, the DropDownList selected value is set into the TextBox value property.


2 Answers

I achieved this scenario using Window.postMessage, which enables cross-origin communication between Window objects. It supports: https://caniuse.com/#feat=mdn-api_window_postmessage

Basic working example for establishing communication between parent and child Window objects

In the parent app,

var childWindow = window.open(CHILD_URL);
setTimeout(() => { // postMessage on some browsers may need setTimout
  childWindow.postMessage( // STEP 1
     "INITIATE_CONNECTION", // message
     CHILD_URL // targetOrigin
  );
}, 500)

function receiveMessageFromChild(event) {
  if (event.origin === CHILD_URL) { // we should always check with the event.origin
    if (event.source) {
      if (event.data === "CONNECTION_SUCCESSFUL") {
        setTimeout(() => {
            event.source.postMessage( // STEP 3 and STEP 7
                "SEND_SOME_DATA_TO_CHILD",
                CHILD_URL);
        }, 500);
      }
      // other messages handling from child
    }
  }
}

if (window.addEventListener) {
  window.addEventListener("message", receiveMessageFromChild, false);
} else if (window.attachEvent) { // for IE
  window.attachEvent("onmessage", receiveMessageFromChild);
}

In the child app,

function receiveMessageFromParent(event) {
  if (event.origin === PARENT_URL) { // we should always check with the event.origin
    var parentWindow = window.opener || event.source;
    if (parentWindow) {
      if (event.data === "INITIATE_CONNECTION" || event.data === "RE_NITIATE_CONNECTION") { // "RE_NITIATE_CONNECTION" msg from parent when parent is refreshed
         setTimeout(() => {
            parentWindow.postMessage( // STEP 2
                "CONNECTION_SUCCESSFUL",
                PARENT_URL);
         }, 500);
      }
      // other messages handling from parent
    }
  }
}

if (window.addEventListener) {
  window.addEventListener("message", receiveMessageFromParent, false);
} else if (window.attachEvent) { // for IE
  window.attachEvent("onmessage", receiveMessageFromParent);
}

To handle parent window refresh and retrieve child window reference after the parent refresh make the following changes in the above codes,

In the parent app,

document.body.onunload = () => { // before refreshing parent, this function will be called
  if (childWindow) {
    setTimeout(() => {
      childWindow.postMessage( // STEP 4
        "PARENT_REFRESHING",
        CHILD_URL
      );
    }, 500);
  }
};

function receiveMessageFromChild(event) {
  // ... above mentioned code in the parent app for this function
  .
  .
  .
  // other messages handling from child
  if (event.data === "PARENT_REFRESHED") {
    setTimeout(() => {
      event.source.postMessage( // STEP 6 - this event.source is a child window reference
        "RE_NITIATE_CONNECTION",
        CHILD_URL
      );
    }, 500);
  }
}

In the child app,

function receiveMessageFromParent(event) {
  // ... above mentioned code in the child app for this function
  .
  .
  .
  // other messages handling from parent
  if (event.data === "PARENT_REFRESHING") {
    setTimeout(() => {
      event.source.postMessage( // STEP 5
        "PARENT_REFRESHED",
        CHILD_URL
      );
    }, 500);
  }
}

In the above example, please refer to the STEPs from 1 to 7. STEP 6 is the child window reference when the parent is refreshed.

like image 72
Aniruddha Shevle Avatar answered Sep 21 '22 15:09

Aniruddha Shevle


You can obtain the reference of child window simply by following trick.

newWin = window.open("", "child_window_name", "width=...");
if (newWin.location.href === "about:blank") {
    newWin = window.open("a.html", "child_window_name", "width=...");
} else {
    // We've already obtained the reference.
    // However, IE and FireFox won't put focus on an already opened window.
    // So we have to do that explicitly:
    newWin.focus();
}

Note you must have a fixed child window name to make this trick works.

Example URL: http://josephj.com/lab/2011/window-open-reconnect/demo.html

like image 42
josephj Avatar answered Sep 21 '22 15:09

josephj