单击时确定 HTML 元素内字符的位置索引
我有一个 HTML 元素,里面只有可见的文本。此示例是一个
元素,但它也可以是
、
或其他 DOM 元素。
<div>This is a simple example.</div>
单击时,我可以获得光标在 div 表面上的位置,但我需要确定单击时最接近的字符和/或其在 div.innerHTML 字符串中的索引。
我在 SVG 文本实体的“getCharNumAtPosition”方法中发现了类似的实现此处。
是否可以在 JavaScript 中实现这样一个与 HTML 一起使用的函数?
(如果解决方案能够在大多数现代浏览器之间移植,与大多数书面语言一起使用,并且基于相对稳定的标准,这样它们以后就不会出现错误,那么它们将是最有用的。)
I have an HTML element with only visible text inside. This example is a <div>
element, but it could be a <span>
, <p>
, or other DOM element.
<div>This is a simple example.</div>
When clicked, I can get the position of the cursor on the surface of the div, but I need to determine the position of the nearest character and/or its index into the div.innerHTML string at the time of the click.
I found a similar implementation in the "getCharNumAtPosition" method in SVG text entities here.
Is it possible to implement such a function in JavaScript that works with HTML?
(Solutions would be most useful if they are portable across most modern browsers, work with most written languages, and are based on relatively stable standards so that they will not become buggy later.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于大多数浏览器来说,这适用于“单击”以及“范围”。 (
selection.type = "caret"
/selection.type = "range"
)。selection.focusOffset()
为您提供内部节点中的位置。如果元素是嵌套的,例如在或
标签内,它将为您提供内部元素内的位置,而不是全文,更多或更少。我无法使用
focusOffset
和“插入符号”类型“选择”子标签的第一个字母(单击,而不是范围选择)。当您单击第一个字母时,它会给出标签开始之前最后一个元素的位置加 1。当您单击第二个字母时,它会正确地给出“1”。但我没有找到访问子元素的第一个元素(偏移0)的方法。这个“选择/范围”的东西似乎有问题(或者对我来说非常不直观)。 ^^但使用起来非常简单,无需嵌套元素! (与您的
配合良好)
这是一个小提琴
2015 年重要编辑-01-18:
这个答案在被接受时有效,但现在不再有效,原因如下。其他答案现在最有用。
Firefox 和 Chrome 都调试了
window.getSelection()
行为。遗憾的是,它现在对于这个用例来说毫无用处。 (阅读文档,IE 9 及更高版本的行为应相同)。现在,字符的中间用于决定偏移量。这意味着点击一个角色可以返回 2 个结果。第一个字符为 0 或 1,第二个字符为 1 或 2,等等。
我更新了 JSFiddle 示例。
请注意,如果您调整窗口大小(Ctrl + 鼠标),Chrome 上的某些点击行为会出现很多错误。
This works with "click", as well as with a "range" for most browsers. (
selection.type = "caret"
/selection.type = "range"
).selection.focusOffset()
gives you the position in the inner node. If elements are nested, within<b>
or<span>
tags for example, it will give you the position inside the inner element, not the full text, more or less. I'm unable to "select" the first letter of a sub tag withfocusOffset
and "caret" type (click, not range select). When you click on the first letter, it gives the position of the last element before the start of tag plus 1. When you click on the second letter, it correctly gives you "1". But I didn't find a way to access the first element (offset 0) of the sub element. This "selection/range" stuff seems buggy (or very non-intuitive to me). ^^But it's quite simple to use without nested elements! (Works fine with your
<div>
)Here is a fiddle
Important edit 2015-01-18:
This answer worked back when it was accepted, but not anymore, for reasons given below. Other answers are now most useful.
Both Firefox and Chrome debugged
window.getSelection()
behavior. Sadly, it is now useless for this use case. (Reading documentation, IE 9 and beyond shall behave the same).Now, the middle of a character is used to decide the offset. That means that clicking on a character can give back 2 results. 0 or 1 for the first character, 1 or 2 for second, etc.
I updated the JSFiddle example.
Please note that if you resize the window (Ctrl + mouse), the behavior is quite buggy on Chrome for some clicks.
您可以使用 JavaScript 将每个字符分解为它自己的 SPAN 标记,并为每个字符添加一个 onclick 事件。然后,单击 SPAN 时从事件数据中读取 x、y 位置。
此外,您还可以访问使用 event.target.innerHTML 单击的角色
You could, using JavaScript, break each character into it's own SPAN tag and add an onclick event for each. Then, read the x, y position from the event data when the SPAN is clicked.
As well, you will have access to the character clicked with event.target.innerHTML
在许多情况下,可能的解决方案是在标记内容的每个字符之间添加零宽度空格字符 (U+200B)。然后使用 javascript
window.getSelection().focusOffset
+ 一些简单的计算来完成这项工作。示例 html 代码(包括零宽度空格字符):
示例 javascript 代码:
似乎可以广泛工作,甚至在 Internet Explorer 上也是如此!
jsFidle: http://jsfiddle.net/by1a9pfm/
In many cases, a possible solution can be to add zero-width space character (U+200B) between each char of the content of the tag. Then using javascript
window.getSelection().focusOffset
+ some simple computations does the job.Sample html code (including zero-width space characters):
Sample javascript code:
Seems to work widely, even on internet explorer!
jsFidle: http://jsfiddle.net/by1a9pfm/
此示例可以快速加载中等大小的文本块,可移植且健壮。尽管它的优雅不是立即显而易见的,但可靠性在于在国际字符和 DOM 事件侦听器 1 之间创建简单的一对一对应关系。
最好仅依赖广泛采用的字符编码、DOM 和 ECMA 标准,如此例所示。其他方法通常依赖于低级事件目标属性或函数(例如 getSelection()),这些属性或函数随着时间的推移既不稳定,也无法跨浏览器和语言移植2。
对于特定应用程序,可以通过多种方式修改示例代码。例如,可以采用其他机制来选择为 charClick 回调初始化哪些 DOM 对象。 i 循环中也可以支持代理对。
This example is quick loading for moderately sized blocks of text, portable, and robust. Although its elegance is not immediately apparent, reliability lies in the creation of a simple one to one correspondence between international characters and DOM event listeners 1.
It is best to relying only on widely adopted character encoding, DOM, and ECMA standards as in this example. Other approaches often rely on low level event target attributes or functions like getSelection(), which are neither stable over time nor portable across browsers and languages 2.
The example code could be modified in a number of ways for specific applications. For instance other mechanisms could be employed to select which DOM objects are initialized for charClick callbacks. Surrogate pairs could be supported in the i loop too.
Full testing is recommended before using this in internationalized production scenarios. If bugs are found, please suggest edits or add comments so that refinements can be added.
Notes
[1] These event listeners could have been added directly but would have required branching for browser portability or the extra weight of libraries that add no particular speed or convenience value for this use case.
[2] See notes about select events in W3C's UI events page.