如何使用JQuery为iframe添加点击事件

59

我在页面上有一个来自第三方(广告)的iframe。当iframe被点击时,我想触发一个点击事件(以记录一些内部统计信息)。类似于:

$('#iframe_id').click(function() {
    //run function that records clicks
});

根据以下HTML内容:

<iframe id="iframe_id" src="http://something.com"></iframe>

我似乎无法让这个的任何变体起作用。 有什么想法吗?

13个回答

40

虽然 iframe 没有 'onclick' 事件,但是你可以尝试捕获 iframe 内文档的点击事件:

document.getElementById("iframe_id").contentWindow.document.body.onclick = 
function() {
  alert("iframe clicked");
}

编辑 尽管这并不能解决您的跨站问题,但是请注意jQuery已经更新以与iFrames良好协作。


虽然这不能解决您的跨站问题,但请注意 jQuery 已更新以更好地使用 iFrames。

$('#iframe_id').on('click', function(event) { });

更新1/2015 由于该链接已不再可用,因此已移除有关iframe解释的链接。

注意 如果iframe来自于与宿主页面不同的域,上述代码将无法工作。您仍然可以尝试使用评论中提到的一些技巧。


2
谢谢,这个很好用,但只适用于来自我的域的内容。如果我尝试加载来自另一个域的第三方内容,则单击事件不会触发。我在网上遇到了一些其他帖子,提到了类似的问题...基本上,您可以玩弄iframe内容,但前提是它是您自己的。我肯定只会处理第三方内容。嗯,还有其他想法吗? - Justin Lucente
6
可以的。尝试在iframe上面放一个透明的div(使用position:absolute)。这样,您就可以捕获该div上的点击事件。不要忘记将它们传递到iframe中(仅适用于简单的iframe内容 - 如果它包含自己的事件处理程序,请勿使用此方法)。 - Traveling Tech Guy
没问题 - 这就是我们在这里的原因 :) 很抱歉它没有成功。 - Traveling Tech Guy
1
Archive.org 是我们的朋友。;^) 博客存档链接 - ruffin
@TravelingTechGuy,您没有提及如何将点击事件传递到iframe。据我所知,pointer-events: none会阻止在透明div上触发点击事件,使透明div变得无意义,因此我不知道如何在iframe和透明div上同时触发事件。 - RaisinBranCrunch
显示剩余4条评论

19

我试图寻找一个更独立的答案,于是开始思考jQuery如何处理事件和自定义事件。由于click(来自jQuery)只是任何事件,我认为我所要做的就是在iframe的内容被点击时触发该事件。因此,这是我的解决方案。

$(document).ready(function () {
    $("iframe").each(function () {
        //Using closures to capture each one
        var iframe = $(this);
        iframe.on("load", function () { //Make sure it is fully loaded
            iframe.contents().click(function (event) {
                iframe.trigger("click");
            });
        });

        iframe.click(function () {
            //Handle what you need it to do
        });
    });
});

5
只有当框架包含来自相同域的页面时才起作用(不违反同源策略)。 - Gurmeet Singh

16

尝试使用这个:iframeTracker jQuery插件,像这样:

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});

1
唯一让我能够捕捉到嵌入的YouTube iframe点击事件的方法。谢谢! - s.webbandit

9

仅当框架包含来自相同域的页面时才有效(不违反同源策略)

请参见:

var iframe = $('#your_iframe').contents();

iframe.find('your_clicable_item').click(function(event){
   console.log('work fine');
});

为了帮助 OP 解决当前的问题,可以在回答中添加一些解释说明。 - ρяσѕρєя K
将“your_clicable_item”更改为“body”,这就是完美的答案。 - geegee
4
仅当框架包含来自相同域的页面时才有效(不违反同源策略)。 - Gurmeet Singh
1
这对我有用,但我不得不将它放在一个函数中,然后在DOM加载和iFrame加载后调用它。感谢@jhonatan2760。 - Eric Milliot-Martinez

7

您可以通过以下方式模拟聚焦/点击事件。 (改编自$(window).blur event affecting Iframe

$(window).blur(function () {
  // check focus
  if ($('iframe').is(':focus')) {
    console.log("iframe focused");
    $(document.activeElement).trigger("focus");// Could trigger click event instead
  }
  else {
    console.log("iframe unfocused");
  }                
});

//Test
$('#iframe_id').on('focus', function(e){
  console.log(e);
  console.log("hello im focused");
})


1
我成功地通过将“焦点”切换到“点击”来停止YouTube视频的网页音频播放,就像您所说的那样。 - Anthony Griggs

2

我试了所有建议的答案,但都没有解决我的问题。最终我采用以下方法解决了类似的情况:

<a href="http://my-target-url.com" id="iframe-wrapper"></a>
<iframe id="iframe_id" src="http://something.com" allowtrancparency="yes" frameborder="o"></iframe>

CSS样式(当然,确切的定位应根据应用程序要求进行更改):

#iframe-wrapper, iframe#iframe_id {
  width: 162px;
  border: none;
  height: 21px;
  position: absolute;
  top: 3px;
  left: 398px;
}
#alerts-wrapper {
  z-index: 1000;
}

当然,现在您可以在iframe-wrapper上捕获任何事件。

2
这将防止在 iframe 中注册所有点击。 - Jeff Ryan
你是对的。它将把所有点击路由到iframe-wrapper元素。这对我很有效,因为在我的情况下,iframe没有交互元素,我只需要它来显示。 - ramigg

1
这将允许您针对iframe中的特定元素进行定位,例如按钮或文本字段,实际上几乎可以定位任何元素。使用on方法时,您可以将选择器作为参数传递。
$(window).load(function(){
    $("#ifameid").contents().on('click' , 'form input' , function(){
            console.log(this);
    });
});

1
你可以使用这段代码来绑定在iframe中的元素的点击事件。

jQuery('.class_in_iframe',jQuery('[id="id_of_iframe"]')[0].contentWindow.document.body).on('click',function(){ 
 console.log("triggered !!")
});


0

根据您绑定点击事件的时间,您可能会遇到一些时间问题,但它将把事件绑定到正确的窗口/文档。不过,实际上绑定到 iframe 窗口可能会获得更好的结果。您可以像这样执行:

    var iframeWin = $('iframe')[0].contentWindow;
    iframeWin.name = 'iframe';
    $(iframeWin).bind('click', function(event) {
        //Do something
        alert( this.name + ' is now loaded' );
    });

0

或许有点老了,但对于那些试图处理同域策略的人来说可能会很有用。

let isOverIframe = null;
$('iframe').hover(function() {
        isOverIframe = true;
    }, function() {
        isOverIframe = false;
    });

$(window).on('blur', function() {
    if(!isOverIframe)
        return;

    // ...
});

基于https://gist.github.com/jaydson/1780598


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接