views:

4389

answers:

10

I am aware of javascript techniques to detect whether a popup is blocked in other browsers (as described in the answer to this question). Here's the basic test:

var newWin = window.open(url);

if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
    //POPUP BLOCKED
}

But this does not work in Chrome. The "POPUP BLOCKED" section is never reached when the popup is blocked.

Of course, the test is working to an extent since Chrome doesn't actually block the popup, but opens it in a tiny minimized window at the lower right corner which lists "blocked" popups.

What I would like to do is be able to tell if the popup was blocked by Chrome's popup blocker. I try to avoid browser sniffing in favor of feature detection. Is there a way to do this without browser sniffing?

Edit: I have now tried making use of newWin.outerHeight, newWin.left, and other similar properties to accomplish this. Google Chrome returns all position and height values as 0 when the popup is blocked.

Unfortunately, it also returns the same values even if the popup is actually opened for an unknown amount of time. After some magical period (a couple of seconds in my testing), the location and size information is returned as the correct values. In other words, I'm still no closer to figuring this out. Any help would be appreciated.

+2  A: 

Check the position of the window relative to the parent. Chrome makes the window appear almost off-screen.

Jason Cohen
I'll try that and let you know my results. Thanks.
Andrew
Google Chrome reports the left and top offsets as 0 when the popup is "blocked". I thought this was my golden ticket, but no. It reports the offsets as 0 immediately after actually opening as well. At some magical point in the future after opening, the top and left offsets are reported correctly.
Andrew
+3  A: 

Jason's answer is the only method I can think of too, but relying on position like that is a little bit dodgy!

These days, you don't really need to ask the question “was my unsolicited popup blocked?”, because the answer is invariably “yes” — all the major browsers have the popup blocker turned on by default. Best approach is only ever to window.open() in response to a direct click, which is almost always allowed.

bobince
I know best practices, etc. But I am in a situation where I need to accomplish this task. That's why I asked this question and not "should I?"
Andrew
+11  A: 

well the "magical time" you speak of is probably when the popup's DOM has been loaded. or else it might be when everything (images, outboard CSS, etc.) has been loaded. you could test this easily by adding a very large graphic to the popup. (clear your cache first!) if you were using a javascript framework like jquery (or something similar), you could use the ready() event (or something similar) to wait for the DOM to load before checking the window offset. the danger in this is that safari detection works in a conflicting way. the popup's DOM will never be ready() in safari because it'll give you a valid handle for the window you're trying to open -- whether it actually opens or not. (in fact, i believe your popup test code above won't work for safari.)

i think the best thing you can do is wrap your test in a setTimeout() and give the popup 3-5 seconds to complete loading before running the test. it's not perfect, but it should work at least 95% of the time.

here's the code i use for cross-browser detection, without the Chrome part.

function _hasPopupBlocker(poppedWindow) {
    var result = false;

    try {
        if (typeof poppedWindow == 'undefined') {
            // Safari with popup blocker... leaves the popup window handle undefined
            result = true;
        }
        else if (poppedWindow && poppedWindow.closed) {
            // This happens if the user opens and closes the client window...
            // Confusing because the handle is still available, but it's in a "closed" state.
            // We're not saying that the window is not being blocked, we're just saying
            // that the window has been closed before the test could be run.
            result = false;
        }
        else if (poppedWindow && poppedWindow.test) {
            // This is the actual test. The client window should be fine.
            result = false;
        }
        else {
            // Else we'll assume the window is not OK
            result = true;
        }

    } catch (err) {
        //if (console) {
        //    console.warn("Could not access popup window", err);
        //}
    }

    return result;
}

What I do is run this test from the parent and wrap it in a setTimeout(), giving the child window 3-5 seconds to load. In the child window, you need to add a test function:

function test() {}

The popup blocker detector tests to see whether the "test" function exists as a member of the child window.

Rich
Rich, you are a javascript popup guru. Thank you. That's exactly what I needed.
Andrew
Any updates on this? Doesn't seem to work anymore... Specifically in Chrome
Flash84x
A: 

window.open() in response to a direct link does not seem to work.

I tried it like this:

<a href="javascript:void(0)"
onclick="window.open('index.php?di=1','win','width=680,height=600,resizable,scrollbars=yes'
);">Link</a>

without success, also:

<a href="javascript:window.open('index.php?di=1','win','width=680,height=600,resizable,scrollbars=yes');" onclick="">Link</a>

results in no action in Google Chrome.

+1  A: 

HI

I modified the solutions described above slightly and think that it is working for Chrome at least. My solution is made to detect if popup is blocked when the main page is opened, not when popup is opened, but i am sure there are some people that can modify it.:-) The drawback here is that the popup-window is displayed for a couple of seconds (might be possible to shorten a bit) when there is no popup-blocker.

