根据内容调整iframe的大小

我正在开发一个类似iGoogle的应用程序。 来自其他应用程序(在其他域)的内容使用iframe显示。

如何调整iframe以适应iframe内容的高度?

我试图破译谷歌使用的JavaScript,但它被混淆了,到目前为止searchnetworking已经没有结果。

更新:请注意,内容是从其他域加载的,所以适用同源策略 。

我们遇到过这种types的问题,但与您的情况略有相反 – 我们正在向其他域的网站提供iframed内容,因此同样的原产地策略也是一个问题。 经过几个小时的拖网谷歌,我们最终find了一个(某种程度上)可行的解决scheme,您可能能够适应您的需求。

围绕同一个来源策略有一个解决方法,但是它需要在iframed内容和framing页面上进行更改,所以如果你没有能力请求更改,那么这个方法对你来说并不是很有用,恐怕。

有一个浏览器的怪癖,它允许我们裙子相同的起源政策 – JavaScript可以与页面上的自己的域名,或与它的页面,但从来没有页面框架,例如,如果你有:

www.foo.com/home.html, which iframes |-> www.bar.net/framed.html, which iframes |-> www.foo.com/helper.html 

那么home.html可以与framed.htmlframed.html )和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.htmlhelper.html ),但不是 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

这里有一个关于如何处理它的解释 ,这可能比我上面稍微清晰!


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> 

https://developer.mozilla.org/en/DOM/window.postMessage

window.postMessage()

window.postMessage是一种安全启用跨源通信的方法。 通常情况下,不同页面上的脚本只允许彼此访问,当且仅当执行它们的页面位于具有相同协议(通常都是http),端口号(80是http的默认值)和主机(模数document.domain被两个页面设置为相同的值)。 window.postMessage提供了一个受控制的机制来绕过这个限制,在正确使用时是安全的。

概要

调用window.postMessage时,会在必须执行的任何挂起的脚本完成时(例如,如果从事件处理程序调用window.postMessage,之前设置的挂起超时等,则剩余的事件处理程序),导致在目标窗口上分派MessageEvent。 )。 MessageEvent具有types消息,其数据属性被设置为提供给window.postMessage的第一个参数的string值,该属性对应于在时间窗口中调用window.postMessage的窗口中主文档的来源。被调用的postMessage,以及一个来自window.postMessage被调用的窗口的源属性。 (事件的其他标准属性与预期值一起出现。)

iFrame-Resizer库使用postMessage来保持iFrame的大小,以及MutationObserver检测内容的变化,而不依赖于jQuery。

https://github.com/davidjbradshaw/iframe-resizer

jQuery:跨域脚本善良

http://benalman.com/projects/jquery-postmessage-plugin/

有resize的iframe窗口的演示…

http://benalman.com/code/projects/jquery-postmessage/examples/iframe/

本文展示了如何去除对jQuery的依赖… Plus有很多有用的信息和链接到其他解决scheme。

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

约翰Resig跨窗口消息

http://ejohn.org/blog/cross-window-messaging/

使用jQuery的最简单的方法是:

 $("iframe") .attr({"scrolling": "no", "src":"http://www.someotherlink.com/"}) .load(function() { $(this).css("height", $(this).contents().height() + "px"); }); 

