简体   繁体   中英

Setting cursor position within editable div based on character offset

Alright, so I need an "input" that allows highlighting parts that are "invalid".

Since I cannot do that with an actual input, I am using a div with contenteditable=true . The algorithm is fairly simple in concept:

  • on keyup
    • validate input
    • replace innerHtml of div with span s that have the correct class
    • use CSS to style errors
    • restore cursor position st the user can just keep typing

And it's that last part that's giving me some issues.

I've found https://stackoverflow.com/a/4812022/3322533 , which is working great to get the offset, however, my attempt at restoring it,

function setCursorPositionWithin(element, pos) {  
  const doc = element.ownerDocument || element.document;
  const win = doc.defaultView || doc.parentWindow;
  let sel;
  const newPosition = document.createRange()
  newPosition.setStart(element, 0)
  newPosition.setEnd(element, 0)

  element.focus();

  if (typeof win.getSelection != "undefined") {
    sel = win.getSelection();
    if (sel.rangeCount > 0) {
        sel.removeAllRanges();
    }
      newPosition.selectNodeContents(element);
      newPosition.setStart(newPosition.startContainer, pos)
      newPosition.setEnd(newPosition.endContainer, pos);
      sel.addRange(newPosition)

  } else if ((sel = doc.selection) && sel.type != "Control") {
    throw Error('IE not supported')
  }
}

is failing because

Uncaught DOMException: Failed to execute 'setStart' on 'Range': There is no child at offset 11.
    at setCursorPositionWithin

How do I construct this range correctly?

JsFiddle

Ok, so the problem seems to be exactly what it says: the range is trying to set the cursor position at the n th position, which may not exist if n is large enough.

The problem is solvable if instead of just wrapping the error sections in span s with classes, we wrap every single character in a span of its own.

I haven't figured out yet why the getCursorPositionWithin is working the way it is, if that is the case, but I guess that's a different question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM