Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

JSFiddle


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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

Работает для перекрестных доменных iframe для рабочего стола и мобильных устройств!

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

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

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

Мохаммед Радван, Ваше решение элегантно. Чтобы обнаружить iframe-клики в Firefox и IE, вы можете использовать простой метод с document.activeElement и таймер, однако... Я искал по всем interwebs метод обнаружения кликов на 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>

Ответ 10

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

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

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

Ответ 11

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

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

Ответ 12

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

Ответ 13

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>

Ответ 14

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

Ответ 15

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

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

с помощью jQuery для выполнения этого.

Ответ 16

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

Ответ 17

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

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

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

Ответ 18

Вот решение, использующее предложенные подходы с 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;
            });
    }
}

Ответ 19

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

    var eventListener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('contentIFrame')) {
        toFunction(); //function you want to call on click
        setTimeout(function(){ window.focus(); }, 0);
    }
    window.removeEventListener('blur', eventListener );
    });