DEV Community

Arnav Bansal
Arnav Bansal

Posted on

How do you split contenteditable text preserving html formatting? [solved]

I'm using contenteditable divs to represent paragraphs in my editor. I've implemented most of the usual editing features

Splitting paragraphs breaks when any HTML formatting is involved.

For example, adding a space and hitting enter results in

&
nbsp;

Of course, ' ' being a single character that represents a space.

Solution (Update)

Okay I figured it out.

innerHTML and innerText aren't useful for DOM manipulation.

However, the selection and ranges API is great for this. extractContents automatically splits elements without breaking markup.

function splitNode(selection, root) {
  let range = selection.getRangeAt(0);
  let {firstChild, lastChild} = root;

  let previousRange = document.createRange();
  previousRange.setStart(firstChild, 0);
  previousRange.setEnd(range.startContainer, range.startOffset);

  let nextRange = document.createRange();
  nextRange.setStart(range.endContainer, range.endOffset);
  nextRange.setEnd(lastChild, lastChild.length);
  return {
    previous: previousRange,
    current: range,
    next: nextRange,
  };
}

let ranges = splitNode(document.getSelection(), contentEditableDiv);
let nextFragment = ranges.next.extractContents();

Top comments (1)

Collapse
 
merrimanxyz profile image
merriman-xyz • Edited

Thanks for posting this.

Worked wonderfully until I tried splitting a content editable that ended in bold text.

Looked at the code and recognized that it could only handle cases where firstChild and lastChild are text nodes.

Made a few tweaks to fix:

  • previousRange.setStart(firstChild, 0); becomes previousRange.setStartBefore(firstChild);
  • nextRange.setEnd(lastChild, lastChild.length); becomes nextRange.setEndAfter(lastChild);