Wykrywanie kliknięć w Iframe przy użyciu JavaScript

Rozumiem, że nie można powiedzieć, co użytkownik robi wewnątrz iframe, jeśli jest to cross domain. To, co chciałbym zrobić, to śledzić, czy użytkownik kliknął w ogóle w iframe. Wyobrażam sobie scenariusz, w którym na górze iframe znajduje się niewidoczne div, a div po prostu przekaże Zdarzenie kliknięcia iframe.

Czy coś takiego jest możliwe? Jeśli tak, to jak bym to zrobił? {[6] } są reklamami, więc nie mam kontroli nad używanymi tagami.
Author: Russ Bradberry, 2010-03-04

18 answers

Czy coś takiego jest możliwe?
Nie. Wszystko, co możesz zrobić, to wykryć mysz wchodzącą do iframe i potencjalnie (choć nie niezawodnie), gdy wróci (np. próba ustalenia różnicy między wskaźnikiem przechodzącym nad reklamą w drodze gdzie indziej a utrzymującym się na reklamie).

Wyobrażam sobie scenariusz, w którym na górze iframe znajduje się niewidoczny div, a div po prostu przekaże Zdarzenie click do iframe.

Nie, Nie ma sposobu na sfałszowanie zdarzenia kliknięcia.

Łapiąc mousedown, uniemożliwisz oryginalnemu kliknięciu dotarcie do iframe. Jeśli można określić, kiedy przycisk myszy miał być naciśnięty można spróbować uzyskać niewidoczny div z drogi tak, że kliknięcie przejdzie... ale nie ma również żadnego zdarzenia, które strzela tuż przed mousedown.

Można spróbować odgadnąć, na przykład patrząc, czy wskaźnik doszedł do spoczynku, zgadując kliknięcie może nadejść. Ale jest to całkowicie zawodne, a jeśli zawiedziesz, stracisz tylko kliknięcie.

 35
Author: bobince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-04 17:46:35

Na podstawie odpowiedzi Mohammeda Radwana wymyśliłem następujące rozwiązanie jQuery. Zasadniczo to, co robi, to śledzenie tego, co ludzie iFrame unoszą się. Następnie, jeśli okno się rozmywa, najprawdopodobniej oznacza to, że użytkownik kliknął baner iframe.

Iframe powinien być umieszczony w div z id, aby upewnić się, że wiesz, który iframe użytkownik kliknął na:
<div class='banner' bannerid='yyy'>
    <iframe src='http://somedomain.com/whatever.html'></iframe>
<div>

Więc:

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

... to utrzymuje overiFrame na poziomie -1, gdy żadne ramki iframe nie są zawisłe lub ustawiony "bannerid" w zawijaniu div gdy ramka iframe jest zawieszona. Wszystko co musisz zrobić, to sprawdzić, czy 'overiFrame' jest ustawiony, gdy okno się rozmywa, w ten sposób: ...

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

Bardzo eleganckie rozwiązanie z drobnym minusem: jeśli użytkownik naciśnie ALT-F4 po najechaniu kursorem myszy na ramkę iFrame, zarejestruje ją jako kliknięcie. Stało się to tylko w Firefoksie, jednak IE, Chrome i Safari tego nie zarejestrowały.

Jeszcze raz dziękuję Mohammed, bardzo przydatne rozwiązanie!

 101
Author: patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-12 00:18:54

Jest to z pewnością możliwe. Działa to w Chrome, Firefox i IE 11 (i prawdopodobnie innych).

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

JSFiddle


Zastrzeżenie: wykrywa tylko pierwsze kliknięcie. Jak rozumiem, tylko tego chcesz.

 97
Author: Paul Draper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-13 11:51:30

Jest to małe rozwiązanie, które działa we wszystkich przeglądarkach, nawet IE8:

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

Możesz go przetestować tutaj: http://jsfiddle.net/oqjgzsm0/

 66
Author: Dmitry Kochin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 10:31:06

Poniższy kod pokaże ci, jeśli użytkownik kliknie / najedzie lub wyjdzie poza ramkę 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>

Musisz zastąpić src w ramce iframe własnym linkiem. Mam nadzieję, że to pomoże. Pozdrawiam, Mo.

 35
Author: Mohammed Radwan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-12 12:58:50

Właśnie znalazłem to rozwiązanie... Próbowałem, podobało mi się..

Działa na cross domain iframes dla komputerów stacjonarnych i mobilnych!

Nie wiem, czy to jest niezawodne jeszcze

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

Happy coding

 10
Author: Tony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 00:04:56

Można to osiągnąć za pomocą zdarzenia rozmycie na elemencie okna.

