views:

1550

answers:

2

When selecting a block of text (possibly spanning across many DOM nodes), is it possible to extract the selected text and nodes using Javascript?

Imagine this HTML code:

<h1>Hello World</h1><p>Hi <b>there!</b></p>

If the user initiated a mouseDown event starting at "World..." and then a mouseUp even right after "there!", I'm hoping it would return:

Text : { selectedText: "WorldHi there!" },
Nodes: [ 
  { node: "h1", offset: 6, length: 5 }, 
  { node: "p", offset: 0, length: 16 }, 
  { node: "p > b", offset: 0, length: 6 } 
]

I've tried putting the HTML into a textarea but that will only get me the selectedText. I haven't tried the <canvas> element but that may be another option.

If not JavaScript, is there a way this is possible using a Firefox extension?

A: 

You may want to start from http://javascript.internet.com/page-details/copy-selected-text.html

+3  A: 

You are in for a bumpy ride, but this is quite possible. The main problem is that IE and W3C expose completely different interfaces to selections so if you want cross browser functionality then you basically have to write the whole thing twice. Also, some basic functionality is missing from both interfaces.

Mozilla developer connection has the story on W3C selections. Microsoft have their system documented on MSDN. I recommend starting at PPK's introduction to ranges.

Here are some basic functions that I believe work:

// selection objects will differ between browsers
function getSelection () {
  return ( msie ) 
    ? document.selection
    : ( window.getSelection || document.getSelection )();
}

// range objects will differ between browsers
function getRange () {
  return ( msie ) 
      ? getSelection().createRange()
      : getSelection().getRangeAt( 0 )
}

// abstract getting a parent container from a range
function parentContainer ( range ) {
  return ( msie )
      ? range.parentElement()
      : range.commonAncestorContainer;
}
Borgar
what do you pass to parentContainer as r?I didn't get it working (parentContainer method)
Khaled Al Hourani
Whoops. Not very clear but that should be a range, I have fixed the variable name. I was thinking it could be used like this:var container = parentContainer( getRange() );Which is not to say that it will work 100%. The code is intended as an example of the type of work that is necessary to do this and may be found wanting. You'll want to understand the APIs you are dealing with (see links).
Borgar