Search code examples
google-chromedom

How does Selection.modify work for a "line" granularity in Chrome?


Here's a simplified contenteditable editor with two lines of text:

let button = document.querySelector("button");


button.addEventListener("click", modify);
function modify() {
  let selection = window.getSelection();
  selection.modify("move", "forward", 'line');
}
<div contenteditable>
  <p>This is a line of text.</p>
  <p>This is a second line of text.</p>
</div>

<button>Extend selection</button>

Steps:

  1. Put your cursor in the first line after "This"
  2. Click the button

Expected: the cursor moves to the end of the first line.

Actual: the cursor moves to somewhere middle of the second line. I'm using Chrome 128 on macOS.

The behavior is not clear to me. The spec (https://w3c.github.io/selection-api/#dom-selection-modify) is not specific on the behavior as well.

My questions:

  1. Why does the cursor move specifically in this way in the given example on Chrome?
  2. Is there any other way for me to move the cursor to the end of the line on Chrome?

Solution

  • The spec itself doesn't appear to be too clear on what each granularity actually means yet - https://w3c.github.io/selection-api/#dom-selection-modify:

    Note: We need to more precisely define what it means to extend or move selection by each granularity.

    sentence would get you to the end of the line in your given example - but technically, it moves to the next sentence, so as soon as you introduce one on that first line, it won't go to the very end any more.

    lineboundary appears to get it where you want it to though, at least in Chrome.

    let button = document.querySelector("button");
    
    
    button.addEventListener("click", modify);
    function modify() {
      let selection = window.getSelection();
      selection.modify("move", "forward", 'lineboundary');
    }
    <div contenteditable>
      <p>This is a line of text. And another.</p>
      <p>This is a second line of text.</p>
    </div>
    
    <button>Extend selection</button>