Détecter le clic dans l'iframe à l'aide de JavaScript

128

Je comprends qu'il n'est pas possible de dire ce que fait l'utilisateur à l'intérieur d'un domaine iframes'il s'agit d'un domaine croisé. Ce que je voudrais faire, c'est suivre si l'utilisateur a cliqué du tout dans le fichier iframe. J'imagine un scénario où il y a un invisible divau-dessus du iframeet le divpassera juste alors l'événement de clic au iframe.

Est-ce que quelque chose comme ça est possible? Si c'est le cas, comment pourrais-je procéder? Ce iframessont des publicités, donc je n'ai aucun contrôle sur les balises utilisées.

Russ Bradberry
la source
4
C'est possible et il existe une solution de crossbrowser: stackoverflow.com/a/32138108/1064513
Dmitry Kochin

Réponses:

39

Est-ce que quelque chose comme ça est possible?

Non. Tout ce que vous pouvez faire est de détecter la souris qui entre dans l'iframe, et potentiellement (mais pas de manière fiable) lorsqu'elle en ressort (c'est-à-dire en essayant de déterminer la différence entre le pointeur passant sur l'annonce sur son chemin ailleurs et persistant sur l'annonce).

J'imagine un scénario où il y a un div invisible au-dessus de l'iframe et le div passera juste alors l'événement de clic à l'iframe.

Non, il n'y a aucun moyen de simuler un événement de clic.

En attrapant la souris, vous empêcheriez le clic d'origine d'accéder à l'iframe. Si vous pouviez déterminer quand le bouton de la souris était sur le point d'être enfoncé, vous pourriez essayer d'éloigner le div invisible pour que le clic passe ... mais il n'y a pas non plus d'événement qui se déclenche juste avant une descente de la souris.

Vous pouvez essayer de deviner, par exemple en regardant si le pointeur s'est immobilisé, en devinant qu'un clic pourrait être sur le point de se produire. Mais ce n'est absolument pas fiable, et si vous échouez, vous venez de perdre un clic.

bobince
la source
4
Oui, ça l'est. Et il y a une solution crossbrowser: stackoverflow.com/a/32138108/1064513
Dmitry Kochin
1
J'ai vérifié ces liens et je pense que la réponse est correcte. Vous ne pouvez détecter qu'un clic dans l'iframe mais pas ce qui a été cliqué.
user568021
Je déconseille, uniquement parce que ce n'est pas tout à fait vrai. La plupart de ce que vous dites est vrai, mais il existe des solutions de contournement, tout comme la réponse la plus populaire sur ce fil.
newms87
154

C'est certainement possible. Cela fonctionne dans Chrome, Firefox et IE 11 (et probablement d'autres).

focus();
var listener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('iframe')) {
        // clicked
    }
    window.removeEventListener('blur', listener);
});

JSFiddle


Attention: cela ne détecte que le premier clic. Si je comprends bien, c'est tout ce que vous voulez.

Paul Draper
la source
1
@the_joric, c'est parce que c'était 4 ans après la question, et les gens ne font normalement pas défiler les premières réponses.
Paul Draper
3
Il convient également de noter que si vous modifiez les onglets du navigateur, le focus () sera déclenché;
Linnay
7
Cela ne fonctionne PAS dans Firefox. JSFiddle contient une erreur qui cache ceci: = au lieu de ===. Il existe une solution de crossbrowser (même dans IE8): stackoverflow.com/a/32138108/1064513
Dmitry Kochin
8
L'événement de flou ne se déclenche pas si l'utilisateur ne clique pas d'abord dans le document principal! De plus, cela n'est pas utilisable pour détecter les clics sur plusieurs iframes, car il n'y a pas d'événement qui se déclenche lorsque le focus passe d'une iframe à une autre (l' blurévénement d'iframe ne se déclenche pas).
Tomáš Kafka
1
pourquoi il y a une dépendance sur focus ();
Prasad Shinde
107

