使用 JavaScript 检测点击进入框架

我明白,它是不可能告诉什么用户正在做一个 iframe内,如果它是跨域。我想做的是跟踪如果用户点击在所有的 iframe。我想象一个场景,有一个不可见的 div上的 iframediv将只是然后通过点击事件的 iframe

这种事有可能吗?如果是的话,我该怎么做?iframes是广告,所以我对使用的标签没有控制权。

237582 次浏览

这种事有可能吗?

没有。您所能做的就是检测进入 iframe 的鼠标,以及可能(尽管不可靠)出来的鼠标(即。试图找出指针在其他地方经过广告和在广告上停留的区别)。

我想象一个场景,在 iframe 顶部有一个不可见的 div,这个 div 会将 click 事件传递给 iframe。

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

通过捕捉鼠标,可以防止原始的点击进入 iframe。如果你能确定鼠标按钮是什么时候被按下的,你可以试着去掉不可见的 div,这样点击就可以通过了... ... 但是在鼠标点下之前也没有触发任何事件。

您可以尝试猜测,例如通过查看指针是否已停止,猜测可能即将发生单击。但它完全不可靠,如果你失败了,你只是失去了自己的点击通过。

下面的代码将显示用户是否单击/悬停或移出 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 替换为您自己的链接。 问候, 莫。

穆罕默德 · 拉德万, 你的解决方案很优雅。要检测 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>

我相信你可以这样做:

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

使用 jQuery 来实现这一点。

基于 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 都没有注册。

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

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

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

可以通过使用 window 元素上的模糊事件来实现这一点。

下面是一个 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)
}
});
});

您可以这样将事件冒泡到父文档:

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

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

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

这当然是可能的,可以在 Chrome、 Firefox 和 IE11(可能还有其他浏览器)中使用。

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>

警告: 这只检测第一次点击。据我所知,这就是你想要的。

找到了解决办法。 我试过了,我很喜欢。

为桌面和移动设备的跨域 iframe 工作!

还不知道是不是万无一失

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

编程愉快

这是一个小型的解决方案,可以在所有浏览器中工作,甚至是 IE8:

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

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

这对我在所有浏览器(包括 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>

就像发现的那样: 使用 JavaScript 检测点击进入框架

= > 我们可以使用 IframeTracker-jquery:

$('.carousel-inner .item').each(function(e) {
var item = this;
var iFrame = $(item).find('iframe');
if (iFrame.length &gt; 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 =&gt; OK');
}
});
console.log('IFrameTrackingRegistred =&gt; OK');
}
})

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

代码是简单的,模糊事件检测失去焦点时,iframe 被点击,并测试如果活动元素是 iframe (如果你有几个 iframe 你可以知道谁被选中)这种情况是经常当你有宣传框。

第二个事件在您返回页面时触发一个焦点方法。它用于可见性更改事件。

下面是使用建议的悬停 + 模糊和活动元素技巧的解决方案,不使用任何库,只使用纯 js。适用于 FF/Chrome。大多数方法与@Mohammed Radwan 提出的方法相同,只是我使用@zone117x 提出的不同方法来跟踪 FF 的 iframe click,因为如果没有添加 用户设置窗户,集中注意力就无法工作:

请求将窗户放在前面 用户设置和窗口之前不能保证是最前面的 此方法返回。

下面是复合方法:

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

结合以上答案的能力,点击一次又一次,而不点击外部 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 );
});

我们可以捕捉到所有的点击。这个想法是在每次点击后,将焦点重新放在 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

假设 -

  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 中,则会考虑单击

我和一个同事遇到了一个类似于 Brian Trumpsett 的问题,我们发现这个帖子非常有帮助。 我们的信息亭在 iframe 中有动画,我们需要跟踪页面活动来设置计时器。

正如这里建议的那样,我们现在不再跟踪点击,而是检测每次点击时焦点的变化,并将其变回原来的样子 下面的代码可以用于 Safari 和 Chrome 操作系统,但是不能用于 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 上工作吗?

我的方法与上面保罗•德雷珀(Paul Draper)提出的方法相似。但是,它不能在 Firefox 中工作,因为 activeElement 没有及时更新以便代码执行。所以我们再等一会儿。

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