使用 JavaScript 检测对 Iframe 的点击

发布于 2024-08-23 10:32:35 字数 262 浏览 4 评论 0 原文

据我所知,如果是跨域,则无法判断用户在 iframe 内做什么。我想做的是跟踪用户是否在 iframe 中单击过。我想象一个场景,在 iframe 顶部有一个不可见的 div,并且 div 会将点击事件传递给 <代码> iframe

这样的事情可能吗?如果是的话,我该怎么办呢? iframe 是广告,因此我无法控制所使用的标签。

I understand that it is not possible to tell what the user is doing inside an iframe if it is cross domain. What I would like to do is track if the user clicked at all in the iframe. I imagine a scenario where there is an invisible div on top of the iframe and the the div will just then pass the click event to the iframe.

Is something like this possible? If it is, then how would I go about it? The iframes are ads, so I have no control over the tags that are used.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

烧了回忆取暖 2024-08-30 10:32:39

我和一位同事遇到了与 Brian Trumpsett 类似的问题,并发现该线程非常有帮助。
我们的信息亭在 iframe 内有动画,我们需要跟踪页面活动来设置计时器。

正如此处所建议的,我们现在不是跟踪点击,而是检测每次点击的焦点变化并将其改回来
以下代码在装有 Safari 和 Chrome 的 macOS 上运行正常,但不适用于 FireFox(为什么?):

var eventListener = window.addEventListener('blur', function() {
if (document.activeElement.classList && document.activeElement.classList[0] == 'contentiFrame') {
    refresh(); //function you want to call on click
            setTimeout(function(){ window.focus(); }, 1);
}
    window.removeEventListener('blur', eventListener );
});

问题是,在 Windows 上,它既不能与 Chrome 一起运行,也不能与 FireFox 一起运行,因此,我们的信息亭无法正常工作。
你知道为什么它不起作用吗?
您有办法让它在 Windows 上运行吗?

A colleague and I, we have a problem similar to that of Brian Trumpsett and found this thread very helpful.
Our kiosk has animations inside iframes and we need to track the page activity to set a timer.

As suggested here, rather than tracking the clicks, we now detect the focus change at each click and change it back
The following code is Okay on macOS with Safari and Chrome but does not work with FireFox (why?):

var eventListener = window.addEventListener('blur', function() {
if (document.activeElement.classList && document.activeElement.classList[0] == 'contentiFrame') {
    refresh(); //function you want to call on click
            setTimeout(function(){ window.focus(); }, 1);
}
    window.removeEventListener('blur', eventListener );
});

The problem is that, on Windows, it works neither with Chrome nor with FireFox and thus, our kiosk is not functional.
Do you know why it is not working ?
Do you have a solution to make it work on Windows ?

极度宠爱 2024-08-30 10:32:39

如发现:使用 JavaScript 检测对 Iframe 的点击

=>;我们可以使用 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');
    }
})

As found there : Detect Click into Iframe using JavaScript

=> We can use 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');
    }
})
请恋爱 2024-08-30 10:32:39

我的方法与上面 Paul Draper 提出的方法类似。但是,它在 Firefox 中不起作用,因为 activeElement 没有及时更新以供代码执行。所以我们稍等一下。

如果您使用 Tab 键进入 iframe,这也会触发。对于我的用例来说,这很好,但您可以过滤该按键。

addEventListenerOnIframe() {
    window.addEventListener('blur', this.onBlur);
}


onBlur = () => {
    setTimeout(() => {
        let activeElement = document.activeElement;
        let iframeElement = document.querySelector('iframe');
        if (activeElement === iframeElement) {
            
            //execute your code here

            //we only want to listen for the first time we click into the iframe
            window.removeEventListener('blur', this.onBlur);
        }
    }, 500);
};

My approach was similar to that proposed by Paul Draper above. However, it didn't work in Firefox because activeElement did not update in time for the code to execute. So we wait a little bit.

This will also fire if you tab into the iframe. For my use case, it's fine, but you could filter for that keypress.

addEventListenerOnIframe() {
    window.addEventListener('blur', this.onBlur);
}


onBlur = () => {
    setTimeout(() => {
        let activeElement = document.activeElement;
        let iframeElement = document.querySelector('iframe');
        if (activeElement === iframeElement) {
            
            //execute your code here

            //we only want to listen for the first time we click into the iframe
            window.removeEventListener('blur', this.onBlur);
        }
    }, 500);
};
聚集的泪 2024-08-30 10:32:39

我相信你可以这样做:

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

使用 jQuery 来完成这个任务。

I believe you can do something like:

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

using jQuery to accomplish this.

败给现实 2024-08-30 10:32:38

以下代码将显示用户是否单击/悬停或移出 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>

