Обнаружение клика в Iframe с использованием JavaScript - PullRequest
111 голосов
/ 04 марта 2010

Я понимаю, что невозможно сказать, что пользователь делает внутри iframe, если он междоменный. Я хотел бы отследить, нажал ли пользователь вообще на iframe. Я представляю себе сценарий, в котором наверху iframe есть невидимый div, и div просто передаст событие click на iframe.

Возможно ли что-то подобное? Если это так, то как бы я поступил об этом? iframes - это объявления, поэтому я не могу контролировать используемые теги.

Ответы [ 18 ]

127 голосов
/ 23 апреля 2014

Это, конечно, возможно. Это работает в Chrome, Firefox и IE 11 (и, возможно, в других).

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

JSFiddle


Предупреждение: это обнаруживает только первый щелчок. Как я понимаю, это все, что вы хотите.

106 голосов
/ 12 ноября 2011

Основываясь на ответе Мохаммеда Радвана, я нашел следующее решение jQuery. По сути, он отслеживает то, что парят люди в iFrame. Затем, если окно размывается, это, скорее всего, означает, что пользователь нажал на баннер iframe.

iframe должен быть помещен в div с идентификатором, чтобы убедиться, что вы знаете, на какой iframe пользователь нажал:

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

так:

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

... это сохраняет overiFrame в -1, когда iFrames не наведены, или «bannerid», установленный в div обтекания при наведении iframe. Все, что вам нужно сделать, это проверить, установлен ли «overiFrame», когда окно размывается, вот так: ...

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

Очень элегантное решение с небольшим недостатком: если пользователь нажимает ALT-F4 при наведении курсора мыши на iFrame, он регистрирует его как щелчок. Это произошло только в FireFox, хотя IE, Chrome и Safari не зарегистрировали его.

Еще раз спасибо, Мухаммед, очень полезное решение!

72 голосов
/ 21 августа 2015

Это небольшое решение, которое работает во всех браузерах, даже в IE8:

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

Вы можете проверить это здесь: http://jsfiddle.net/oqjgzsm0/

36 голосов
/ 04 марта 2010

Возможно ли что-то подобное?

Нет.Все, что вы можете сделать, это обнаружить мышь, входящую в iframe, и, возможно, (хотя и ненадежно), когда она возвращается (т. Е. Пытается определить разницу между указателем, проходящим над рекламой на пути куда-то еще, и задерживающимся наad).

Я представляю себе сценарий, в котором наверху iframe находится невидимый div, и div просто передает событие click в iframe.

Нет, нет способа подделать событие щелчка.

Улавливая mousedown, вы предотвратите попадание исходного клика в iframe.Если бы вы могли определить, когда должна была быть нажата кнопка мыши, вы могли бы попытаться убрать невидимый элемент div, чтобы щелчок прошел ... но также не происходит событие, которое срабатывает непосредственно перед mousedown.

Вы можете попытаться угадать, например, посмотрев, остановился ли указатель, предположив, что может произойти щелчок.Но это совершенно ненадежно, и если вы терпите неудачу, вы просто теряете клик.

35 голосов
/ 13 июня 2010

Следующий код покажет вам, если пользователь нажимает / наводит курсор или выходит из фрейма: -

<!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>

Вам необходимо заменить src в iframe своей собственной ссылкой. Надеюсь, это поможет. С Уважением, Мо

10 голосов
/ 18 июня 2015

Только что нашел это решение ... Я попробовал, мне понравилось ..

Работает для междоменных фреймов для ПК и мобильных устройств!

Не знаю, надежно ли это еще

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

Счастливое кодирование

5 голосов
/ 03 апреля 2013

Этого можно добиться с помощью события размытия в элементе окна.

Вот плагин jQuery для отслеживания кликов по iframe (при нажатии на iframe он запускает пользовательскую функцию обратного вызова): https://github.com/finalclap/iframeTracker-jquery

Используйте это так:

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
5 голосов
/ 15 февраля 2013

см. http://jsfiddle.net/Lcy797h2/ для моего давно сложенного решения, которое не работает надежно в 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();
3 голосов
/ 08 апреля 2013

Вы можете сделать это для отправки событий родительскому документу:

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

Просто добавьте список событий для других событий.

3 голосов
/ 12 июня 2011

Мохаммед Радван, Ваше решение элегантно. Чтобы обнаружить клики iframe в Firefox и IE, вы можете использовать простой метод с document.activeElement и таймером, однако ... Я искал во всех интервалах метод обнаружения кликов на iframe в Chrome и Safari. На грани отказа, я нахожу ваш ответ. Спасибо, сэр!

Некоторые советы: Я нашел ваше решение более надежным при непосредственном вызове функции init (), а не через attachOnloadEvent (). Конечно, чтобы сделать это, вы должны вызывать init () только после HTML-кода iframe. Так это будет выглядеть примерно так:

<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>
...