views:

453

answers:

1

Right now I'm capturing users' text selections through s = window.getSelection() and range = s.getRangeAt(0) (browser's impls aside). Whenever a selection within a <p> is made, I can easily call range.surroundContents(document.createElement("em")) to have the selected text wrapped with an <em> tag.

In this example, however,

<p>This is the Foo paragraph.</p>
<p>This is the Bar paragraph.</p>
<p>This is the Baz paragraph.</p>

when a user makes a text selection from Foo to Baz, I cannot call range.surroundContents: Firefox fails with The boundary-points of a range does not meet specific requirements." code: "1 because the selection is not valid HTML.

In that case, I'd like to somehow obtain the following state in the DOM:

<p>This is the <em>Foo paragraph.</em></p>
<p><em>This is the Bar paragraph.</em></p>
<p><em>This is the Baz</em> paragraph.</p>

Any ideas?


FYI: I've been trying with the Range API but I can't see a straightforward way of achieving that result. With

var r = document.createRange();
r.setStart(range.startContainer, range.startOffset);
r.setEnd(range.endContainer, range.endOffset+40);
selection.addRange(r);

I can eventually hack something by repositioning the offsets, but only for the 'start' and 'end' containers! (i.e. in this case the Bar paragraph, how do I wrap it?)

+1  A: 

That is when you add contentEditable=true attribute to the parent of those paragraphs, select any text, even across paragraphs, then make the call

document.execCommand('italic', false, null);

and finally if desired set contentEditable attribute back to false.

Btw, this works on IE too, except that to enter editable mode I think it is called designMode or something, google for it.

Murali VP
Very good answer- but: I have already tried this and it's not really going to work for me as will need to access the <em> positions/offsets for something else. Unless you know how to get hold of them with contentEditable? Thanks anyway
frank06
Well if you are not really keen on <em> but can live with an <i> tag for what you want to do, then the following would work:document.execCommand('styleWithCSS', false, false);document.execCommand('italic', false, null);
Murali VP