How do I prevent Google Chrome from blocking my popup?
Asked Answered
S

7

47

On my website there is a button that just used to call a function that calls window.open, however, recently an adjustment was needed to do a server-side check before the popup was opened.

Ever since the code was added that does the AJAX call, browsers blocks the popup, that is opened in the success callback of the AJAX call. I read that browsers might block the popup if it's not called by a user click event, so I tried setting the AJAX request to async: false, which solved the problem in Firefox, but Google Chrome still keeps blocking my popup. Is there any way to get around this?

I could move the server-side check to the page that gets opened in the popup, but I'd like to do it before opening the popup, if possible.

Code:

<a id="attackButton" href="#">Attack Base!</a>

<script type="text/javascript">
$(function() {
    $('#attackButton').click(function() {
        $.ajax({
            url: baseurl + '/index.php?option=com_pbbgs&format=raw&getinfo=goingame',
            data: { 'gameid': 618 },
            dataType: 'text',
            async: false,
            type: 'POST',
            success: function(data) {
                eval(data);

                if (window.gameURL) {
                    goingameRaw();
                }
            }
        });

        return false;
    });
});

function goingameRaw()
{
    window.open(window.gameURL,'test','left=20,top=20,width=1024,height=640,toolbar=0,resizable=0,location=0');
}
</script>

Example response body:

window.gameURL="http://mydomain.com/index.php?option=com_pbbgs&format=raw&startgame=618&width=1024&height=640";checktutorial('js','attack');
Subdiaconate answered 5/1, 2011 at 10:21 Comment(1)
Possible duplicate of Avoid browser popup blockersInflux
C
52

Yes, popups should be a direct result of a user action. Doing them in ajax callback will not do the trick. Also, using async:false is bad - in FF it is known to block the whole browser. Think of some other way to do the check:

  • it could be the first thing you do in the popup
  • you can open the popup on click and manipulate it later when the callback fires
  • you can require the user to click again some button to trigger the popup (probably the worst solution)
  • you can do it on page load
Crabbe answered 5/1, 2011 at 10:28 Comment(6)
I suspected as much, thanks. I implemented your second suggestion.Subdiaconate
There is a good example here theandystratton.com/2012/…Wilhoit
@Emil Why is number 3 the worst? One click on a Javascript confirm when the UI is out of sync with the logged in state because the user has hit the back button or something? I'm going to try it.Metasomatism
Yeah I agree it sucks.Metasomatism
@Emil Ivanov. Second option worked for me.i.e opening window first then manipulate.thanks.Gesundheit
@Emi lvanov: in my case 1st page showing window.open null but in another page its showing window.open properly open .i am understand why its occur?Incondite
O
23

Following up on Emil's excellent answer, "you can open the popup on click and manipulate it later when the callback fires". I used this implementation.

$('#attackButton').click(function() {

New code here

    var win = window.open('');
    window.oldOpen = window.open;
    window.open = function(url) { // reassignment function
        win.location = url;
        window.open = oldOpen;
        win.focus();
    }

end new code

    $.ajax({
        url: baseurl + '/index.php',
        data: { 'gameid': 618 },
        type: 'POST',
        success: function(data) {
            window.open('some url'); // will call reassignment function above 
        }
    });

    return false;
});
Orbadiah answered 16/2, 2012 at 22:2 Comment(6)
There is no need to have add a global variable 'oldOpen' and overload the native global 'open'. This is all within the same closure, the scope chain is perfectly fine. Just create a local function "myWinGo" or whatever and use that.Leigh
That's a good point for this example. However, if the window.open call is in a library that you don't want to change or if you want to leave calls as window.open for readability, then overriding is a good choice.Orbadiah
Wow, genius little function! It even restores the window.open afterwards.Padrone
I get a blank new tab as soon as var win = window.open(''); is executed. Ideally, I want the new window to open only in the ajax success.Finfoot
@BenjaminCrouzier Unfortunately that sort of window popup disconnected from the user click seems to be what Chrome blocks.Orbadiah
@BenjaminCrouzier After calling win = window.open() you can call window.focus() and then, if the ajax fails, win.close(). That way, the user shouldn't be annoyed by the popup.Frigid
H
5

You can open a window that is not blocked just under the onclick event, if you open it on ajax call it is considered popup. However I used this method with success for some time to open a popup and not be blocked.

http://en.nisi.ro/blog/development/javascript/open-new-window-window-open-seen-chrome-popup/

Hhour answered 31/12, 2013 at 8:28 Comment(1)
Dead link! These kinds of answers are highly discouraged on SO, for this reason in particular.Amerind
A
3

Here is a vanilla JavaScript solution, I am using for one of my websites, to bypass the popup blocker in Chrome.

Let us say we have the following HTML button:

<button id="clickMe">Click Me!</button>

Now when the user clicks on the button, the first thing you should do is open an empty new window. After the Fetch request is finished, update the actual window URL. If the request fails, simply close the window:

const button = document.querySelector('#clickMe');

// add click event listener
button.addEventListener('click', () => {

    // open an empty window
    const tab = window.open('about:blank');

    // make an API call
    fetch('https://reqres.in/api/users')
        .then(res => res.json())
        .then(json => {

            // TODO: do something with JSON response

            // update the actual URL
            tab.location = 'https://attacomsian.com';
            tab.focus();
        })
        .catch(err => {
            // close the empty window
            tab.close();
        });
});

Alberto answered 24/2, 2020 at 20:45 Comment(0)
I
2

In my case the window.open was launched inside a promise in angular, which turned the popup blocker on, my solution was:

$scope.gotClick = function(){

  var myNewTab = browserService.openNewTab();
  someService.getUrl().then(
    function(res){
      browserService. updateTabLocation(res.url, myNewTab);
    }
  );
};

browserService:

this.openNewTab = function(){
  var newTabWindow = $window.open();
  return newTabWindow;
}

this.updateTabLocation = function(tabLocation, tab) {
  if(!tabLocation){
    tab.close();
  }
  tab.location.href = tabLocation;
}

this is how you can open a new tab using the promise response and not invoking the popup blocker.

Insurance answered 27/10, 2016 at 11:57 Comment(0)
S
1

The previous solution did not work for me, but I based on it and used named window.

internalCounter++;
var tabbedWin = window.open('','windowName_'+internalCounter);
$.ajax({
        url: url,
        async: false,
        indexValue:internalCounter,
        success: function(){
            var w= window.open(url, 'windowName_'+this.indexValue);                
            w.focus();
        }
})
Sucy answered 31/5, 2016 at 13:18 Comment(1)
referencing the solution from gabeSucy
P
0

I use this method:

  1. Redirect to the same page with download url added as parameter:
window.location.href = window.location.protocol + '//' +
                    window.location.host + window.location.pathname +
                    "?download=" + encodeURIComponent(urlToDownload)
  1. Detect this parameter on page initialization and redirect to download:
function param(name){
    var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if (!results) { return 0; }
    return results[1] || 0;
}

var downloadParam = param('download');
if (downloadParam) {
    window.location = decodeURIComponent(downloadParam);
}
Peper answered 9/7, 2017 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.