然而,另一个跨域iframe调整问答

我如何调整从另一个域的iframe

-编辑

向下滚动一些解决scheme..或阅读如何不这样做:D

经过数小时的代码黑客攻击,结论是iframe中的任何内容都无法访问,即使是在我的域上呈现的滚动条也是如此。 我已经尝试了很多技术无济于事。

为了节省你的时间,甚至不要走这条路线只使用sendMessages跨域通信。 有插件的HTML <5,我使用 – 去底部的一个很好的例子:)


过去几天,我一直在尝试将iframe集成到一个站点中。 这是一个短期的解决scheme,而另一方开发和API(可能需要几个月…),因为这是短期的解决scheme,我们想要使用easyXDM-我有权访问另一个域名,但它的要求很难添加p3p标题,因为它是…..

3个内联框架

我find的最接近的解决scheme是3个内置框架 – 但它的精髓在于铬和Safari浏览器,所以我不能使用它。

在铬打开

http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179

测量滚动条

我发现另一篇文章如何使用scrollheight来尝试和调整窗体..理论上,它运作良好,但我不能适当使用iframes滚动高度..

document.body.scrollHeight 

那obvoisly使用身体高度(不能访问这些属性100%是基于客户端显示canvaz而不是x域的文件高度)

我厌倦了使用jquery获取iframes的高度

 $('#frameId').Height() $('#frameId').clientHeight $('#frameId').scrollHeight 

返回铬和ie不同的值 – 或者根本没有意义。 问题是,框架内的所有内容都被拒绝 – 即使滚动条…

计算样式

但是,如果我检查和iframe的铬元素它bladdy显示我的iframe中的文件维度(使用jQuery的X域来获取iframe.heigh – 访问被拒绝)计算的CSS中没有什么 在这里输入图像说明

现在铬是如何计算的? (编辑 – 浏览器使用其在渲染引擎中的内部版本重新呈现页面以计算所有这些设置 – 但是没有附加到任何地方以防止跨域欺诈..如此..)

HTML4

我读了HTML4.x的规范,它说那里应该有通过document.element公开的只读值,但它的访问被拒绝通过jQuery

代理框架

我沿着代理网站的路线返回并计算哪个是好的。直到用户通过iframelogin,代理获取login页面而不是实际的内容。 也有人呼吁两次的页面是不能接受的

http://www.codeproject.com/KB/aspnet/asproxy.aspx

http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/

重新渲染页面

我没有走这么远,但有jscript引擎在那里将看源代码,并重新呈现基于源文件的页面。 但这将需要黑客那些jscripts ..那不是商业实体的理想情况…和一些invole纯java小程序或服务器端渲染

http://en.wikipedia.org/wiki/Server-side_JavaScript

http://htmlunit.sourceforge.net/ <-java不是jscript

http://maxq.tigris.org/


编辑09-2013 更新

所有这些都可以通过HTML5套接字完成。 但easyXDM对于非HTML5投诉页面来说是非常好的回退。

解决scheme1极好的解决scheme

使用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.com/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> 

并且在调用者域上,他们只需要在同一个地方添加intermiedate_frame html和easyXDM.js。 就像一个父文件夹 – 那么你可以访问相对目录或一个包含的文件夹只为你。

选项1

如果你不想把脚本添加到所有的页面,看看选项2!

然后他们可以添加一个简单的jscript到每个需要resize的页面的末尾。 无需在每个页面中包含easyxdm。

  <script type="text/javascript"> window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) ); }; </script> 

我修改了它发送的参数。 如果您希望宽度能够正常工作,则其他域中的页面需要在类似于以下内容的样式中包含页面的宽度:

 <style type="text/css"> html, body { overflow: hidden; margin: 0px; padding: 0px; background-color: rgb(75,0,85); color:white; width:660px } a { color:white; visited:white; } </style> 

这对我很好。 如果宽度不包括在内,那么框架的行为有点奇怪,试图猜测它应该是什么,如果你需要的话,它不会缩小。

scheme2

修改中间帧来轮询更改

