javascript - Undvik webbläsarens popup-blockerare


Jag utvecklar ett OAuth-autentiseringsflöde helt i JavaScript och jag vill visa användaren fönstret "ge åtkomst" i ett popup-fönster, men det blockeras.

Hur kan jag förhindra att popup-fönster skapade av antingen window.open eller window.showModalDialog blockeras av olika webbläsares popup-blockerare?

Svar #1

Den allmänna regeln är att popup-blockerare kommer att aktiveras om window.open eller liknande anropas från JavaScript som inte anropas av direkt användaråtgärd. Det vill säga, du kan anropa window.open som svar på ett knappklick utan att träffas av popup-blockeraren, men om du placerar samma kod i ett timer-händelse kommer den att blockeras. Djupet på anropskedjan är också en faktor - vissa äldre webbläsare tittar endast på den omedelbara anroparen, nyare webbläsare kan spåra lite bakåt för att se om anroparens anropare var ett musklick etc. Håll det så grunt som möjligt för att undvika popup-blockerare.

Svar #2

Baserat på Jason Sebrings mycket användbara tips, och på det som behandlats här och där, hittade jag en perfekt lösning för mitt fall:

Pseudokod med Javascript-exempel:

  1. skapa omedelbart ett tomt popupfönster vid användaråtgärd

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

    (Berika anropet till window.open med vilka ytterligare alternativ du behöver.)

    Valfritt: lägg till ett meddelande om "väntar". Exempel:

    a) En extern HTML-sida: ersätt raden ovan med

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

    b) Text: lägg till följande rad under den ovanstående:

     importantStuff.document.write('Loading preview...');
    
  2. fyll den med innehåll när den är klar (till exempel när AJAX-anropet har återvänt)

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

    Alternativt kan du stänga fönstret här om du ändå inte behöver det (om AJAX-förfrågan misslyckas, till exempel - tack till @Goose för kommentaren):

     importantStuff.close();
    

Jag använder faktiskt denna lösning för en mailto-omdirigering, och den fungerar på alla mina webbläsare (Windows 7, Android). _blank-delen hjälper förresten för att mailto-omdirigeringen ska fungera på mobiler.

Svar #3

Som en god praxis tycker jag att det är en bra idé att testa om en popup blockerades och vidta åtgärder i så fall. Du behöver veta att window.open har ett returvärde, och det värdet kan vara null om åtgärden misslyckades. Till exempel, i följande kod:

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;
}

om popup-fönstret blockeras kommer window.open att returnera null. Så funktionen kommer att returnera false.

Som ett exempel, föreställ dig att anropa denna funktion direkt från vilken länk som helst med target="_blank": om popup-fönstret öppnas framgångsrikt kommer returvärdet false att blockera länkens åtgärd, annars om popupen blockeras kommer returvärdet true att tillåta standardbeteendet (öppna ett nytt _blank-fönster) och fortsätta.

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

På så sätt kommer du att få ett popup-fönster om det fungerar, och ett _blank-fönster om det inte gör det.

Om popup-fönstret inte öppnas kan du:

  • öppna ett tomt fönster som i exemplet och fortsätt
  • öppna ett falskt popupfönster (en iframe inuti sidan)
  • informera användaren ("vänligen tillåt popup-fönster för denna webbplats")
  • öppna ett tomt fönster och sedan informera användaren etc..

Svar #4

Dessutom, Swiss Mister post, i mitt fall startades window.open inuti ett löfte, vilket aktiverade popup-blockeraren, min lösning var: i Angular:

$scope.gotClick = function(){

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

    }
  );
};

webbläsartjänst:

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

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

så här kan du öppna en ny flik med hjälp av promise-svaret utan att utlösa popup-blockeraren.

Relaterade artiklar