You’re starting to see it more and more. You select some text on a website and — woosh — something happens. Sometimes you expect the action. Oftentimes you don’t. Regardless, these things are possible due to DOM ranges.
And DOM ranges are terrible.
I don’t mean they are a terrible idea. I mean they’re terrible to work with. Of course there is no single, standard API to work with. Of course Internet Explorer adds another level of challenge. And of course you’re going to at some point have to know how these things work if you expect to be a JavaScript ninja.
There are many reasons to deal with ranges. Some lame services will hijack your selection and inject in their own tags. If you’ve ever needed to hack around a WYSWYG editor then ranges will be on the docket. Or say you’re leading a team that allows users to select text on a page and do things like highlight it, make a note attached to it or even place a bookmark at that point in the page. That’d be my job.
The default range object seems good enough for a lot of tasks. Where it starts to show its weakness is interacting with the DOM outside of just the range.
You want to take what a user has selected and wrap it in a decorative <span>
? That should be easy, right? What happens if that selection starts in the middle of an <li>
, moves down a few paragraphs, enters a <div>
and ends a few levels deeper in the node tree? Well, you can’t just wrap that in a single element.
The browsers all try to be helpful. Really, they do. If your range starts in the middle of an <em>
tag but ends outside of it the range you get back from the browser will automatically split the tag properly if you wrap it. That’s nice. But if you remove that wrapper now you have a split tag that equates to more child nodes in memory than in code. That makes for bad assumptions later.
During my research into and development of this project I’ve found a stunning lack of comprehensive information (much less example code) for DOM ranges. Obviously PPK is the place to start but his level of detail is light and — at best — beginner. I’ve worked with some guys at Google who are on the Closure Library team and are ridiculously smart. Even they didn’t plan for the basic needs I have. Or it could be I’m doing it wrong.
In any case, I’ll be working on a series of entries to this blog that will go through what I’ve learned, show some code, talk about common pitfalls, propose some best practices and hopefully shine some light on the dark corner that is DOM ranges.