admin管理员组文章数量:1279235
I want to position a pop-up element directly below the text caret/blinking text cursor in a textarea or content editable element.
I've found answers that give me the text index within an element where the caret exists, but as far as I can tell this is useless to me. (like this)
I need something similar to the event.pageX and pageY properties available with mouse-events, but I want that same thing for the position of my text editor caret. Anyone know how to do this?
I want to position a pop-up element directly below the text caret/blinking text cursor in a textarea or content editable element.
I've found answers that give me the text index within an element where the caret exists, but as far as I can tell this is useless to me. (like this)
I need something similar to the event.pageX and pageY properties available with mouse-events, but I want that same thing for the position of my text editor caret. Anyone know how to do this?
Share Improve this question asked Sep 6, 2020 at 22:57 EthanEthan 8171 gold badge9 silver badges28 bronze badges 1- jQuery can help. Some code would be nice too – GetSet Commented Sep 6, 2020 at 23:02
2 Answers
Reset to default 6The accepted answer is wrong. Whether or not that has worked 2 years ago I can't tell. It works for text content, yes, but not for input and textarea values, which was what the question specifically was about.
Just try it out here: select the page text and it works, select input box text and it doesn't.
document.addEventListener('mouseup', function() { console.log(window.getSelection().getRangeAt(0).getBoundingClientRect()) })
<p>Lorem ipsum ... <input value="bla bla"/></p>
<textarea style="width: 100px; height: 50px;"> Lorem ipsum bla bla bla
</textarea>
<p>Input <b>box</b><p>
<input value="Lorem"/>
So what does work? I have found somewhere during frantic searching an approach which seems utterly crazy, but possibly is the only thing that works.
Make a hidden (but not un-rendered) div on which you apply all puted style properties from your input box.
How do you know what the selected input box is? The getSelection() range is meaningless if your have select text in an input box. You must find the input box by document.activeElement (because it has the focus). Now you have that input box with selectionStart and selectionEnd properties. Copy that input's puted style properties onto your hidden div.
Now and put the value text from the input box inside, up until the start of your selected text, e.g., input.value.substring(0, input.selectionStart)
.
Now append a little after that text, and then measure the position of that span, relative to the div.
Finally add that relative position to the position of your real input box. And voilà you have the position of the cursor!
Crazy, I know. And I will do it now because I know of no other solution.
Here it is:
function showPopUp() {
let popUpPos = getSelection()
.getRangeAt(0)
.getBoundingClientRect();
if(popUpPos.x == 0 && popUpPos.y == 0) {
const input = document.activeElement;
const div = document.createElement('div');
for(style of input.putedStyleMap())
div.style[style[0]] = style[1].toString();
div.textContent = input.value.substring(0, input.selectionStart);
const span = document.createElement('span');
div.insertBefore(span, null);
document.body.insertBefore(div, null);
const [divPos, spanPos, inputPos] =
[div, span, input].map(e => e.getBoundingClientRect());
popUpPos = {
x: inputPos.x + (spanPos.x - divPos.x),
y: inputPos.y + (spanPos.y - divPos.y)
};
}
const popUp = document.body.insertAdjacentHTML('beforeend',
`<div style="position: absolute;
top: ${popUpPos.y}px;
left: ${popUpPos.x}px;
border: 2px solid green;'">Look!</div>`);
}
document.addEventListener('mouseup', showPopUp);
<p>Lorem ipsum ... <input value="bla bla"/></p>
<textarea style="width: 100px; height: 50px;"> Lorem ipsum bla bla bla
</textarea>
<p>Input <b>box</b><p>
<input value="Lorem"/>
Now as I have done this to meet the needs of a real app, I found a whole slur of little issues that I had to overe. Here is an (inplete) list:
- a default textarea has no width or height style, to copy that, need to actually read the getBoundingClientRect() to size the hidden div
- scrollbar! need to scroll the hidden div to the same location
- word wrapping, right before the span, put an unbreakable zero-width space and put the text after the selection in after the span, the span then wraps with the following word as needed.
- vertical positioning of the pop up under the current line requires you use the bottom of the span, not the y position. (Not sure if left and x are different in some right-to-left writing schemes perhaps?)
You can't get the exact coordinates of the text caret effortlessly, but this snippet will give you a rect
object with the approximate coordinates of the window's current selection. You may have to also add/subtract use additional offsets of containing elements depending on your styling.
const selection = window.getSelection();
const range = selection.getRangeAt(0);
rect = range.getBoundingClientRect();
Note: This won't work in input
or textarea
in the browsers I'm familiar with
本文标签: javascriptHow to find X and Y position of text caretcursorStack Overflow
版权声明:本文标题:javascript - How to find X and Y position of text caretcursor - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741265175a2368324.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论