40

I have a page that enable user to perform image manipulation via HTML5 canvas, on the page, there's a facebook share button for sharing a generated image of the canvas on facebook.

When the link is clicked, an ajax request is sent to the server (ASP.NET MVC) to perform the image generation, save the image on the server, then generate a url(that links to the image) that is returned as the ajax response. The returned url is what I want to pass as the parameter for facebook to share. The issue is that popup blocker is blocking facebook share dialog when I call "window.open".

Is there any other way to open a new tab without popup blocker. I believe that since the user initiated the action, there should be a way for me to bypass popup blocker. Thanks.

Syma
  • 564
  • 1
  • 4
  • 11
  • Check the solutions given here http://stackoverflow.com/questions/4907843/open-url-in-new-tab-using-javascript – Pal Singh Sep 19 '13 at 03:47
  • 1
    None of the solution in the answers works for me. Still getting popup blocker. – Syma Sep 19 '13 at 04:05
  • This doesn't directly answer the question, but is a last-resort if you can't do it any other way: Instead of opening the URL in a new browser tab, you could create a link on the page for the user to click that opens the URL to a new tab. – John Gilmer Aug 27 '20 at 10:13

3 Answers3

59

Update Oct 2014:

It was noted correctly in the comments, that Firefox has deprecated the synchronous setting in June 2014, but it is still working in this browser.

Furthermore, Chrome received updates which will only allow this to work as wanted if the ajax call returns in less than a second. Which is rather hard to gurantee. I've created another question devoted to the Chrome timeout: Synchronous Ajax - does Chrome have a timeout on trusted events?

The linked post contains a JSFiddle demonstrating this concept and the problem.

Original Answer

Short answer: Make the ajax request synchronous.

Full answer: A browser will only open a tab/popup without the popup blocker warning, if the command to open the tab/popup comes from a trusted event. That means: The user has to actively click somewhere to open a popup.

In your case, the user performs a click so you have the trusted event. You do loose that trusted context however, by performing the Ajax request. Your success handler does not have that event any more. The only way to circumvent this is to perform a synchronous Ajax request which will block your browser while it runs, but will preserve the event context.

In jQuery this should do the trick:

$.ajax({
 url: 'http://yourserver/',
 data: 'your image',
 success: function(){window.open(someUrl);},
 async: false
});
Christopher Lörken
  • 2,582
  • 16
  • 17
  • 1
    @AnkitChauhan do you care to elaborate? It's still working in all browsers I know... – Christopher Lörken Apr 09 '14 at 13:57
  • Adding async:false makes chrome stop blocking about a third of the blockups for me. The rest still get blocked. All are blocked without async:false. This still helped for me though because I solved it in another way with this knowledge. I opened a blank window on the onclick-handler and also make an ajax-request(async or not doesn't really matter), which when finishes writes to the created window. – Clox Jun 25 '14 at 09:07
  • This works great and is simply genious to solve that big issue!! – anderswelt Aug 13 '14 at 15:05
  • 2
    On chrome it won't work for firefox async false is been deprecatred – Kunal Vashist Sep 09 '14 at 06:04
  • @kunal-vashist Thanks for the note, Mozilla indeed deprecated synchronous XHR requests with the release of Firefox 30 in June 2014 (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests). It does still work both in Firefox and in Chrome. There is one thing worth noting: Chrome seems to have a 1 second timeout in which the call needs to be finished. See this related entry: http://stackoverflow.com/questions/25446125/synchronous-ajax-does-chrome-have-a-timeout-on-trusted-events (I do not know since when) – Christopher Lörken Oct 07 '14 at 18:55
  • They key part here for me is that it is the 'trusted event' that avoids the pop-up blocker (at least in chrome). – Steven Anderson Aug 21 '15 at 04:35
  • 1
    Please move the update up and the older workaround to the bottom. – prasanthv Oct 18 '17 at 13:51
24

Here's how I got round the issue of my async ajax request losing the trusted context:

I opened the popup directly on the users click, directed the url to about:blank and got a handle on that window. You could probably direct the popup to a 'loading' url while your ajax request is made

var myWindow = window.open("about:blank",'name','height=500,width=550');

Then, when my request is successful, I open my callback url in the window

function showWindow(win, url) {
    win.open(url,'name','height=500,width=550');
}
vimalloc
  • 3,025
  • 3
  • 26
  • 37
wsgeorge
  • 1,718
  • 13
  • 20
7

The answer from wsgeorge is the one that got me on the right track. Here is a function that hopefully illustrates the technique more clearly.

function openNewAjaxTab(url) {
    var tabOpen = window.open("about:blank", 'newtab'),
        xhr = new XMLHttpRequest();

    xhr.open("GET", '/get_url?url=' + encodeURIComponent(url), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            tabOpen.location = xhr.responseText;
        }
    }
    xhr.send(null);
}
Community
  • 1
  • 1
Chris Broski
  • 2,122
  • 24
  • 21
  • When `window.open("about:blank", 'newtab')` works it opens a new tab. When `tabOpen.location = xhr.responseText;` works, it changes tabOpen objects location prop, however, a new windows url does not redirect to setted url on tabOpen. – efirat Jun 16 '17 at 07:23