【问题标题】:Detect click inside iframe (same domain/sub domain) in Chrome using jQuery使用 jQuery 在 Chrome 中检测 iframe(相同域/子域)内的点击
【发布时间】:2012-09-18 13:21:17
【问题描述】:

这个问题被问了很多,答案通常是相似的。

简单来说,当点击 iframe 的内容时,我需要一个函数来执行。

出于本演示的目的,我有 http://mydomain.com/iframe.html,其中包含一个 ID 为“iframeID”的 iframe 和一个源 http://mydomain.com

此代码有效:

jQuery(document).ready(function(){
    $('#iframeID').contents().click(function(event) {
        console.log('Clicked! ' + event.pageX + ' - ' + event.pageY);
    });
});

但是,此代码仅适用于 Internet Explorer。我需要一个适用于所有浏览器的解决方案。

好消息是,这都在同一个域上,所以如果我需要在 iframe 源或 iframe.html 中添加额外的代码,那很好。我只需要它跨浏览器工作。

还有一点需要注意,我希望它能够跨子域工作。

我知道它不适用于不同的域,但据我了解,子域应该没问题吗?是否需要任何额外的步骤才能工作?

感谢您的帮助!

【问题讨论】:

  • 是否可以选择使用跨文档消息传递 (XDM)?它适用于 IE8 和更新的以及所有现代浏览器。 developer.mozilla.org/en-US/docs/DOM/window.postMessage 如果您需要对旧版浏览器的支持,可以查看:easyxdm.net/wp 另请参阅:stackoverflow.com/questions/7652646/…
  • 看起来值得探索。我不完全理解它,但示例代码是我可以玩的。 IE8+ 很好 - 他们在 IE8 之前制作了浏览器? :-P 如果你有一个基于我发布的原始代码的实际示例,那就太棒了。
  • 我发布了一个例子。我没有分析您的原始代码,但我试图使其非常通用且易于适应。希望对你有帮助

标签: jquery html iframe


【解决方案1】:

这是我放在 jsFiddle 上的一个示例,它演示了使用 XDM 的一种方法: This is the demo 包括this fiddle as a child iframe

HTML(父):

<h1>Parent window</h1>
<input id="message-for-child" type="text" value="" placeholder="(message for child)">
<button id="parent-to-child-button">Send to child</button>
<br>
<p id="parent-message"></p>
<br>
<iframe id="child" src="http://fiddle.jshell.net/quant/G2uq6/show/"></iframe>

JavaScript(父):

// parent_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function parent_on_message(e) {
    console.log("parent_on_message event fired: ", e);
    // You really should check origin for security reasons
    // https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
    if (e.origin.search(/^http[s]?:\/\/.*\.jshell\.net/) != -1
        && !($.browser.msie && $.browser.version <= 7)) {
        var returned_pair = e.data.split('=');
        if (returned_pair.length != 2)
            return;
        if (returned_pair[0] === 'message-for-parent') {
            $("p#parent-message").html(returned_pair[1]);
        }
        else
            console.log("Parent received invalid message");
    }
}

jQuery(document).ready(function($) {
    // Setup XDM listener (except for IE < 8)
    if (!($.browser.msie && $.browser.version <= 7)) {
        // Connect the parent_on_message(e) handler function to the receive postMessage event
        if (window.addEventListener)
            window.addEventListener("message", parent_on_message, false);
        else
            window.attachEvent("onmessage", parent_on_message);
    }


    $("button#parent-to-child-button").on("click", function(e) {
        console.log("Sending: " + $("input#message-for-child").attr("value"));
        $("iframe#child").get(0).contentWindow.postMessage('message-for-child=' + $("input#message-for-child").attr("value"), '*');
        
    });

        
});

HTML(子):

<h1>Child</h1>
<input id="message-for-parent" type="text" value="" placeholder="(message for parent)">
<button id="child-to-parent-button">Send to parent</button>
<br>
<p id="child-message"></p>

JavaScript(子):

// child_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function child_on_message(e) {
    console.log("child_on_message event fired: ", e);
    // You really should check origin for security reasons
    // https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
    if (e.origin.search(/^http[s]?:\/\/.*\.jshell\.net/) != -1
        && !($.browser.msie && $.browser.version <= 7)) {
        var returned_pair = e.data.split('=');
        if (returned_pair.length != 2)
            return;
        if (returned_pair[0] === 'message-for-child') {
            $("p#child-message").html(returned_pair[1]);
        }
        else
            console.log("Child received invalid message");
    }
}

jQuery(document).ready(function($) {
    // Setup XDM listener (except for IE < 8)
    if (!($.browser.msie && $.browser.version <= 7)) {
        // Connect the child_on_message (e) handler function to the receive postMessage event
        if (window.addEventListener)
            window.addEventListener("message", child_on_message , false);
        else
            window.attachEvent("onmessage", child_on_message );
    }


    $("button#child-to-parent-button").on("click", function(e) {
        console.log("Sending: " + $("input#message-for-parent").attr("value"));
        parent.window.postMessage('message-for-parent=' + $("input#message-for-parent").attr("value"), '*');
        
    });

        
});

进一步阅读:

【讨论】:

  • 很棒的工作。我不能感谢你......我真的不能。我没有足够的代表来投票,但我会尝试一下,让它更符合我的需求,如果我没有其他问题,我会尽快将其标记为答案。
  • 很高兴你喜欢它!但是,标准的警告词仍然适用:永远不要将 SO 答案作为学习底层技术的替代品。此代码不提供任何形式的保证或保证 :)
  • 当然。我从 SO 中学到了很多东西。无论是我提出的问题,还是我通过搜索找到的答案。这是一个很棒的地方,像您这样放弃时间来提供出色答案的人使它变得很棒。我会从中学到很多东西。
  • 好的,我认为这可能足以解决我真正需要做的事情。但我想我现在把自己弄糊涂了。我真正想要的是,当在 iframe 中单击链接时,该链接将加载到父窗口中。当然默认行为是在子 iframe 中打开链接。我在原始消息中发布的代码的变体在单击链接时有效,但仅在 IE 中有效。我们还在看 XDM 吗?我不想修改子框架中的代码(如果可能的话)。抱歉跑来跑去:(
  • 你在说这样的事情吗? window.top.location.href="//www.google.com";或者您是说您希望 iframe 中的所有“常规”链接都在顶部窗口中打开? jsfiddle.net/quant/HfKQz/25
【解决方案2】:

如果您只想在顶部窗口而不是在 iframe 内部打开 iframe 中的链接,请查看How to force link from iframe to be opened in the parent window

只需将其放在 iframe HTML 的头部即可:

<base target="_parent" />

【讨论】:

  • 狂热的工作 - 为什么有时最简单的事情会让你眼前一亮,最好的解决方案?我已将您的原始答案标记为答案,因为它最准确地回答了我的原始问题。然而,具有讽刺意味的是,我只需要这么简单的东西。出色的工作,很抱歉我的问题没有更简洁
猜你喜欢
  • 1970-01-01
  • 2020-07-30
  • 2015-06-02
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 2017-10-20
  • 1970-01-01
相关资源
最近更新 更多