Обнаружение щелчка в Iframe с помощью JavaScript

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

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

18 ответов


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

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

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

нет, нет способа подделать событие click.

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

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


основываясь на ответе Мохаммеда Радвана, я придумал следующее решение 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 не зарегистрировали его.

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


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

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

JSFiddle


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


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

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

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


следующий код покажет вам, если пользователь нажмет / наведет курсор или выйдет из 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>

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


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

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

Не знаю, является ли он надежным еще

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

удачи в кодировании


вы можете достичь этого, используя событие размытия в элементе window.

вот плагин jQuery для отслеживания нажатия на iframes (он будет запускать пользовательскую функцию обратного вызова при нажатии 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)
        }
    });
});

см.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();

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

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

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

вы можете сделать это, чтобы пузырь события родительского документа:

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

просто продлить eventlist для нескольких событий.


я столкнулся с ситуацией, когда мне пришлось отслеживать клики по кнопке социальных сетей, втянутой через iframe. При нажатии на кнопку откроется новое окно. Вот мое решение:--2-->

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

это работает для меня во всех браузерах (включая 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>


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

просто сделайте невидимый слой над iframe, который возвращается при нажатии и поднимается, когда mouseleave событие будет уволен !!
Необходим jQuery

это решение не распространяется первым щелчком мыши внутри 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>

Это определенно работает, если iframe из того же домена, что и ваш родительский сайт. Я не тестировал его для междоменных сайтов.

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

без jQuery вы можете попробовать что-то вроде этого, но снова я не пробовал это.

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

вы даже можете фильтровать результаты:

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

Я считаю, что вы можете сделать что-то вроде:

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

использование jQuery для этого.


Как там нашел : обнаружение щелчка в Iframe с помощью JavaScript

=> мы можем использовать 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');
    }
})

основываясь на ответе пола Дрейпера, я создал решение, которое работает непрерывно, когда у вас есть Iframes, которые открывают другую вкладку в браузере. Когда вы возвращаете страницу, продолжайте быть активными, чтобы обнаружить щелчок по фреймворку, это очень распространенная ситуация:

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

код прост, событие размытия обнаруживает потерю фокуса при нажатии iframe и проверяет, является ли активный элемент iframe (если у вас есть несколько iframe, вы можете знать, кто был выбран) это ситуация часто возникает, когда у вас есть рекламные рамки.

второе событие запускает метод фокуса при возвращении на страницу. используется событие изменения видимости.


вот решение, использующее предлагаемые подходы с помощью hover+blur и трюков с активными элементами, а не библиотек, просто чистый js. Отлично работает для FF / Chrome. В основном подход такой же, как @Mohammed Radwan, за исключением того, что я использую другой метод, предложенный @zone117x для отслеживания iframe click for FF, потому что