Sur la base de la réponse de Mohammed Radwan, j'ai proposé la solution jQuery suivante. Fondamentalement, ce qu'il fait est de suivre ce que les gens d'iFrame planent. Ensuite, si la fenêtre est floue, cela signifie très probablement que l'utilisateur a cliqué sur la bannière iframe.

l'iframe doit être placé dans un div avec un identifiant, pour vous assurer que vous savez sur quelle iframe l'utilisateur a cliqué:

<div class='banner' bannerid='yyy'>
    <iframe src='http://somedomain.com/whatever.html'></iframe>
<div>

alors:

$(document).ready( function() {
    var overiFrame = -1;
    $('iframe').hover( function() {
        overiFrame = $(this).closest('.banner').attr('bannerid');
    }, function() {
        overiFrame = -1
    });

... cela maintient overiFrame à -1 quand aucun iFrames n'est survolé, ou le 'bannerid' défini dans le div wrapping lorsqu'un iframe est survolé. Tout ce que vous avez à faire est de vérifier si 'overiFrame' est défini lorsque la fenêtre est floue, comme ceci: ...

    $(window).blur( function() {
        if( overiFrame != -1 )
            $.post('log.php', {id:overiFrame}); /* example, do your stats here */
    });
});

Solution très élégante avec un inconvénient mineur: si un utilisateur appuie sur ALT-F4 en passant la souris sur un iFrame, il l'enregistrera comme un clic. Cela ne s'est produit que dans FireFox, IE, Chrome et Safari ne l'ont pas enregistré.

Merci encore Mohammed, solution très utile!

patrick
la source
J'ai + 1-ed cette réponse, bien qu'elle présente les problèmes suivants: 1. Lorsqu'il y a plusieurs iframes, vous cliquez sur l'un d'eux, puis immédiatement sur un autre - le deuxième clic n'est pas détecté. 2. Les clics multiples dans une iframe ne sont pas non plus comptés. 3. Ne fonctionne pas correctement sur mobile, car vous ne pouvez pas faire d'événement "survolez" avec un doigt.
Sych
Le script ci-dessus est utilisé par moi pour détecter les clics en dehors de mon site. La plupart des réseaux publicitaires proposent désormais des bannières dans des cadres. Si vous cliquez sur un puis sur un autre rapidement avant de partir au premier clic, techniquement, je veux connaître le dernier clic que vous avez réellement laissé. Donc, dans mon cas, c'est un comportement voulu. Il détecte également très bien les clics sur les bannières mobiles. Le survol doit donc être lancé juste avant que le clic ne soit exécuté
patrick
Ne fonctionne pas en cas d'éléments svg dans le contenu iframe :( stackoverflow.com/questions/32589735/…
Serhiy
@Serhiy, c'est parce que vous ne quittez pas réellement la page d'origine en cliquant sur l'iframe ...
patrick
6
Cette réponse est la meilleure d'entre elles, cependant, si vous souhaitez recevoir chaque clic dans l'iframe, vous devez en retirer le focus une fois que l'utilisateur a cliqué afin de surveiller les clics supplémentaires. Cela devrait être ajouté à la section $ (fenêtre) .blur (): setTimeout(function(){ window.focus(); }, 0);. Désormais, l'utilisateur clique, met le focus dans l'iframe, le script récupère ce focus et peut désormais surveiller les changements de focus ultérieurs à partir des clics futurs.
HelpingHand
89

C'est une petite solution qui fonctionne dans tous les navigateurs même IE8:

var monitor = setInterval(function(){
    var elem = document.activeElement;
    if(elem && elem.tagName == 'IFRAME'){
        clearInterval(monitor);
        alert('clicked!');
    }
}, 100);

Vous pouvez le tester ici: http://jsfiddle.net/oqjgzsm0/

