How to do Facebook/Gmail like Page Loads/Updates using IFrames and JavaScript

May 22, 2011 | By Rakhitha | Filed in: JavaScript, Tech.

You may have noticed how websites like Facebook and Gmail load/update pages on browser without actually reloading the entire thing. It can come handy in your own websites specially when you need to change a small potion of the content that is already shown in the screen. Or you need to change the data shown in the page without having to reload the entire thing.

This can be done easily using only a hidden iframe and some java script code provided that few conditions are met.

Basically following is what you need to do. You need to have a hidden iframe, to which you will load specific information from the server. Then, you need to have created div tags surrounding the regions of the visible page that you need to update. Each div need a unique tag id. You need to create another web page (not visible to user) which will have the information that you need to show.  This web page also need to have div tags surrounding the different information that you need it to transfer from server to client.

For simplicity lets assume that your visible web page has one place which you need to dynamically update. We will mark that region using a div tag with id “placeHolder”.  Your non visible web page/content source which has the information needed to be shown in place holder will contain another div with id “content”. Now what we need to do is to load this page in to your hidden iframe. And once that is loaded, we need to look for its div tag with id “content”. We need to copy the internal content of that div into our place holder div in visible page. While this process is being done in the background, we can show an animated image on our place holder until things are loaded.

I’ll try to explain this with the code.

HTML Code



<iframe id="myIFrame" width=300 height=300 style="Display:none;" onload = "loadDone();">
<!--
We use this iframe to load the pages that we need to load.
Loading will be done by setting src property of the iframe.
Once the specified page is loaded iframe will call loadDone() 
function which is set to onload event. 
that function will simply copy the relevant content from
 loaded page in to the div shown bellow.-->
</iframe>

<!--Following is the place holder
 in which we will show the loaded data-->
<div id="placeHolder"></div>

<script type="text/javascript">
loadPage("url to load");
</script>

In above HTML code line 5-13 has the code for hidden iframe, to which we will load the invisible pages with content that need to be shown in updatable parts of the visible page. Note that onload event of iframe is set to a function named loadDone(). This function takes care of copying information from hidden page in to visible place holders. We can’t call this function directly because we have to wait until our data page is fully loaded. That’s why we use onload event. We will look in to the logic of the function later.

In line 17 we have our place holder. Technically you can have any number of place holders as long as each one has a unique id. Also for each place holder in your visible page, you will need a separate div with a unique id in your invisible page to carry the information from server to client.

In line 20 we call a function named loadPage(…). This is the function that trigger the process of loading a data page in to our hidden iframe and then indirectly trigger the process of updating place holders through onload event of iframe.

Java Script Code

/*
This function will be called everytime a page
is loaded in to our hidden iframe.
As this is set to its onload event.
*/
function loadDone()
{
	// Find the hidden iframe object
	var myiframe = document.getElementById("myIFrame");
	// We only need to go ahead if the iframe has some page.
	if(document.getElementById("myIFrame").src)
	{
		//Now we need to locate the document object
		//of the paged loaded inside iframe
		//Logic will slightly differ for different browsers.
		if (myiframe.contentDocument)
		{
			//firefox, opera
			myiframe = (myiframe.contentDocument);
		}
		else if (myiframe.contentWindow)
		{
			//IE
			myiframe = (myiframe.contentWindow);
		}

		if(myiframe.document)
		{
			myiframe = (myiframe.document);
		}
		//At this point myiframe variable should be
		//pointing to document object of the page in
		//hidden iframe.
		//we assume that the page has a div tag with id 'content'
		//and inside that we have the stuff that we need to show.
		set(myiframe.getElementById("content"));

	}

}
/*
Following function simply set the innerHTML value of the place holder
to the data we loaded through iframe
*/
function set(s)
{
	var placeHolder = document.getElementById("placeHolder");
	placeHolder.innerHTML= s.innerHTML;
}

/*
This is the function that we will be calling to trigger the update process.
it take one parameter which is the url of the page that we try to load.
*/
function loadPage(url)
{
	//Before loading the page that we need to load
	//we first set the text 'Loading...' in to our placeholder.
	var placeHolder = document.getElementById("placeHolder");
	placeHolder.innerHTML = "Loading...";

	//Then we load the page in to iframe
	//This will trigger loadDone function once the page is loaded
	document.getElementById("myIFrame").src = url;
}

