Comment puis-je détecter si un navigateur bloque une fenêtre contextuelle?

130

Parfois, je suis tombé sur une page Web qui tente d'ouvrir une nouvelle fenêtre (pour l'entrée de l'utilisateur ou quelque chose d'important), mais le bloqueur de fenêtres contextuelles empêche cela de se produire.

Quelles méthodes la fenêtre d'appel peut-elle utiliser pour s'assurer que la nouvelle fenêtre s'est lancée correctement?

Nathan Bedford
la source

Réponses:

160

Si vous utilisez JavaScript pour ouvrir la fenêtre contextuelle, vous pouvez utiliser quelque chose comme ceci:

var newWin = window.open(url);             

if(!newWin || newWin.closed || typeof newWin.closed=='undefined') 
{ 
    //POPUP BLOCKED
}
omar
la source
Voici une réponse pour chrome: detect-bloqué-popup-in-chrome
Ajwaka
@ajwaka pourriez-vous préciser si cette réponse échoue pour Chrome, ou y a-t-il une raison pour laquelle l'autre réponse est meilleure pour Chrome? Merci!
Crashalot le
@ajwaka au moins aujourd'hui ce code semble fonctionner sur chrome, d'où la question.
Crashalot le
@Crashalot - Vous me posez des questions sur quelque chose auquel j'ai répondu il y a 6 ans - Je ne me souviens malheureusement plus de la situation et les navigateurs ont parcouru un long chemin en 6 ans.
ajwaka le
40

J'ai essayé plusieurs des exemples ci-dessus, mais je n'ai pas pu les faire fonctionner avec Chrome. Cette approche simple semble fonctionner avec Chrome 39, Firefox 34, Safari 5.1.7 et IE 11. Voici l'extrait de code de notre bibliothèque 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
la source
1
@Surendra s'il vous plaît, pouvez-vous préciser ce que vous voulez dire par «ne fonctionne pas»? Une erreur au moment de l'analyse? Une erreur lors de l'exécution? Le popup s'ouvre mais il est marqué comme bloqué? Le popup est bloqué mais il est marqué comme ouvert? Je ne vois aucune raison pour laquelle l'explorateur échouerait, à moins que l'appel de focus () sur NULL ne soit autorisé.Dans ce cas, un test pour NULL avant l'essai fonctionnerait.
FrancescoMM
IE renvoie toujours null, même si le popup a réussi.
Devin Garner
34

Mise à jour: les pop-ups existent depuis des temps très anciens. L'idée initiale était d'afficher un autre contenu sans fermer la fenêtre principale. À partir de maintenant, il existe d'autres moyens de le faire: JavaScript est capable d'envoyer des requêtes pour le serveur, les popups sont donc rarement utilisés. Mais parfois, ils sont toujours utiles.

Dans le passé, les sites malveillants ont beaucoup abusé des popups. Une mauvaise page pourrait ouvrir des tonnes de fenêtres contextuelles avec des publicités. Alors maintenant, la plupart des navigateurs essaient de bloquer les popups et de protéger l'utilisateur.

La plupart des navigateurs bloquent les fenêtres contextuelles si elles sont appelées en dehors des gestionnaires d'événements déclenchés par l'utilisateur comme onclick.

Si vous y réfléchissez, c'est un peu délicat. Si le code est directement dans un gestionnaire onclick, c'est facile. Mais qu'est-ce que le popup s'ouvre dans setTimeout?

Essayez ce code:

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

La fenêtre contextuelle s'ouvre dans Chrome, mais est bloquée dans Firefox.

… Et cela fonctionne aussi dans Firefox:

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

La différence est que Firefox traite un délai d'expiration de 2000 ms ou moins est acceptable, mais après cela - supprime la «confiance», en supposant que maintenant c'est «en dehors de l'action de l'utilisateur». Ainsi, le premier est bloqué, et le second ne l'est pas.


Réponse originale qui était en cours en 2012:

Cette solution de vérification du bloqueur de popup a été testée dans FF (v11), Safari (v6), Chrome (v23.0.127.95) et IE (v7 & v9). Mettez à jour la fonction displayError pour gérer le message d'erreur comme bon vous semble.

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

Usage:

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

J'espère que cela t'aides! :)

