Evita i blocchi popup del browser

Sto sviluppando un stream di autenticazione OAuth puramente in JavaScript e voglio mostrare all’utente la finestra “concedere l’accesso” in un popup, ma viene bloccato.

Come posso impedire che windows popup create da window.open o window.showModalDialog vengano bloccate dai blocchi popup dei diversi browser?

La regola generale è che i blocchi dei popup si window.open se window.open o simile è invocato da javascript che non è invocato dall’azione diretta dell’utente . Cioè, puoi chiamare window.open in risposta a un clic del pulsante senza essere colpito dal blocco popup, ma se inserisci lo stesso codice in un evento timer verrà bloccato. Anche la profondità della catena di chiamate è un fattore: alcuni browser meno recenti guardano solo il chiamante immediato, i browser più recenti possono tornare indietro un po ‘per vedere se il chiamante è un clic del mouse, ecc. Tenetelo il più basso ansible per evitare i blocchi dei popup.

Basato sul suggerimento molto utile di Jason Sebring , e sulle cose coperte qua e là , ho trovato una soluzione perfetta per il mio caso:

Pseudo codice con snippet di Javascript:

  1. crea immediatamente un popup vuoto sull’azione dell’utente

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

    Facoltativo: aggiungi un messaggio informativo “in attesa”. Esempi:

    a) Una pagina HTML esterna: sostituire la riga precedente con

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

    b) Testo: aggiungi la seguente riga sotto la precedente:

     importantStuff.document.write('Loading preview...'); 
  2. riempilo con il contenuto quando è pronto (ad esempio quando viene restituita la chiamata AJAX)

     importantStuff.location.href = 'http://shrib.com'; 

Arricchisci la chiamata a window.open con le opzioni aggiuntive di cui hai bisogno.

In realtà uso questa soluzione per un reindirizzamento mailto e funziona su tutti i miei browser (Windows 7, Android). Il bit _blank aiuta il reindirizzamento mailto a lavorare su mobile, btw.

La tua esperienza? Qualche modo per migliorare questo?

Inoltre, il signor Mister post, nel mio caso il window.open è stato lanciato all’interno di una promise, che ha triggersto il blocco popup, la mia soluzione era: in angular:

 $scope.gotClick = function(){ var myNewTab = browserService.openNewTab(); someService.getUrl().then( function(res){ browserService.updateLocation(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; } 

è così che puoi aprire una nuova scheda usando la risposta di promise e non invocando il blocco popup.

Come buona pratica penso che sia una buona idea verificare se un popup è stato bloccato e intervenire nel caso. Devi sapere che window.open ha un valore di ritorno, e quel valore può essere nullo se l’azione fallisce. Ad esempio, nel seguente codice:

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

se il popup è bloccato, window.open restituirà null. Quindi la funzione restituirà false.

Ad esempio, immagina di chiamare questa funzione direttamente da qualsiasi link con target="_blank" : se il popup viene aperto correttamente, restituendo false bloccherà l’azione di collegamento, altrimenti se il popup è bloccato, restituendo true verrà lasciato il comportamento predefinito (aperto nuova finestra _blank) e continua.

  

In questo modo avrai un popup se funziona, e una finestra _blank se no.

Se il popup non si apre, puoi:

  • apri una finestra vuota come nell’esempio e vai avanti
  • aprire un popup falso (un iframe all’interno della pagina)
  • informare l’utente (“si prega di consentire popup per questo sito”)
  • aprire una finestra vuota e informare l’utente ecc.

dall’API JavaScript oauth di Google:

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

Vedi l’area in cui si legge:

Impostazione dell’autenticazione

L’implementazione del client di OAuth 2.0 utilizza una finestra popup per richiedere all’utente di accedere e approvare l’applicazione. La prima chiamata a gapi.auth.authorize può triggersre i blocchi dei popup, in quanto apre la finestra popup in modo indiretto. Per impedire l’triggerszione del blocco popup durante le chiamate auth, chiamare gapi.auth.init (callback) quando viene caricato il client. Il callback fornito verrà eseguito quando la libreria è pronta per effettuare chiamate di authorization.

Direi che si tratta di una risposta reale di cui sopra nel modo in cui spiega se c’è una risposta immediata, non farà scattare l’allarme popup. Il “gapi.auth.init” sta facendo in modo che l’api avvenga immediatamente.

Applicazione pratica

Ho creato un microservizio di autenticazione open source utilizzando passaporto nodo su npm e i vari pacchetti passaporto per ciascun provider. Ho usato un approccio di reindirizzamento standard alla terza parte dandogli un URL di reindirizzamento per tornare a. Questo era programmatico, quindi potrei avere diversi posti da redirect a se login / registrazione e su pagine particolari.

github.com/sebringj/athu

passportjs.org

Non volevo creare la nuova pagina a meno che la richiamata non fosse stata restituita correttamente, quindi l’ho fatto per simulare il clic dell’utente:

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

Ho provato più soluzioni, ma la sua è l’unica che ha funzionato per me in tutti i browser

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

Il modo più semplice per sbarazzarsi di questo è, che ha funzionato molto bene per me –

  1. Non utilizzare document.open ().
  2. Invece usa this.document.location.href = location; dove location è l’url da caricare

Es:

  
Abc

Funziona molto bene Saluti