Dmitry Kochin
la source
1
Et si vous avez plusieurs iframes et que vous ne connaissez pas leur identifiant?
shankshera
1
seule solution fiable multi-navigateurs qui fonctionne également dans le dernier FF! Merci beaucoup. Il mérite plus upvotes
BrainOverflow
6
@shankshera Obtenez simplement elem.id, c'est votre identifiant iframe :). Voir jsfiddle.net/oqjgzsm0/219
Tomáš Kafka
1
J'utilise ceci pour suivre les clics sur les boutons sociaux. Mais comme 3/4 de ceux que j'utilise utilisent des iframes, je dois suivre les clics dans plusieurs iframes. J'ai mis à jour le violon pour permettre cela: jsfiddle.net/oqjgzsm0/273 . Il définit un nouvel intervalle qui vérifie si un clic est en dehors de la dernière iframe cliquée. Réinitialise ensuite l'intervalle d'origine pour vérifier à nouveau les clics. Il ne suit pas plusieurs clics dans la même iframe sans un clic en dehors de celui-ci.
brouxhaha
14
Outre le fait que l'utilisation d'un intervalle de boucle continue à un tel rythme n'est pas une très bonne idée, cela détectera les faux positifs si l'utilisateur se concentre sur l'iframe via la navigation par touche de tabulation
Kaiido
36

Le code suivant vous montrera si l'utilisateur clique / survole ou sort de l'iframe: -

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Detect IFrame Clicks</title>
<script type="text/javascript">
    $(document).ready(function() {
        var isOverIFrame = false;

        function processMouseOut() {
            log("IFrame mouse >> OUT << detected.");
            isOverIFrame = false;
            top.focus();
        }

        function processMouseOver() {
            log("IFrame mouse >> OVER << detected.");
            isOverIFrame = true;
        }

        function processIFrameClick() {
            if(isOverIFrame) {
                // replace with your function
                log("IFrame >> CLICK << detected. ");
            }
        }

        function log(message) {
            var console = document.getElementById("console");
            var text = console.value;
            text = text + message + "\n";
            console.value = text;
        }

        function attachOnloadEvent(func, obj) {
            if(typeof window.addEventListener != 'undefined') {
                window.addEventListener('load', func, false);
            } else if (typeof document.addEventListener != 'undefined') {
                document.addEventListener('load', func, false);
            } else if (typeof window.attachEvent != 'undefined') {
                window.attachEvent('onload', func);
            } else {
                if (typeof window.onload == 'function') {
                    var oldonload = onload;
                    window.onload = function() {
                        oldonload();
                        func();
                    };
                } else {
                    window.onload = func;
                }
            }
        }

        function init() {
            var element = document.getElementsByTagName("iframe");
            for (var i=0; i<element.length; i++) {
                element[i].onmouseover = processMouseOver;
                element[i].onmouseout = processMouseOut;
            }
            if (typeof window.attachEvent != 'undefined') {
                top.attachEvent('onblur', processIFrameClick);
            }
            else if (typeof window.addEventListener != 'undefined') {
                top.addEventListener('blur', processIFrameClick, false);
            }
        }

        attachOnloadEvent(init);
    });
</script>
</head>
<body>
<iframe src="www.google.com" width="100%" height="1300px"></iframe>
<br></br>
<br></br>
<form name="form" id="form" action=""><textarea name="console"
id="console" style="width: 100%; height: 300px;" cols="" rows=""></textarea>
<button name="clear" id="clear" type="reset">Clear</button>
</form>
</body>
</html>

Vous devez remplacer le src dans l'iframe par votre propre lien. J'espère que cela vous aidera. Cordialement, Mo.

Mohammed Radwan
la source
1
Basé sur des tests rapides, l'exemple donné (après avoir corrigé l'URL) semble fonctionner dans IE 8, de manière assez fiable dans Chrome 14.0.835.186 m, mais pas du tout dans Firefox 6.0.2.
Matthew Flaschen
Fonctionne bien pour Chrome, mais ne fonctionne pas pour Firefox v62, car lorsque vous cliquez sur l' événement de flou iframe n'est pas lancé
slesh
11