您需要将 iframe 中的 src 替换为您自己的链接。希望这会有所帮助。
问候,
莫。

The following code will show you if the user click/hover or move out of the 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>

You need to replace the src in the iframe with your own link. Hope this'll help.
Regards,
Mo.

站稳脚跟 2024-08-30 10:32:38

刚刚找到这个解决方案...
我尝试过,我喜欢它..

适用于桌面和移动设备的跨域 iframe!

不知道是否万无一失

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

快乐编码

Just found this solution...
I tried it, I loved it..

Works for cross domain iframes for desktop and mobile!

Don't know if it is foolproof yet

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

Happy coding

冷默言语 2024-08-30 10:32:38

您可以通过使用窗口元素上的模糊事件来实现此目的。

这是一个用于跟踪 iframe 上点击的 jQuery 插件(当点击 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)
        }
    });
});

You can achieve this by using the blur event on window element.

Here is a jQuery plugin for tracking click on iframes (it will fire a custom callback function when an iframe is clicked) :
https://github.com/finalclap/iframeTracker-jquery

Use it like this :

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
南冥有猫 2024-08-30 10:32:38

请参阅 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();

see http://jsfiddle.net/Lcy797h2/ for my long winded solution that doesn't work reliably in 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();
第几種人 2024-08-30 10:32:38

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>

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

Just make a invisible layer over the iframe that go back when click and go up when mouseleave event will be fired !!
Need jQuery

this solution don't propagate first click inside 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>

慕巷 2024-08-30 10:32:38

这适用于所有浏览器(包括 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>

This works for me on all browsers (included 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>

一生独一 2024-08-30 10:32:38

将上述答案与一次又一次单击的能力相结合,而无需单击外部 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 );
    });

Combining above answer with ability to click again and again without clicking outside 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 );
    });
浅笑依然 2024-08-30 10:32:38

穆罕默德·拉德万,
你的解决方案很优雅。要检测 Firefox 和 IE 中的 iframe 点击,您可以使用带有 document.activeElement 和计时器的简单方法,但是...我在互联网上搜索了一种检测 Chrome 和 Safari 中 iframe 点击的方法。在放弃的边缘,我找到了你的答案。谢谢您,先生!

一些提示:
我发现直接调用 init() 函数(而不是通过 AttachOnloadEvent())时您的解决方案更可靠。当然,要做到这一点,您必须仅在 iframe html 之后调用 init() 。所以它看起来像:

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

Mohammed Radwan,
Your solution is elegant. To detect iframe clicks in Firefox and IE, you can use a simple method with document.activeElement and a timer, however... I have searched all over the interwebs for a method to detect clicks on an iframe in Chrome and Safari. At the brink of giving up, I find your answer. Thank you, sir!

Some tips:
I have found your solution to be more reliable when calling the init() function directly, rather than through attachOnloadEvent(). Of course to do that, you must call init() only after the iframe html. So it would look something like:

<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>
无可置疑 2024-08-30 10:32:38

您可以执行此操作,将事件冒泡到父文档:

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

只需扩展事件列表以获取更多事件。

You can do this to bubble events to parent document:

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

Just extend the eventlist for more events.

绅士风度i 2024-08-30 10:32:38

我遇到了一种情况,我必须跟踪通过 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();

I ran into a situation where I had to track clicks on a social media button pulled in through an iframe. A new window would be opened when the button was clicked. Here was my solution:

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();
极度宠爱 2024-08-30 10:32:38

如果 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
  }
});

This definitely works if the iframe is from the same domain as your parent site. I have not tested it for cross-domain sites.

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

Without jQuery you could try something like this, but again I have not tried this.

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

You can even filter your results:

$(window.frames['YouriFrameId']).mousedown(function(event){   
  var eventId = $(event.target).attr('id');      
  if (eventId == 'the-id-you-want') {
   //  do something
  }
});
心安伴我暖 2024-08-30 10:32:38

我们可以捕获所有的点击。这个想法是在每次点击后重置 iFrame 外部元素的焦点:

    <input type="text" style="position:fixed;top:-1000px;left:-1000px">
    <div id="message"></div>
    <iframe id="iframe" src="//example.com"></iframe>
    <script>
        focus();
        addEventListener('blur', function() {
            if(document.activeElement = document.getElementById('iframe')) {
                message.innerHTML += 'Clicked';
                setTimeout(function () {
                    document.querySelector("input").focus();
                    message.innerHTML += ' - Reset focus,';
                }, 1000);
            }  
        });
    </script>

JSFiddle

