IFRAME 加载完成时的 JavaScript 回调?

发布于 2024-12-12 08:15:11 字数 557 浏览 1 评论 0原文

我需要在 IFRAME 加载完成时执行回调。我无法控制 IFRAME 中的内容,因此无法从那里触发回调。

该 IFRAME 是通过编程方式创建的,我需要将其数据作为回调中的变量传递,并销毁该 iframe。

有什么想法吗?

编辑:

这是我现在所拥有的:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.src = url;            
    document.body.appendChild(iFrameObj);   

    $(iFrameObj).load(function() 
    {
        document.body.removeChild(iFrameObj);
        callback(iFrameObj.innerHTML);
    });
}

此回调在 iFrame 加载之前进行,因此回调没有返回数据。

I need to execute a callback when an IFRAME has finished loading. I have no control over the content in the IFRAME, so I can't fire the callback from there.

This IFRAME is programmaticly created, and I need to pass its data as a variable in the callback, as well as destroy the iframe.

Any ideas?

EDIT:

Here is what I have now:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.src = url;            
    document.body.appendChild(iFrameObj);   

    $(iFrameObj).load(function() 
    {
        document.body.removeChild(iFrameObj);
        callback(iFrameObj.innerHTML);
    });
}

This callsback before the iFrame has loaded, so the callback has no data returned.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

凉栀 2024-12-19 08:15:11

首先,从函数名称 xssRequest 来看,听起来您正在尝试跨站点请求 - 如果这是正确的,您将无法读取 iframe 的内容。

另一方面,如果 iframe 的 URL 在您的域上,您可以访问正文,但我发现如果我使用超时来删除 iframe,则回调可以正常工作:

// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
  if (typeof callback == 'function') {
    callback($('body', this.contentWindow.document).html());
  }
  setTimeout(function () {$('#frameId').remove();}, 50);
});

First up, going by the function name xssRequest it sounds like you're trying cross site request - which if that's right, you're not going to be able to read the contents of the iframe.

On the other hand, if the iframe's URL is on your domain you can access the body, but I've found that if I use a timeout to remove the iframe the callback works fine:

// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
  if (typeof callback == 'function') {
    callback($('body', this.contentWindow.document).html());
  }
  setTimeout(function () {$('#frameId').remove();}, 50);
});
不及他 2024-12-19 08:15:11

我正在使用 jQuery,令人惊讶的是,这似乎加载了,因为我刚刚测试并加载了一个很重的页面,并且在我看到 iframe 加载之前我没有收到警报几秒钟:

$('#the_iframe').load(function(){
    alert('loaded!');
});

所以,如果您不想使用 jQuery,请采取查看他们的源代码,看看这个函数对于 iframe DOM 元素的行为是否有所不同,稍后我会自己查看,因为我感兴趣并发布在这里。另外我只在最新的 chrome 中进行了测试。

I am using jQuery and surprisingly this seems to load as I just tested and loaded a heavy page and I didn't get the alert for a few seconds until I saw the iframe load:

$('#the_iframe').load(function(){
    alert('loaded!');
});

So if you don't want to use jQuery take a look at their source code and see if this function behaves differently with iframe DOM elements, I will look at it myself later as I am interested and post here. Also I only tested in the latest chrome.

惟欲睡 2024-12-19 08:15:11

iframe 的innerHTML 为空,因为您的iframe 标记没有包围父文档中的任何内容。为了从 iframe 的 src 属性引用的页面获取内容,您需要访问 iframe 的 contentDocument 属性。如果 src 来自不同的域,则会抛出异常。这是一项安全功能,可防止您在其他人的页面上执行任意 JavaScript,这会产生跨站点脚本漏洞。下面是一些示例代码,说明了我正在讨论的内容:

<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>

<h1>Parent</h1>

