DEV Community

Arnav Bansal
Arnav Bansal

Posted on

How do you detect what line it is in wrapped text elements?

I'm implementing a custom editor that uses rows of contenteditable divs. I'm having trouble implementing the right behavior for the 'up' or 'down' key.

When the 'up' key is pressed, I need to detect whether the caret is on the first line of text, and move the caret to the div above. Likewise for the 'down' key and the last line of text.

Thanks!

Top comments (7)

Collapse
 
erikwhiting88 profile image
Erik

Hi Arnav. I'm not at a computer right now to see if this will work but I have an idea.

is the size of your div static? if so, maybe you can figure out how many characters your input gets to before it goes to the next line, and then check the string location of your cursor. for example, say you can type 80 characters per line you can say something like

if (user_input == KEY.up) {
  if (cursor_location > 80) {
    // go up a line
  else { 
    // go up a div
  }
}

I hope this helps

Collapse
 
erikwhiting88 profile image
Erik

hi Arnav, did you ever get this figured out?

Collapse
 
itsarnavb profile image
Arnav Bansal

Hey Erik! I did figure out a solution, for variable sized divs

getLinePosition = () => {
    let r = getSelection().getRangeAt(0);
    let s = document.createElement('span');
    r.insertNode(s);
    let top = ((s.offsetTop - s.parentNode.offsetTop) === 0);
    let bottom = ((s.offsetTop - s.parentElement.offsetTop + s.offsetHeight) >= s.parentElement.offsetHeight);
    s.parentNode.removeChild(s);
    return {top, bottom};
  }

This returns an object {top: Boolean, bottom: Boolean} which works just enough for my purpose.

It can be modified to return the exact line number too if needed. s.offsetTop-s.parentNode.offsetTop returns a number that's fontHeight*lineNumber, which when divided by font height returns the line number.

I'm sure there's a less messy way of doing this that doesn't require adding a span.

Apologies for not replying sooner!

Thread Thread
 
erikwhiting88 profile image
Erik

looks great! is this running live anywhere?

Thread Thread
 
itsarnavb profile image
Arnav Bansal

Just deployed it. You can try the functionality here: laughing-gates-6a6364.netlify.com

If you press the up/down arrows, you move between the paragraphs (two separate contenteditable divs) only on the first and last lines.

(It's not a completely usable editor yet; still needs much fixing)

Thread Thread
 
erikwhiting88 profile image
Erik

very nice. Is this mostly just an exercise or do you have plans for this kind of feature?

Thread Thread
 
itsarnavb profile image
Arnav Bansal

I'm developing a platform where I need an editor with some custom features. I felt the need to understand all the moving parts of an editor.

My platform: deeplink.space