仅在 Chrome 中调整 iframe 大小问题

Posted

技术标签:

【中文标题】仅在 Chrome 中调整 iframe 大小问题【英文标题】:Resizing Iframe issue in Chrome only 【发布时间】:2012-03-16 21:18:35 【问题描述】:

好的,到此为止。 Stack Overflow 处女在这里,但希望你们能够帮助我。

我一直在尝试根据 iframe 的内容调整 iframe 的高度。内容会随着用户在一系列表单中的进展而变化,这意味着每次提交都会产生一个新表单,其中有 3 个表单。

iframe 加载时调用下面的代码,

function checkHeight() 
    var frame=document.getElementById('frame');
    var doc=frame.contentWindow.document;
    var data=doc.getElementById('data');
    alert(data);
    var data_height=data.offsetHeight;
    if(data_height) 
        frame.style.height=data_height + 'px';
        alert('height has been set');
    

这在 Mozilla、IE 和 Safari 的 mac 和 pc 版本上都可以正常工作,但我在使用 chrome 时遇到了很大的问题。它没有返回框架内的文档。这是权限错误还是什么?!

我也尝试过 contentDocument 但无济于事。

所有文档都驻留在我的服务器上,并且都在同一个文件夹中。

提前致谢。

【问题讨论】:

不确定您是否会找到解决方案 - code.google.com/p/chromium/issues/detail?id=6402 感谢 Alex 提供的链接,一些有用的东西,但我可能仍会继续寻找解决方案。 祝你好运,伙计。如果您找到解决方案,请发表评论。 对不起,我忘了说要显示的表格在子页面的 内 【参考方案1】:

编辑:

我已重新阅读您的问题 - 仅计算 iframe 文档内的高度并调用父调整大小函数是否更简单,因为它们位于同一个安全沙箱中(即在同一个域中)?

原文:

由于从不同域嵌入 iframe(无法访问 iframe..document)时会发生类似的事情,我推测这种方法会起作用:

    首先:计算文档本身(即 iframe 内部)的文档高度。 对于旧版浏览器,使用 window.postMessage/hash 轮询将值传递给父级。 a neat library 会为您处理兼容性问题。 接收父级中的值并相应地调整 iframe 的大小。

同样,这可能有点矫枉过正,但鉴于该解决方案已经过测试,可以在不同的安全沙箱之间完全按照您的要求行事,如果 iframe 更简单的场景也应该是这种情况在同一个域中。

话虽如此,如果它们在同一个域中(与小部件/不可混搭的第三方内容相反),真的需要 iframe 吗?听起来这只是设置 jQuery 以发出 ajax 请求并用新数据填充容器的问题。

【讨论】:

非常感谢。使用 this.style.height 作为参数调用 prent 函数似乎可以解决问题【参考方案2】:

这似乎是一个相当直截了当的问题,所以我不确定为什么会有这么奇怪的答案,所以也许我完全错过了这个问题,但这是我的解决方案,一个是 x 域,另一个不是(注意:打开/写入/关闭,只是为了模拟服务器交互,使发生的事情更加明显......)

第一个 x 域样式:

// METHOD #1: postMessage() x-domain (chrome, ff, ie8+, safari, etc)
var d = document,
    iframe = d.createElement('iframe');
iframe.height = 0;
d.getElementsByTagName('body')[0].appendChild(iframe);

window.onmessage = function(msg)  
  iframe.height = parseInt(msg.data, 10);
;

var fd = iframe.contentDocument || iframe.contentWindow.document;
fd.open();
fd.write('<!DOCTYPE ht' + 'ml><ht' + 'ml><he' + 
         'ad><scri' + 'pt>' +
         'window.onload = function()' +

         'var db = document.body,' +
         'de = document.documentElement;' +

         'window.parent.postMessage(' + 
           'Math.max(db.scrollHeight, de.scrollHeight, db.offsetHeight, de.offsetHeight, db.clientHeight, de.clientHeight),' +
           '"*"' +
         ');' +

         ';</scr' + 'ipt></he' + 'ad><bo' + 
         'dy style="background:#afa"><div style="border:s' +
         'olid 1px black;padding:50px;line-height:50px">method #1: x-domain<b' +
         'r />test<br />test</div></bo' + 'dy></ht' + 
         'ml>');
fd.close();

下一个更兼容的同域版本:

// METHOD #2: manually same-domain (all browsers? [with tweaks] )

var iframe2 = d.createElement('iframe');

iframe2.height = 0;

iframe2.onload = function() 
  var xfd = iframe2.contentDocument || iframe2.contentWindow.document,
      db = xfd.body,
      de = xfd.documentElement;

  iframe2.height = Math.max(db.scrollHeight, de.scrollHeight, db.offsetHeight, de.offsetHeight, db.clientHeight, de.clientHeight);

;

d.getElementsByTagName('body')[0].appendChild(iframe2);

fd = iframe2.contentDocument || iframe2.contentWindow.document;
fd.open();
fd.write('<!DOCTYPE ht' + 'ml><ht' + 'ml><he' + 
         'ad></he' + 'ad><bo' + 
         'dy style="background:#aaf"><div style="padding:50px;line-height:50px;border:s' +
         'olid 1px black;">method #2: same domain<b' +
         'r />test2<br />test2</div></bo' + 'dy></ht' + 
         'ml>');
fd.close();

你可以在这里看到它的实际效果:http://jsbin.com/ifevad

我希望这会有所帮助 -ck

【讨论】:

非常感谢。投票赞成一个完整而完整的有效答案。【参考方案3】:

这个非常相同的示例在 Windows 上的 Chrome 17 中使用给定的 html 文件对我有用:

index.html:

<html>
<head>
</head>
<body>
<iframe src="index2.html" id="test">
</iframe>
</body>
</html>

index2.html

<html>
<head>
</head>

<body>
<div id="test_div">
    Ohai
</div>
</body>
</html>

然后我在chrome开发者窗口中使用了这个:

i = document.getElementById('test')
doc = i.contentWindow.document
data=doc.getElementById('test_div');
i.style.height = data.offsetHeight + 'px'

唯一的问题是直接打开 .html 文件时它不起作用 - 我必须启动一个 Web 服务器。 我使用了这个(它是默认的 Python 服务器):

server.py

import SimpleHTTPServer
import SocketServer

PORT = 8080

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

【讨论】:

我真的不想走这条路,还有其他方法吗? 或者是chrome在尝试访问URL中未直接指示的文件时总是会看到障碍。我在想,如果 iframe 页面引用通过 url 发送并通过 Javasrcip 应用于框架,那么可能会有更好的结果,你怎么看? “不想走这条路”是什么意思?您不托管您的网站吗? Chrome(实际上,我认为是所有浏览器)不允许您从与您不在同一个域中的站点访问 iframe。 我知道,这是同源策略。我所有的文件都在同一个位置,因此应该允许跨所有页面访问,我正在尝试找出 Chrome 无法正常工作的原因,我不认为完全需要打开服务器。 好吧,当您以 file:// 打开页面时,它的打开方式与通常不同。因此,同源策略仍然会阻止您访问 iframe。您是说您正在尝试创建一个您不打算托管的网站?

以上是关于仅在 Chrome 中调整 iframe 大小问题的主要内容,如果未能解决你的问题,请参考以下文章

仅在 Chrome 中出现 2 个深度 iFrame 的“拒绝框架”错误

仅在 Chrome 上出现 iframe 高度问题

调整 Chrome 地址栏屏蔽的大小问题 (Android)

如何让 chrome 重新渲染 iframe

iframe 仅在 Firefox 中不加载

无法在 iframe 中调整大小 [重复]