I put this in the section of my 'main' window

<script type="text/JavaScript" language="JavaScript">

 var mine = window.open('popuptest.htm','popuptest','width=1px,height=1px,left=0,top=0,scrollbars=no');
 if(!mine|| mine.closed || typeof mine.closed=='undefined')
  {
    popUpsBlocked = true       
    alert('Popup blocker detected ');
    if(mine)
      mine.close();
 }
 else
 {
    popUpsBlocked = false    
    var cookieCheckTimer = null;
    cookieCheckTimer =  setTimeout('testPopup();', 3500);
 }


function testPopup()
{
  if(mine)
  {
    if(mine.test())
    {
       popUpsBlocked = false;
    }
    else
    {
        alert('Popup blocker detected ');
         popUpsBlocked = true;
     }
    mine.close();
}

} 
</script>

The popuptest looks like this:

<!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" >
<head>
    <title>Popup test</title>
<script type="text/javascript" language="Javascript">
   function test() {if(window.innerHeight!=0){return true;} else return false;}
</script>
</head>

<body>
</body>
</html>

As i call the test-function on the popup-page after 3500 ms the innerheight has been set correctly by Chrome.

I use the variable popUpsBlocked to know if the popups are displayed or not in other javascripts. i.e

function ShowConfirmationMessage()
{
if(popUpsBlocked)
 { 
  alert('Popups are blocked, can not display confirmation popup. A mail will be sent with the confirmation.');
 } 
 else
 { 
  displayConfirmationPopup();
 }
 mailConfirmation();
}
Lars
+1  A: 

I had a similar problem with popups not opening in Chrome. I was frustrated because I wasn't trying to do something sneaky, like an onload popup, just opening a window when the user clicked. I was DOUBLY frustrated because running my function which included the window.open() from the firebug command line worked, while actually clicking on my link didn't! Here was my solution:

Wrong way: running window.open() from an event listener (in my case, dojo.connect to the onclick event method of a DOM node).

dojo.connect(myNode, "onclick", function() {
    window.open();
}

Right way: assigning a function to the onclick property of the node that called window.open().

myNode.onclick = function() {
    window.open();
}

And, of course, I can still do event listeners for that same onclick event if I need to. With this change, I could open my windows even though Chrome was set to "Do not allow any site to show pop-ups". Joy.

If anyone wise in the ways of Chrome can tell the rest of us why it makes a difference, I'd love to hear it, although I suspect it's just an attempt to shut the door on malicious programmatic popups.

Chris
A: 

As far as I can tell (from what I've tested) Chrome returns a window object with location of 'about:blank'. So, the following should work for all browsers:

var newWin = window.open(url);
if(!newWin || newWin.closed || typeof newWin.closed=='undefined' || newWin.location=='about:blank')
{
    //POPUP BLOCKED
}
Yoav Aharoni
A: 

Yoav, the location shows the same regardless of whether the pop up is blocked or not.

Anyone else have an answer that doesn't involve making the user wait 3.5 seconds?

Mark
A: 

Here's a version that is currently working in Chrome. Just a small alteration away from Rich's solution, though I added in a wrapper that handles the timing too.

function checkPopupBlocked(poppedWindow) {
 setTimeout(function(){doCheckPopupBlocked(poppedWindow);}, 5000);
}

function doCheckPopupBlocked(poppedWindow) {

    var result = false;

    try {
        if (typeof poppedWindow == 'undefined') {
            // Safari with popup blocker... leaves the popup window handle undefined
            result = true;
        }
        else if (poppedWindow && poppedWindow.closed) {
            // This happens if the user opens and closes the client window...
            // Confusing because the handle is still available, but it's in a "closed" state.
            // We're not saying that the window is not being blocked, we're just saying
            // that the window has been closed before the test could be run.
            result = false;
        }
        else if (poppedWindow && poppedWindow.outerWidth == 0) {
            // This is usually Chrome's doing. The outerWidth (and most other size/location info)
         // will be left at 0, EVEN THOUGH the contents of the popup will exist (including the
         // test function we check for next). The outerWidth starts as 0, so a sufficient delay
         // after attempting to pop is needed.
            result = true;
        }
        else if (poppedWindow && poppedWindow.test) {
            // This is the actual test. The client window should be fine.
            result = false;
        }
        else {
            // Else we'll assume the window is not OK
            result = true;
        }

    } catch (err) {
        //if (console) {
        //    console.warn("Could not access popup window", err);
        //}
    }

    if(result)
     alert("The popup was blocked. You must allow popups to use this site.");
}

To use it just do this:

var popup=window.open('location',etc...);
checkPopupBlocked(popup);

If the popup get's blocked, the alert message will display after the 5 second grace period (you can adjust that, but 5 seconds should be quite safe).

Kandelon