it-swarm.com.ru

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

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

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

103
Russ Bradberry

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

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

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

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

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

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

36
bobince

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

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

JSFiddle


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

116
Paul Draper

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

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

103
patrick

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

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

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

71
Dmitry Kochin

Следующий код покажет вам, если пользователь нажимает/наводит курсор или выходит из 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 своей собственной ссылкой. Надеюсь, что это поможет . С уважением, __. Мо.

35
Mohammed Radwan

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

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

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

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

Удачного кодирования

10
Tony

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

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

Вот плагин 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
Vince

Мохаммед Радван, Ваше решение элегантно. Чтобы обнаружить клики 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>
3
zone117x

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

3
sidanmor

Я столкнулся с ситуацией, когда мне приходилось отслеживать клики на кнопках социальных сетей, вставленных через фрейм. Новое окно будет открыто при нажатии кнопки. Вот мое решение:

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

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

$('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
Taner Topal

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>

2
r1si

Это определенно работает, если 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
  }
});
1
Jonathan Tonge

Как найдено там: Обнаружить клик в 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');
    }
})
0
Mickaël

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

Делает запрос, чтобы вывести окно на передний план. Может произойти сбой из-за Пользовательские настройки и окно не гарантированно будут самыми передними этот метод возвращает.

Вот сложный метод:

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

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

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

используя jQuery для достижения этой цели.

0
Daniel Sellers

Основываясь на ответе Пола Дрейпера, я создал решение, которое работает непрерывно, когда у вас есть 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, вы можете знать, кто был выбран), такая ситуация часто возникает, когда у вас есть рекламные кадры. ,.

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

0
freedeveloper