jQuery .ready 在动态插入的 iframe 中

IT技术 javascript jquery iframe thickbox galleria
2021-01-29 02:23:31

当有人点击图片时,我们正在使用 jQuery厚框动态显示 iframe。在这个 iframe 中,我们使用了Galleria一个 javascript 库来显示多张图片。

问题似乎是$(document).readyiframe 中的 iframe 似乎被触发得太快,iframe 内容甚至还没有加载,因此 Galleria 代码没有正确应用于 DOM 元素。 $(document).ready似乎使用 iframe 父就绪状态来决定 iframe 是否已就绪。

如果我们将 document ready 调用的函数提取到一个单独的函数中,并在超时 100 毫秒后调用它。它可以工作,但我们不能冒险使用慢速计算机进行生产。

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });

我的问题:我们应该绑定哪个 jQuery 事件才能在动态 iframe 准备好而不仅仅是它的父级时执行我们的代码?

6个回答

我回答了一个类似的问题(请参阅IFRAME 加载完成后的 Javascript 回调?)。您可以使用以下代码获得对 iframe 加载事件的控制:

function callIframe(url, callback) {
    $(document.body).append('<IFRAME id="myId" ...>');
    $('iframe#myId').attr('src', url);

    $('iframe#myId').load(function() {
        callback(this);
    });
}

在处理 iframe 时,我发现使用 load 事件而不是文档就绪事件已经足够了。

load 事件不适用于用于下载的 iframe。像 <iframe src="my.pdf"/>
2021-03-24 02:23:31
加载的问题是它在所有图像和子帧都加载后触发。类似 jQuery 的 ready 事件会更有用。
2021-04-03 02:23:31
您不应该在调用 attr('src') 之前设置加载事件吗?
2021-04-06 02:23:31
不,没关系。Load 事件至少要到下一个事件循环才会触发。
2021-04-06 02:23:31

使用 jQuery 1.3.2 以下对我有用:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});

修订:!实际上,上面的代码有时看起来在 Firefox 中可以工作,但在 Opera 中却不一定。

相反,我为我的目的实施了一个轮询解决方案。简化下来看起来像这样:

$(function() {
  function manipIframe() {
    el = $('body', $('iframe').contents());
    if (el.length != 1) {
      setTimeout(manipIframe, 100);
      return;
    }
    el.html('Hello World!');
  }
  manipIframe();
});

这不需要被调用的 iframe 页面中的代码。所有代码都驻留在父框架/窗口中并从其执行。

@cam8001:这是一个错字 - 现在已修复。
2021-03-16 02:23:31
setTimeout() 中提到的 movePreview 功能是什么?
2021-03-21 02:23:31
我最终也使用了轮询解决方案。其他解决方案似乎只取得了部分成功。但是,对我来说,在成功之前,我需要检查 javascript 函数是否存在,而不仅仅是检查 iframe 的内容。例如。(typeof iframe.contentWindow.myfunc == 'function')
2021-03-30 02:23:31
此解决方案是递归的,每次调用都会占用内存。如果 iframe 永远不会加载,那么它将永远调用越来越深,直到内存耗尽。我建议setInterval改为投票。
2021-04-03 02:23:31

在 IFrames 中,我通常通过在块的最后放置一个小脚本来解决这个问题:

<body>
The content of your IFrame
<script type="text/javascript">
//<![CDATA[
   fireOnReadyEvent();
   parent.IFrameLoaded();
//]]>
</script>
</body>

这对我来说大部分时间都在工作。有时,最简单、最幼稚的解决方案是最合适的。

+1 这个解决方案对我很有用!一个很好的补充是,您可以parent使用 获取 jQuery 的副本并用于parent.$(document).ready(function(){ parent.IFrameLoaded( ); });初始化 iframe。
2021-04-06 02:23:31

按照 DrJokepu 和 David Murdoch 的想法,我实现了一个更完整的版本。需要父级和 iframe 上的 jQuery 以及 iframe 在您的控制中。

iframe 代码:

var iframe = window.frameElement;

if (iframe){
    iframe.contentDocument = document;//normalization: some browsers don't set the contentDocument, only the contentWindow

    var parent = window.parent;
    $(parent.document).ready(function(){//wait for parent to make sure it has jQuery ready
        var parent$ = parent.jQuery;

        parent$(iframe).trigger("iframeloading");

        $(function(){
            parent$(iframe).trigger("iframeready");
        });

        $(window).load(function(){//kind of unnecessary, but here for completion
            parent$(iframe).trigger("iframeloaded");
        });

        $(window).unload(function(e){//not possible to prevent default
            parent$(iframe).trigger("iframeunloaded");
        });

        $(window).on("beforeunload",function(){
            parent$(iframe).trigger("iframebeforeunload");
        });
    });
}

父测试代码:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});
无论出于何种原因,在父级中使用 $(iframe).ready(function...) 都不适合我。在 iframe dom 准备好之前,回调函数似乎正在执行。使用这个方法效果很好!
2021-04-06 02:23:31

找到了问题的解决方案。

当您单击打开 iframe 的厚框链接时,它会插入一个 id 为 TB_iframeContent 的 iframe。

而不是依赖$(document).readyiframe 代码中事件,我只需要绑定到父文档中 iframe 的 load 事件:

$('#TB_iframeContent', top.document).load(ApplyGalleria);

此代码位于 iframe 中,但绑定到父文档中的控件事件。它适用于 Firefox 和 IE。

找到解决方案了吗?看来 Pier 已经发布了。不管你自己有没有发现,礼仪就是接受他的回答,从而奖励他回答你的时间。
2021-03-26 02:23:31
码头的解决方案,这(和我在我的代码丢失)是上下文之间的区别top.document,让我有代码里面的iframe能够在iframe中加载告诉。(尽管load自此答案以来已被弃用,应替换为on("load")。)
2021-04-01 02:23:31