¿Cómo puedo detectar si un navegador está bloqueando una ventana emergente?

130

Ocasionalmente, me encuentro con una página web que intenta abrir una nueva ventana (para la entrada del usuario, o algo importante), pero el bloqueador de ventanas emergentes evita que esto suceda.

¿Qué métodos puede usar la ventana de llamada para asegurarse de que la nueva ventana se inicie correctamente?

Nathan Bedford
fuente

Respuestas:

160

Si usa JavaScript para abrir la ventana emergente, puede usar algo como esto:

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}
omar
fuente
Aquí hay una respuesta para Chrome: detect-blocked-popup-in-Chrome
ajwaka
@ajwaka, ¿podría aclarar si esta respuesta falla para Chrome o hay alguna razón por la que la otra respuesta es mejor para Chrome? ¡Gracias!
Crashalot
@ajwaka, al menos hoy, este código parece funcionar en Chrome, de ahí la pregunta.
Crashalot
@Crashalot: me preguntas sobre algo que respondí hace 6 años: lamentablemente ya no recuerdo la situación y los navegadores han recorrido un largo camino en 6 años.
ajwaka
40

Intenté varios de los ejemplos anteriores, pero no pude hacer que funcionaran con Chrome. Este enfoque simple parece funcionar con Chrome 39, Firefox 34, Safari 5.1.7 e IE 11. Aquí está el fragmento de código de nuestra biblioteca JS.

openPopUp: function(urlToOpen) {
    var popup_window=window.open(urlToOpen,"myWindow","toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=400, height=400");            
    try {
        popup_window.focus();   
    } catch (e) {
        alert("Pop-up Blocker is enabled! Please add this site to your exception list.");
    }
}
DanielB
fuente
1
@Surendra por favor, ¿puede especificar lo que quiere decir con "no funciona"? ¿Un error en el tiempo de análisis? ¿Un error en tiempo de ejecución? ¿Se abre la ventana emergente pero está marcada como bloqueada? ¿La ventana emergente está bloqueada pero está marcada como abierta? No veo ninguna razón por la que el explorador falle esto, a menos que se permita llamar a focus () en NULL, en cuyo caso, una prueba de NULL antes del intento simplemente funcionaría.
FrancescoMM
IE siempre devuelve nulo, incluso si la ventana emergente fue exitosa.
Devin Garner
34

Actualización: las ventanas emergentes existen desde tiempos muy antiguos. La idea inicial era mostrar otro contenido sin cerrar la ventana principal. A partir de ahora, hay otras formas de hacerlo: JavaScript puede enviar solicitudes de servidor, por lo que rara vez se utilizan ventanas emergentes. Pero a veces todavía son útiles.

En el pasado, los sitios malvados abusaron mucho de las ventanas emergentes. Una página incorrecta podría abrir toneladas de ventanas emergentes con anuncios. Entonces, la mayoría de los navegadores intentan bloquear las ventanas emergentes y proteger al usuario.

La mayoría de los navegadores bloquean las ventanas emergentes si se llaman fuera de los controladores de eventos activados por el usuario, como onclick.

Si lo piensas, es un poco complicado. Si el código está directamente en un controlador onclick, entonces eso es fácil. Pero, ¿cuál es la ventana emergente que se abre en setTimeout?

Prueba este código:

 // open after 3 seconds
setTimeout(() => window.open('http://google.com'), 3000);

La ventana emergente se abre en Chrome, pero se bloquea en Firefox.

... Y esto también funciona en Firefox:

 // open after 1 seconds
setTimeout(() => window.open('http://google.com'), 1000);

La diferencia es que Firefox trata un tiempo de espera de 2000 ms o menos aceptable, pero después de eso, elimina la "confianza", suponiendo que ahora está "fuera de la acción del usuario". Entonces el primero está bloqueado y el segundo no.


Respuesta original que era actual 2012:

Esta solución para la comprobación del bloqueador de elementos emergentes se ha probado en FF (v11), Safari (v6), Chrome (v23.0.127.95) e IE (v7 y v9). Actualice la función displayError para manejar el mensaje de error como mejor le parezca.

var popupBlockerChecker = {
    check: function(popup_window){
        var scope = this;
        if (popup_window) {
            if(/chrome/.test(navigator.userAgent.toLowerCase())){
                setTimeout(function () {
                    scope.is_popup_blocked(scope, popup_window);
                },200);
            }else{
                popup_window.onload = function () {
                    scope.is_popup_blocked(scope, popup_window);
                };
            }
        } else {
            scope.displayError();
        }
    },
    is_popup_blocked: function(scope, popup_window){
        if ((popup_window.innerHeight > 0)==false){ 
            scope.displayError();
        }
    },
    displayError: function(){
       alert("Popup Blocker is enabled! Please add this site to your exception list.");
    }
};

Uso:

var popup = window.open("http://www.google.ca", '_blank');
popupBlockerChecker.check(popup);

¡Espero que esto ayude! :)

