I've recently been working on a cross-browser Range and selection library called Rangy. In its current version it's not dissimilar in concept to IERange but goes beyond it in terms of implementation of the DOM level 2 Range and HTML 5 selection specifications, and also in terms of stability and workarounds for browser bugs. There's currently a pre-alpha release that is stable and (in my opinion) the best there is out there.
There are other features that I intend to add but I've initially focussed on creating a really good cross-browser Range and selection implementation, which is pretty much complete in the current release.
http://code.google.com/p/rangy
Update: Added example
The following uses some Rangy extensions to Ranges to easily iterate over text nodes within a selection and surround each one:
function surroundSelectedText(templateElement){
var range, sel = rangy.getSelection();
var ranges = sel.getAllRanges();
var textNode, it, el;
for (var i = 0, len = ranges.length; i < len; ++i) {
range = ranges[i];
// If one or both of the range boundaries falls in the middle
// of a text node, the following line splits the text node at the
// boundary
range.splitBoundaries();
// The following line creates a simple iterator that iterates
// over the nodes within the range. The first parameter is an
// array of valid nodeTypes (in this case, text nodes only)
it = range.createNodeIterator([3]);
while ( (textNode = it.next()) ) {
el = templateElement.cloneNode(false);
textNode.parentNode.insertBefore(el, textNode);
el.appendChild(textNode);
}
}
}
var span = document.createElement("span");
span.style.color = "green";
span.style.fontWeight = "bold";
surroundSelectedText(span);