Avoid browser popup blockers

JavascriptPopupModal DialogPopup Blocker

Javascript Problem Overview


I'm developing an OAuth authentication flow purely in JavaScript and I want to show the user the "grant access" window in a popup, but it gets blocked.

How can I prevent pop up windows created by either window.open or window.showModalDialog from being blocked by the different browsers' pop-up blockers?

Javascript Solutions


Solution 1 - Javascript

The general rule is that popup blockers will engage if window.open or similar is invoked from javascript that is not invoked by direct user action. That is, you can call window.open in response to a button click without getting hit by the popup blocker, but if you put the same code in a timer event it will be blocked. Depth of call chain is also a factor - some older browsers only look at the immediate caller, newer browsers can backtrack a little to see if the caller's caller was a mouse click etc. Keep it as shallow as you can to avoid the popup blockers.

Solution 2 - Javascript

Based on Jason Sebring's very useful tip, and on the stuff covered here and there, I found a perfect solution for my case:

Pseudo code with Javascript snippets:

  1. immediately create a blank popup on user action

     var importantStuff = window.open('', '_blank');
    

    (Enrich the call to window.open with whatever additional options you need.)

    Optional: add some "waiting" info message. Examples:

    a) An external HTML page: replace the above line with

     var importantStuff = window.open('http://example.com/waiting.html', '_blank');
    

    b) Text: add the following line below the above one:

     importantStuff.document.write('Loading preview...');
    
  2. fill it with content when ready (when the AJAX call is returned, for instance)

     importantStuff.location.href = 'https://example.com/finally.html';
    

    Alternatively, you could close the window here if you don't need it after all (if ajax request fails, for example - thanks to @Goose for the comment):

     importantStuff.close();
    

I actually use this solution for a mailto redirection, and it works on all my browsers (windows 7, Android). The _blank bit helps for the mailto redirection to work on mobile, btw.

Solution 3 - Javascript

As a good practice I think it is a good idea to test if a popup was blocked and take action in case. You need to know that window.open has a return value, and that value may be null if the action failed. For example, in the following code:

function pop(url,w,h) {
	n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
	if(n==null) {
		return true;
	}
	return false;
}

if the popup is blocked, window.open will return null. So the function will return false.

> As an example, imagine calling this function directly from any link > with target="_blank": if the popup is successfully opened, returning > false will block the link action, else if the popup is blocked, > returning true will let the default behavior (open new _blank > window) and go on.

<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >

> This way you will have a popup if it works, and a _blank window if > not.

If the popup does not open, you can:

  • open a blank window like in the example and go on
  • open a fake popup (an iframe inside the page)
  • inform the user ("please allow popups for this site")
  • open a blank window and then inform the user etc..

Solution 4 - Javascript

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

$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.

Solution 5 - Javascript

from Google's oauth JavaScript API:

http://code.google.com/p/google-api-javascript-client/wiki/Authentication

See the area where it reads:

Setting up Authentication

The client's implementation of OAuth 2.0 uses a popup window to prompt the user to sign-in and approve the application. The first call to gapi.auth.authorize can trigger popup blockers, as it opens the popup window indirectly. To prevent the popup blocker from triggering on auth calls, call gapi.auth.init(callback) when the client loads. The supplied callback will be executed when the library is ready to make auth calls.

I would guess its relating to the real answer above in how it explains if there is an immediate response, it won't trip the popup alarm. The "gapi.auth.init" is making it so the api happens immediately.

Practical Application

I made an open source authentication microservice using node passport on npm and the various passport packages for each provider. I used a standard redirect approach to the 3rd party giving it a redirect URL to come back to. This was programmatic so I could have different places to redirect back to if login/signup and on particular pages.

github.com/sebringj/athu

passportjs.org

Solution 6 - Javascript

I tried multiple solutions, but his is the only one that actually worked for me in all the browsers

let newTab = window.open(); newTab.location.href = url;

Solution 7 - Javascript

My use case: In my react app, Upon user click there is an API call performed to the backend. Based on the response, new tab is opened with the api response added as params to the new tab URL (in same domain).

The only caveat in my use case is that it takes more for 1 second for the API response to be received. Hence pop-up blocker shows up (if it is active) when opening up URL in a new tab.

To circumvent the above described issue, here is the sample code,

var new_tab=window.open()
axios.get('http://backend-api').then(response=>{
    const url="http://someurl"+"?response"
    new_tab.location.href=url;
}).catch(error=>{
    //catch error
})

Summary: Create an empty tab (as above line 1) and when the API call is completed, you can fill up the tab with the url and skip the popup blocker.

Solution 8 - Javascript

@here I found it's work fine in all browsers

window.open(URL) || window.location.assign(URL)

Solution 9 - Javascript

Just use window.location.href = yourUrl or a url with target='_blank'

window.open() has too many issues, if it's more than one second from a user action a lot of browsers treat it as a popup and block it

Solution 10 - Javascript

I didn't want to make the new page unless the callback returned successfully, so I did this to simulate the user click:

function submitAndRedirect {
  apiCall.then(({ redirect }) => {
      const a = document.createElement('a');
      a.href = redirect;
      a.target = '_blank';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
  });
}

Solution 11 - Javascript

The easiest way to get rid of this is to:

  1. Dont use document.open().
  2. Instead use this.document.location.href = location; where location is the url to be loaded

Ex :

<script>
function loadUrl(location)
{
this.document.location.href = location;
}</script>

<div onclick="loadUrl('company_page.jsp')">Abc</div>

This worked very well for me. Cheers

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPablo FernandezView Question on Stackoverflow
Solution 1 - JavascriptdthorpeView Answer on Stackoverflow
Solution 2 - JavascriptSwiss MisterView Answer on Stackoverflow
Solution 3 - JavascriptFrancescoMMView Answer on Stackoverflow
Solution 4 - JavascriptDavidView Answer on Stackoverflow
Solution 5 - JavascriptKing FridayView Answer on Stackoverflow
Solution 6 - JavascriptpomobcView Answer on Stackoverflow
Solution 7 - JavascriptshyamView Answer on Stackoverflow
Solution 8 - JavascriptMzkZeeshanView Answer on Stackoverflow
Solution 9 - JavascriptDr. Freddy DimethyltryptamineView Answer on Stackoverflow
Solution 10 - Javascriptuser3479425View Answer on Stackoverflow
Solution 11 - Javascriptpramodshetty001View Answer on Stackoverflow