samson
samson

Reputation: 1152

Rangy for subdivided contenteditable div

So, I'm playing around with the (AWESOME) Rangy text selection package. I'm editing text inside of a span with contenteditable=true, with the goal of having a text input element which allows individual styling of each character. Let me stress that last point -- each character should be in its own span. This works fine if I don't need to preserve the styling from one keystroke to the next -- I just do something like

var newHTML = field.innerText.split('').map(function(c){
    return ('<span class="letter">'+c+'</span>');
}).join('');
$(field).empty().append(newHTML);

and use Rangy's (1.3) saveCharacterRange() function to restore the selection, and it's all good.

The problem comes when I've already styled some of those spans, and I delete one, replacing it with new text. I want newly inserted text to be unstyled, but instead it gets inserted into the preceding (or following, if the selection is at the beginning) span. I've tried to work around this by explicitly collapsing the selection's region after (or before) the focusNode, but it seems to not allow the endContainer (or startContainer) to be anything other than a text node... I've even verified that I can create a text range which collapses where I want it, but the selection object's setSingleRange() seems to collapse back around the text node.

I tried inserting a new node and placing the selection wholly inside it, which does work when the new node has content in it before calling insertNode(), but I obviously can't be inserting extra content between each character...

Here's a fiddle demonstrating what I'm talking about. Thanks for any help!

Upvotes: 0

Views: 439

Answers (2)

samson
samson

Reputation: 1152

Maybe somebody out there can expand on this, but I think save/restoreCharacterRanges() is the key to fixing this problem. I've got it working (assuming your selection region is collapsed) in this fiddle, though not the way I'd like -- this approach (removing the just added content and moving into a new span) causes a flicker between keyup and keydown. I'd really like to be able to move the cursor (on keydown) into a fresh span, which would appear seamless to the user...

... and here's a fiddle that works with long selections, but not pasting...

Update

I've switched over to the 'insert a <span>&#8024;</span> and move the selection region into it' approach, which seemed to be working great, until I started trying different browsers. The behavior is completely different in each browser! Chrome correctly moves the cursor into a 'blank' span when required, but then removes the accent; Firefox handles accented characters perfectly, but fails to move into the new span after deleting a character which follows a new span; Safari displays the accent mark then moves into the new span, leaving the accent mark orphaned... And all three will display the original bug when deleting an old letter which follows a new one! Also, it seems like the different browsers are reporting different keycodes when modifier keys are pressed. Is this a lost cause? Am I missing something? Here's a fiddle with the new code.

Upvotes: 0

Tim Down
Tim Down

Reputation: 324627

I think you're falling foul of a common issue: browsers (particularly WebKit) have specific ideas of where in the document the selection and caret are allowed to be. Here's a recent answer of mine on this subject:

https://stackoverflow.com/a/21591165/96100

Upvotes: 1

Related Questions