Thayne
Thayne

Reputation: 7042

Chrome window.open after ajax request acts like popup

I have a situation where, when a user pushes a button I perform an ajax request, and then use the result of the ajax request to generate a URL which I want to open in a new tab. However, in chrome when I call window.open in the success handler for the ajax request, it opens in a new window like a popup (and is blocked by popup-blockers). My guess is that since the the success code is asynchronous from the click handling code that chrome thinks it wasn't triggered by a click, even though it is causally related to a click. Is there any way to prevent this without making the ajax request synchronous?

EDIT Here is some minimal code that demonstrates this behaviour:

$('#myButton').click(function() {
    $.ajax({
        type: 'POST',
        url: '/echo/json/',
        data: {'json': JSON.stringify({
            url:'http://google.com'})},
        success: function(data) {
            window.open(data.url,'_blank');
        }
    });
});

http://jsfiddle.net/ESMUA/2/

One note of clarification: I am more conerned about it opening in a separate window rather than a tab, than I am about it being blocked by a popup blocker.

Upvotes: 18

Views: 47720

Answers (5)

Ilker Cat
Ilker Cat

Reputation: 1952

There is no reliable way. If your tab/window has been blocked by a pop-blocker in FF and IE6 SP2 then window.open will return the value null.

https://developer.mozilla.org/en-US/docs/Web/API/Window/open#FAQ

How can I tell when my window was blocked by a popup blocker? With the built-in popup blockers of Mozilla/Firefox and Internet Explorer 6 SP2, you have to check the return value of window.open(): it will be null if the window wasn't allowed to open. However, for most other popup blockers, there is no reliable way.

Upvotes: 1

Afzal Naushahi
Afzal Naushahi

Reputation: 175

The answer posted by @pstenstrm above (Edit 2) mostly works, but I added just one line to it to make the solution more elegant. The ajax call in my case was taking more than a second and the user facing a blank page posed a problem. The good thing is that there is a way to put HTML content in the new window that we've just created.

e.g:

$('#a').on('click', function(e){
    e.preventDefault();
    var wi = window.open('about:blank', '_blank');
    $(wi.document.body).html("<p>Please wait while you are being redirected...</p>");

    setTimeout(function(){ // async
        wi.location.href = 'http://google.com';
    }, 500);
});

This fills the new tab with the text "Please wait while you are being redirected..." which seems more elegant than the user looking at a blank page for a second. I wanted to post this as the comment but don't have enough reputation.

Upvotes: 9

bughunter1999
bughunter1999

Reputation: 202

What worked for me was:

var win = window.open('about:blank', '_blank');

myrepository.postmethod('myserviceurl', myArgs)
.then(function(result) {
    win.location.href = 'http://yourtargetlocation.com/dir/page';
});

You open the new window tab before the sync call while you're still in scope, grab the window handle, and then re-navigate once you receive the ajax results in the promise.

Upvotes: 12

rajesh
rajesh

Reputation: 382

Try adding async: false. It should be working

$('#myButton').click(function() {
$.ajax({
    type: 'POST',
    async: false,
    url: '/echo/json/',
    data: {'json': JSON.stringify({
        url:'http://google.com'})},
    success: function(data) {
        window.open(data.url,'_blank');
    }
});
});

Upvotes: 14

pstenstrm
pstenstrm

Reputation: 6489

Try to add

window.open(url,'_blank');

Edit

Well, I don't think you can get around popup-blockers when opening a page that's not the immediate result of a user action (i.e. not async).

You could try something like this though, it should look like a user action to a popup-blocker:

var $a = $('<a>', {
        href: url,
        target: '_blank' 
    });

$(document.body).append($a);
$a.click();

Edit 2

Looks like you're better of keeping things sync.

As long as the new window is "same origin" you have some power to manipulate it with JS.

$('#a').on('click', function(e){
    e.preventDefault();
    var wi = window.open('about:blank', '_blank');

    setTimeout(function(){ // async
        wi.location.href = 'http://google.com';
    }, 500);
});

Upvotes: 22

Related Questions