跨域 iframe 调整大小

如何从另一个域调整 iframe 的大小?

过去几天,我一直在尝试将一个 iframe 集成到一个站点中。这是一个短期的解决方案,而另一方开发和 API (可能需要几个月...) 因为这是作为短期解决方案,我们确实想使用 easyXDM-我有权访问其他域,但它的困难足以要求他们添加 p3p 头,因为它是... ..。

3个 iframe

我找到的最接近的解决方案是3 iframe-但它去精神的 chrome 和狩猎,所以我不能使用。

用铬合金打开

Http://css-tricks.com/examples/iframeresize/crossdomain.php#frameid=frame-one&height=1179

测量滚动条

I found a another post on how to use the scrollheight to try and resize the form.. in theory it works well but I could not apply it properly using the iframes scroll height..

document.body.scrollHeight

这显然使用了主体高度(不能100% 访问这些属性是基于客户端显示画布而不是 X 域文档高度)

我尝试使用 jQuery 来获得 iframe 的高度

$('#frameId').Height()


$('#frameId').clientHeight


$('#frameId').scrollHeight

返回的值在 chrome 和 ie 中不同-或者根本没有意义。 问题是框架内的所有东西都被拒绝了-甚至滚动条..。

计算样式

但是,如果我检查 iframe 的 chrome 中的元素,它会很糟糕地向我显示 iframe 内部的文档维度(使用 jQuery x-domain 来拒绝 iframe. heigh-access) 计算出的 CSS < img src = “ https://i.stack.imgur.com/wox5C.jpg”alt = “”/>

中没有任何内容

Now how does chrome calculate that? (edit- browser re-renders the page using its build in rendering engine to calculate all these settings - but are not attached anywhere to prevent cross-domain fraud.. so..)

HTML4

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

代理框架

I went down the route of proxying the site back and calculating which is OK.. until a user logs in through the iframe and the proxy gets a login page instead of the actual content. Also to some calling the page twice is not acceptable

Http://www.codeproject.com/kb/aspnet/asproxy.aspx

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

重新渲染页面

I did not go this far but there are jscript engines out there that will look at the source and re-render the page based on the source file. but it would require hacking those jscripts.. and that's not an ideal situation for commercial entities... 有些调用纯 Java 小应用程序或服务器端呈现

Http://en.wikipedia.org/wiki/server-side_javascript

Http://htmlunit.sourceforge.net/ <-java 而非 jscript

Http://maxq.tigris.org/


所有这些都可以用 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>

在调用者域中,它们只需要将中间 _ frame HTML 和 easyXDM.js添加到相同的位置。像父文件夹-然后你可以访问相对目录或包含的文件夹只为你。

93669 次浏览

Are you looking to find the height of the page contained within the iframe? I got some javascript working which checks the height of the iframe content then sets the iframe's height to the height of the content.

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


document.getElementById('iFrameId').height = Height;

However, this only works if the page you are showing in the iframe is on the same domain. If it's not you cannot access the required information. Hence, the access denied error.

The thing is - there is no other way than using Cross-Domain Messaging for this since you need to get the computed height from a document in one domain, to a document in a different domain.

So, either you do this using postMessage (works in all moder browsers), or you spend 5 minutes adapting the resize iframe example from easyXDM.

The other party really just needs to copy a few files onto their domain, and add a single line of code to their document..

Instead of use scroll=no on the iframe, I change it to "auto". Then, I get the size of the actual window

$(window).height();

and use that as the iframe height attribute.

Well, the result is...

We will never have the "page" scroll, only the "iframe" scroll. When You navigate, doesn't matter who is the scroll, but the important is that there's only 1.

Well, there's the problem of the user simply resize the window while he's navigating. To solve that, I use:

setInterval(getDocHeight, 1);

Did You think that that solution will cause any bugs? It's working for me, and on the iFrame I had dynamic contect generated by php. I'm afraid of future bugs with that...

Similar to what Sean has mentioned, you can use postMessage. I've spent so much time trying different ways to resize iframe with cross-domain but no luck until I stumbled on this great blog post by David Walsh: http://davidwalsh.name/window-iframe

This is a combination of my code and David's solution. My solution is geared specifically toward resizing iframes.

In the child page, find the height of the page and pass it to the parent page (which contains the iframe). Replace element_id with your element id (html, body, whatever).

<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

On the parent window, add this code. Replace iframe_id with your 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>

If you open the console, you will see the height being printed in the console log. This will help you in debugging which is why I left it there.

Best, Baker

Having looked a lots of different solution to this I ended up writing a simple small library to take a account of a number of different use cases. As I needed a solution that supported multiple user generated iFrames on a portal page, supported browser resizes and could cope with the host page JavaScript loading after the iFrame. I also add support for sizing to width and a callback function and allow the override of the body.margin, as you will likely want to have this set to zero.

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

The iframe code is just a little self-contained JavaScript, so that it's a good guest on other people pages.

The script is then initialised on the host page with the following available options.

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
);
}
});

To resize an iframe, here's a simple script:

this goes in the head: (this was written for a php script, for html, change the ' to " and the \" to '...

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

end of head

this goes in the body (remember, this was written for a php script, for html change all the ' to " and the \" to '...)

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

bonus: there's some hints above. As it is set for php scripting, you can do a lot with it...to learn more, do more...

the key to this is "sizeframe1" .... for multiple "resizers" on the same page, copy the same script but change the id in iframe and the name in the script in the head, and viola! you have multiple resizers on the same page...it works very well!

have phun.

Nowadays there is only 4 solutions I know:

Only the third one can resolve many problems. For example you can create responsive iFrame; close it from inside or you can communicate with it. But to do that you need iFrame in Iframe and the "third party cookies" workaround (optional).

I've created an article about it with example: Event-driven cross-domain iFrame

Have you looked into the 'object-fit' HTML5 attributes? Scales video/images to the iframe, rather than scaling the iframe (nice if you grab a medium-sized image that ends up being 5,000px in width). The "fit" option (others are "cover" and "fill") uses a sort-of-letterbox approach to fit the source in while preserving the aspect ratios. For viewing by the HTML5-less out there, it looks like there a whoooole lot of polyfills available. This one is great, but a bug on Edge's end has kept it incompatible with Microsoft's New Nightmare for about a year, now: https://github.com/anselmh/object-fit

EDIT: To get around cross domain issues, you can always just do the work in a Chrome Extension Content Script, since it thinks it's part of the page you're sticking your iframe on.

HTTPS another link get height to iframe autoheight

https://-a.com content:

 <!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 content:

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

Work Table:

xcom http > ycom https WORK

xcom https > ycom https WORK

xcom http > ycom http WORK

xcom https > ycom http WORK

Test Work Screenshot