From line 6 to 40 of about javascript code we have the function which does the real work. It simply extract the information that we need to update on visible page and call set function which does actual updating. Only thing that you need to note here is line 36. That is where we extract the code block (div) with id ‘content’ and pass in to set method. If you have multiple placeholders to update you will need to repeat this line for each place holder, and for each placeholder you need to read from a different tag id. Also you will need to make some changes in set function to support multiple place holders.

From line 55 to 64 we have the function that you will call to trigger an update. This function takes the URL of the page that serve as the content producer. It must contain the div tags that your javascript will be looking for to read the content. Also it must be noted that this page must be hosted on same domain as your visible page which has the place holder. This code will not work across multiple domains due to security reasons.

In my code I have called this function just inside a javascript block. That is only for demonstration purposes. In practical applications you will call this as a button action or as a link onclock event.

In loadPage function it is line 64 which trigger actual loading. Line 59 and 60 are there to show some progress indicator on our place holder until the required data is loaded and place holder is updated with data. I am just showing text “Loading…” there. I hope you can figure out how to replace that with an animated image like in Facebook as well as how to make this work for multiple placeholders.

If you going to try this out you need to have both pages hosted in a web server before testing. You can use IIS or any other server hosted in locale machine. Testing with html files directly in hard disk will not work. Browser look for a proper http url and both pages must be hosted under same domain (http://localhost will do) for this to work.

Hope you find this helpful
/Rakhitha


Tags: , , , ,

8 comments on “How to do Facebook/Gmail like Page Loads/Updates using IFrames and JavaScript

  1. Bart says:

    I get the following error when trying out your script:

    Error: Permission denied for to get property HTMLDocument.getElementById
    Source File: http://localhost/#/profile/latest/
    Line: 42

    It seems like firefox does not allow you to access the element from another page.

  2. Rakhitha says:

    I just tested this with firefox and it worked fine. But i used firefox version 7.0.1. Which version did you use.

    Also make sure both pages are in same server and the second page is accessed using relative URL.

    You could also try to add a javascript function to the page that you are loading in to the frame and use that function to return the innerHTML property of the content DIV instead of directly calling getElement… from the other page.

    /Rakhitha

  3. Bart says:

    Ok, nevermind, I got localhost and www mixed up in my script so the domains weren’t te same, stupid mistake 🙂

    I was also wondering te following, I see that facebook uses relative urls like:

    http://www.facebook.com#!profile.php?sk=abcdef
    but Twitter uses clean urls like
    http://www.twitter.com#!search/abcdef

    I use a function to load the page into the Iframe like:

    function processHash(hash){
    document.getElementById(“iframe”).src = “/pages/” + hash
    }

    where hash is passed to this function like profile.php?id=1

    But if I would like to pass it like profile/1/

    Should I than convert the url in my processHash function to a relative url or isn’n this the best way?

    greetings
    Bart

  4. Rakhitha says:

    I have not done much web related work recently. So I might not be the pest person to answer this. Hope the following info helps.

    Based on what I know shebang/parameterised notation is used only to make this type of dynamically loaded content boockmarkable. Whatever comes after # is handled by your code. In that way i think you just need to change you code of handling your id.

    But if you use ?id=1 kind of format that becomes a URL query string parameter and you can easily access that value in your code through query string parameter variable. if you use /id/1/ kind of format you will have to extract the value from the url.

    I personally like /id/1/ kind of URL. (check the url of this blog post for example :).) I think, It can be relatively more search engine friendly if your id value also have a meaningful value instead of just a number (for example in this post url, its the post title).

    Regards!
    /Rakhitha

  5. Peter says:

    Great script, but is it possible history isn’t working that well? Or do you have to implement that as a seperate thing?
    I thought the iframe made sure of that.

  6. Rakhitha says:

    Thanks!
    I haven’t tested it’s effect on history. May be it will be taken care of by iframe. Or you might will have to do some manipulation on history object.

    You might be able to find out if you do a little bit of testing.

    Regards!
    /Rakhitha

  7. Peter says:

    Ok thanks, I thought u used an iFrame for history purposes?
    Because why should you use an iFrame otherwise? Can’t you just use Ajax to load the content without refreshing?