views:

679

answers:

2

Following code displays two buttons: AJAX popup and Direct popup. They are supposed to open the same page in a new window. Direct popup calls just window.open() in onclick event. AJAX popup does AJAX call and then in stateChanged() function calls window.open() just in the same way.

Both of them work in FF, but AJAX popup doesn't in IE, it displays annoying popup warning.

I actually think I understand what is going on. Popup blockers generally allow one popup per one click. In this case the relationship between click and popup gets lost because of AJAX call. But in my case the url to open is provided by server side component via AJAX response. So I can't just get rid of the AJAX call. I also can't force the users to use FF or to alter their popup blocker settings in IE.

Any ideas or workarounds are welcome.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
 <head>
  <title> popup test </title>
 <script type="text/javascript">
var xmlhttp;
function loadXMLDoc(url)
{
if (window.XMLHttpRequest)
  {
  // code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp = new XMLHttpRequest();
  }
else if (window.ActiveXObject)
  {
  // code for IE6, IE5
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
else
    {
  alert ("Your browser does not support XMLHTTP!");
  return;
  }
xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}

function stateChanged()
{
if (xmlhttp.readyState==4)
  {
  if (xmlhttp.status==200)
    {
     window.open('popup.html', '_blank');
    }
  else
    {
    alert("Problem retrieving XML data:" + xmlhttp.statusText);
    }
  }
}

</script>
 </head>

 <body>
  <button type="button" onclick="loadXMLDoc('popup.html')">AJAX popup</button>
  <button type="button" onclick="window.open('popup.html', '_blank');">Direct popup</button>
 </body>
</html>
A: 

The reason why is the new window is delayed from the initial click event. That delay causes the browser to not associate the click event with the new window and will block it. There is no way around it other than asking the user to mark your site as safe.

So your trick to see if the page is there before you open it will not work. You can try doing a synchronous request, but that is probably will cause worse issues than a blocked pop up window.

epascarello
+1  A: 

As you suggest, this is due to the second window.open not being in direct response to user activity.

One approach would be to open the window in the click handler, before starting the Ajax call, set to display a "Loading..." message. Then, when the URL is received from the Ajax call, point the popup to where it should be - assuming you do:

var popup;

function loadXMLDoc(url) {
    popup = window.open("loading.html");
    // and all the Ajaxy bits after that...
}

then all you need is

function stateChanged() {
    // the readystate stuff...
    var ultimateUrl = /* grab stuff from Ajax response */;
    popup.location.href = ultimateUrl;
}
NickFitz
As always, it is a bit more complicated. The server side component returns commands to the browser component and one of the commands might be "open url". But I don't know in advance, that the "open url" command will be returned. I could open the popup window just in case, but I'm not sure I can hide it from user if there is no "open url" command. In case you are wandering what kind of obscure application this is - it is Chiba XForms engine (http://chiba.sourceforge.net/).
Tambet