103 votes

Détecter les fenêtres pop-up bloquées dans Chrome

Je suis au courant des techniques javascript permettant de détecter si une fenêtre popup est bloquée dans d'autres navigateurs (comme décrit dans la réponse à cette question ). Voici le test de base :

var newWin = window.open(url);

if(!newWin || newWin.closed || typeof newWin.closed=='undefined')
{
    //POPUP BLOCKED
}

Mais cela ne fonctionne pas dans Chrome. La section "POPUP BLOCKED" n'est jamais atteinte lorsque la popup est bloquée.

Bien sûr, le test fonctionne dans une certaine mesure puisque Chrome ne bloque pas réellement la popup, mais l'ouvre dans une minuscule fenêtre minimisée dans le coin inférieur droit qui répertorie les popups "bloquées".

Ce que j'aimerais, c'est pouvoir dire si la popup a été bloquée par le bloqueur de popup de Chrome. J'essaie d'éviter le reniflage du navigateur pour privilégier la détection des fonctionnalités. Existe-t-il un moyen de faire cela sans renifler le navigateur ?

Modifier : J'ai maintenant essayé d'utiliser newWin.outerHeight , newWin.left et d'autres propriétés similaires pour y parvenir. Google Chrome renvoie toutes les valeurs de position et de hauteur à 0 lorsque la fenêtre contextuelle est bloquée.

Malheureusement, il renvoie également les mêmes valeurs même si la popup est effectivement ouverte pendant une durée inconnue. Après une période magique (quelques secondes dans mes tests), les informations sur l'emplacement et la taille sont renvoyées avec les valeurs correctes. En d'autres termes, je n'ai toujours pas trouvé de solution à ce problème. Toute aide serait la bienvenue.

0 votes

Yoav, l'emplacement s'affiche de la même manière, que la fenêtre pop-up soit bloquée ou non. Quelqu'un d'autre a une réponse qui n'implique pas que l'utilisateur doive attendre 3,5 secondes ?

0 votes

Les dernières solutions d'InvisibleBacon et d'Andy ne fonctionnent pas dans Chrome 10 : le message "failed for chrome" apparaît même si la pop-up de test s'est affichée avec succès. Une idée ?

0 votes

Je pense qu'une nouvelle question s'impose, car certaines de ces solutions semblent n'avoir fonctionné qu'avec les premières versions de Chrome.

66voto

Ringo Points 1401

