Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cssom-1] A more direct method than caretPositionFromPoint() #10346

Open
keithamus opened this issue May 17, 2024 · 1 comment
Open

[cssom-1] A more direct method than caretPositionFromPoint() #10346

keithamus opened this issue May 17, 2024 · 1 comment

Comments

@keithamus
Copy link
Member

Right now CSSOM-1 specifies the following:

partial interface Document {
  CaretPosition? caretPositionFromPoint(double x, double y, ShadowRoot... shadowRoots);
};

However, it's common in editors to want to place a popover under the user's existing caret, to give them contextual auto-complete information. For example typing : in a textarea on GitHub.com results in an emoji picker being shown, while @ results in a username list being shown. For short form content it's fine to position these popups to the textareas rect but it's much better usability if we can position them close to the user's caret. Unfortunately there isn't a great way to handle this. The solution we use today is to clone the textarea as a div, and copy a bunch of its layout effecting computes styles (such as font, size, writing direction, borders) over so that we can get a Range back from the div (it's not possible to get a Range from the <textarea>'s text content. With the Range we can get the boundingClientRect.

caretPositionFromPoint seems like it might be a reasonable solution to this however it seems as though this method would find a nearest theoretical caret (please correct me if I'm wrong here), while what we likely need is "get the currently visible caret inside the textarea". It's likely that with this API we'll still need to do the clone/range hack to get sufficient position data just to get the point to query the caret position.

I'd like to propose an API instead like:

partial interface Element {
  CaretPosition? currentCaretPosition()
};

This method would return the currently visible caret of the node, if it had one (so if it was an active textarea, input, or contenteditable). If it didn't have a visible caret, it would return null.

/cc @sanketj & @smaug---- with whom I've already discussed this idea.

@siliu1
Copy link
Contributor

siliu1 commented May 24, 2024

Hi Keith,

I think what you want is the selection bounds regardless of where is current selection. For contenteditable div, you can get current selection bounds using document.getSelection().getRangeAt(0).getBoundingClientRect(). For textarea/input element, there is no way to get selection bounds today.

Instead of adding currentCaretPosition() API on Element, I would like to propose the following:

partial interface HTMLTextAreaElement {
  [NewObject] DOMRect getSelectionBoundingClientRect();
}

partial interface HTMLInputElement {
  [NewObject] DOMRect getSelectionBoundingClientRect();
}

getSelectionBoundingClientRect() would return the bounding rect of current selection in textarea/input element. The bounding rect is the caret rect if the selection is collapsed. If there is no active selection in textarea/input, it would return empty rect.

The new proposed API aligns with existing selection APIs on textarea/input such as select(), selectionStart, selectionEnd, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants