为什么jQuery在使用样式标签填充iframe时会删除body和head标签,但不是没有?

时间:2012-04-08 04:47:14

标签: javascript jquery iframe

如果我运行以下代码,则会移除body和head标签。

<iframe src='blank.htm'>
    <html>
    <head>
        <style type="text/css">

        </style>
    </head>
    <body>
        test
    </body>
    </html>
</iframe>
<script>
    $('iframe').load(function () {
        var contents = $('iframe').text();
        $('iframe').contents().find('html').html(contents);
    });
</script>

如果我删除样式标记,则所有内容都会正确显示。为什么这样,我怎么能让它停止去除头部和身体标签?我希望内容按原样填充,无需任何操作。

2 个答案:

答案 0 :(得分:16)

我遇到了同样的问题并从this SO question学到了实际上是浏览器执行剥离,作为解析innerHTML属性的一部分,这是jQuery使用的内容在.html()内部。

相反,问题实际上是jQuery使用了一个中间新的DIV,我认为不允许包含某些标签,从而导致剥离。

然后到解决方案。它就像直接设置innerHTML元素的html属性一样简单,如下所示:

// This forcibly removes head, body, and other tags, since it internally uses an empty DIV and its innerHTML property
jQuery(targetElement).html(exitHtml);

// This works fine
h = document.getElementsByTagName('html')[0];
h.innerHTML = htmlString;

对于您的具体情况,只需将html元素置于 iframe内即可。 您的最终代码可能是:

<script>
    $('iframe').load(function () {
        var contents = $('iframe').text();
        iframeHtml = $('iframe').contents().find('html').get(0);
        iframeHtml.innerHTML = contents;
    });
</script>

答案 1 :(得分:3)

您可以按照以下步骤了解如何将iframe内容复制到字符串,修改它并在iframe中替换它。这些步骤旨在在您的Chrome调试器中执行,仅用于教育/演示目的。一旦您了解了该过程,您就可以尝试在您的网站上的代码中进行复制。

在Chrome调试器中一次运行一个功能:

// test iframe I loaded in a sandbox also at http://example.com
$('body div:first').before('<iframe src="http://example.com/company"></iframe>');

// retrieved the body of the iframe - I cloned it so I could perform operations
  // on the copy without bothering the iframe content.
iBody = $('iframe:first').contents().find('body').clone();

// got the head
iHead = $('iframe:first').contents().find('head').html();

// if there is script in the body, it really messes things up. So in my tests, 
  // I had to remove it before adding it back to the iframe.
iBody.find("script").remove();

// verify there are no script elements
ibody.html(); 

// replace the iframe head
$('iframe:first').contents().find('head').html(iHead);

// replace the iframe body first with a placeholder. The body is the sensitive 
  // part. If you destroy the DOM, it can make the entire page, including 
    // the parent, turn completely white.
$('iframe:first').contents().find('body').html('<div></div>');

// ** inserted something in the copy to prove we modified it!!
iBody.append("<div style='position:absolute;z-index:5000; color:red; " + 
    "background-color:white;'>JAMES WAS HERE</div>");

// now replace the body
$('iframe:first').contents().find('body').html(iBody);
  

在网站的底部,在iframe内部,我在白色背景上看到了红色的消息。我也可以在消息来源中看到它:

$('iframe:first').contents().find('body').html();

我在匿名网站上执行了这些操作,使用Chrome的调试器控制台来运行命令。第一个命令在主页中使用iframe中的站点公司页面创建iframe。剩下的命令获取iframe的头部和主体,克隆身体,向身体克隆添加一些东西,如“JAMES WAS HERE”消息,然后用该副本替换iframe体。

我还通过在浏览器中加载http://getsatisfaction.com并在iframe中加载http://getsatisfaction.com/explore/product-innovation来验证相同的结果。通过重复上述步骤,我看到了我的信息,“JAMES WAS HERE”。

**我遇到的最严重的问题是无法在副本中保留JavaScript或CSS样式标记。样式的解决方案是在将主体添加回iframe之前进行所有样式修改。 **

出于某种原因,浏览器尝试运行JavaScript并引发错误。这些错误的上下文让我觉得JavaScript是在顶层上下文而不是iframe上下文中运行的!这对你来说可能是一个障碍。您可能需要提出另一个计划,以便在弹出窗口或内联中显示预览。此外,在使用不同JavaScript的不同网站上,这可能会有所不同。它在IE中也可能表现得很奇怪。

简而言之,我实际上并不认为这个解决方案会支持生产网站,因为必须在iframe中删除JavaScript;但是,根据您的需要,如果您不需要使用iframe DOM来使用任何JavaScript,则可以将其投入生产。

然而,这是一个值得探讨的有趣问题!