Je viens de trouver cette solution ... je l'ai essayé, j'ai adoré.

Fonctionne pour les iframes interdomaines pour ordinateur de bureau et mobile!

Je ne sais pas si c'est encore infaillible

window.addEventListener('blur',function(){
      if(document.activeElement.id == 'CrossDomainiframeId'){
        //do something :-)
      }
});

Bon codage

Tony
la source
2
Cette même réponse (peut-être une version légèrement meilleure) a été publiée un an plus tôt ici sur cette même page: stackoverflow.com/a/23231136/470749
Ryan
5

Vous pouvez y parvenir en utilisant l'événement de flou sur l'élément de fenêtre.

Voici un plugin jQuery pour suivre les clics sur les iframes (il déclenchera une fonction de rappel personnalisée lorsqu'un iframe est cliqué): https://github.com/finalclap/iframeTracker-jquery

Utilisez-le comme ceci:

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
Vince
la source
5

voir http://jsfiddle.net/Lcy797h2/ pour ma solution de longue haleine qui ne fonctionne pas de manière fiable dans IE

        $(window).on('blur',function(e) {    
            if($(this).data('mouseIn') != 'yes')return;
            $('iframe').filter(function(){
                return $(this).data('mouseIn') == 'yes';
            }).trigger('iframeclick');    
        });

        $(window).mouseenter(function(){
            $(this).data('mouseIn', 'yes');
        }).mouseleave(function(){
            $(this).data('mouseIn', 'no');
        });

        $('iframe').mouseenter(function(){
            $(this).data('mouseIn', 'yes');
            $(window).data('mouseIn', 'yes');
        }).mouseleave(function(){
            $(this).data('mouseIn', null);
        });

        $('iframe').on('iframeclick', function(){
            console.log('Clicked inside iframe');
            $('#result').text('Clicked inside iframe'); 
        });
        $(window).on('click', function(){
            console.log('Clicked inside window');
            $('#result').text('Clicked inside window'); 
        }).blur(function(){
            console.log('window blur');
        });

        $('<input type="text" style="position:absolute;opacity:0;height:0px;width:0px;"/>').appendTo(document.body).blur(function(){
                $(window).trigger('blur');
            }).focus();
DiverseAndRemote.com
la source
Son génial coding man .... ce que je veux vraiment ... + 1 à @Omar Jackman .. tellement utile pour capturer cliquez sur la publicité youtube
saun4frsh
4

Cela fonctionne pour moi sur tous les navigateurs (y compris Firefox)

https://gist.github.com/jaydson/1780598

https://jsfiddle.net/sidanmor/v6m9exsw/

var myConfObj = {
  iframeMouseOver : false
}
window.addEventListener('blur',function(){
  if(myConfObj.iframeMouseOver){
    console.log('Wow! Iframe Click!');
  }
});

document.getElementById('idanmorblog').addEventListener('mouseover',function(){
   myConfObj.iframeMouseOver = true;
});
document.getElementById('idanmorblog').addEventListener('mouseout',function(){
    myConfObj.iframeMouseOver = false;
});
<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>

<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>

Sidanmor
la source
3

Mohammed Radwan, votre solution est élégante. Pour détecter les clics iframe dans Firefox et IE, vous pouvez utiliser une méthode simple avec document.activeElement et une minuterie, cependant ... J'ai cherché partout dans les interwebs une méthode pour détecter les clics sur un iframe dans Chrome et Safari. Au bord de l'abandon, je trouve votre réponse. Merci Monsieur!

Quelques conseils: j'ai trouvé votre solution plus fiable lorsque vous appelez directement la fonction init (), plutôt que via attachOnloadEvent (). Bien sûr, pour ce faire, vous ne devez appeler init () qu'après l'iframe html. Cela ressemblerait donc à quelque chose comme:

<script>
var isOverIFrame = false;
function processMouseOut() {
    isOverIFrame = false;
    top.focus();
}
function processMouseOver() { isOverIFrame = true; }
function processIFrameClick() {
    if(isOverIFrame) {
    //was clicked
    }
}

function init() {
    var element = document.getElementsByTagName("iframe");
    for (var i=0; i<element.length; i++) {
        element[i].onmouseover = processMouseOver;
        element[i].onmouseout = processMouseOut;
    }
    if (typeof window.attachEvent != 'undefined') {
        top.attachEvent('onblur', processIFrameClick);
    }
    else if (typeof window.addEventListener != 'undefined') {
        top.addEventListener('blur', processIFrameClick, false);
    }
}
</script>

<iframe src="http://google.com"></iframe>

<script>init();</script>
zone117x
la source
3

Vous pouvez le faire pour afficher les événements dans le document parent:

$('iframe').load(function() {
    var eventlist = 'click dblclick \
                    blur focus focusin focusout \
                    keydown keypress keyup \
                    mousedown mouseenter mouseleave mousemove mouseover mouseout mouseup mousemove \
                    touchstart touchend touchcancel touchleave touchmove';

    var iframe = $('iframe').contents().find('html');

    // Bubble events to parent
    iframe.on(eventlist, function(event) {
        $('html').trigger(event);
    });
});

Étendez simplement la liste d'événements pour plus d'événements.

Taner Topal
la source
J'ai utilisé l'événement «touchend» et cela a fonctionné! Votre réponse m'a beaucoup aidé!
3

Je suis tombé sur une situation où je devais suivre les clics sur un bouton de réseau social tiré via une iframe. Une nouvelle fenêtre s'ouvrirait lorsque le bouton était cliqué. Voici ma solution:

var iframeClick = function () {
    var isOverIframe = false,
    windowLostBlur = function () {
        if (isOverIframe === true) {
            // DO STUFF
            isOverIframe = false;
        }
    };
    jQuery(window).focus();
    jQuery('#iframe').mouseenter(function(){
        isOverIframe = true;
        console.log(isOverIframe);
    });
    jQuery('#iframe').mouseleave(function(){
        isOverIframe = false;
        console.log(isOverIframe);
    });
    jQuery(window).blur(function () {
        windowLostBlur();
    });
};
iframeClick();
pizzarob
la source
3

http://jsfiddle.net/QcAee/406/

Créez simplement un calque invisible sur l'iframe qui revient lorsque vous cliquez et monte lorsque l'événement mouseleave sera déclenché !!
Besoin de jQuery

cette solution ne se propage pas au premier clic dans l'iframe!

$("#invisible_layer").on("click",function(){
		alert("click");
		$("#invisible_layer").css("z-index",-11);

});
$("iframe").on("mouseleave",function(){
		$("#invisible_layer").css("z-index",11);
});
iframe {
    width: 500px;
    height: 300px;
}
#invisible_layer{
  position: absolute;
  background-color:trasparent;
  width: 500px;
  height:300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message"></div>
<div id="invisible_layer">

</div>
<iframe id="iframe" src="//example.com"></iframe>

r1si
la source
1

Cela fonctionne certainement si l'iframe provient du même domaine que votre site parent. Je ne l'ai pas testé pour les sites inter-domaines.

$(window.frames['YouriFrameId']).click(function(event){  /* do something here  */ });
$(window.frames['YouriFrameId']).mousedown(function(event){ /* do something here */ });
$(window.frames['YouriFrameId']).mouseup(function(event){ /* do something here */ });

Sans jQuery, vous pouvez essayer quelque chose comme ça, mais encore une fois, je n'ai pas essayé cela.

window.frames['YouriFrameId'].onmousedown = function() { do something here }

Vous pouvez même filtrer vos résultats:

$(window.frames['YouriFrameId']).mousedown(function(event){   
  var eventId = $(event.target).attr('id');      
  if (eventId == 'the-id-you-want') {
   //  do something
  }
});
Jonathan Tonge
la source
1

Combinant la réponse ci-dessus avec la possibilité de cliquer encore et encore sans cliquer à l'extérieur de l'iframe.

    var eventListener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('contentIFrame')) {
        toFunction(); //function you want to call on click
        setTimeout(function(){ window.focus(); }, 0);
    }
    window.removeEventListener('blur', eventListener );
    });
