Getting The Selected Text as HTML Using Javascript

I’m not really on top of my time management yet, but this was hard enough to find that I think it warrants a blog post anyway…

Have you ever tried looking up how to use Javascript to get the selected HTML in a browser window in a form that can then be sent via XMLHTTPRequest or fed into an ordinary form field? (eg. for POSTing to a quote-collector tool) It’s a surprisingly difficult piece of info to find. (Hence why I’m partly writing this as a reminder to myself)

First, you’ll probably end up visiting the QuirksMode Range Intro to learn about window.getSelection() in browsers like Gecko/Firefox and the equivalent Internet Explorer scripting, but all you’ll learn there is how to get the selection as plain text… and that’s no secret.

Once you’ve got the selection/range, things become a little trickier because, once again, Internet Explorer and everyone else do things differently. In Internet Explorer, it’s as simple as range.htmlText but in other browsers, it’s a little less obvious.

First, you call range.cloneContents() to get a DocumentFragment object. This is more or less equivalent to Copy (Ctrl+C) when copying and pasting things. Then you create a <div> element, use div.appendChild(clonedSelection), and then grab the HTML as text from div.innerHTML. Don’t go looking for ways to serialize DOM nodes to XML. It’s non-portable and a bit of a red herring.

Here’s my solution, descended from the complete code fragment I eventually found on a thread on the FCKEditor forums:

getSelectionHTML = ->
    # Everyone but IE supports DOM selections
    if window.getSelection
        sel = window.getSelection()
    # IE Selections (Must come last to avoid messing with Opera)
    else if document.selection
        return document.selection.createRange().htmlText
    # Fail safely
    else
        return ""

    if sel.getRangeAt
        # Everything but IE and old Safari
        range = sel.getRangeAt(0)
    else
        # Old Safari
        range = document.createRange()
        range.setStart(sel.anchorNode, sel.anchorOffset)
        range.setEnd(sel.focusNode, sel.focusOffset)

    # Convert the document fragment to a string
    div = document.createElement('div')
    div.appendChild(range.cloneContents())
    return div.innerHTML

# For those of you who can't readily compile CoffeeScript into Javascript,
# 1. Visit http://jashkenas.github.com/coffee-script/
# 2. Click "Try CoffeeScript" and paste this into the left-hand pane
# 3. Copy the result from the right-hand pane.

Now that you know, why not create some interesting bookmarklets?

Creative Commons License
This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
This entry was posted in Geek Stuff. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution under the same terms as the associated post.