We can catch all the clicks. The idea is to reset focus on an element outside the iFrame after each click:

    <input type="text" style="position:fixed;top:-1000px;left:-1000px">
    <div id="message"></div>
    <iframe id="iframe" src="//example.com"></iframe>
    <script>
        focus();
        addEventListener('blur', function() {
            if(document.activeElement = document.getElementById('iframe')) {
                message.innerHTML += 'Clicked';
                setTimeout(function () {
                    document.querySelector("input").focus();
                    message.innerHTML += ' - Reset focus,';
                }, 1000);
            }  
        });
    </script>

JSFiddle

慕巷 2024-08-30 10:32:38

假设 -

  1. 您的脚本在 iframe 外部运行,但不在最外面的 window.top 窗口中运行。 (对于最外面的窗口,其他模糊解决方案就足够了)
  2. 打开一个新页面,替换当前页面/新选项卡中的新页面,并将控件切换到新选项卡。

这适用于有源和无源 iframe

var ifr = document.getElementById("my-iframe");
var isMouseIn;
ifr.addEventListener('mouseenter', () => {
    isMouseIn = true;
});
ifr.addEventListener('mouseleave', () => {
    isMouseIn = false;
});
window.document.addEventListener("visibilitychange", () => {
    if (isMouseIn && document.hidden) {
        console.log("Click Recorded By Visibility Change");
    }
});
window.addEventListener("beforeunload", (event) => {
    if (isMouseIn) {
        console.log("Click Recorded By Before Unload");
    }
});

如果打开新选项卡/卸载同一页面并且鼠标指针位于 iframe 内,则视为单击

Assumptions -

  1. Your script runs outside the iframe BUT NOT in the outermost window.top window. (For outermost window, other blur solutions are good enough)
  2. A new page is opened replacing the current page / a new page in a new tab and control is switched to new tab.

This works for both sourceful and sourceless iframes

var ifr = document.getElementById("my-iframe");
var isMouseIn;
ifr.addEventListener('mouseenter', () => {
    isMouseIn = true;
});
ifr.addEventListener('mouseleave', () => {
    isMouseIn = false;
});
window.document.addEventListener("visibilitychange", () => {
    if (isMouseIn && document.hidden) {
        console.log("Click Recorded By Visibility Change");
    }
});
window.addEventListener("beforeunload", (event) => {
    if (isMouseIn) {
        console.log("Click Recorded By Before Unload");
    }
});

If a new tab is opened / same page unloads and the mouse pointer is within the Iframe, a click is considered

总以为 2024-08-30 10:32:38

根据 Paul Draper 的回答,我创建了一个解决方案,当您拥有在浏览器中打开其他选项卡的 Iframe 时,该解决方案可以连续工作。当你返回页面继续处于活动状态时检测框架上的点击,这是一种很常见的情况:

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

代码很简单,blur 事件检测 iframe 被点击时失去焦点,并测试活动元素是否为iframe(如果您有多个 iframe,您可以知道谁被选中)当您有宣传框架时,这种情况经常发生。

当您返回页面时,第二个事件会触发 focus 方法。它用于可见性更改事件。

Based in the answer of Paul Draper, I created a solution that work continuously when you have Iframes that open other tab in the browser. When you return the page continue to be active to detect the click over the framework, this is a very common situation:

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

The Code is simple, the blur event detect the lost of focus when the iframe is clicked, and test if the active element is the iframe (if you have several iframe you can know who was selected) this situation is frequently when you have publicity frames.

The second event trigger a focus method when you return to the page. it is used the visibility change event.

一绘本一梦想 2024-08-30 10:32:38

这是使用悬停+模糊和活动元素技巧的建议方法的解决方案,没有任何库,只是纯js。适用于 FF/Chrome。大多数方法与 @Mohammed Radwan 提出的方法相同,只是我使用 @zone117x 提出的不同方法来跟踪 FF 的 iframe 点击,因为如果没有添加 window.focus 就无法工作。 //developer.mozilla.org/en-US/docs/Web/API/Window/focus" rel="nofollow noreferrer">用户设置

发出将窗口置于前面的请求。它可能会失败,因为
用户设置和窗口之前不能保证位于最前面
该方法返回。

这是复合方法:

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

Here is solution using suggested approaches with hover+blur and active element tricks, not any libraries, just pure js. Works fine for FF/Chrome. Mostly approache is same as @Mohammed Radwan proposed, except that I use different method proposed by @zone117x to track iframe click for FF, because window.focus is not working without addition user settings:

Makes a request to bring the window to the front. It may fail due to
user settings and the window isn't guaranteed to be frontmost before
this method returns.

Here is compound method:

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;
            });
    }
}
若沐 2024-08-30 10:32:37

这当然是可能的。这适用于 Chrome、Firefox 和 IE 11(可能还有其他版本)。

const message = document.getElementById("message");

// main document must be focused in order for window blur to fire when the iframe is interacted with. 
// There's still an issue that if user interacts outside of the page and then click iframe first without clicking page, the following logic won't run. But since the OP is only concerned about first click this shouldn't be a problem.
window.focus()