Talha Asif
la source
1

Nous pouvons capter tous les clics. L'idée est de réinitialiser le focus sur un élément en dehors de l'iFrame après chaque clic:

    <input type="text" style="position:fixed;top:-1000px;left:-1000px">
    <div id="message"></div>
    <iframe id="iframe" src="//example.com"></iframe>
    <script>
        focus();
        addEventListener('blur', function() {
            if(document.activeElement = document.getElementById('iframe')) {
                message.innerHTML += 'Clicked';
                setTimeout(function () {
                    document.querySelector("input").focus();
                    message.innerHTML += ' - Reset focus,';
                }, 1000);
            }  
        });
    </script>

JSFiddle

Alexandre Muraviov
la source
0

Je pense que vous pouvez faire quelque chose comme:

$('iframe').contents().click(function(){function to record click here });

en utilisant jQuery pour accomplir cela.

Daniel Vendeurs
la source
0

Comme trouvé ici: Détecter le clic dans l'iframe à l'aide de JavaScript

=> Nous pouvons utiliser iframeTracker-jquery :

$('.carousel-inner .item').each(function(e) {
    var item = this;
    var iFrame = $(item).find('iframe');
    if (iFrame.length > 0) {
        iFrame.iframeTracker({
            blurCallback: function(){
                // Do something when iFrame is clicked (like firing an XHR request)
                onItemClick.bind(item)(); // calling regular click with right context
                console.log('IFrameClick => OK');
            }
        });
        console.log('IFrameTrackingRegistred => OK');
    }
})
Mickaël
la source
0

