根据内容调整iframe的大小
我正在开发类似iGoogle的应用程序。使用iframe显示其他应用程序(在其他域上)的内容。
如何调整iframe的大小以适合iframe内容的高度?
我试图破译Google使用的javascript,但它被混淆了,到目前为止,在网络上搜索是徒劳的。
更新:请注意,内容是从其他域加载的,因此适用同源策略。
解决方案
这有点棘手,因为我们必须知道iframe页面何时加载,而当我们无法控制其内容时就很难理解。可以在iframe中添加onload处理程序,但我过去曾尝试过这样做,并且它在浏览器中的行为也大不相同(不要猜测谁是最烦人的...)。我们可能必须将一个函数添加到iframe页面中,以执行调整大小并将某些脚本注入到内容中,以监听加载事件或者调整大小事件,然后调用上一个函数。我正在考虑向页面添加功能,因为我们想确保其安全性,但是我不知道这样做会多么容易。
我相信这一点应该可以奏效。
parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight;
在iframe内容上加载时将其加载到身体上。
http://www.phinesolutions.com/use-jquery-to-adjust-the-iframe-height.html上的解决方案效果很好(使用jQuery):
<script type=”text/javascript”> $(document).ready(function() { var theFrame = $(”#iFrameToAdjust”, parent.document.body); theFrame.height($(document.body).height() + 30); }); </script>
我不知道我们需要增加30个长度... 1个对我有用。
仅供参考:如果我们在iFrame上已经具有" height"属性,则只会添加style =" height:xxx"。这可能不是我们想要的。
iGoogle小工具必须积极实现调整大小,因此我的猜测是在跨域模型中,如果没有远程内容以某种方式参与,我们将无法做到这一点。如果内容可以使用典型的跨域通信技术将新大小的消息发送到容器页面,则其余的操作很简单。
我们遇到了这类问题,但与情况稍有不同,我们正在向其他域上的站点提供iframed内容,因此相同的来源策略也是一个问题。经过数小时的拖曳Google搜寻,我们最终找到了一个(某种程度上..可行的)解决方案,我们也许可以适应需求。
有一种方法可以绕过相同的原始策略,但是它需要同时在iframed内容和框架页面上进行更改,因此,如果我们无法在两边都请求更改,则此方法对我们将不会很有用,我耽心。
有一个浏览器怪癖,它使我们能够规避相同的源策略,javascript可以与自己域上的页面或者已对其进行格式化的页面进行通信,但不能与框架内的页面进行通信,例如如果你有:
www.foo.com/home.html, which iframes |-> www.bar.net/framed.html, which iframes |-> www.foo.com/helper.html
那么" home.html"可以与" framed.html"(iframed)和" helper.html"(相同域)进行通信。
Communication options for each page: +-------------------------+-----------+-------------+-------------+ | | home.html | framed.html | helper.html | +-------------------------+-----------+-------------+-------------+ | www.foo.com/home.html | N/A | YES | YES | | www.bar.net/framed.html | NO | N/A | YES | | www.foo.com/helper.html | YES | YES | N/A | +-------------------------+-----------+-------------+-------------+
framed.html
可以将消息发送到helper.html
(iframed),但不能发送消息到" home.html`"(子对象不能与父对象进行跨域通信)。
这里的关键是helper.html可以接收来自framed.html的消息,并且还可以与home.html进行通信。
因此,从本质上讲,在加载framed.html时,它会计算出自己的高度,然后告诉helper.html,将消息传递给home.html,然后可以调整其中framed.html的iframe的大小。坐。
我们发现将消息从framed.html传递到helper.html的最简单方法是通过URL参数。为此,framed.html具有指定了src =''的iframe。当其" onload"触发时,它会评估自己的高度,并将iframe的src设置为" helper.html?height = N"。
这里有一个关于Facebook如何处理它的解释,这可能比上面的我的解释更清楚!
代码
在www.foo.com / home.html
中,需要以下javascript代码(顺便说一下,可以从任何域上的.js文件加载该代码):
<script> // Resize iframe to full height function resizeIframe(height) { // "+60" is a general rule of thumb to allow for differences in // IE & and FF height reporting, can be adjusted as required.. document.getElementById('frame_name_here').height = parseInt(height)+60; } </script> <iframe id='frame_name_here' src='http://www.bar.net/framed.html'></iframe>
在www.bar.net/framed.html中:
<body onload="iframeResizePipe()"> <iframe id="helpframe" src='' height='0' width='0' frameborder='0'></iframe> <script type="text/javascript"> function iframeResizePipe() { // What's the page height? var height = document.body.scrollHeight; // Going to 'pipe' the data to the parent through the helpframe.. var pipe = document.getElementById('helpframe'); // Cachebuster a precaution here to stop browser caching interfering pipe.src = 'http://www.foo.com/helper.html?height='+height+'&cacheb='+Math.random(); } </script>
www.foo.com/helper.html的内容:
<html> <!-- This page is on the same domain as the parent, so can communicate with it to order the iframe window resizing to fit the content --> <body onload="parentIframeResize()"> <script> // Tell the parent iframe what height the iframe needs to be function parentIframeResize() { var height = getParam('height'); // This works as our parent's parent is on our domain.. parent.parent.resizeIframe(height); } // Helper function, parse param from request string function getParam( name ) { name = name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]"); var regexS = "[\?&]"+name+"=([^&#]*)"; var regex = new RegExp( regexS ); var results = regex.exec( window.location.href ); if( results == null ) return ""; else return results[1]; } </script> </body> </html>
如果我们不需要处理来自其他域的iframe内容,请尝试以下代码,它可以完全解决问题,而且很简单:
<script language="JavaScript"> <!-- function autoResize(id){ var newheight; var newwidth; if(document.getElementById){ newheight=document.getElementById(id).contentWindow.document .body.scrollHeight; newwidth=document.getElementById(id).contentWindow.document .body.scrollWidth; } document.getElementById(id).height= (newheight) + "px"; document.getElementById(id).width= (newwidth) + "px"; } //--> </script> <iframe src="usagelogs/default.aspx" width="100%" height="200px" id="iframe1" marginheight="0" frameborder="0" onLoad="autoResize('iframe1');"></iframe>
这是一个简单的解决方案,它使用动态生成的样式表,该样式表由与iframe内容相同的服务器提供服务。样式表非常简单地"知道" iframe中的内容,并且知道用于对iframe进行样式设置的尺寸。这绕过了相同的原始策略限制。
http://www.8degrees.co.nz/2010/06/09/dynamically-resize-an-iframe-depending-on-its-content/
因此,提供的iframe代码将具有一个随附的样式表,例如...
<link href =" http://your.site/path/to/css?contents_id=1234&dom_id=iframe_widget" rel =" stylesheet" type =" text / css" />? <iframe id =" iframe_widget" src =" http://your.site/path/to/content?content_id=1234" frameborder =" 0" width =" 100%" scrolling =" no"> </ iframe>
这确实要求服务器端逻辑能够计算iframe呈现内容的尺寸。
https://developer.mozilla.org/en/DOM/window.postMessage
window.postMessage() window.postMessage is a method for safely enabling cross-origin communication. Normally, scripts on different pages are only allowed to access each other if and only if the pages which executed them are at locations with the same protocol (usually both http), port number (80 being the default for http), and host (modulo document.domain being set by both pages to the same value). window.postMessage provides a controlled mechanism to circumvent this restriction in a way which is secure when properly used. Summary window.postMessage, when called, causes a MessageEvent to be dispatched at the target window when any pending script that must be executed completes (e.g. remaining event handlers if window.postMessage is called from an event handler, previously-set pending timeouts, etc.). The MessageEvent has the type message, a data property which is set to the string value of the first argument provided to window.postMessage, an origin property corresponding to the origin of the main document in the window calling window.postMessage at the time window.postMessage was called, and a source property which is the window from which window.postMessage is called. (Other standard properties of events are present with their expected values.)
iFrame-Resizer库使用postMessage来使iFrame保持其内容的大小,并使用MutationObserver来检测内容的更改并且不依赖jQuery。
https://github.com/davidjbradshaw/iframe-resizer
jQuery:跨域脚本编写的好处
http://benalman.com/projects/jquery-postmessage-plugin/
拥有调整iframe窗口大小的演示...
http://benalman.com/code/projects/jquery-postmessage/examples/iframe/
本文展示了如何消除对jQuery的依赖... Plus还有很多有用的信息以及与其他解决方案的链接。
http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/
准系统示例...
http://onlineaspect.com/uploads/postmessage/parent.html
window.postMessage上的HTML 5工作草案
http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
John Resig关于跨窗口消息传递
http://ejohn.org/blog/cross-window-messaging/