Kevin B
la source
20
Je pense que vous avez besoin de plus de soulignements
Jacob Stamm
Dans Firefox, cela affiche la page vierge et vous ne pouvez même pas voir le message du bloqueur de popup sur la page d'ouverture. Comment fermer la page blanche?
user460114
Notez que si l'url de la popup est un fichier téléchargeable (qui a Content-Disposition: attachment;dans l'en-tête de la réponse), la popup se fermera immédiatement, donc le setTimeoutcode échouera, et le navigateur se plaindra que "Popup Blocker est activé!". Pour Chrome, je recommande la solution de @ DanielB et cela fonctionne très bien.
wonsuc
1
@wonsuc lors de l'ouverture d'un lien qui a un en- Content-Disposition: attachment;tête, vous n'avez pas besoin de l'ouvrir dans une fenêtre contextuelle. Créez simplement un lien direct vers l'actif que vous souhaitez télécharger et le comportement natif du navigateur vous permettra de télécharger sans vous rediriger hors de la page en cours.
Kevin B
@KevinB Je dois dire que je suis dans une situation spécifique. Je dois télécharger plusieurs fichiers qui génèrent des fichiers PDF à partir de HTML. Et si le contenu HTML est volumineux, cela prend parfois plusieurs secondes et si je l'utilise window.location, si le premier fichier prend trop de temps à générer, il sera ignoré au démarrage de la deuxième requête. C'est la raison pour laquelle je dois utiliser window.open, car window.locationne me fait jamais savoir quand la réponse se termine.
wonsuc
12

Une «solution» qui fonctionnera toujours quelle que soit la société ou la version du navigateur consiste simplement à mettre un message d'avertissement à l'écran, quelque part près du contrôle qui créera une fenêtre contextuelle, qui avertit poliment l'utilisateur que l'action nécessite un pop- et de les activer pour le site.

Je sais que ce n'est pas de la fantaisie ou quoi que ce soit, mais cela ne peut pas être plus simple et ne nécessite que 5 minutes de test, alors vous pouvez passer à d'autres cauchemars.

Une fois que l'utilisateur a autorisé les pop-ups pour votre site, il serait également prudent de ne pas en faire trop. La dernière chose que vous voulez faire est d'ennuyer vos visiteurs.

UncaAlby
la source
1
Malheureusement, parfois toutes les autres solutions à cette question ne sont pas acceptables - seulement celle-ci. Pourquoi? Parce qu'ils essaient tous d'afficher une fenêtre contextuelle - pas seulement de détecter si les fenêtres contextuelles sont activées. Et si je veux le faire en silence?
Sagi Mann
Une chose à retenir ici est également qu'un utilisateur ne peut pas toujours activer uniquement les fenêtres contextuelles pour votre site. Dans les anciennes versions de safari par exemple, un utilisateur peut uniquement activer ou désactiver complètement le bloqueur de popup, aucune liste blanche n'est disponible.
Jeremy
1

J'ai combiné les solutions @Kevin B et @ DanielB.
C'est beaucoup plus 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;
};

Usage:

var popup = window.open('https://www.google.com', '_blank');
if (isPopupBlockerActivated(popup)) {
    // Do what you want.
}
wonsuc
la source
1
isPopupBlockerActivated la fonction ne revient jamais return (popupWindow.innerHeight > 0) === false;. Votre fonction renvoie false lorsque votre navigateur n'est pas Chrome. Parce que le chargement est un processus asynchrone. Votre fonction retourne false puis onload exécuté mais son résultat ne revient jamais.
Onur Gazioğlu
0

J'ai essayé beaucoup de solutions, mais la seule que j'ai pu proposer qui fonctionnait également avec uBlock Origin, était d'utiliser un délai d'attente pour vérifier l'état fermé de la fenêtre contextuelle.

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

De toute évidence, c'est un hack; comme toutes les solutions à ce problème.

Vous devez prévoir suffisamment de temps dans votre setTimeout pour tenir compte de l'ouverture et de la fermeture initiales, donc cela ne sera jamais complètement précis. Ce sera une position d'essais et d'erreurs.

Ajoutez ceci à votre liste de tentatives.

Michael Giovanni Pumo
la source
0

Une approche simple si vous possédez également le code enfant serait de créer une variable simple dans son html comme ci-dessous:

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

Et puis vérifiez son existence du parent quelque chose de similaire à ce qui suit:

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

Nous attendons un certain temps pour nous assurer que la page Web a été chargée et vérifier son existence. Évidemment, si la fenêtre ne se chargeait pas après 1500 ms, la variable le serait toujours undefined.

Lalit Umbarkar
la source
-1

En utilisant l'événement onbeforeunload, nous pouvons vérifier comme suit

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

il ouvrira 2 fenêtres noires en arrière-plan

la fonction renvoie une valeur booléenne.

Yash Bora
la source