Détecter cliquez dans Iframe en utilisant JavaScript

Je comprends qu'il n'est pas possible de dire ce que l'utilisateur fait dans un iframe s'il s'agit d'un domaine croisé. Ce que je voudrais faire est de suivre si l'Utilisateur a cliqué du tout dans le iframe. J'imagine un scénario où il y a un div invisible au-dessus du iframe et le div passera alors l'événement click au iframe.

Quelque chose comme ça est possible? Si c'est le cas, comment pourrais-je aller à ce sujet? Les iframes sont des annonces, donc je n'ai aucun contrôle sur les balises utilisées.

98
demandé sur Russ Bradberry 2010-03-04 20:25:21

18 réponses

Quelque chose comme ça est possible?

Non. Tout ce que vous pouvez faire est de détecter la souris entrant dans l'iframe, et potentiellement (mais pas de manière fiable) quand elle revient (ie. essayer de déterminer la différence entre le pointeur passant au-dessus de l'annonce sur son chemin ailleurs et s'attarder sur l'annonce).

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

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

En attrapant le mousedown, 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 pressé, vous pourriez essayer d'obtenir la div invisible de la route afin que le clic passe... mais il n'y a pas non plus d'événement qui se déclenche juste avant un mousedown.

Vous pouvez essayer de deviner, par exemple en cherchant à voir si le pointeur s'est arrêté, en devinant un clic pourrait être sur le point de venir. Mais c'est totalement peu fiable, et si vous échouez, vous venez de vous perdre un clic.

35
répondu bobince 2010-03-04 17:46:35

Sur la base de la réponse de Mohammed Radwan, j'ai trouvé la solution jQuery suivante. Fondamentalement, ce qu'il fait est de garder une trace de ce que les gens iFrame sont en vol stationnaire. Ensuite, si la fenêtre est floue, cela signifie probablement que l'Utilisateur a cliqué sur la bannière iframe.

L'iframe doit être placé dans un div avec un id, pour vous assurer de savoir sur quel iframe l'Utilisateur a cliqué:

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

Donc:

$(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 wrapping div quand un iframe est plané. 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 en 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!

101
répondu patrick 2011-11-12 00:18:54

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


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

97
répondu Paul Draper 2017-05-13 11:51:30

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/

66
répondu Dmitry Kochin 2015-08-21 10:31:06

Le code suivant vous montrera si l'utilisateur clique / survole ou quitte 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. Espérons que cela va aider. Égard, Mo.

35
répondu Mohammed Radwan 2012-05-12 12:58:50

Vient de trouver cette solution... Je l'ai essayé, je l'ai aimé..

Fonctionne pour les iframes Cross domain pour bureau et mobile!

Je ne sais pas encore s'il est infaillible

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

Codage Heureux

10
répondu Tony 2015-06-18 00:04:56

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

Voici un plugin jQuery pour suivre cliquez sur iframes (il déclenchera une fonction de rappel personnalisée quand 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)
        }
    });
});
5
répondu Vince 2013-04-03 17:29:41

Voir http://jsfiddle.net/Lcy797h2/{[3] } pour ma solution à long terme 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();
5
répondu DiverseAndRemote.com 2017-01-30 16:37:18

Mohamed 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. Je vous remercie, monsieur!

Quelques conseils: J'ai trouvé que votre solution était plus fiable lors de l'appel direct de la fonction init (), plutôt que via attachOnloadEvent(). De cours pour ce faire, vous devez appeler init() seulement après l'iframe html. Donc, cela ressemblerait à 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>
3
répondu zone117x 2011-06-12 17:57:31

Vous pouvez le faire pour les événements de bulle au 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);
    });
});

Il suffit d'étendre la liste d'événements pour plus d'événements.

3
répondu Taner Topal 2013-04-08 12:46:00

Je suis tombé dans une situation où je devais suivre les clics sur un bouton de médias sociaux tiré par un iframe. Une nouvelle fenêtre serait ouverte lorsque le bouton a été 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();
3
répondu pizza-r0b 2014-01-29 17:58:31

Cela fonctionne pour moi sur tous les navigateurs (Firefox inclus)

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>

3
répondu sidanmor 2017-01-22 15:06:09

Http://jsfiddle.net/QcAee/406/

Il suffit de créer un calque invisible sur l'iframe qui remonte lorsque vous cliquez et monte lorsque l'événement mouseleave sera déclenché !!
Besoin de jQuery

Cette solution ne se propage pas en premier clic dans 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>
2
répondu r1si 2016-05-10 09:13:03

Cela fonctionne définitivement 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 pourriez 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
  }
});
1
répondu Jonathan Tonge 2012-04-07 04:14:42

Je crois que vous pouvez faire quelque chose comme:

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

En utilisant jQuery pour accomplir cela.

0
répondu Daniel Sellers 2011-07-12 17:10:54

Comme trouvé ici: détecter cliquez dans Iframe en utilisant 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');
    }
})
0
répondu Mickaël 2018-01-20 23:43:30

Basé sur 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 retournez la page continuer à être actif pour détecter le clic sur le cadre, 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 flou détecte la perte de focus 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équemment lorsque vous avez des cadres publicitaires.

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

0
répondu freedeveloper 2018-08-25 01:21:14

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

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

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;
            });
    }
}
0
répondu slesh 2018-10-04 11:46:42