timdown / rangy

A cross-browser JavaScript range and selection library.
MIT License
2.25k stars 368 forks source link

Save/Restore Character Ranges (from textrange module) breaks on Enter press. #430

Open jamesfriedal opened 7 years ago

jamesfriedal commented 7 years ago

I'm using a content editable div.

Every time the user writes @ or # the following word is wrapped in span tags and becomes blue (like twitter). I'm making use of textrange module to remember wherer the caret is as the innerHTML gets wiped each time.

It works absolutely perfectly, except from enter press in the content editable div. it breaks.

The same issue was raised in a comment by petya petrov here: https://stackoverflow.com/questions/5595956/replace-innerhtml-in-contenteditable-div

Code posted Below


<div contenteditable="true" class="testing"> Lorem ipsum eius laudas, vero, fuga cum @harry molestiae.</div>

<script>

const textarea = document.querySelector('.testing');

textarea.addEventListener('input', function() {
  const arrayOfStrings = this.textContent.split(' ');
  const newHTML = arrayOfStrings
    .map((split) => {
      if (split.startsWith('@') || split.startsWith('#'))
        split = `<span class = 'blueSpan'>${split}</span>`
      return split
    })
    .join(' ');
  const savedSel = rangy.getSelection().saveCharacterRanges(textarea)
  this.innerHTML = newHTML
  rangy.getSelection().restoreCharacterRanges(textarea, savedSel);
});

</script>
jiggy1com commented 6 years ago

how bout if you listen to keyup and preventDefault() if the keycode is 13 (enter)? else run your input handler. If you need to retain the carriage returns in your textarea, maybe you could split by the carriage return first, then loop that array and run your code ... then finally join the carriage return array