2

I haven't quite been able to pin this one down, as others are reporting success in Chrome, but I have reproduced the problem in Chrome 44 and not in Firefox 33.1. Turning on Incognito Mode (i.e. no extensions), and making an exemption in the Popup Blocker settings had no effect.

I have a popup window with a form, and the target of the form is _blank. The intention is that the form submission will go to a new tab in the parent window. The popup then closes itself.

However, the new tab is not opening unless I remove the code to make the popup close itself.

I imagine I'm triggering popup prevention somewhere (particularly because I can't reproduce via a local file:/// URL; only with remote content), but I haven't been able to work out why closing the popup window after submission would ruin the submission itself. I can't see anything relevant in the developer console.

I also tried, instead of the onsubmit, adding to the submit button onclick="setTimeout('window.close()',1);return true;", with the same effect; in fact, this is the terrible code actually found in the application I'm trying to debug.

What's going on?

Here's a terrible self-contained testcase that reproduces the problem.

var trigger = null;
var popup   = null;

window.onload = function() {
  trigger = document.getElementById('trigger');
  trigger.onclick = function() {
    popup = window.open('', 'thePopup', 'width=450,height=450');
    if (popup == null) {
      console.error("Failed to open popup window :(");
    }
    else {
      populatePopup();
    }
  };
};

function populatePopup() {
  popup.document.write('<html><body>');
  popup.document.write('<form method="GET" action="http://google.com/?q=test" target="_blank" onsubmit="window.close()">');
  popup.document.write('<input type="submit" value="Click here now" />');
  popup.document.write('</form>');
  popup.document.write('</body></html>');
}
<a href="#" id="trigger">Click here</a>

(Sadly, due to the popup factor, this snippet won't run at all, at least not in my browser. However, the frame content may be copy/pasted verbatim into a file to be tested.)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Javascript event handlers are executed before the standard event behavior. So any code attached to a javascript onsubmit handler, will run before the form is submitted. Hence the use of the timeout. Find a better event to close the popup on (like the server answer after the submit) or do the form post yourself, or just keep using a timeout onsubmit, instead of onclick. – Shilly Aug 26 '15 at 11:36
  • @Shilly: Hum.. putting the timeout back but making it longer (1s) does work. Seems really hacky to guess at a good timeout though :( – Lightness Races in Orbit Aug 26 '15 at 11:40
  • The duration of the timeout doesn't really matter. Even with a 0 second timeout, the function the timeout runs, will be sheduled behind all the other things the browser does. (reflow content, run other script code, etc) The problem with the original timeout, was that it triggered onclick, not onsubmit. – Shilly Aug 26 '15 at 11:45
  • @Shilly: Sadly, apparently not. I understand that it should queue the event handler regardless of the actual duration requested but, for whatever reason, with a 1ms timeout that's simply not working for me. :( Hence my surprise, confusion and question. – Lightness Races in Orbit Aug 26 '15 at 11:49
  • Alrighty then.I don't know exactly how the timings for the form submit will work, so if you need a longer timeout... I'm a bit afraid alas, that it won't be consistent, so do test enough. I don't really get the point sadly. I'm assuming you're posting data to some server and don't care about the server response? Else you'd just close the popup when the response arrives. – Shilly Aug 26 '15 at 11:57
  • @Shilly: The popup cannot be closed from a new tab/page context. (Can it?) That would be perfect otherwise. – Lightness Races in Orbit Aug 26 '15 at 12:06
  • `popup = window.open('', 'thePopup', 'width=450,height=450');` is in your code, so you can just go `popup.close()` from the main page that opened the popup. – Shilly Aug 26 '15 at 12:10
  • @Shilly: The main page that opened the popup has no knowledge of when the form was submitted. I could put an event handler on the form from the main page that opened the popup, but that's equivalent to doing so in the popup itself, which isn't working. – Lightness Races in Orbit Aug 26 '15 at 12:14
  • The best solution would obv be to just submit the form yourself using an ajax call, so that you can have a callback to close the popup. If that's not possible for some reason, you could try some things with the form target, since that will capture the result of the form submission. I've never tried form target kludges myself though, so results may vary. – Shilly Aug 26 '15 at 12:40
  • @Shilly: Can't use AJAX. If I used AJAX to submit the form, the only way I'd be able to load the on-submit page in its new tab would be via JavaScript, but browers won't allow AJAX handlers to open new windows because of popup prevention. – Lightness Races in Orbit Aug 26 '15 at 13:37
  • I'm not convinced ajax handlers can't open pages, but that's besides the point. Anyway, since you do have a an onsubmit page showing the result, you can just pass the reference to the popup window from the main window to the results page by using `window.postMessage` and an appropriate handler on the results page. Then you can close the popup from the results page. edit: Thinking of it, wont `window.opener.close()` work on the results page? – Shilly Aug 26 '15 at 13:41
  • @Shilly: FWIW, http://stackoverflow.com/a/20235765/560648. re. `window.postMessage` oooh... re. `window.opener.close()` OOOOH! yesssss it will :D – Lightness Races in Orbit Aug 26 '15 at 13:54
  • Thanks for the link, didn't know that yet. Offtopic: Easy to work around though by having the callback call a function on the main page that will open the new window instead of writing that code directly into the ajax callback. Anyways, stuff like this is why I switched to single page apps. :) – Shilly Aug 26 '15 at 14:01
  • @Shilly: No again that won't work. The point is that popups are allowed only when a direct result of a user action. Putting popup opening code in an AJAX handler separates that code from the user action, and calling a further function doesn't change that :) – Lightness Races in Orbit Aug 26 '15 at 14:03

1 Answers1

2

You can try this form target kludge if you can't use ajax calls: Basically, you set the target of the form to an iframe you include in the popup. This will make the result of your form submit, namely the google page you're grabbing, to be shown in the iframe. You can then add an event listener to the load event of this iframe on the onsubmit event of the form.

<form method="GET" action="http://google.com/?q=test" target="after" onsubmit="close()">
<input type="submit" value="Click here now" />
</form>
<iframe id="after" name="after"></iframe>
<script>
function close() {
    document.querySelector('#after').addEventListener('load', function() {
        window.close();
    });
}
</script>
Shilly
  • 8,511
  • 1
  • 18
  • 24