This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.

Wednesday, August 24, 2005

AJAX Tutorial: A Tale of Two IFrames (or, How To Control Your Browsers History)

This is a mini-tutorial on the black art of iframes and browser history, known to AJAX experts but rarely presented clearly.

An iframe is an internal frame that can point to and load up an arbitrary URL within your HTML page. Here is an example small iframe showing Google, right in this document:



Your browser history is the list of pages you have visited. When you press the back and forward buttons in your browser, you are jumping through your browser history.

Sometimes, for various reasons, programmers want to control what is placed into their browser's history or not. Think of this as a primitive that can be used in more elaborate AJAX and DHTML hacks; it's a building block useful in all kinds of crazy AJAX kung-fu. It's good to know about these tricks when confronted with AJAX design issues, or when you stumble across very strange bugs which might be caused by the different kinds of iframes I will present.

There are two kinds of iframes, those that are right within your HTML and loaded in the page:
<html>
<body>
<iframe id="testFrame"
src="http://www.google.com">
</iframe>
</body>
</html>
and those that are created dynamically, through the DOM and JavaScript, after the page is finished loading:
<html>
<head>
<script language="JavaScript">
function initialize() {
var testFrame =
document.createElement("IFRAME");
testFrame.id = "testFrame";
testFrame.src = "http://www.google.com";
document.body.appendChild(testFrame);
}
</script>
</head>

<body onload="initialize()">
</body>
</html>

Okay, fine, so there are two kinds of iframes; who cares? Well, it turns out these two kinds of iframes have completely different behaviors when it comes to history in different browsers!

Here's the lowdown for each kind of browser.

In Firefox:
In Internet Explorer:
In Safari:
You can see this for yourself with the following demos. In both demos we dynamically change the iframe's location between four different web sites.

In the first demo, when we are dealing with an iframe that is in the HTML on page load, you will find that all of these sites are in the browser's history in both Firefox and IE. Press the back and forward buttons when the popup saying "Finished" appears, and you will see the iframe's contents change between each site.

In the second demo, when we are dealing with a dynamicly created iframe, you will find that only the initial page load is in the browser's history, while all sites are in the history in IE.

One small footnote. If you have a static iframe that is loaded in the HTML, and that iframe has a src value initially:

<iframe src="http://www.google.com"></iframe>


then this initial value is not placed into the browser's history, only successive changes to that static iframe are placed into the history.

You can use the special behavior of these two kinds of iframes for some real trickery. I won't go too much into possible uses, since I mostly want to highlight the differences between these two iframes in this tutorial. First, you make them invisible using CSS. Then, you decide whether you want something to enter the history or not, choosing the appropriate kind of iframe. If you are using the iframe remote communication technique instead of XmlHttpRequest, for old browser compatibility, knowing the difference between these two kinds of iframes can be very useful, since you can choose whether remote iframe communication is placed into the history or not.

AJAX: Creating Huge Bookmarklets

A bookmarklet is a special piece of JavaScript code that can be dragged into a user's link toolbar, and which later can be clicked on to implement cross-site behavior. People have done all sorts of cool stuff with it.

Bookmarklets have size limitations, which differ based on browser and platform, since they must fit into a certain number of characters. They can also be difficult to maintain for more sophisticated scripts, since every line of JavaScript code has to be jammed into one line.

I've put together a way to have huge, arbitrarily sized bookmarklets, where most of the code resides outside of the bookmarklet link. I'll explain how this works in this mini-tutorial.

First, view the entire code. The essential idea is that we dynamically insert a new script element into the DOM through our bookmarklet. Here is the code that is within the bookmarklet URL, formatted to be more readable:
function loadScript(scriptURL) {
var scriptElem = document.createElement('SCRIPT');
scriptElem.setAttribute('language', 'JavaScript');
scriptElem.setAttribute('src', scriptURL);
document.body.appendChild(scriptElem);
}

loadScript('http://216.203.40.101/projects/tutorials/'
+ 'creating_huge_bookmarklets/helloworld.js');
In the code above we create a new script element and set it to the new URL. We then call the script with a URL that is different than the Coding in Paradise site, to show that cross site scripting insertion works. We then append the new script block to the document. The script we use, helloworld.js, is very simple:

alert("Hello World!");

When this script is loaded, it will immediately cause the Hello World message to appear.

The full loadScript method and method call are rolled into a single javascript: URL to turn it into a bookmarklet.

Try the script yourself, dragging the link to your toolbar. Then, navigate to other sites and click the bookmarklet link; you will see the message Hello World appear, loaded from an external script. You can also view a screencast that shows the bookmarklet in action, being dragged to the toolbar and working cross site.

This code has been tested in IE 6+ and Firefox.

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]