web-dev-qa-db-fra.com

Détecter Cliquez sur 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é dans la variable iframe. J'imagine un scénario où il y a une div invisible au-dessus de la iframe et la div passera juste l'événement click à la iframe

Est-ce que quelque chose comme ça est possible? Si c'est le cas, comment pourrais-je m'y prendre? La iframes étant une annonce, je n’ai aucun contrôle sur les balises utilisées.

103
Russ Bradberry

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 éventuellement (mais pas de manière fiable) lorsqu’elle revient (c.-à-d. En essayant de déterminer la différence entre le pointeur qui passe au-dessus de l’annonce et le reste 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 à l'iframe.

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

En attrapant le mousedown, vous empêchez le clic d'origine d'arriver à l'iframe. Si vous pouviez déterminer le moment où le bouton de la souris allait être enfoncé, vous pourriez essayer d'éloigner la div invisible de sorte 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 regardant si le pointeur s'est immobilisé, en devinant qu'un clic est sur le point de se produire. Mais c'est totalement peu fiable, et si vous échouez, vous venez de vous perdre un clic.

36
bobince

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


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

116
Paul Draper

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

l'iframe doit être placé dans une div avec un identifiant, pour que vous sachiez sur quel 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
    });

... ceci maintient overiFrame à -1 quand aucun iFrames n'est survolé ou le 'bannerid' défini dans la division enveloppante lorsqu'un iframe est survolé. Tout ce que vous avez à faire est de vérifier si "overiFrame" est défini lorsque la fenêtre s'estompe, 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 lors du survol de la souris sur un iFrame, il l'enregistrera comme un clic. Cela ne s'est toutefois produit que dans Firefox, IE, Chrome et Safari ne l'ont pas enregistré. 

Merci encore Mohammed, solution très utile!

103
patrick

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/

71
Dmitry Kochin

Le code suivant vous indiquera 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 ça va aider ... Amitiés, Mo.

35
Mohammed Radwan

Je viens de trouver cette solution .... Je l’ai essayée, j’ai adoré.

Fonctionne pour les iframes interdomaines pour ordinateurs de bureau et mobiles!

Je ne sais pas si c'est encore infaillible

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

Bonne codage

10
Tony

voir http://jsfiddle.net/Lcy797h2/ pour ma solution longue 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
DiverseAndRemote.com

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

Voici un plugin jQuery pour le suivi, cliquez sur les iframes (une fonction de rappel personnalisée sera déclenchée lorsqu'un clic sur un iframe est fait): 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
Vince

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 parcouru tous les sites Web pour trouver une méthode permettant de 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 devez appeler init () uniquement après le 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
zone117x

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
sidanmor

Je me suis retrouvé dans une situation où je devais suivre les clics sur un bouton de réseau social tiré d'un iframe. Une nouvelle fenêtre serait ouverte lorsque le bouton serait 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
pizza-r0b

Vous pouvez le faire pour faire en sorte que les événements soient affichés 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);
    });
});

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

3
Taner Topal

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

Créez simplement une couche invisible sur l'iframe qui remontera au clic et remontera quand l'événement mouseleave sera déclenché !!
Besoin de jQuery

cette solution ne se propage pas du 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
r1si

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

$(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
Jonathan Tonge

Comme trouvé ici: Detect Cliquez sur 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
Mickaël

Voici une solution en utilisant les approches suggérées avec les astuces hover + blur et élément actif, pas de librairies, juste de js purs. Fonctionne bien pour FF/Chrome. La plupart du temps, l'approche est identique à celle proposée par @Mohammed Radwan, sauf que j'utilise une méthode différente proposée par @ zone117x pour suivre un clic sur iframe pour 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 à cause de les paramètres utilisateur et la fenêtre n’est pas forcément au premier plan 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
slesh

Je crois que vous pouvez faire quelque chose comme:

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

en utilisant jQuery pour y parvenir.

0
Daniel Sellers

Basé sur la réponse de Paul Draper, j'ai créé une solution qui fonctionne en permanence lorsque des iframes ouvrent un autre onglet du navigateur. Lorsque vous revenez sur la page qui reste active pour détecter le clic sur la structure, la situation est 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 focus lorsque l'utilisateur clique sur l'iframe et vérifie si l'élément actif est l'iframe (si vous avez plusieurs iframe, vous pouvez savoir qui a été sélectionné). .

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

0
freedeveloper