<script type="text/javascript">
function on_load(iframe) {
  try {
    // Displays the first 50 chars in the innerHTML of the
    // body of the page that the iframe is showing.
    // EDIT 2012-04-17: for wider support, fallback to contentWindow.document
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    alert(doc.body.innerHTML.substring(0, 50));
  } catch (e) {
    // This can happen if the src of the iframe is
    // on another domain
    alert('exception: ' + e);
  }
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>

为了进一步说明该示例,请尝试使用它作为 iframe 的内容:

<h1>Child</h1>

<a href="http://www.google.com/">Google</a>

<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>

The innerHTML of your iframe is blank because your iframe tag doesn't surround any content in the parent document. In order to get the content from the page referred to by the iframe's src attribute, you need to access the iframe's contentDocument property. An exception will be thrown if the src is from a different domain though. This is a security feature that prevents you from executing arbitrary JavaScript on someone else's page, which would create a cross-site scripting vulnerability. Here is some example code the illustrates what I'm talking about:

<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>

<h1>Parent</h1>

<script type="text/javascript">
function on_load(iframe) {
  try {
    // Displays the first 50 chars in the innerHTML of the
    // body of the page that the iframe is showing.
    // EDIT 2012-04-17: for wider support, fallback to contentWindow.document
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    alert(doc.body.innerHTML.substring(0, 50));
  } catch (e) {
    // This can happen if the src of the iframe is
    // on another domain
    alert('exception: ' + e);
  }
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>

To further the example, try using this as the content of the iframe:

<h1>Child</h1>

<a href="http://www.google.com/">Google</a>

<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>
谷夏 2024-12-19 08:15:11

当诸如 word 文档和 pdf 之类的文档被流式传输到 iframe 时,我不得不这样做,并找到了一个效果很好的解决方案。关键是处理 iframe 上的 onreadystatechanged 事件。

假设您的框架的名称是“myIframe”。首先在代码启动的某处(我在 iframe 之后的任何位置内联执行)添加类似的内容来注册事件处理程序:

document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;

我无法在 iframe 上使用 onreadystatechage 属性,我不记得为什么,但应用程序必须在 IE 7 和 Safari 3 中工作,所以这可能是一个因素。

以下是如何获取完整状态的示例:

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}

I have had to do this in cases where documents such as word docs and pdfs were being streamed to the iframe and found a solution that works pretty well. The key is handling the onreadystatechanged event on the iframe.

Lets say the name of your frame is "myIframe". First somewhere in your code startup (I do it inline any where after the iframe) add something like this to register the event handler:

document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;

I was not able to use an onreadystatechage attribute on the iframe, I can't remember why, but the app had to work in IE 7 and Safari 3, so that may of been a factor.

Here is an example of a how to get the complete state:

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}
夕色琉璃 2024-12-19 08:15:11

当 i 框架内容在 IE 上完全加载时,我想隐藏等待的微调器 DIV,我几乎尝试了 Stackoverflow.com 中提到的所有解决方案,但没有任何效果如我所愿。

然后我有一个想法,当 iframe 内容完全加载时,可能会触发 $(window) load 事件。这正是所发生的事情。所以,我写了这个小脚本,它就像魔术一样起作用:

 $(window).load(function() {
     //alert("Done window ready ");
     var lblWait = document.getElementById("lblWait");
     if (lblWait != null) {
         lblWait.style.visibility = "false";
         document.getElementById("divWait").style.display = "none";
     }
 });

希望这会有所帮助。

I wanted to hide the waiting spinner DIV when the i frame content is fully loaded on IE, i tried literally every solution mentioned in Stackoverflow.com, but with nothing worked as i wanted.

Then I had an idea, that when the iframe content is fully loaded, the $(window) load event might be fired. And that is exactly what happened. So, I wrote this small script, which worked like a magic:

 $(window).load(function() {
     //alert("Done window ready ");
     var lblWait = document.getElementById("lblWait");
     if (lblWait != null) {
         lblWait.style.visibility = "false";
         document.getElementById("divWait").style.display = "none";
     }
 });

Hope this helps.

蓝梦月影 2024-12-19 08:15:11

如果 iFrame 已加载,此函数将立即运行您的回调函数,或者等到 iFrame 完全加载。

这还解决了以下问题:

  1. Chrome 使用 about:blank 页面初始化每个 iFrame,该页面将具有 readyState ==“complete”。稍后,它会将 `about:blank 替换为实际的 iframe src 值。因此,readyState的初始值不会代表实际iFrame的readyState。因此,除了检查readyState值之外,该函数还解决了about:blank问题。

  2. DOMContentLoaded 事件不适用于 iFrame。因此,如果 iFrame 尚未加载,它会使用 load 事件来运行回调函数。 load 事件相当于 readyState == "complete" ,用于检查 iFrame 是否已加载。因此,在任何情况下,回调函数都会在 iFrame 完全加载后运行。

  3. iFrame src 可以进行重定向,因此加载与原始 src url 不同的页面。此功能也适用于该场景。

将您想要在 iFrame 完成加载时运行的回调函数以及 元素传递给此函数:

function iframeReady(callback, iframeElement) {
    const iframeWindow = iframeElement.contentWindow;
    if ((iframeElement.src == "about:blank" || (iframeElement.src != "about:blank" && iframeWindow.location.href != "about:blank")) && iframeWindow.document.readyState == "complete") {
        callback();
    } else {
        iframeWindow.addEventListener("load", callback);
    }
}

This function will run your callback function immediately if the iFrame is already loaded or wait until the iFrame is completely loaded.

This also addresses the following issues:

  1. Chrome initializes every iFrame with an about:blank page which will have readyState == "complete". Later, it will replace `about:blank with the actual iframe src value. So, the initial value of readyState will not represent the readyState of your actual iFrame. Therefore, besides checking for readyState value, this function also addresses the about:blank issue.

  2. DOMContentLoaded event doesn't work with iFrame. So it uses the load event for running the callback function if iFrame isn't already loaded. The load event is equivalent to readyState == "complete" which has been used to check whether iFrame is already loaded. So, in any scenario, the callback function will run after iFrame is fully loaded.

  3. iFrame src can have redirects and therefore load a page different from the original src url. This function will also work in that scenario.

