cross-domain iframe resizing

How to resize iframe from another domain

-Edit

Scroll down for some solutions .. or read how NOT to do it: D

After many hours of hacking code, the conclusion is that everything inside the iframe is inaccessible, even the scroll bars that appear in my domain. I tried many methods to no avail.

To save your time, don’t even go down this route, just use sendMessages for cross-domain communication. There are plugins for HTML <5 that I use- Go to the bottom for a nice example :)




For the past few days, I have been trying to integrate iframes into the site. This is a short-term solution, while the other side is developing, and the API (may take months ...) And since it is like a short-term solution that we wanted to use easyXDM-, I have access to another domain, but it is quite difficult to ask them add p3p header as it is .....

3 frames

The closest solution I found was 3 iframes-, but it has smart chrome and safari, so I cannot use this.

open in chrome

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

Scroll bar measurement

I found another post on how to use scrollheight to try to resize the form. Theoretically, this works well, but I could not apply it correctly using the iframes scroll height.

document.body.scrollHeight 

That obvoisly uses body height (cannot access these properties, 100% based on the canvaz client display, not the height of the x-domains document)

I tried using jquery to get iframes height

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

return values ​​differ in chrome, etc. - or just don't make sense at all. The problem is that everything inside the denied frame is even a scrollbar ...

Computational Styles

But if I check the element in the chrome iframe, it bladdy shows me the sizes of the documents inside the iframe (using jquery x-domain to get iframe.heigh - access is denied). In computed CSS enter image description here there is nothing,

Now, how did chrome figure it out? (the edit- browser re-renders the page using its assembly in the rendering engine to calculate all of these parameters - but they are not tied anywhere to prevent cross-domain fraud .. so ..)

HTML4

I read the HTML4.x specification and it says that there should be read-only values ​​through the document.element document, but access to them is denied through jquery

Proxy framework

I went along the path of proxying the site and calculated that everything is in order .. until the user logs in through the iframe and the proxy server receives a login page instead of the actual content. Also for some calls the page is twice unacceptable

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

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

Redisplay page

I haven’t gone that far, but there are jscript engines that will look at the source and re-render the page based on the source file. but it will require hacking these jscripts .. and this is not an ideal situation for commercials ... and some invoke pure java applets or server visualization

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

http://htmlunit.sourceforge.net/ <-java not jscript

http://maxq.tigris.org/




EDIT 09-2013 UPDATE

All of this can be done using HTML5 sockets. But easyXDM is great for non-HTML5 complaint pages.

Solution 1 A very big solution!

Using easyXDM

On your server, you created a page in the form

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

and in the caller domain they just need to add intermiedate_frame html and easyXDM.js in the same place. As a parent folder - then you can access relative directories or a folder that is at your disposal just for you.

OPTION 1

If you do not want to add scripts to all pages, look at option 2!

Then they can simply add plain jscript to the end of every page that needs to be resized. You do not need to enable easyxdm on each of these pages.

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

I changed the parameters that it sends. If you want the width to work correctly, then pages on another domain should include the page width in a style that looks something like this:

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

This works great for me. If the width is not included, then the frame behaves a little strange, and it tries to guess what it should be .. and will not be reduced if you need it.

OPTION 2

Change the intermediate frame to poll changes

Your intermediate frame should look something like this.

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

The interval may be more efficient for chaeck if the size has changed and is only sent if the resizing is sending messages every 500 ms. If you complete this check, you can change the poll to 50 ms! have some fun




Work in browsers and fast. Great debugging features!

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



Solution 2 (works, but not very good)

Therefore, if you have mutual agreement with another domain, you can add a library to handle sendmessage. If you do not have access to another domain, keep looking for more hacks- because I could not find or fully justify them that I found.

Thus, Head tags will be included in another domain.

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

In club.js there are only some user calls that I made to resize calls and contains ..

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

And your page will do all the hard work and has a good script ...

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



OPTION 3

They are currently a small JS library for managing cross-domain resizing of iFrames, but the iFrame still needs a bit of JavaScript, but it's just 2.8k (765 Gzipped bytes) of embedded JS that has no dependencies and it does nothing until called by the parent page. This means that this is a good guest in other people.