Sur la base de la réponse de Paul Draper, j'ai créé une solution qui fonctionne en continu lorsque vous avez des Iframes qui ouvrent un autre onglet dans le navigateur. Lorsque vous revenez la page continue à être active pour détecter le clic sur le framework, c'est une situation très courante:

          focus();
        $(window).blur(() => {
           let frame = document.activeElement;
           if (document.activeElement.tagName == "IFRAME") {
             // Do you action.. here  frame has the iframe clicked
              let frameid = frame.getAttribute('id')
              let frameurl = (frame.getAttribute('src'));
           }            
        });

        document.addEventListener("visibilitychange", function () {
            if (document.hidden) {

            } else {
                focus();
            }
        });

Le code est simple, l'événement de flou détecte la perte de mise au point lorsque l'iframe est cliqué, et teste si l'élément actif est l'iframe (si vous avez plusieurs iframe vous pouvez savoir qui a été sélectionné) cette situation est fréquente lorsque vous avez des cadres publicitaires .

Le deuxième événement déclenche une méthode de focus lorsque vous revenez à la page. il est utilisé pour l'événement de changement de visibilité.

développeur libre
la source
0

Voici une solution utilisant des approches suggérées avec hover + blur et astuces d'éléments actifs, pas de bibliothèques, juste des js purs. Fonctionne bien pour FF / Chrome. La plupart du temps, l'approche est la même que celle proposée par @Mohammed Radwan, sauf que j'utilise une méthode différente proposée par @ zone117x pour suivre le clic iframe pour FF, car window.focus ne fonctionne pas sans ajout de paramètres utilisateur :

Fait une demande pour amener la fenêtre à l'avant. Cela peut échouer en raison des paramètres utilisateur et la fenêtre n'est pas garantie d'être au premier plan avant le retour de cette méthode.

Voici la méthode composée:

