获取范围相对于其父容器的开始和结束偏移量
假设我有这个 HTML 元素:
<div id="parent">
Hello everyone! <a>This is my home page</a>
<p>Bye!</p>
</div>
用户用鼠标选择“home”。
我希望能够确定他的选择从 #parent
开始有多少个字符(以及他的选择从 #parent
末尾开始有多少个字符结束)。即使他选择了 HTML 标签,这也应该有效。 (我需要它在所有浏览器中工作)
range.startOffset
看起来很有希望,但它只是相对于范围的直接容器的偏移量,并且仅当容器是文本节点时才是字符偏移量。
Suppose I have this HTML element:
<div id="parent">
Hello everyone! <a>This is my home page</a>
<p>Bye!</p>
</div>
And the user selects "home" with his mouse.
I want to be able to determine how many characters into #parent
his selection starts (and how many characters from the end of #parent
his selection ends). This should work even if he selects an HTML tag. (And I need it to work in all browsers)
range.startOffset
looks promising, but it is an offset relative only to the range's immediate container, and is a character offset only if the container is a text node.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
更新
正如评论中所指出的,我原来的答案(如下)仅返回选择的结尾或插入符位置。调整代码以返回开始和结束偏移量相当容易;这是一个这样做的示例:
这是一个函数,它将获取指定元素内插入符号的字符偏移量;然而,这是一个幼稚的实现,几乎肯定会与换行符不一致,并且不会尝试处理通过 CSS 隐藏的文本(我怀疑 IE 会正确地忽略此类文本,而其他浏览器不会)。正确处理所有这些事情将很棘手。我现在已经为我的Rangy 库。
实例:http://jsfiddle.net/TjXEG/900/
UPDATE
As pointed out in the comments, my original answer (below) only returns the end of the selection or the caret position. It's fairly easy to adapt the code to return a start and an end offset; here's an example that does so:
Here's a function that will get the character offset of the caret within the specified element; however, this is a naive implementation that will almost certainly have inconsistencies with line breaks, and makes no attempt to deal with text hidden via CSS (I suspect IE will correctly ignore such text while other browsers will not). To handle all this stuff properly would be tricky. I've now attempted it for my Rangy library.
Live example: http://jsfiddle.net/TjXEG/900/
经过几天的试验,我发现了一种看起来很有希望的方法。由于
selectNodeContents()
无法正确处理
标签,因此我编写了一个自定义算法来确定 a 中每个node
的文本长度内容可编辑
。为了计算选择开始,我将所有前面节点的文本长度相加。这样,我就可以处理(多个)换行符:After experimenting a few days I found a approach that looks promising. Because
selectNodeContents()
does not handle<br>
tags correctly, I wrote a custom algorithm to determine the text length of eachnode
inside acontenteditable
. To calculate e.g. the selection start, I sum up the text lengths of all preceding nodes. That way, I can handle (multiple) line breaks:我知道这已经有一年了,但这篇文章是许多有关查找插入符位置的问题的热门搜索结果,我发现这很有用。
在将元素从内容可编辑 div 中的一个位置拖放到另一个位置后,我尝试使用 Tim 上面的出色脚本来查找新的光标位置。它在 FF 和 IE 中工作得很好,但在 Chrome 中,拖动操作突出显示了拖动开始和结束之间的所有内容,这导致返回的 caretOffset 太大或太小(通过长度选定的区域)。
我在第一个 if 语句中添加了几行,以检查是否已选择文本并相应地调整结果。新声明如下。如果在这里添加此内容不合适,请原谅我,因为这不是OP想要做的,但正如我所说,对与插入位置相关的信息的多次搜索使我找到了这篇文章,所以它(希望)可能对其他人有帮助。
Tim 的第一个 if 语句添加了几行 (*):
I know this is a year old, but this post is a top search result for a lot of questions on finding the Caret position and I found this useful.
I was trying to use Tim's excellent script above to find the new cursor position after having drag-dropped an element from one position to another in a content editable div. It worked perfectly in FF and IE, but in Chrome, the dragging action highlighted all content between the beginning and end of the drag, which resulted in the returned
caretOffset
being too large or small (by the length of the selected area).I added a few lines to the first if statement to check if text has been selected and adjust the result accordingly. The new statement is below. Forgive me if it's inappropriate to add this here, as it's not what the OP was trying to do, but as I said, several searches on info related to Caret position led me to this post, so it's (hopefully) likely to help someone else.
Tim's first if statement with added lines(*):
该解决方案的工作原理是计算返回到父容器的前一个同级的文本内容的长度。它可能无法涵盖所有边缘情况,尽管它确实可以处理任何深度的嵌套标签,但如果您有类似的需求,那么这是一个很好、简单的起点。
This solution works by counting length of text content of previous siblings walking back up to the parent container. It probably doesn't cover all edge cases, although it does handle nested tags of any depth, but it's a good, simple place to start from if you have a similar need.