Oto wtyczka jQuery do śledzenia kliknięcia na iframes (uruchomi niestandardową funkcję zwrotną po kliknięciu iframe) : https://github.com/finalclap/iframeTracker-jquery

Użyj go tak:

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
 5
Author: Vince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-03 17:29:41

Zobacz http://jsfiddle.net/Lcy797h2 / dla mojego dlugiego rozwiazania ktore nie dziala niezawodnie w 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
Author: DiverseAndRemote.com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-30 16:37:18

Mohammed Radwan, Twoje rozwiązanie jest eleganckie. Aby wykryć kliknięcia iframe w Firefoksie i IE, możesz użyć prostej metody z dokumentem.activeElement i timer, jednak... Przeszukałem cały interwebs pod kątem metody wykrywania kliknięć na iframe w Chrome i Safari. U progu poddania się, znajduję Twoją odpowiedź. Dziękuję Panu!

Kilka porad: Odkryłem, że Twoje rozwiązanie jest bardziej niezawodne podczas bezpośredniego wywoływania funkcji init (), a nie poprzez attachOnloadEvent (). Z oczywiście aby to zrobić, musisz wywołać INIT () dopiero po iFrame html. Więc wyglądałoby to tak:

<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
Author: zone117x,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-12 17:57:31

Możesz to zrobić, aby dodać zdarzenia do dokumentu nadrzędnego:

$('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);
    });
});

Po prostu rozszerz listę wydarzeń o więcej wydarzeń.

 3
Author: Taner Topal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-08 12:46:00

Wpadłem na sytuację, w której musiałem śledzić kliknięcia przycisku mediów społecznościowych wciśniętego przez ramkę iframe. Nowe okno zostanie otwarte po kliknięciu przycisku. Oto moje rozwiązanie:

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
Author: pizza-r0b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-29 17:58:31

To działa dla mnie na wszystkich przeglądarkach (wliczając Firefoksa)

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
Author: sidanmor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-22 15:06:09

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

Po prostu utwórz niewidoczną warstwę nad ramką iframe, która powróci po kliknięciu i przejdzie w górę, gdy zdarzenie mouseleave zostanie wywołane !!
Need jQuery

To rozwiązanie nie propaguje pierwszego kliknięcia wewnątrz 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
Author: r1si,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 09:13:03

To zdecydowanie działa, jeśli ramka iframe pochodzi z tej samej domeny, co Twoja Strona nadrzędna. Nie testowałem go dla witryn między domenami.

$(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 */ });

Bez jQuery można spróbować czegoś takiego, ale znowu nie próbowałem tego.

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

Możesz nawet filtrować swoje wyniki:

$(window.frames['YouriFrameId']).mousedown(function(event){   
  var eventId = $(event.target).attr('id');      
  if (eventId == 'the-id-you-want') {
   //  do something
  }
});
 1
Author: Jonathan Tonge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-07 04:14:42

Wierzę, że możesz zrobić coś takiego:

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

Używanie jQuery do tego celu.

 0
Author: Daniel Sellers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 17:10:54

Jak tam znaleźć: wykrywanie Kliknięcia w Iframe przy użyciu JavaScript

= > Możemy użyć 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
Author: Mickaël,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-20 23:43:30

Bazując na odpowiedzi Paula Drapera, stworzyłem rozwiązanie, które działa nieprzerwanie, gdy masz Iframes, które otwierają inną kartę w przeglądarce. Po powrocie strona nadal będzie aktywna, aby wykryć kliknięcie na frameworku, jest to bardzo częsta sytuacja:

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

Kod jest prosty, Zdarzenie rozmycie wykrywa utratę ostrości po kliknięciu ramki iframe i sprawdza, czy aktywny element jest ramką iframe (jeśli masz kilka ramek iframe, możesz wiedzieć, kto został wybrany) często, gdy masz ramki reklamowe.

Drugie zdarzenie uruchamia metodę focus po powrocie do strony. służy do zdarzenia zmiany widoczności.

 0
Author: freedeveloper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-25 01:21:14

Oto rozwiązanie przy użyciu sugerowanych podejść z hover+blur i active element tricks, Nie żadnych bibliotek, tylko czysty js. Działa dobrze dla FF / Chrome. Przeważnie approach jest taki sam jak zaproponowany przez @Mohammeda Radwana, z tym, że używam innej metody zaproponowanej przez @zone117x do śledzenia kliknięć iframe dla FF, ponieważ okno.focus nie działa bez dodania ustawienia użytkownika :

Prosi o przeniesienie okna na front. Może się nie udać z powodu ustawienia użytkownika i okno nie jest gwarantowane przed ta metoda zwraca.

Oto metoda złożona:

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
Author: slesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 11:46:42