仅在 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 的“拒绝框架”错误