DOM Range and HTML5 Selection

We’ve written a lot about the support we’re building in Internet Explorer 9 to allow developers to write the same markup and get the same results across browsers. IE9 includes two new features that are great for web developers writing same markup: DOM Range and the HTML5 Text Selection APIs. DOM Range provides a simple, consistent way to extract and manipulate a piece of a document. It’s also the underlying unit of the HTML5 Text Selection APIs, which help you connect with one of the common ways that users interact with the browser – selecting text.

As a developer, HTML5 Selection gives you a way to programmatically get and set the pieces of a page your users select, as seen in this code snippet:

As you might guess from the names used in the snippet, the slice of the document you get back is defined in terms of DOM Range. A Range is really just a way of describing a piece of a document, enabling you to operate on it as you see fit. For example, if I want to edit the inline style of all the elements in the Range:

Internet Explorer has long had similar functionality to Range, via the proprietary TextRange and HTMLDocument.selection objects. TextRanges were created and manipulated in terms of characters, words, and lines. These were useful abstractions, but they could potentially lead to some ambiguity, and didn’t lend themselves to easy manipulation by DOM APIs.

To see some of the advantages of DOM Range and HTML5 Selection, we’ll use a demo I created in the test drive site that relies on them. In the demo, there is a text editor that receives the user selection, extracts the nodes inside, applies arbitrary operations to them, and then re-inserts them where they came from. This allows a caller to set an inline style on each of the elements in a selection to make its text color green, for example.

Setting text color is an example of functionality you can easily achieve with TextRange’s execCommand method, which has a set of predefined operations. But what about operations that fall outside this scope, like translating a piece of text?

To see an example in action, try using the ‘Translate’ command in the demo. This command makes an AJAX call to Bing Translate, passing off each of the elements in the user selection for translation. Because a Range operates in terms of nodes and offsets, this is just another operation; the operation receives some nodes, performs the operation, and then puts them back. This pattern allows the code to be generalized for other operations..

If I try to do the same thing with TextRange, I cannot use execCommand. To do this I have to extract the text content, pass it off for translation, then delete the old text and re-insert the new. In the process, I lose previous operations like text or size changes, because the lack of node-awareness doesn’t provide enough information to extract individual pieces, modify them, and then put them back in their original containers.

As Dean mentioned in a recent post, one of our goals for this release is enabling developers to write the same markup for all browsers. During our planning research, we collected usage data showing that DOM Range and the HTML5 Selection APIs were among the most-used on the Web. Supporting widely-used APIs is a big part of achieving the “same markup” ideal, so these APIs are a high priority.

However, it’s worth pointing out that if you have an application that depends on the old APIs, they continue to work as before in the latest mode, making your upgrade path to IE9 easier. Wherever possible, we recommend using techniques Tony Ross wrote about to send IE9 the same markup for Range as you send other browsers

We hope the end result of supporting these APIs is a better experience for you, the developer. As a reflection of the work we’ve done here to improve interoperability, the IE9 Acid3 score increases. The current Platform Preview now passes tests 7, 9, 12, and 13.

It’s been a lot of fun working on this, and I can’t wait to see what other developers do with it.