Pass in your callback function that you want to run when the iFrame finishes loading and the <iframe> element to this function:

function iframeReady(callback, iframeElement) {
    const iframeWindow = iframeElement.contentWindow;
    if ((iframeElement.src == "about:blank" || (iframeElement.src != "about:blank" && iframeWindow.location.href != "about:blank")) && iframeWindow.document.readyState == "complete") {
        callback();
    } else {
        iframeWindow.addEventListener("load", callback);
    }
}
醉态萌生 2024-12-19 08:15:11

我有和你类似的问题。我所做的是使用一种叫做 jQuery 的东西。然后您在 javascript 代码中执行的操作是这样的:

$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.

    $("#myIframeId").load(function(){
       callback($("#myIframeId").html());
       $("#myIframeId").remove();

    });

});

看起来您在从中获取 html 之前先删除了 iFrame。现在,我确实看到了一个问题:p

希望这会有所帮助:)。

I had a similar problem as you. What I did is that I use something called jQuery. What you then do in the javascript code is this:

$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page.

    $("#myIframeId").load(function(){
       callback($("#myIframeId").html());
       $("#myIframeId").remove();

    });

});

It seems as you delete you iFrame before you grab the html from it. Now, I do see a problem with that :p

Hope this helps :).

仙女山的月亮 2024-12-19 08:15:11

我的项目中有类似的代码,运行良好。
将我的代码调整为您的函数,解决方案可能如下:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.id = 'myUniqueID';
    document.body.appendChild(iFrameObj);       
    iFrameObj.src = url;                        

    $(iFrameObj).load(function() 
    {
        callback(window['myUniqueID'].document.body.innerHTML);
        document.body.removeChild(iFrameObj);
    });
}

也许您有一个空的innerHTML,因为(一个或两个原因):
1. 你应该将它用于 body 元素
2. 您已从页面 DOM 中删除了 iframe

I have a similar code in my projects that works fine.
Adapting my code to your function, a solution could be the following:

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.id = 'myUniqueID';
    document.body.appendChild(iFrameObj);       
    iFrameObj.src = url;                        

    $(iFrameObj).load(function() 
    {
        callback(window['myUniqueID'].document.body.innerHTML);
        document.body.removeChild(iFrameObj);
    });
}

Maybe you have an empty innerHTML because (one or both causes):
1. you should use it against the body element
2. you have removed the iframe from the your page DOM

电影里的梦 2024-12-19 08:15:11

我认为加载事件是正确的。
不正确的是您从 iframe content dom 检索内容的方式。

您需要的是 iframe 中加载的页面的 html,而不是 iframe 对象的 html。

您所要做的就是使用 iFrameObj.contentDocument 访问内容文档。
如果 iframe 中加载的页面与当前页面位于同一域中,则返回该页面的 dom。

我会在删除 iframe 之前检索内容。

我已经在 Firefox 和 Opera 中进行了测试。

然后我认为您可以使用 $(childDom).html()$(childDom).find('some selecter') ... 检索数据

I think the load event is right.
What is not right is the way you use to retreive the content from iframe content dom.

What you need is the html of the page loaded in the iframe not the html of the iframe object.

What you have to do is to access the content document with iFrameObj.contentDocument.
This returns the dom of the page loaded inside the iframe, if it is on the same domain of the current page.

I would retreive the content before removing the iframe.

I've tested in firefox and opera.

Then i think you can retreive your data with $(childDom).html() or $(childDom).find('some selector') ...

绾颜 2024-12-19 08:15:11

我过去遇到过完全相同的问题,我发现解决该问题的唯一方法是将回调添加到 iframe 页面中。当然,只有当您可以控制 iframe 内容时,这才有效。

I've had exactly the same problem in the past and the only way I found to fix it was to add the callback into the iframe page. Of course that only works when you have control over the iframe content.

烟花肆意 2024-12-19 08:15:11

使用 onload 属性将解决您的问题。

这是一个例子。

function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>

这是你想要的吗?

点击此处了解更多信息。

Using onload attrbute will solve your problem.

Here is an example.

function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>

Is this what you want?

Click here for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文