Julian Jelfs’ Blog

Cross-domain automatic iframe resizing

Posted in Uncategorized by julianjelfs on December 3, 2009

As we all know there are security restrictions when script from domain A tries manipulate content from domain B. This causes a lot of inconvenience. One example is automatic iframe resizing. It sounds simple on the face of it. When your iframe content loads you just need to tell the parent window what the content size is and then it can resize the iframe for you. The problem is that if the iframe content does not come from the same domain as the main page, you cannot do this. At least you cannot do this in the way you expect to.

This is a fairly well documented problem and the most common solution is to use the url fragment identifier hack. Basically this hack exploits the fact that any window or frame can set the location of any other window or frame (although perhaps counter intuitively it cannot read the location of a window from a different domain).

This trick can be used to accomplish cross-domain iframe resizing. Having googled this subject I found a good post on how to do this here. While the code in that post works well, I think it is quite verbose and in the end I reduced it to the following:

For each frame on the page, set the hash fragment of the frame’s src attribute to be the frame’s id:

<iframe id="myFrame"
    scrolling="no"
    frameborder="0"
    width="100%"
    src="whatever.aspx?name=val#myFrame">
</iframe>

In the main page add the following script to execute when the page starts up (I’m using jQuery here but you don’t have to):

window.setInterval(function(){
    var hash = window.location.hash.replace("#","");
    if(hash.length == 0)
        return;

    var pair = hash.split("=");
    $("#"+pair[0]).animate({height:pair[1]});
    window.location.hash = "";
}, 100);
and in each content page being loaded add the follow script to execute when the page starts up:
window.setInterval(function(){
    if(top == self)
        return;

    var bh = $("body").height();
    var wh = $(window).height();

    if  (Math.abs(bh - wh) > 10){
        var hash = self.location.hash.replace("#","");
        if(hash.length == 0)
            return;
        top.location.hash = hash + "=" + (bh + 10);
    }
}, 100);

What’s happening? Each content window is running a loop which detects if its window is either too big or too small and if it is, it writes a name value pair containing the id of the frame and the required height e.g. frameId=500 to the hash fragment of the main window’s url. It gets the frameId from its own hash fragment. This is allowed because we are simply writing to the hash, not trying to read. It will not cause a reload because we are only updating the hash fragment.

Meanwhile the main page is running a loop to monitor its own hash fragment looking for modifications made by the frames. When it finds a name value pair in its hash fragment it simply finds the corresponding frame and sets its height (animation an optional extra).

Obviously you can set the interval on the loops to whatever is appropriate.

Advertisements