你的中间框架应该看起来像这样

  <!doctype html> <html> <head> <title>Frame</title> <script type="text/javascript" src="easyXDM.js"> </script> <script type="text/javascript"> var iframe; var socket = new easyXDM.Socket({ //This is a fallback- not needed in many cases swf: "easyxdm.swf", onReady: function(){ iframe = document.createElement("iframe"); iframe.frameBorder = 0; document.body.appendChild(iframe); iframe.src = "THE HOST FRAME"; iframe.onchange = messageBack(); }, onMessage: function(url, origin){ iframe.src = url; } }); //Probe child.frame for dimensions. function messageBack(){ socket.postMessage ( iframe.contentDocument.body.clientHeight + "," + iframe.contentDocument.body.clientWidth); }; //Poll for changes on children every 500ms. setInterval("messageBack()",500); </script> <style type="text/css"> html, body { overflow: hidden; margin: 0px; padding: 0px; width: 100%; height: 100%; } iframe { width: 100%; height: 100%; border: 0px; } </style> </head> <body> </body> </html> 

如果大小发生变化,间隔可以变得更加有效,只有在维度发生变化时才发送,而不是每隔500ms发送一次消息。 如果你执行这个检查,那么你可以改变轮询低至50毫秒! 玩的开心


跨浏览器工作,速度很快。 伟大的debuggingfunction!

 Excellent Work to Sean Kinsey who made the script!!! 

解决scheme2 (工作但不是很好)

所以基本上,如果你有与其他域的共识,那么你可以添加一个库来处理sendmessage。 如果你没有任何访问其他域..继续寻找更多的黑客 – 因为我找不到或完全certificate我发现的这些。

所以其他域将包括这些头标签

 <script src="scripts/jquery-1.5.2.min.js" type="text/javascript"></script> <script src="scripts/jquery.postmessage.min.js" type="text/javascript"></script> <script src="scripts/club.js" type="text/javascript"></script> 

在club.js只是一些自定义调用我为resize调用和包含..

  $(document).ready(function () { var parent_url = decodeURIComponent( document.location.hash.replace( /^#/, '' ) ),link; //Add source url hash to each url to authorise callback when navigating inside the frame.Without this clicking any links will break the communication and no messages will be received $('a[href]').each(function(){ this.href = this.href + document.location.hash ; }); //Get the dimensions and send back to calling page. var h1 = document.body.scrollHeight; var w1 = document.body.scrollWidth; $.postMessage({ if_height: h1, if_width: w1 }, parent_url, parent ); }); 

而你的网页将会做所有的努力工作,并有一个很好的脚本…

  //This is almost like request.querystring used to get the iframe data function querySt(param, e) { gy = e.split("&"); for (i = 0; i < gy.length; i++) { ft = gy[i].split("="); if (ft[0] == param) { return ft[1]; } } } $(function () { // Keep track of the iframe dimensions. var if_height; var if_width; // Pass the parent page URL into the Iframe in a meaningful way (this URL could be // passed via query string or hard coded into the child page, it depends on your needs). src = 'http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm' + '#' + encodeURIComponent(document.location.href), // Append the Iframe into the DOM. iframe = $('<iframe " src="' + src + '" width="100%" height="100%" scrolling="no" frameborder="0"><\/iframe>').appendTo('#iframe'); // Setup a callback to handle the dispatched MessageEvent event. In cases where // window.postMessage is supported, the passed event will have .data, .origin and // .source properties. Otherwise, this will only have the .data property. $.receiveMessage(function (e) { // Get the height from the passsed data. //var h = Number(e.data.replace(/.*if_height=(\d+)(?:&|$)/, '$1')); var h = querySt("if_height", e.data); var w = querySt("if_width", e.data); if (!isNaN(h) && h > 0 && h !== if_height) { // Height has changed, update the iframe. iframe.height(if_height = h); } if (!isNaN(w) && w > 0 && w !== if_width) { // Height has changed, update the iframe. iframe.width(if_width = w); } //For debugging only really- can remove the next line if you want $('body').prepend("Recieved" + h + "hX" + w + "w .. "); // An optional origin URL (Ignored where window.postMessage is unsupported). //Here you must put the other domain.com name only! This is like an authentication to prevent spoofing and xss attacks! }, 'http://www.OTHERDOMAIN.co.uk'); }); 

scheme3

他们现在是一个小型的JS库,用于pipe理resize的跨域iFrames,它仍然需要iFrame有一点JavaScript,但是,这是只有2.8k(765字节Gzipped)的本地JS没有任何依赖在父页面调用之前它什么也不做。 这意味着这是其他人系统上的好客人。

这段代码使用了mutationObserver来检测DOM的变化,并寻找resize的事件,使iFrame保持大小的内容。 适用于IE8 +。

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

问题是 – 除了使用跨域消息传递之外,没有别的办法了,因为您需要从一个域中的文档到另一个域中的文档计算高度。

因此,要么使用postMessage (适用于所有现代浏览器),要么使用easyXDM 调整resize iframe示例 5分钟。

另一方真的只需要复制几个文件到他们的域,并添加一行代码到他们的文件..

类似于肖恩提到的,你可以使用postMessage。 我花了很多时间尝试不同的方式来调整iframe的跨域,但没有运气,直到我偶然发现了伟大的博客文章大卫沃尔什: http : //davidwalsh.name/window-iframe

这是我的代码和David的解决scheme的组合。 我的解决scheme专门针对调整内嵌框架。

在子页面中,find页面的高度并将其传递给父页面(其中包含iframe)。 用你的元素id(html,body,什么)replaceelement_id。

 <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 IDreplaceiframe_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> 

如果您打开控制台,您将看到在控制台日志中打印的高度。 这将帮助你debugging,这就是为什么我把它留在那里。

最好的贝克

看了很多不同的解决scheme之后,我写了一个简单的小型库来logging一些不同的用例。 由于我需要一个支持门户页面上的多个用户生成的iFrames的解决scheme,支持的浏览器resize,并可以处理iFrame后的主机页面JavaScript加载。 我还添加了对宽度和callback函数的大小的支持,并允许覆盖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 ); } }); 

而不是在iframe上使用scroll = no,我将其更改为“auto”。 然后,我得到实际窗口的大小

 $(window).height(); 

并将其用作iframe高度属性。

那么结果是…

我们永远不会有“页面”滚动,只有“iframe”滚动。 当你浏览的时候,滚动的人不重要,但重要的是只有1。

那么,用户在浏览时只需调整窗口的大小就可以了。 为了解决这个问题,我使用:

 setInterval(getDocHeight, 1); 

你认为这个解决scheme会造成什么错误? 它正在为我工​​作,并在iFrame上我有dynamic比较生成的PHP。 我害怕将来的错误

现在只有4个我知道的解决scheme:

  • postMessage的。 有些浏览器当然不支持 。
  • window.location.hash操作。 我认为这是解决scheme2
  • easyXDM
  • window.name传输

只有第三个可以解决很多问题。 例如, 您可以创build响应式iFrame ; 从里面closures它,或者你可以与它沟通 。 但要做到这一点,你需要iframe中的iframe和“第三方cookie”解决方法(可选)。

我用例子创build了一篇关于它的文章: 事件驱动的跨域iFrame

你有没有看过“对象适合”的HTML5属性? 将video/图像缩放到iframe,而不是缩放iframe(如果抓取最终宽度为5000px的中等大小的图像,则不错)。 “适合”选项(其他是“封面”和“填充”)使用信箱的方式来适应来源,同时保持高宽比。 对于HTML5以外的地方来看,它看起来像是有很多可用的polyfill。 这个很好,但Edge的一个bug使它与微软的New Nightmare在一年之内不兼容,现在是https://github.com/anselmh/object-fit

编辑:要解决跨域的问题,你总是可以在Chrome扩展内容脚本中完成这项工作,因为它认为它是粘贴在你的iframe上的页面的一部分。

您是否正在寻找包含在iframe中的页面的高度? 我得到了一些javascript工作,它检查iframe内容的高度,然后将iframe的高度设置为内容的高度。

 var Height = document.getElementById('iFrameId').contentWindow.document.body.scrollHeight; document.getElementById('iFrameId').height = Height; 

但是,只有当您在iframe中显示的页面位于同一个域上时,此function才有效。 如果不是,则无法访问所需的信息。 因此,访问被拒绝错误。

要调整一个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”….对于同一页面上的多个“resizer”,复制相同的脚本,但改变iframe中的id和头部脚本中的名称,以及viola! 你在同一页面上有多个resizer …它工作得很好!

有phun。