This code uses mutationObserver to detect DOM changes, and also looks for resize events so that the iFrame remains the size of the content. Works in IE8 +.

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

+81
html css scripting cross-domain iframe
May 6 '11 at 8:18
source share
9 answers

The fact is that there is no other way for this than using cross-domain transfer, since you need to get the calculated height from a document in one domain, into a document in another domain.

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

The other side really just needs to copy several files to their domain and add one line of code to their document.

+9
May 6 '11 at 3:06 p.m.
source share
— -

Similar to what Sean mentioned, you can use postMessage. I spent so much time trying to resize the iframe differently using a cross-domain, but no luck until I came across this wonderful David Walsh blog post: http://davidwalsh.name/window-iframe

This is a combination of my code and David's solution. My solution is specifically designed to resize iframes.

On the child page, find the page height and pass it to the parent page (containing 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 

In 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 that the height will be printed in the console log. This will help you in debugging, so I left it there.

Best, Baker

+22
Mar 21 '13 at 21:34
source share

Having reviewed many different solutions, I ended up writing a small, small library to calculate several different use cases. Since I needed a solution that supported several iFrames created by the user on the portal page, supported browser sizes and the ability to handle loading JavaScript on the main page after iFrame. I also add size support for the width and callback function and allow the redefinition of body.margin, as you will most likely want this set to be zero.

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

Iframe code is just a little stand-alone JavaScript, so it’s a good guest on other people's pages.

Then the script is initialized on the main page with the following available parameters.

 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 ); } }); 
+6
Jun 17 '13 at 22:17
source share

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

 $(window).height(); 

and use this as an iframe height attribute.

Well, the result ...

We will never have a scroll of the "page", only an "iframe" scroll. When you move, it doesn't matter who the scroll is, but what matters is that there is only 1.

Well, there the user problem simply resizes the window during navigation. To solve this problem, I use:

 setInterval(getDocHeight, 1); 

Did you think that this decision would cause errors? It works for me, and on iFrame I had a dynamic contet created by php. I am afraid of future mistakes with this ...

0
Dec 03 '11 at 3:13
source share

Currently, I know only 4 solutions:

Only the third solution can solve many problems. For example, you can create a responsive iFrame ; close it from the inside or , you can chat with it . But for this you need an iFrame in the iframe and a workaround for third-party cookies (optional).

I created an article about this with an example: Event-Driven Cross-Domain iFrame

0
Apr 01 '15 at 21:14
source share

Have you examined the HTML5 attributes appropriate for the object? Scales video / images in an iframe, rather than scaling an iframe (nice if you capture a medium-sized image that ends in a width of 5000 pixels). The “fit” option (others - “cover” and “fill”) uses a letter-sorting approach to match the source while maintaining proportions. To view HTML5-less, there seem to be many polyps there. This is great, but an error at the end of Edge kept it incompatible with Microsoft New Nightmare for a year now: https://github.com/anselmh/object-fit p>

EDIT. To get around cross-domain issues, you can always simply work with the contents of the internal contents of Chrome Script, since it considers it to be part of the page on which you attach your iframe.

0
Mar 12 '16 at 5:42 on
source share

Https another link get height 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> 



Desktop:

xcom http> ycom https WORK

xcom https> ycom https WORK

xcom http> ycom http WORK

xcom https> ycom http WORK

Test work screenshots

0
Jan 05 '18 at 13:38
source share

Do you want to find the height of the page contained in the iframe? I got some javascript work that checks the height of the contents of an iframe and then sets the height of the iframe 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 displayed in the iframe is in the same domain. If not, you cannot get the necessary information. Therefore, access is denied.

-2
May 6 '11 at 8:32
source share

To resize the iframe, here is just a script:

this goes to the head: (it was written for php script, for html, change "to" and "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

it goes in the body (remember that it was written for php script, for html change everything "to" and "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 are some hints above. Since it is configured for php scripts, you can do a lot with it ... learn more, do more ...

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

have phun.

-2
Jan 09 '14 at 23:25
source share



All Articles