window.addEventListener("blur", () => {
  setTimeout(() => {
    if (document.activeElement.tagName === "IFRAME") {
      message.textContent = "clicked " + Date.now();
      console.log("clicked");
    }
  });
}, { once: true });
<div id="message"></div>
<iframe width="50%" height="300" src="//example.com"></iframe>

警告:这仅检测第一次点击。据我了解,这就是你想要的。

This is certainly possible. This works in Chrome, Firefox, and IE 11 (and probably others).

const message = document.getElementById("message");

// main document must be focused in order for window blur to fire when the iframe is interacted with. 
// There's still an issue that if user interacts outside of the page and then click iframe first without clicking page, the following logic won't run. But since the OP is only concerned about first click this shouldn't be a problem.
window.focus()

window.addEventListener("blur", () => {
  setTimeout(() => {
    if (document.activeElement.tagName === "IFRAME") {
      message.textContent = "clicked " + Date.now();
      console.log("clicked");
    }
  });
}, { once: true });
<div id="message"></div>
<iframe width="50%" height="300" src="//example.com"></iframe>

Caveat: This only detects the first click. As I understand, that is all you want.

忆伤 2024-08-30 10:32:37

这是一个适用于所有浏览器甚至 IE8 的小解决方案:

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

您可以在这里测试它:http://jsfiddle.net/oqjgzsm0/

This is small solution that works in all browsers even IE8:

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

You can test it here: http://jsfiddle.net/oqjgzsm0/

内心荒芜 2024-08-30 10:32:37

根据 Mohammed Radwan 的回答,我想出了以下 jQuery 解决方案。基本上它的作用是跟踪 iFrame 人们悬停的内容。然后,如果窗口模糊,则很可能意味着用户单击了 iframe 横幅。

iframe 应该放在带有 id 的 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
    });

...
当没有 iFrame 悬停时,这会将 overiFrame 保持为 -1,或者当 iframe 悬停时,在包装 div 中设置“bannerid”。您所要做的就是检查窗口模糊时是否设置了“overiFrame”,如下所示:
...

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

非常优雅的解决方案,但有一个小缺点:如果用户在将鼠标悬停在 iFrame 上时按下 ALT-F4,它会将其记录为单击。不过这只发生在 FireFox 中,IE、Chrome 和 Safari 没有注册它。

再次感谢穆罕默德,非常有用的解决方案!

Based on Mohammed Radwan's answer I came up with the following jQuery solution. Basically what it does is keep track of what iFrame people are hovering. Then if the window blurs that most likely means the user clicked the iframe banner.

the iframe should be put in a div with an id, to make sure you know which iframe the user clicked on:

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

so:

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

...
this keeps overiFrame at -1 when no iFrames are hovered, or the 'bannerid' set in the wrapping div when an iframe is hovered. All you have to do is check if 'overiFrame' is set when the window blurs, like so:
...

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

Very elegant solution with a minor downside: if a user presses ALT-F4 when hovering the mouse over an iFrame it will log it as a click. This only happened in FireFox though, IE, Chrome and Safari didn't register it.

Thanks again Mohammed, very useful solution!

筱武穆 2024-08-30 10:32:37

这样的事情可能吗?

不。您所能做的就是检测鼠标进入 iframe,并可能(尽管不可靠)检测鼠标何时返回(即尝试找出在其他地方经过广告的指针与停留在广告上的指针之间的区别)在广告上)。

我想象一个场景,iframe 顶部有一个不可见的 div,然后该 div 会将点击事件传递给 iframe。

不,没有办法伪造点击事件。

通过捕获 mousedown,您可以防止原始点击到达 iframe。如果您可以确定鼠标按钮何时将被按下,您可以尝试将不可见的 div 移开,以便单击能够通过...但是在鼠标按下之前也不会触发任何事件。

您可以尝试猜测,例如查看指针是否静止,猜测可能即将发出咔嗒声。但这是完全不可靠的,如果你失败了,你就失去了点击率。

Is something like this possible?

No. All you can do is detect the mouse going into the iframe, and potentially (though not reliably) when it comes back out (ie. trying to work out the difference between the pointer passing over the ad on its way somewhere else versus lingering on the ad).

I imagine a scenario where there is an invisible div on top of the iframe and the the div will just then pass the click event to the iframe.

Nope, there is no way to fake a click event.

By catching the mousedown you'd prevent the original click from getting to the iframe. If you could determine when the mouse button was about to be pressed you could try to get the invisible div out of the way so that the click would go through... but there is also no event that fires just before a mousedown.

You could try to guess, for example by looking to see if the pointer has come to rest, guessing a click might be about to come. But it's totally unreliable, and if you fail you've just lost yourself a click-through.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文