Como posso detectar se um navegador está bloqueando um pop-up?

130

Ocasionalmente, encontrei uma página da Web que tenta abrir uma nova janela (para entrada do usuário ou algo importante), mas o bloqueador de pop-ups impede que isso aconteça.

Quais métodos a janela de chamada pode usar para garantir que a nova janela seja iniciada corretamente?

Nathan Bedford
fonte

Respostas:

160

Se você usa JavaScript para abrir o pop-up, pode usar algo como isto:

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}
omar
fonte
Aqui está uma resposta para chrome: detectar-bloqueado-popup-in-cromo
ajwaka
@ajwaka, você poderia esclarecer gentilmente se essa resposta falhou no chrome ou existe algum motivo para que a outra resposta seja melhor para o chrome? obrigado!
Crashalot
@ajwaka, pelo menos hoje, esse código parece funcionar no chrome, daí a questão.
Crashalot
@Crashalot - Você está me perguntando sobre algo que eu respondi há 6 anos - infelizmente não lembro mais da situação e os navegadores percorreram um longo caminho em 6 anos.
ajwaka 03/04
40

Eu tentei vários dos exemplos acima, mas não consegui fazê-los funcionar com o Chrome. Essa abordagem simples parece funcionar com o Chrome 39, Firefox 34, Safari 5.1.7 e IE 11. Aqui está o trecho de código da nossa 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
fonte
1
@ Surendra, por favor, você pode especificar o que quer dizer com "não está funcionando"? Um erro no momento da análise? Um erro no tempo de execução? O pop-up é aberto, mas está marcado como bloqueado? O pop-up está bloqueado, mas está marcado como aberto? Não vejo nenhum motivo para o explorer falhar nisso, a menos que seja permitido chamar focus () em NULL; nesse caso, um teste para NULL antes da tentativa funcionaria.
FrancescoMM
O IE sempre retorna nulo, mesmo que o pop-up tenha sido bem-sucedido.
Devin Garner
34

Atualização: Os pop-ups existem desde os tempos realmente antigos. A ideia inicial era mostrar outro conteúdo sem fechar a janela principal. A partir de agora, existem outras maneiras de fazer isso: o JavaScript pode enviar solicitações de servidor, portanto os pop-ups raramente são usados. Mas às vezes eles ainda são úteis.

No passado, sites malignos abusavam muito de pop-ups. Uma página ruim pode abrir toneladas de janelas pop-up com anúncios. Portanto, agora a maioria dos navegadores tenta bloquear pop-ups e proteger o usuário.

A maioria dos navegadores bloqueia pop-ups se forem chamados fora dos manipuladores de eventos acionados pelo usuário, como o onclick.

Se você pensar bem, isso é um pouco complicado. Se o código estiver diretamente em um manipulador onclick, é fácil. Mas qual é o pop-up aberto no setTimeout?

Tente este código:

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

O pop-up é aberto no Chrome, mas é bloqueado no Firefox.

… E isso também funciona no Firefox:

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

A diferença é que o Firefox trata um tempo limite de 2000ms ou menos são aceitáveis, mas depois disso - remove a "confiança", assumindo que agora está "fora da ação do usuário". Então o primeiro está bloqueado e o segundo não.


Resposta original atual em 2012:

Esta solução para verificação de bloqueadores de pop-up foi testada no FF (v11), Safari (v6), Chrome (v23.0.127.95) e IE (v7 e v9). Atualize a função displayError para manipular a mensagem de erro como desejar.

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 isto ajude! :)

Kevin B
fonte
20
Eu acho que você precisa de mais sublinhados
Jacob Stamm
No firefox, isso exibe a página em branco e você nem consegue ver a mensagem do bloqueador de pop-ups na página do abridor. Como fechar a página em branco?
user460114
Observe que se o URL do pop-up for um arquivo para download (que tem Content-Disposition: attachment;no cabeçalho de resposta), o pop-up será fechado imediatamente, portanto o setTimeoutcódigo falhará e o navegador reclamará que "O bloqueador de pop- ups está ativado!". Para o Chrome, eu recomendo a solução do @ DanielB e funciona muito bem.
wonsuc 27/02/19
1
@wonsuc ao abrir um link com um Content-Disposition: attachment;cabeçalho, você não precisa abri-lo em um pop-up. Basta criar um link direto para o ativo que você deseja baixar e o comportamento nativo do navegador permitirá que você faça o download sem redirecioná-lo para fora da página atual.
Kevin B
@ KevinB Devo dizer que estou em uma situação específica. Eu tenho que baixar vários arquivos que estão gerando arquivos PDF a partir de HTML. E se o conteúdo HTML for grande, às vezes leva alguns segundos e, se eu usar window.location, se o primeiro arquivo demorar muito para ser gerado, ele será ignorado quando o segundo pedido for iniciado. Essa é a razão pela qual tenho que usar window.open, pois window.locationnunca me avisa quando a resposta termina.
wonsuc 28/02/19
12

Uma "solução" que sempre funcionará, independentemente da empresa ou versão do navegador, é simplesmente colocar uma mensagem de aviso na tela, em algum lugar próximo ao controle que criará um pop-up, que educadamente avisa o usuário que a ação requer um pop- e habilitá-los para o site.

Sei que não é nada chique, mas não pode ser mais simples e requer apenas 5 minutos de teste; então você pode passar para outros pesadelos.

Depois que o usuário permitir pop-ups para o seu site, também será considerado se você não exagerar nos pop-ups. A última coisa que você quer fazer é irritar seus visitantes.

UncaAlby
fonte
1
Infelizmente, algumas vezes todas as outras soluções nesta questão não são aceitáveis ​​- somente essa. Por quê? Porque todos eles tentam exibir um pop-up - não apenas detectam se os pop-ups estão ativados. E se eu quiser fazer isso silenciosamente?
Sagi Mann
Algo a lembrar aqui também é que um usuário nem sempre pode ativar pop-ups para o seu site. Em versões mais antigas do safari, por exemplo, um usuário só pode ativar ou desativar completamente o bloqueador de pop-ups, sem a lista de permissões disponível.
Jeremy
1

Combinei as soluções @ Kevin B e @ DanielB.
Isto é muito mais simples.

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
fonte
1
isPopupBlockerActivated a função nunca retorna return (popupWindow.innerHeight > 0) === false;. Sua função retorna false quando seu navegador não é o Chrome. Porque onload é um processo assíncrono. Sua função retorna false e, em seguida, onload executado, mas seu resultado nunca retorna.
Onur Gazioğlu
0

Eu tentei muitas soluções, mas a única que eu consegui e que também funcionou com o uBlock Origin foi utilizando um tempo limite para verificar o status fechado do pop-up.

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, isso é um hack; como todas as soluções para esse problema.

Você precisa fornecer tempo suficiente no seu setTimeout para contabilizar a abertura e o fechamento inicial, para que nunca seja totalmente preciso. Será uma posição de tentativa e erro.

Adicione isso à sua lista de tentativas.

Michael Giovanni Pumo
fonte
0

Uma abordagem simples, se você também possui o código filho , seria criar uma variável simples em seu html, como abaixo:

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

E, em seguida, verifique a existência do pai com algo semelhante ao seguinte:

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

Aguardamos algum tempo para garantir que a página da Web foi carregada e verificamos sua existência. Obviamente, se a janela não carregasse após 1500ms, a variável ainda estaria undefined.

Lalit Umbarkar
fonte
-1

Usando o evento onbeforeunload, podemos verificar da seguinte forma

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

ele abrirá 2 janelas pretas em segundo plano

a função retorna valor booleano.

Yash Bora
fonte