It’s For-IE-day: Week 7

ieday

This week let’s take a look at some of the document model (DOM) extensions added into IE8, like

  • DOM storage,
  • an AJAX navigation enhancement,
  • safer JSON and HTML handling,
  • improvements to XMLHttpRequest, and
  • cross-domain request support.

 

DOM Storage

DOM Storage objects are part of the HTML 5 Working Draft that Microsoft has pulled into IE8, via the localStorage and sessionStorage properties of the window object. DOM storage is essentially a property bag of name/value pairs which can be used to store state on the client, like cookies do; however, DOM storage has a number of advantages over cookies:

  • Cookies can only store 4KB, while DOM storage provides about 10 MB per storage area,
  • DOM storage does not expire,
  • Items in DOM storage are not transmitted to the server with requests as cookies are, and
  • The simple name/value pair paradigm is easier than parsing a cookie value to extract the relevant bits of data.

The Storage object has a number of methods to get and set values, determine the amount of used and remaining, and clear the storage.  Two events are also provided which fire when storage has changed and been committed to disk (in XML format).

Here’s a quick demo.  Using IE8 (of course!), enter some text in the box below then click the Save button.   Next, hit the Retrieve button and you should see the message you entered in an alert box

 

 

The script behind this is pretty simple:

 <input type="text" id="domText" />
<input  onclick="localStorage.setItem('exampleKey', domText.value);" 
     value="Save Data" type="button" />
<input  onclick="alert(localStorage.getItem('exampleKey'));" 
     value="Get Data" type="button" />

So where’s the data go?  It’s written to an XML file in your user directory, for example:

C:\Users\joneil\AppData\Local\Microsoft\Internet Explorer\DOMStore\ADJQXSUG

 

AJAX Navigation Enhancement

AJAX is great for the user experience: instead of a full page refresh, a back-door XmlHttpRequest fetches some new data and markup and updates just a portion of your page.  But what happens when you hit the back button?  get what you wanted, namely the previous state of the AJAX-enabled page, or do you end up with the page you were looking at three hours ago?

To provide a consistent page navigation experience, IE8 now treats modifications to the window.location.hash property as an individual navigation.  As a result, the browser history and the Address bar will reflect the current hash property (the segment of the URL after the #).

By adding a handler to the new onhashchange event, you can detect a previous state for that page and restore it as if had been a full page navigation.  I’ve outfitted my Local User Groups map (which is always available in my blog sidebar, by the way) to save the Virtual Earth zoom level in the hash each time it changes.  If you use IE8 to view the page (and make sure the Document Mode is IE8 Standards – check here if you’re not sure how to tell), you can zoom in and out, then hit the back button to traverse all of your zoom changes versus going back to the previous page.

Here’s the relevant code from that page; yup, that’s all that was needed!

 document.body.onhashchange = resetZoom;
map.AttachEvent("onendzoom", setZoom);

function resetZoom()
{
   var zoom = window.location.hash.substr(1);
   if (zoom == "") zoom = 6;
   map.SetZoomLevel(zoom);
}

function setZoom(e)
{
   window.location.hash = map.GetZoomLevel();
}

 

Safer JSON and HTML Handling

When exchanging data through services or just handling input in standard Web Forms controls, you always have to be on the lookout for injection attacks: bits of markup that, when interpreted in the context of the page script, can cause havoc.  This is especially important these days as we’re seeing more and more mashup applications that grab bits of content from various other sources, which may or may not be trustworthy.

Typically, you have to go through great pains to make sure that the content you are importing or accessing isn’t going to contain harmful executable constructs.  Maybe you’ve written sophisticated parsers and regular expression tests or used third party libraries like json2.js.    IE8 comes with a new method to help sanitize HTML input and an entire new JSON object to support that format.

toStaticHTML

window.toStaticHTML will take HTML input, perhaps from postMessage, which sends a text payload from one document to another, and remove script constructs.   As an example, press the button below the text box, and you’ll see the resulting HTML string, sans script.

JSON object

JavaScript Object Notation (JSON) is a popular format for communicating data between lightweight Web services and AJAX applications.  Since the data format of JSON is JavaScript itself, a simple call to the eval() method can reconstitute a potentially complex object from a string.  Of course, the eval method will also run any executable JavaScript that happens to be part of that string!

One alternative is to use a JSON parser to make sure there’s no evil lurking in the string you are about to evaluate, but there’s obviously a performance hit for doing so.  IE8 implements native JSON handling functions including stringify, which creates a JSON string from a script object, and parse, which safely converts a string back to the object.

XMLHttpRequest improvements

The XMLHttpRequest object is, of course, the workhorse of Web 2.0 applications, but back at its inception over a decade ago, the scope of its use today was certainly not foreseen.  So to provide more control in your AJAX-based applications, specifically in handling timeouts, a new property and event have been added:

timeout property

Set this value, in milliseconds, to indicate a timeout for the request.

ontimeout event handler

Handle the request timeout scenario, perhaps updating a status area on the page to indicate failure of the request.

Note too, that with IE8 the number of connections per server that can be established has increased from 2 to 6 (for HTTP 1.1) and from 4 to 6 (for HTTP 1.0) for broadband connections (for dial-up, it’s unchanged).  This means that there will typically be more pipes open for AJAX-style requests resulting in a better user-experience.  The maxConnectionsPerServer property on the window object is  available to return the maximum connections available, so you can adjust your scripts and use of the timeout capabilities appropriately.

 

Cross-domain Requests

The browser security model includes a policy known as site-of-origin, which restricts pages from accessing data from a different domain.  One way of working around this is proxying the request through the original server, so the cross-domain access is avoided.  IE8 introduces a new XDomainRequest object to make this even easier.

XDomainRequest works in similar fashion to XMLHttpRequest, with open and send methods and an onload event (in lieu of onreadystatechange).  A cross-domain request sent via XMLHttpRequest won’t leave the browser, but one issued with XDomainRequest will send a request to the the targeted server by using a HTTP header called Origin set to the site-of-origin.  The connection to the server will only succeed if the server responds with a Access-Control-Allow-Origin:* header value; otherwise, the error event on the XDomainRequest object will fire.

Note, this object is specific to Internet Explorer; however, the negotiation strategy is part of the W3C’s draft framework on client-side cross-domain communication.

A restriction similar to cross-domain requests occurs when portions of a single web page comprised of content from different domains try to interact.  Like with cross-domain requests, there have been workarounds, but using cross-document messaging provides a cleaner, safer, and better performing alternative.  Cross-document messaging leverages the postMessage method of the document object (along with an onmessage event) to communicate among different segments of the same page, such as IFrames containing content from different origins.   These constructs do directly implement the draft recommendations in HTML 5.