function () {
    const state = {};

    (function (setup) {
        if (typeof window.addEventListener !== 'undefined') {
            window.addEventListener('load', setup, false);
        } else if (typeof document.addEventListener !== 'undefined') {
            document.addEventListener('load', setup, false);
        } else if (typeof window.attachEvent !== 'undefined') {
            window.attachEvent('onload', setup);
        } else {
            if (typeof window.onload === 'function') {
                const oldonload = onload;
                window.onload = function () {
                    oldonload();
                    setup();
                };
            } else {
                window.onload = setup;
            }
        }
    })(function () {
        state.isOverIFrame = false;
        state.firstBlur = false;
        state.hasFocusAcquired = false;

        findIFramesAndBindListeners();

        document.body.addEventListener('click', onClick);

        if (typeof window.attachEvent !== 'undefined') {
            top.attachEvent('onblur', function () {
                state.firstBlur = true;
                state.hasFocusAcquired = false;
                onIFrameClick()
            });
            top.attachEvent('onfocus', function () {
                state.hasFocusAcquired = true;
                console.log('attachEvent.focus');
            });
        } else if (typeof window.addEventListener !== 'undefined') {
            top.addEventListener('blur', function () {
                state.firstBlur = true;
                state.hasFocusAcquired = false;
                onIFrameClick();
            }, false);
            top.addEventListener('focus', function () {
                state.hasFocusAcquired = true;
                console.log('addEventListener.focus');
            });
        }

        setInterval(findIFramesAndBindListeners, 500);
    });

    function isFF() {
        return navigator.userAgent.search(/firefox/i) !== -1;
    }

    function isActiveElementChanged() {
        const prevActiveTag = document.activeElement.tagName.toUpperCase();
        document.activeElement.blur();
        const currActiveTag = document.activeElement.tagName.toUpperCase();
        return !prevActiveTag.includes('BODY') && currActiveTag.includes('BODY');
    }

    function onMouseOut() {
        if (!state.firstBlur && isFF() && isActiveElementChanged()) {
            console.log('firefox first click');
            onClick();
        } else {
            document.activeElement.blur();
            top.focus();
        }
        state.isOverIFrame = false;
        console.log(`onMouseOut`);
    }

    function onMouseOver() {
        state.isOverIFrame = true;
        console.log(`onMouseOver`);
    }

    function onIFrameClick() {
        console.log(`onIFrameClick`);
        if (state.isOverIFrame) {
            onClick();
        }
    }

    function onClick() {
        console.log(`onClick`);
    }

    function findIFramesAndBindListeners() {
        return Array.from(document.getElementsByTagName('iframe'))
            .forEach(function (element) {
                element.onmouseover = onMouseOver;
                element.onmouseout = onMouseOut;
            });
    }
}
slesh
la source
0

Hypothèses -

  1. Votre script s'exécute en dehors de l'iframe MAIS PAS dans la fenêtre window.top la plus à l'extérieur. (Pour la fenêtre la plus à l'extérieur, d'autres solutions de flou sont assez bonnes)
  2. Une nouvelle page est ouverte remplaçant la page actuelle / une nouvelle page dans un nouvel onglet et le contrôle est basculé vers un nouvel onglet.

Cela fonctionne à la fois pour les iframes source et sans source

var ifr = document.getElementById("my-iframe");
var isMouseIn;
ifr.addEventListener('mouseenter', () => {
    isMouseIn = true;
});
ifr.addEventListener('mouseleave', () => {
    isMouseIn = false;
});
window.document.addEventListener("visibilitychange", () => {
    if (isMouseIn && document.hidden) {
        console.log("Click Recorded By Visibility Change");
    }
});
window.addEventListener("beforeunload", (event) => {
    if (isMouseIn) {
        console.log("Click Recorded By Before Unload");
    }
});

Si un nouvel onglet est ouvert / la même page se décharge et que le pointeur de la souris se trouve dans l'Iframe, un clic est considéré

Sahil Maniar
la source