Reputation: 1686
Due to how some of our pages work, JS can get injected into the page at any point and sometimes this JS closes the current window. The problem is that I need to attach an event listener to the onunload
of the window so that a value may be returned from the window to the parent page. But because the window close script may be injected at any point, I can't bind this event to the onload
due to how it works so I was hoping to use DOMContentLoaded
since that event will trigger before the injected script does.
However in my tests, I cannot get anything to bind to DOMContentLoaded
on the parent page where the new window is being created.
Here is an what I am currently working with: Plunker
We only need this to work in Chrome at the moment.
Our current method of doing this works like this (pseudocode):
onButtonClick = function(){
win = window.open(...);
win.onload = function(){
win.onunload = function(){
//Bind some function that will get the window's "return value" and pass it to the parent page
//This will never happen if the window closes itself before the page is done loading
};
};
};
Can I use DOMContentLoaded
to accomplish what I want? If so, how do I properly attach it to the window?
Note: I cannot bind the onunload
event directly to the window once it is created. It seems to fire the onunload
event twice (once when the window opens and once when it closes). You can see this happening if you use the bindOnCreate
function in my example.
Upvotes: 10
Views: 4601
Reputation: 13848
Alternatively, you can send a message from the child window to its opener, rather than let opener to handle child window's unload event. This will be much easier and you don't need to worry about the injection point. Also you can get rid of twice unload event, as Andrew Dunai has already given the reason for this issue.
Here I give a very simple demo, only shows the skeleton of my messaging solution:
parent.html
<button id="open">Open Window</button>
<button id="close">Close Window</button>
<div></div>
<script>
var child;
document.querySelector('#open').addEventListener('click', function() {
document.querySelector('div').innerHTML = '';
child = window.open('child.html', 'child', 'width=600,height=600');
}, false);
document.querySelector('#close').addEventListener('click', function() {
child.close();
}, false);
window.addEventListener('message', function(e) {
document.querySelector('div').innerHTML = e.data;
}, false);
</script>
child.html
<input type="text" value="" placeholder="input something">
<script>
window.addEventListener('beforeunload', function() {
var msg = document.querySelector('input').value;
window.opener.postMessage(msg, '*');
}, false);
</script>
Either you close child window by click its own window's close button, or the button in parent window, the value in child's input will always send to parent and presented.
This is the key approach for one of my side project, and works very well.
Upvotes: 1
Reputation: 3129
If you change line 58 from
w.document.addEventListener('DOMContentLoaded', ...)
to
w.addEventListener('DOMContentLoaded', ...)
it works. I'll try to explain what's actually going on under the hood:
about:blank
. You can check this by logging w.location.toString()
in onunload
event handler (see next step).window.open
, thus triggering onunload
for about:blank
(first time).about:blank
page because you added events to window.document
, not window
; and right now as we have another URL loaded, window.document
is completely different object than one step before.onunload
is triggered again (second time) because your onunload
event was connected to window.If you addEventListener
for pop-up's window
, it receives events from all window.document
-s that will be loaded inside that window because of JS event bubbling mechanism.
I hope this answers your questions.
Upvotes: 10