http://www.phinesolutions.com/use-jquery-to-adjust-the-if​​rame-height.html上的解决scheme效果很好(使用jQuery):;

 <script type=”text/javascript”> $(document).ready(function() { var theFrame = $(”#iFrameToAdjust”, parent.document.body); theFrame.height($(document.body).height() + 30); }); </script> 

我不知道你需要增加30的长度… 1为我工作。

仅供参考 :如果您的iFrame上已有“高度”属性,则只需添加style =“height:xxx”。 这可能不是你想要的。

可能有点迟了,因为所有其他答案都比较老:-)但是…这是我的解决scheme。 在实际的FF,Chrome和Safari 5.0中testing。

CSS:

 iframe {border:0; overflow:hidden;} 

JavaScript的:

 $(document).ready(function(){ $("iframe").load( function () { var c = (this.contentWindow || this.contentDocument); if (c.document) d = c.document; var ih = $(d).outerHeight(); var iw = $(d).outerWidth(); $(this).css({ height: ih, width: iw }); }); }); 

希望这会帮助任何人。

这是一个简单的解决scheme,它使用与iframe内容相同的服务器提供的dynamic生成样式表。 很简单,样式表“知道”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的渲染内容的尺寸。

最后,我发现一些其他解决scheme,使用window.postMessage(message, targetOrigin);从iframe向父网站发送数据window.postMessage(message, targetOrigin); 。 这里我解释我是怎么做的。

网站A = http://foo.com网站B = http://bar.com

SiteB正在siteA网站内加载

SiteB网站有这条线

 window.parent.postMessage("Hello From IFrame", "*"); 

要么

 window.parent.postMessage("Hello From IFrame", "http://foo.com"); 

然后siteA有以下代码

 // Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers. var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; var eventer = window[eventMethod]; var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message"; // Listen to message from child IFrame window eventer(messageEvent, function (e) { alert(e.data); // Do whatever you want to do with the data got from IFrame in Parent form. }, false); 

如果你想添加安全连接,你可以在eventer(messageEvent, function (e) {})

 if (e.origin == 'http://iframe.example.com') { alert(e.data); // Do whatever you want to do with the data got from IFrame in Parent form. } 

对于IE

IFrame内:

  window.parent.postMessage('{"key":"value"}','*'); 

外:

  eventer(messageEvent, function (e) { var data = jQuery.parseJSON(e.data); doSomething(data.key); }, false); 

这个答案只适用于使用Bootstrap的网站。 Bootstrap的响应式embeddedfunction可以完成这项工作。 它基于内容的宽度(而不是高度)。

 <!-- 16:9 aspect ratio --> <div class="embed-responsive embed-responsive-16by9"> <iframe class="embed-responsive-item" src="http://www.youtube.com/embed/WsFWhL4Y84Y"></iframe> </div> 

jsfiddle: http : //jsfiddle.net/00qggsjj/2/

http://getbootstrap.com/components/#responsive-embed

我正在实施ConroyP的框架框架解决scheme来取代基于设置document.domain的解决scheme,但发现很难在不同的浏览器中正确地确定iframe内容的高度(现在使用FF11,Ch17和IE9进行testing)。

ConroyP使用:

 var height = document.body.scrollHeight; 

但是,这只适用于初始页面加载。 我的iframe有dynamic内容,我需要调整某些事件的iframe。

我最终做的是使用不同的JS属性为不同的浏览器。

 function getDim () { var body = document.body, html = document.documentElement; var bc = body.clientHeight; var bo = body.offsetHeight; var bs = body.scrollHeight; var hc = html.clientHeight; var ho = html.offsetHeight; var hs = html.scrollHeight; var h = Math.max(bc, bo, bs, hc, hs, ho); var bd = getBrowserData(); // Select height property to use depending on browser if (bd.isGecko) { // FF 11 h = hc; } else if (bd.isChrome) { // CH 17 h = hc; } else if (bd.isIE) { // IE 9 h = bs; } return h; } 

getBrowserData()是由Ext Core的“启发”浏览器检测functionhttp://docs.sencha.com/core/source/Ext.html#method-Ext-apply

这对FF和IE运行良好,但随后出现了Chrome的问题。 其中一个是计时问题,显然需要Chrome一段时间来设置/检测iframe的高度。 然后,如果iframe高于内容,则Chrome也不会正确返回iframe中内容的高度。 当高度降低时,这不适用于dynamic内容。

为了解决这个问题,我总是将iframe设置为较低的高度,然后检测内容的高度,然后将iframe的高度设置为正确的值。

 function resize () { // Reset the iframes height to a low value. // Otherwise Chrome won't detect the content height of the iframe. setIframeHeight(150); // Delay getting the dimensions because Chrome needs // a few moments to get the correct height. setTimeout("getDimAndResize()", 100); } 

代码没有优化,这是从我的develtesting:)

希望有人认为这有帮助!

 <html> <head> <script> function frameSize(id){ var frameHeight; document.getElementById(id).height=0 + "px"; if(document.getElementById){ newheight=document.getElementById(id).contentWindow.document.body.scrollHeight; } document.getElementById(id).height= (frameHeight) + "px"; } </script> </head> <body> <iframe id="frame" src="startframe.html" frameborder="0" marginheight="0" hspace=20 width="100%" onload="javascript:frameSize('frame');"> <p>This will work, but you need to host it on an http server, you can do it locally. </p> </body> </html> 

TinyMCE做到这一点,而不是混淆。

iGoogle小工具必须积极实施resize,所以我的猜测是在跨域模式中,如果没有以某种方式参与远程内容,就无法做到这一点。 如果您的内容可以使用典型的跨域通信技术将新的大小的消息发送到容器页面,则其余部分很简单。

当你想缩小一个网页,以适应iframe的大小:

  1. 您应该调整iframe以适应内容
  2. 然后你应该用加载的网页内容缩小整个iframe

这里是一个例子:

 <div id="wrap"> <IFRAME ID="frame" name="Main" src ="http://www.google.com" /> </div> 

 <style type="text/css"> #wrap { width: 130px; height: 130px; padding: 0; overflow: hidden; } #frame { width: 900px; height: 600px; border: 1px solid black; } #frame { zoom:0.15; -moz-transform:scale(0.15);-moz-transform-origin: 0 0; } </style> 

下面是一个jQuery方法,通过iframe的src属性在json中添加信息。 这里是一个演示,resize和滚动这个窗口..结果与JSON的url看起来像这样… http://fiddle.jshell.net/zippyskippy/RJN3G/show/#{docHeight:5124,windowHeight:1019,scrollHeight: 571}#

这里的源代码小提琴http://jsfiddle.net/zippyskippy/RJN3G/

 function updateLocation(){ var loc = window.location.href; window.location.href = loc.replace(/#{.*}#/,"") + "#{docHeight:"+$(document).height() + ",windowHeight:"+$(window).height() + ",scrollHeight:"+$(window).scrollTop() +"}#"; }; //setInterval(updateLocation,500); $(window).resize(updateLocation); $(window).scroll(updateLocation); 

获取iframe内容的高度,然后把它给这个iframe

  var iframes = document.getElementsByTagName("iframe"); for(var i = 0, len = iframes.length; i<len; i++){ window.frames[i].onload = function(_i){ return function(){ iframes[_i].style.height = window.frames[_i].document.body.scrollHeight + "px"; } }(i); } 

使用jquery加载(跨浏览器):

  <iframe src="your_url" marginwidth="0" marginheight="0" scrolling="No" frameborder="0" hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%" width="100%"></iframe> function loaderIframe(){ var heightIframe = $('#containiframe').contents().find('body').height(); $('#frame').css("height", heightFrame); } 

在响应页面中resize:

 $(window).resize(function(){ if($('#containiframe').length !== 0) { var heightIframe = $('#containiframe').contents().find('body').height(); $('#frame').css("height", heightFrame); } }); 

使用jQuery:

parent.html

 <body> <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <style> iframe { width: 100%; border: 1px solid black; } </style> <script> function foo(w, h) { $("iframe").css({width: w, height: h}); return true; // for debug purposes } </script> <iframe src="child.html"></iframe> </body> 

child.html

 <body> <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <script> $(function() { var w = $("#container").css("width"); var h = $("#container").css("height"); var req = parent.foo(w, h); console.log(req); // for debug purposes }); </script> <style> body, html { margin: 0; } #container { width: 500px; height: 500px; background-color: red; } </style> <div id="container"></div> </body> 

这是有点棘手,因为你必须知道何时加载iframe页面,这是非常困难的,当你不能控制其内容。 它可能添加一个onload处理程序的iframe,但我已经尝试过,它有不同的浏览器行为(不猜猜谁是最讨厌的…)。 您可能需要添加一个函数到执行resize的iframe页面,并在内容中插入一些脚本来监听加载事件或调整事件大小,然后调用前一个函数。 我想添加一个function的页面,因为你想确保它的安全,但我不知道要做多么容易。

这个我相信的东西应该工作。

 parent.document.getElementById(iFrameID).style.height=framedPage.scrollHeight; 

加载这个iframe内容的正文。

我有一个简单的解决scheme,并要求你确定在链接的宽度和高度,请尝试(它适用于大多数浏览器):

 <a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>