📜 ⬆️ ⬇️

Automatic cross-domain height setting Iframe

I think many who have encountered the iframe in their work have also faced the task of setting the height of this i-frame itself.

This may be necessary, for example, when you want to enable users to put widgets from your site on their site, and you want the size of the container (iframe) of the widget to match the size of the contents of this widget.

In Yandex, you can find many solutions to this problem, but most of them have one problem: they do not support the ability to resize a window when the contents of the iframe and the parent element are in different domains.
')
There is one good cross-domain solution , but it was written in 2007, and much has changed since then. Therefore, we had to develop a solution to this problem on our own, based on the above solution.



Actually, the main thing that has changed is the window.postMessage tool, which allows browser windows to exchange messages, appeared. Due to this we will be able to make an analogue of the above solution, which has the following advantages:


Our code should not depend on any external factors, and to use it, it should be enough to connect 2 js files on the content side of the frame (one for postMessage, and the thief - ours), and on the client side to connect also 2 js files and add There are two attributes for the iframe - id and name (must be identical), as well as on ifload to hang up the iframe registration.

To work with postmessage we will use the following library:
postmessage.freebaseapps.com
This library is a very convenient wrapper for window.postMessage, which, among other things, also allows using data transfer via hash in browsers that do not support window.postMessage.

The logic of the script is extremely simple - on the client page we “register” the iframe - send the child page (which is in the iframe) the identifier of this iframe and subscribe to messages from the child page. Upon receipt of the message - resize.

On the side of the child page (which is in the iframe), we in turn subscribe to registration messages, when it arrives, we remember the identifier and turn on the timer, which, when the size of the frame changes in size, sends the parent page information that the iframe needs to be changed.

Actually that's all. The script code itself:

FrameManager.js (client script)
var FrameManager = { registerFrame : function(frame) { pm({ target: window.frames[frame.id], type: "register", data: {id:frame.id}, url: frame.contentWindow.location }); pm.bind(frame.id, function(data) { var iframe = document.getElementById(data.id); if (iframe == null) return; iframe.style.height = (data.height+12).toString() + "px"; }); } }; 


Frame.js (script for frame content)
 var FrameHeightManager = { FrameId: '', getCurrentHeight : function() { myHeight = 0; if( typeof( window.innerWidth ) == 'number' ) { myHeight = window.innerHeight; } else if( document.documentElement && document.documentElement.clientHeight ) { myHeight = document.documentElement.clientHeight; } else if( document.body && document.body.clientHeight ) { myHeight = document.body.clientHeight; } return myHeight; }, publishHeight : function() { if (this.FrameId == '') return; //   jQuery -        if(typeof jQuery === "undefined") { var actualHeight = (document.body.scrollHeight > document.body.offsetHeight)?document.body.scrollHeight:document.body.offsetHeight; var currentHeight = this.getCurrentHeight(); } else { var actualHeight = $("body").height(); var currentHeight = $(window).height(); } if(Math.abs(actualHeight - currentHeight) > 20) { pm({ target: window.parent, type: this.FrameId, data: {height:actualHeight, id:this.FrameId} }); } } }; pm.bind("register", function(data) { FrameHeightManager.FrameId = data.id; //     this window.setInterval(function() {FrameHeightManager.publishHeight.call(FrameHeightManager)}, 300); }); 


And we will write 2 test html-pages:

test.html (parent)
 <!DOCTYPE html> <html> <body> <script src="postmessage.js"></script> <script src="FrameManager.js"></script> <iframe height="10" id="frame1" name="frame1" src="test2.html" onload="FrameManager.registerFrame(this)" scrolling="no" frameborder="0" marginheight="0" marginwidth="0" ></iframe> </body> </html> 


test2.html (child)
 <!DOCTYPE html> <html> <body> <!--<script src="http://yandex.st/jquery/1.7.1/jquery.min.js"></script>--> <script src="postmessage.js"></script> <script src="Frame.js"></script> <div style="border:1px solid red;margin:0; height:200px;"> test </div> </body> </html> 


In the child page, you can also uncomment a piece of code with a jquery connection — then the height definition will be more accurate. I would be grateful for the normal cross-browser functions for determining the size of the page and the window, I used the first ones that I found - they work, but pixels on 10 in the webkite allow for error.

For me, this is uncritical, because I have jquery on the client side (i.e., in the child page), but someone may not have it - then the code will still work.

Source: https://habr.com/ru/post/140316/


All Articles