Eh bien, le "moment magique" dont vous parlez est probablement lorsque le DOM de la popup a été chargé. Ou bien lorsque tout (images, CSS externes, etc.) a été chargé. Vous pouvez facilement tester cela en ajoutant un très grand graphique à la fenêtre contextuelle (videz d'abord votre cache !). Si vous utilisez un cadre Javascript comme jQuery (ou quelque chose de similaire), vous pouvez utiliser l'événement ready() (ou quelque chose de similaire) pour attendre le chargement du DOM avant de vérifier le décalage de la fenêtre. Le danger est que la détection de Safari fonctionne de manière conflictuelle : le DOM de la popup ne sera jamais ready() dans Safari parce qu'il vous donnera un handle valide pour la fenêtre que vous essayez d'ouvrir - qu'elle s'ouvre réellement ou non. (en fait, je crois que le code de test de votre popup ci-dessus ne fonctionnera pas pour safari).

Je pense que la meilleure chose à faire est d'envelopper votre test dans un setTimeout() et de donner au popup 3 à 5 secondes pour terminer le chargement avant de lancer le test. Ce n'est pas parfait, mais cela devrait fonctionner au moins 95% du temps.

Voici le code que j'utilise pour la détection inter-navigateurs, sans la partie Chrome.

function _hasPopupBlocker(poppedWindow) {
    var result = false;

    try {
        if (typeof poppedWindow == 'undefined') {
            // Safari with popup blocker... leaves the popup window handle undefined
            result = true;
        }
        else if (poppedWindow && poppedWindow.closed) {
            // This happens if the user opens and closes the client window...
            // Confusing because the handle is still available, but it's in a "closed" state.
            // We're not saying that the window is not being blocked, we're just saying
            // that the window has been closed before the test could be run.
            result = false;
        }
        else if (poppedWindow && poppedWindow.test) {
            // This is the actual test. The client window should be fine.
            result = false;
        }
        else {
            // Else we'll assume the window is not OK
            result = true;
        }

    } catch (err) {
        //if (console) {
        //    console.warn("Could not access popup window", err);
        //}
    }

    return result;
}

Ce que je fais, c'est que j'exécute ce test à partir du parent et que je le place dans un setTimeout(), donnant à la fenêtre enfant 3 à 5 secondes pour se charger. Dans la fenêtre enfant, vous devez ajouter une fonction de test :

fonction test() {}

Le détecteur de popup blocker vérifie si la fonction "test" existe en tant que membre de la fenêtre enfant.

AJOUTÉ LE 15 JUIN 2015 :

Je pense que la façon moderne de gérer cela serait d'utiliser window.postMessage() pour que l'enfant informe le parent que la fenêtre a été chargée. L'approche est similaire (l'enfant dit au parent qu'il est chargé), mais le moyen de communication a été amélioré. J'ai été en mesure d'effectuer cette opération à partir de l'enfant :

$(window).load(function() {
  this.opener.postMessage({'loaded': true}, "*");
  this.close();
});

Le parent écoute ce message en utilisant :

$(window).on('message', function(event) {     
  alert(event.originalEvent.data.loaded)
}); 

J'espère que cela vous aidera.

0 votes

Rich, tu es un gourou du popup javascript. Merci. C'est exactement ce dont j'avais besoin.

4 votes

Des mises à jour sur ce sujet ? Ça ne semble plus fonctionner... En particulier dans Chrome

0 votes

Je pense avoir trouvé un moyen de faire fonctionner cela pour les nouvelles versions de Chrome. Voir ma réponse pour plus de détails.

16voto

Andy Points 912

Une seule amélioration au snipet d'InvisibleBacon (testé dans IE9, Safari 5, Chrome 9 et FF 3.6) :

var myPopup = window.open("popupcheck.htm", "", "directories=no,height=150,width=150,menubar=no,resizable=no,scrollbars=no,status=no,titlebar=no,top=0,location=no");
if (!myPopup)
    alert("failed for most browsers");
else {
    myPopup.onload = function() {
        setTimeout(function() {
            if (myPopup.screenX === 0) {
                alert("failed for chrome");
            } else {
                // close the test window if popups are allowed.
                myPopup.close();  
            }
        }, 0);
    };
}

0 votes

Pourquoi fermer la fenêtre si les popups sont autorisées ? Ne serait-ce pas fermer la popup que vous vouliez ouvrir en premier lieu ?

3 votes

En utilisant jQuery, au lieu de onload, je ferais $(myPopup).ready(). En exécutant localement, mon IE était trop rapide, et "onload" avait déjà eu lieu.

12voto

Kevin B Points 436

Ce qui suit est un jQuery solution à la vérification du bloqueur de popup. Elle 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 vous le souhaitez.

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

Utilisation :

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

J'espère que cela vous aidera ! :)

0 votes

C'est vraiment utile. Merci de partager.

0 votes

Votre bienvenue Suvendu, je suis heureux que vous l'ayez trouvé utile ! Bon codage ! :)

1 votes

J'ai modifié ce code pour passer dans/autour de l'url qui tente d'être ouvert. Cela permet à la méthode _displayError() d'afficher une alerte (j'utilise toastr) notifiant l'utilisateur qu'il y a un problème et de fournir un lien cliquable qui contournera la plupart des bloqueurs puisqu'il s'agit d'un lien direct. Merci de partager !

10voto

InvisibleBacon Points 2263

La réponse de Rich ne fonctionnera plus pour Chrome. Il semble que Chrome exécute réellement tout Javascript dans la fenêtre popup maintenant. J'ai fini par vérifier que la valeur screenX est égale à 0 pour vérifier si les fenêtres pop-up sont bloquées. Je pense aussi avoir trouvé un moyen de garantir que cette propriété est finale avant la vérification. Cela ne fonctionne que pour les popups de votre domaine, mais vous pouvez ajouter un gestionnaire onload comme ceci :

var myPopup = window.open("site-on-my-domain", "screenX=100");
if (!myPopup)
    alert("failed for most browsers");
else {
    myPopup.onload = function() {
        setTimeout(function() {
            if (myPopup.screenX === 0)
                alert("failed for chrome");
        }, 0);
    };
}

Comme beaucoup l'ont signalé, la propriété "screenX" indique parfois une valeur différente de zéro pour les popups qui ont échoué, même après le chargement. J'ai également constaté ce comportement, mais si vous ajoutez la vérification après un délai de zéro ms, la propriété screenX semble toujours fournir une valeur cohérente.

Faites-moi savoir s'il existe des moyens de rendre ce script plus robuste. Il semble toutefois fonctionner pour mes besoins.

0 votes

Ce n'est pas le cas pour moi, onload ne s'enflamme jamais.

9voto

Cela a marché pour moi :

    cope.PopupTest.params = 'height=1,width=1,left=-100,top=-100,location=no,toolbar=no,menubar=no,scrollbars=no,resizable=no,directories=no,status=no';
    cope.PopupTest.testWindow = window.open("popupTest.htm", "popupTest", cope.PopupTest.params);

    if( !cope.PopupTest.testWindow
        || cope.PopupTest.testWindow.closed
        || (typeof cope.PopupTest.testWindow.closed=='undefined')
        || cope.PopupTest.testWindow.outerHeight == 0
        || cope.PopupTest.testWindow.outerWidth == 0
        ) {
        // pop-ups ARE blocked
        document.location.href = 'popupsBlocked.htm';
    }
    else {
        // pop-ups are NOT blocked
        cope.PopupTest.testWindow.close();
    }

Les valeurs outerHeight et outerWidth sont destinées à chrome, car l'astuce 'about:blank' mentionnée plus haut ne fonctionne plus dans chrome.

1 votes

Bien vu pour les modifications apportées au chrome et merci de l'avoir mis à jour ici. Votre réponse devrait être marquée comme correcte.

0 votes

Les paramètres outerWidth et outerHeight ne fonctionnent plus dans Chrome non plus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X