jQuery .ready在动态插入的iframe中

Eti*_*neT 181 javascript iframe jquery thickbox galleria

当有人点击图片时,我们使用jQuery thickbox动态显示iframe.在这个iframe中,我们使用galleria一个javascript库来显示多张图片.

问题似乎是$(document).ready在iframe似乎过早被解雇并且iframe内容甚至尚未加载,因此galleria代码未在DOM元素上正确应用. $(document).ready似乎使用iframe父就绪状态来决定iframe是否准备就绪.

如果我们在单独的函数中提取由文档就绪调用的函数,并在超过100毫秒后调用它.它有效,但我们不能利用慢速计算机生产机会.

$(document).ready(function() { setTimeout(ApplyGalleria, 100); });
Run Code Online (Sandbox Code Playgroud)

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

Pie*_*igi 290

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

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

    $('iframe#myId').load(function() {
        callback(this);
    });
}
Run Code Online (Sandbox Code Playgroud)

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

  • load事件不适用于用于下载的iframe.喜欢<iframe src ="my.pdf"/></iframe> (29认同)
  • 你不应该在调用attr('src')之前设置load事件吗? (17认同)
  • 不,没关系.加载事件将至少在下一个事件循环之前触发. (15认同)
  • [`.load()`事件已被弃用.使用`.on("load",handler)`代替.](http://api.jquery.com/load-event/) (5认同)
  • 加载问题是当所有图像和子帧都已加载时它会触发.像ready事件这样的jQuery会更有用. (3认同)
  • "动态插入",因为iframe标记是通过客户端上的javascript插入DOM中的.因此,根据客户端上发生的条件或事件,iframe可以在页面上添加或不添加. (2认同)
  • load 事件不会为加载处理程序绑定时已经加载的 iFrame 触发。因此,它无法与 iFrame 的 `jQuery(document).ready()` 相提并论。我能想到的唯一解决方案是复制 jQuery 如何为已加载 jQuery 的框架执行此操作。 (2认同)

小智 29

使用jQuery 1.3.2,以下对我有用:

$('iframe').ready(function() {
  $('body', $('iframe').contents()).html('Hello World!');
});
Run Code Online (Sandbox Code Playgroud)

修订:!实际上上面的代码看起来有点像在Firefox中工作,看起来在Opera中看起来不像.

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

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

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

  • 此解决方案是递归的,每次调用都会占用内存。如果 iframe 永远不会加载,那么它将永远调用越来越深,直到内存耗尽。我建议改为使用`setInterval` 进行轮询。 (2认同)

Tam*_*ege 14

在IFrame中,我通常通过在块的最末端放一个小脚来解决这个问题:

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

这项工作大部分时间都适合我.有时,最简单,最天真的解决方案是最合适的.

  • 这不适用于跨域位置 (10认同)
  • +1这个解决方案对我很有用!一个很好的补充是你可以达到`parent`来获取jQuery的副本并使用`parent.$(document).ready(function(){parent.IFrameLoaded();});`来初始化iframe . (4认同)

Ric*_*tas 9

遵循Dr.Jokepu和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");
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

父测试代码:

$(function(){
    $("iframe").on("iframeloading iframeready iframeloaded iframebeforeunload iframeunloaded", function(e){
        console.log(e.type);
    });
});
Run Code Online (Sandbox Code Playgroud)