Kevin B
fuente
20
Creo que necesitas más guiones bajos
Jacob Stamm
En Firefox, esto muestra la página en blanco y ni siquiera puede ver el mensaje del bloqueador de ventanas emergentes en la página de inicio. ¿Cómo cerrar la página en blanco?
user460114
Tenga en cuenta que si la URL emergente es un archivo descargable (que tiene Content-Disposition: attachment;en el encabezado de respuesta), la ventana emergente se cerrará inmediatamente, por lo tanto, el setTimeoutcódigo fallará y el navegador se quejará de que "¡El Bloqueador de ventanas emergentes está habilitado!". Para Chrome, recomiendo la solución de @ DanielB y funciona muy bien.
wonsuc
1
@wonsuc al abrir un enlace que tiene un Content-Disposition: attachment;encabezado, no necesita abrirlo en una ventana emergente. Simplemente haga un enlace directo al activo que desea descargar y el comportamiento nativo del navegador le permitirá descargar sin redirigirlo fuera de la página actual.
Kevin B
@KevinB Tengo que decir que estoy en una situación específica. Tengo que descargar varios archivos que generan archivos PDF a partir de HTML. Y si el contenido HTML es grande, a veces lleva varios segundos y si lo uso window.location, si el primer archivo tarda demasiado en generarse, se ignorará cuando se inicie la segunda solicitud. Esa es la razón por la que tengo que usar window.open, ya que window.locationnunca me avisa cuando finaliza la respuesta.
wonsuc
12

Una "solución" que siempre funcionará independientemente de la compañía o versión del navegador es simplemente colocar un mensaje de advertencia en la pantalla, en algún lugar cercano al control que creará una ventana emergente, que advierte cortésmente al usuario que la acción requiere una ventana emergente. arriba y habilitarlos para el sitio.

Sé que no es lujoso ni nada, pero no puede ser más simple y solo requiere unos 5 minutos de prueba, luego puedes pasar a otras pesadillas.

Una vez que el usuario ha permitido ventanas emergentes para su sitio, también sería considerado si no se excede en las ventanas emergentes. Lo último que quieres hacer es molestar a tus visitantes.

UncaAlby
fuente
1
Desafortunadamente, a veces todas las otras soluciones en esta pregunta no son aceptables, solo esta. ¿Por qué? Debido a que todos intentan mostrar una ventana emergente, no solo detectan si las ventanas emergentes están habilitadas. ¿Qué pasa si quiero hacerlo en silencio?
Sagi Mann
Algo para recordar aquí también es que un usuario no siempre puede habilitar las ventanas emergentes para su sitio. En versiones anteriores de safari, por ejemplo, un usuario solo puede habilitar o deshabilitar el bloqueador de ventanas emergentes por completo, no hay listas blancas disponibles.
Jeremy
1

Combiné las soluciones de @Kevin B y @ DanielB.
Esto es mucho más simple.

var isPopupBlockerActivated = function(popupWindow) {
    if (popupWindow) {
        if (/chrome/.test(navigator.userAgent.toLowerCase())) {
            try {
                popupWindow.focus();
            } catch (e) {
                return true;
            }
        } else {
            popupWindow.onload = function() {
                return (popupWindow.innerHeight > 0) === false;
            };
        }
    } else {
        return true;
    }
    return false;
};

Uso:

var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
    // Do what you want.
}
wonsuc
fuente
1
isPopupBlockerActivated La función nunca regresa return (popupWindow.innerHeight > 0) === false;. Su función devuelve falso cuando su navegador no es Chrome. Porque onload es un proceso asincrónico. Su función devuelve falso y luego se ejecuta la carga, pero su resultado nunca regresa.
Onur Gazioğlu
0

He intentado muchas soluciones, pero la única que se me ocurrió que también funcionó con uBlock Origin fue utilizar un tiempo de espera para verificar el estado cerrado de la ventana emergente.

function popup (url, width, height) {
    const left = (window.screen.width / 2) - (width / 2)
    const top = (window.screen.height / 2) - (height / 2)
    let opener = window.open(url, '', `menubar=no, toolbar=no, status=no, resizable=yes, scrollbars=yes, width=${width},height=${height},top=${top},left=${left}`)

    window.setTimeout(() => {
        if (!opener || opener.closed || typeof opener.closed === 'undefined') {
            console.log('Not allowed...') // Do something here.
        }
    }, 1000)
}

Obviamente esto es un hack; como todas las soluciones a este problema.

Debe proporcionar suficiente tiempo en su setTimeout para dar cuenta de la apertura y cierre iniciales, por lo que nunca será completamente preciso. Será una posición de prueba y error.

Agregue esto a su lista de intentos.

Michael Giovanni Pumo
fuente
0

Un enfoque simple si también posee el código hijo , sería crear una variable simple en su html como se muestra a continuación:

    <script>
        var magicNumber = 49;
    </script>

Y luego verifique su existencia del padre algo similar a lo siguiente:

    // Create the window with login URL.
    let openedWindow = window.open(URL_HERE);

    // Check this magic number after some time, if it exists then your window exists
    setTimeout(() => {
        if (openedWindow["magicNumber"] !== 32) {
            console.error("Window open was blocked");
        }
    }, 1500);

Esperamos un tiempo para asegurarnos de que se haya cargado la página web y verificamos su existencia. Obviamente, si la ventana no se carga después de 1500 ms, la variable aún lo sería undefined.

Lalit Umbarkar
fuente
-1

Al usar el evento onbeforeunload podemos verificar lo siguiente

    function popup()
    {
        var chk=false;
        var win1=window.open();
        win1.onbeforeunload=()=>{
            var win2=window.open();
            win2.onbeforeunload=()=>{
                chk=true;
            };
        win2.close();
        };
        win1.close();
        return chk;
    }

abrirá 2 ventanas negras en el fondo

La función devuelve un valor booleano.

Yash Bora
fuente