[英]cross-domain iframe resize
如何从另一个域调整 iframe 的大小?
过去几天我一直在尝试将 iframe 集成到网站中。 这是一个短期解决方案,而另一方开发和 API(可能需要几个月......)因为这是我们想要使用 easyXDM 的短期解决方案 - 我可以访问另一个域,但要求他们这样做已经够难了按原样添加 p3p 标头.....
3 个 iframe
我找到的最接近的解决方案是 3 个 iframe——但它是 chrome 和 safari 的精神,所以我不能使用它。
用铬打开
http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179
测量滚动条
我发现了另一篇关于如何使用滚动高度来尝试调整表单大小的帖子。理论上它运行良好,但我无法使用 iframe 滚动高度正确应用它。
document.body.scrollHeight
这显然使用了身体高度(无法访问这些属性 100% 是基于客户端显示画布而不是 x 域文档高度)
我尝试使用 jQuery 获取 iframe 高度
$('#frameId').Height()
$('#frameId').clientHeight
$('#frameId').scrollHeight
返回值在 chrome 和 ie 中不同 - 或者根本没有意义。 问题是框架内的所有内容都被拒绝 - 甚至滚动条......
计算样式
但是,如果我检查 iframe 的 chrome 中的元素,它会严重地向我显示 iframe 内的文档尺寸(使用 jQuery x-domain 获取 iframe.heigh - 访问被拒绝)计算的 CSS 中没有任何内容
现在chrome是如何计算的? (编辑 - 浏览器使用其内置渲染引擎重新渲染页面以计算所有这些设置 - 但没有附加到任何地方以防止跨域欺诈......所以......)
HTML4
我阅读了 HTML4.x 的规范,它说应该有通过 document.element 公开的只读值,但是通过 jQuery 拒绝访问
代理帧
我沿着代理站点的路线返回并计算哪个可以..直到用户通过 iframe 登录并且代理获取登录页面而不是实际内容。 还有一些调用页面两次是不可接受的
http://www.codeproject.com/KB/aspnet/asproxy.aspx
http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/
重新渲染页面
我没有走这么远,但是那里有 jscript 引擎可以查看源代码并根据源文件重新呈现页面。 但它需要破解那些 jscripts.. 这对于商业实体来说不是一个理想的情况......有些调用纯 Java 小程序或服务器端渲染
http://en.wikipedia.org/wiki/Server-side_JavaScript
http://htmlunit.sourceforge.net/ <-java 不是 jscript
所有这些都可以通过 HTML5 套接字来完成。 但是easyXDM对于非HTML5投诉页面来说是一个很好的后备方案。
解决方案 1非常棒的解决方案!
使用easyXDM
在您的服务器上,您以以下形式设置页面
<html>
<head>
<script src="scripts/easyXDM.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
var transport = new easyXDM.Socket(/** The configuration */{
remote: "http://www.OTHERDOMAIN.example/resize_intermediate.html?url=testpages/resized_iframe_1.html",
//ID of the element to attach the inline frame to
container: "embedded",
onMessage: function (message, origin) {
var settings = message.split(",");
//Use jquery on a masterpage.
//$('iframe').height(settings[0]);
//$('iframe').width(settings[1]);
//The normal solution without jquery if not using any complex pages (default)
this.container.getElementsByTagName("iframe")[0].style.height = settings[0];
this.container.getElementsByTagName("iframe")[0].style.width = settings[1];
}
});
</script>
</head>
<body>
<div id="embedded"></div>
</body>
在调用者域中,他们只需要在同一个地方添加intermediate_frame HTML 和easyXDM.js
。 就像父文件夹一样 - 然后您可以访问相关目录或仅适合您的包含文件夹。
与 Sean 提到的类似,您可以使用 postMessage。 我花了很多时间尝试不同的方法来调整跨域 iframe 的大小,但没有运气,直到我偶然发现了 David Walsh 的这篇很棒的博客文章:http: //davidwalsh.name/window-iframe
这是我的代码和大卫的解决方案的组合。 我的解决方案专门针对调整 iframe 的大小。
在子页面中,找到页面的高度并将其传递给父页面(包含 iframe)。 将 element_id 替换为您的元素 id(html、body 等)。
<script>
function adjust_iframe_height(){
var actual_height = document.getElementById('element_id).scrollHeight;
parent.postMessage(actual_height,"*");
//* allows this to post to any parent iframe regardless of domain
}
</script>
<body onload="adjust_iframe_height();">
//call the function above after the content of the child loads
在父窗口中,添加此代码。 将 iframe_id 替换为您的 iframe ID:
<script>
// Create IE + others compatible event handler
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child window
eventer(messageEvent,function(e) {
console.log('parent received message!: ',e.data);
document.getElementById('iframe_id').height = e.data + 'px';
},false);
</script>
如果您打开控制台,您将在控制台日志中看到正在打印的高度。 这将帮助您进行调试,这就是我将其留在那里的原因。
最好的,贝克
问题是 - 除了使用跨域消息传递之外别无他法,因为您需要从一个域中的文档获取计算高度到不同域中的文档。
因此,您要么使用postMessage
(适用于所有现代浏览器)执行此操作,要么花 5 分钟调整来自 easyXDM 的resize iframe 示例。
对方真的只需要复制几个文件到他们的域中,然后在他们的文档中添加一行代码..
在看了很多不同的解决方案之后,我最终编写了一个简单的小型库来考虑许多不同的用例。 因为我需要一个在门户页面上支持多个用户生成的 iFrame 的解决方案,支持浏览器调整大小并且可以应对 iFrame 之后加载的主机页面 JavaScript。 我还添加了对宽度大小和回调函数的支持,并允许覆盖 body.margin,因为您可能希望将此设置为零。
https://github.com/davidjbradshaw/iframe-resizer
iframe 代码只是一些自包含的 JavaScript,因此它是其他人页面上的好客人。
然后使用以下可用选项在主机页面上初始化脚本。
iFrameResize({
log : true, // For development
autoResize : true, // Trigering resize on events in iFrame
contentWindowBodyMargin: 8, // Set the default browser body margin style (in px)
doHeight : true, // Calculates dynamic height
doWidth : false, // Calculates dynamic width
enablePublicMethods : true, // Enable methods within iframe hosted page
interval : 32, // interval in ms to recalculate body height, 0 to disable refreshing
scrolling : false, // Enable the scrollbars in the iFrame
callback : function(messageData){ // Callback fn when message is received
$('p#callback').html(
'<b>Frame ID:</b> ' + messageData.iframe.id +
' <b>Height:</b> ' + messageData.height +
' <b>Width:</b> ' + messageData.width +
' <b>Event type:</b> ' + messageData.type
);
}
});
现在我只知道4个解决方案:
只有第三种才能解决很多问题。 例如,您可以创建响应式 iFrame ; 从里面关闭它,或者你可以与它交流。 但要做到这一点,您需要 iframe 中的 iFrame 和“第三方 cookie”解决方法(可选)。
我用示例创建了一篇关于它的文章:事件驱动的跨域 iFrame
您是否查看过“适合对象”的 HTML5 属性? 将视频/图像缩放到 iframe,而不是缩放 iframe(如果您抓取最终宽度为 5,000 像素的中等大小的图像,那就太好了)。 “适合”选项(其他是“覆盖”和“填充”)使用一种信箱类型的方法来适应源,同时保留纵横比。 对于那些没有 HTML5 的人来说,看起来有很多可用的 polyfills。 这个很棒,但是 Edge 端的一个错误使它与微软的 New Nightmare 不兼容大约一年,现在: https ://github.com/anselmh/object-fit
编辑:要解决跨域问题,您始终可以在 Chrome 扩展内容脚本中完成工作,因为它认为它是您粘贴 iframe 的页面的一部分。
HTTPS 另一个链接获取 iframe 自动高度的高度
<!DOCTYPE html>
<html>
<head>
<title>Test Page</title>
</head>
<body>
Test Page:
<hr/>
<iframe id="iframe" src="https://-b.com" style="width:100%;min-height:600px;border:none;" scrolling="no" ></iframe>
<script>
// browser compatibility: get method for event
// addEventListener(FF, Webkit, Opera, IE9+) and attachEvent(IE5-8)
var myEventMethod =
window.addEventListener ? "addEventListener" : "attachEvent";
// create event listener
var myEventListener = window[myEventMethod];
// browser compatibility: attach event uses onmessage
var myEventMessage =
myEventMethod == "attachEvent" ? "onmessage" : "message";
// register callback function on incoming message
myEventListener(myEventMessage, function (e) {
// we will get a string (better browser support) and validate
// if it is an int - set the height of the iframe #my-iframe-id
if (e.data === parseInt(e.data))
document.getElementById('iframe').height = e.data + "px";
}, false);
</script>
</body>
</html>
https://-b.com iframe 内容:
<!DOCTYPE html>
<html>
<head>
<title>Test Iframe Content</title>
<script type="text/javascript">
// all content including images has been loaded
window.onload = function() {
// post our message to the parent
window.parent.postMessage(
// get height of the content
document.body.scrollHeight
// set target domain
,"*"
)
};
</script>
</head>
<body>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>1
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>2
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>3
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>4
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>5
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>6
</body>
</html>
工作表:
xcom http > ycom https 工作
xcom https > ycom https 工作
xcom http > ycom http 工作
xcom https > ycom http 工作
我没有在 iframe 上使用 scroll=no,而是将其更改为“auto”。 然后,我得到实际窗口的大小
$(window).height();
并将其用作 iframe 高度属性。
嗯,结果是……
我们永远不会有“页面”滚动,只有“iframe”滚动。 当你导航时,谁是卷轴并不重要,但重要的是只有 1 个。
好吧,存在用户在导航时简单地调整窗口大小的问题。 为了解决这个问题,我使用:
setInterval(getDocHeight, 1);
您是否认为该解决方案会导致任何错误? 它对我有用,在 iFrame 上我有 php 生成的动态内容。 我怕以后会出现这样的错误...
要调整 iframe 的大小,这是一个简单的脚本:
这在头脑中:(这是为 php 脚本编写的,对于 html,将 ' 更改为 " 并将 \" 更改为 '...
<script type='text/javascript'>
<!--
function resizeIframe(id){
/*
this.obj=obj
//this.obj.width=null
//this.obj.width=window.frames[\"sizeframe1\"].document.body.scrollWidth
this.obj.style.height=\"\" // for Firefox and Opera
setTimeout(\"this.obj.style.height=this.obj.contentWindow.document.body.scrollHeight+(notIE?heightOffset:0)\",10) // setTimeout required for Opera
*/
el=document.getElementById(id)
el.style.height='200px' // for Firefox and Opera
setTimeout('el.style.height=el.contentWindow.document.body.scrollHeight+\"px\"',1) // setTimeout required for Opera
}
// -->
</script>"
头尾
这在正文中(请记住,这是为 php 脚本编写的,对于 html,将所有 ' 更改为 " 并将 \" 更改为 '...)
<iframe onload='resizeIframe(this.id)' allowTransparency=\"true\" name='ccpaymentwindow' id='sizeframe1' marginwidth='1' marginheight='1' height='700' width='690' border='0' frameborder='1' scrolling='no' src='ccmslink.php?variable1=" . $variable1 . "'></iframe>
奖金:上面有一些提示。 因为它是为 php 脚本设置的,所以你可以用它做很多事情......要了解更多,做更多......
关键是“sizeframe1”....对于同一页面上的多个“调整大小”,复制相同的脚本,但更改 iframe 中的 id 和头部脚本中的名称,还有 viola! 您在同一页面上有多个大小调整器...效果很好!
有朋。
您是否要查找 iframe 中包含的页面高度? 我有一些 javascript 工作,它检查 iframe 内容的高度,然后将 iframe 的高度设置为内容的高度。
var Height = document.getElementById('iFrameId').contentWindow.document.body.scrollHeight;
document.getElementById('iFrameId').height = Height;
但是,这仅适用于您在 iframe 中显示的页面位于同一域中的情况。 如果不是,您将无法访问所需的信息。 因此,访问被拒绝错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.