据我所知,如果用户是跨域,则无法告知用户在iframe
内做了什么。我想要做的是跟踪用户是否在iframe
中完全点击了。我想象一个场景,div
顶部有一个不可见的iframe
,而div
只会将点击事件传递给iframe
。
这样的事情可能吗?如果是,那我该怎么办呢? iframes
是广告,因此我无法控制所使用的代码。
答案 0 :(得分:123)
这当然是可能的。这适用于Chrome,Firefox和IE 11(可能还有其他)。
focus();
var listener = window.addEventListener('blur', function() {
if (document.activeElement === document.getElementById('iframe')) {
// clicked
}
window.removeEventListener('blur', listener);
});
警告:这只会检测到第一次点击。据我了解,这就是你想要的一切。
答案 1 :(得分:105)
根据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悬停时,将“bannerid”设置在包装div中。你需要做的就是检查当窗口模糊时是否设置了'overiFrame',如下所示: ...
$(window).blur( function() {
if( overiFrame != -1 )
$.post('log.php', {id:overiFrame}); /* example, do your stats here */
});
});
非常优雅的解决方案,有一个小缺点:如果用户将鼠标悬停在iFrame上时按下ALT-F4,它会将其记录为单击。这只发生在FireFox中,IE,Chrome和Safari没有注册。
再次感谢穆罕默德,非常有用的解决方案!
答案 2 :(得分:72)
这是一个小型解决方案,适用于所有浏览器,甚至IE8:
var monitor = setInterval(function(){
var elem = document.activeElement;
if(elem && elem.tagName == 'IFRAME'){
clearInterval(monitor);
alert('clicked!');
}
}, 100);
您可以在此处进行测试:http://jsfiddle.net/oqjgzsm0/
答案 3 :(得分:35)
以下代码将显示用户是否单击/悬停或移出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。希望这会有所帮助。 问候, 沫。
答案 4 :(得分:34)
这样的事情可能吗?
没有。所有你能做的就是检测进入iframe的鼠标,并且当它返回时可能(虽然不可靠)(即试图找出在其他地方传递广告的指针与在广告)。
我想象一个场景,iframe顶部有一个不可见的div,然后div会将click事件传递给iframe。
不,没有办法伪造点击事件。
通过捕捉mousedown,您可以阻止原始点击进入iframe。如果您可以确定何时按下鼠标按钮,您可以尝试将不可见的div放在一边,这样点击就可以通过......但是在mousedown之前也没有事件会发生。
您可以尝试猜测,例如通过查看指针是否已经停止,猜测点击可能即将到来。但它完全不可靠,如果你失败了,你就会失去一次点击。
答案 5 :(得分:10)
刚刚找到这个解决方案...... 我试过了,我喜欢它..
适用于桌面和移动设备的跨域iframe!
不知道它是否万无一失
window.addEventListener('blur',function(){
if(document.activeElement.id == 'CrossDomainiframeId'){
//do something :-)
}
});
快乐编码
答案 6 :(得分:5)
您可以通过在窗口元素上使用blur事件来实现此目的。
这是一个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)
}
});
});
答案 7 :(得分:5)
请参阅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 :(得分:3)
这适用于所有浏览器(包括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>
答案 9 :(得分:3)
一些提示: 我发现你的解决方案在直接调用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>
答案 10 :(得分:3)
我遇到了一种情况,我必须跟踪通过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();
答案 11 :(得分:3)
您可以执行此操作以将事件冒泡到父文档:
$('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);
});
});
只需为更多活动扩展活动列表。
答案 12 :(得分:2)
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);
});
&#13;
iframe {
width: 500px;
height: 300px;
}
#invisible_layer{
position: absolute;
background-color:trasparent;
width: 500px;
height:300px;
}
&#13;
<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>
&#13;
答案 13 :(得分:1)
如果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
}
});
答案 14 :(得分:1)
将以上答案与无需在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 );
});
答案 15 :(得分:1)
我们可以捕获所有点击。这样做的目的是在每次单击后将焦点重新放在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>
答案 16 :(得分:0)
我相信你可以这样做:
$('iframe').contents().click(function(){function to record click here });
使用jQuery来实现这一目标。
答案 17 :(得分:0)
在那里找到:Detect Click into Iframe using JavaScript
=&GT;我们可以使用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');
}
})
答案 18 :(得分:0)
基于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,则可以知道选择了谁),这种情况在您经常出现时有宣传框架。
当您返回页面时,第二个事件触发了一个聚焦方法。用于可见性更改事件。
答案 19 :(得分:0)
这里是使用带有悬停+模糊和活动元素技巧的建议方法的解决方案,而不是任何库,仅是纯js。适用于FF / Chrome。除我使用@ zone117x提出的不同方法来跟踪FF的iframe点击外,大多数方法与@Mohammed Radwan提出的方法相同,因为 window.focus 在没有添加user settings的情况下无法正常工作:< / p>
请求将窗口移到最前面。可能由于以下原因而失败 用户设置,并且不能保证窗口位于最前面 此方法返回。
这是复合方法:
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;
});
}
}
答案 20 :(得分:0)
假设-
这同时适用于有源和无源 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中,则认为是单击
答案 21 :(得分:0)
我和一位同事,我们遇到了与 Brian Trumpsett 类似的问题,并且发现此线程非常有帮助。 我们的信息亭在 iframe 中有动画,我们需要跟踪页面活动以设置计时器。
正如这里所建议的,我们现在不是跟踪点击次数,而是检测每次点击时的焦点变化并将其改回来 以下代码在 macOS 上可以使用 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 上运行吗?
答案 22 :(得分:0)
我的方法类似于上面 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);
};