我希望能够找出相对于特定父节点,用户在网页中选择文字(突出显示)的位置(也称为:偏移量,索引).
我一直在使用Rangy来帮助我,但是它似乎没有在API中内置偏移属性.这是我到目前为止的内容:
function GetSelectionIndexRelativeTo(parentNodeId)
{
var parentNode = document.getElementById(parentNodeId);
var txt = rangy.getSelection().toString();
var code = rangy.getSelection().toHtml();
var len = code.length;
var x1 = ; // THIS IS WHAT I REALLY WANT. WHAT DO I DO?
var x2 = x1 + len;
return {
text: txt,
html: code,
start: x1,
end: x2,
length: len
}
}
举一些例子:
PAGETEXT: <poem><title>Galaxy</title>Twinkle Twinkle Little Star</poem>
1. SELECTION: Galaxy
RELATIVETO: title
RESULT: start = 0
2. SELECTION: Star
RELATIVETO: poem
RESULT: start = 43
3. SELECTION: Twinkle (the second one)
RELATIVETO: poem
RESULT: start = 28
解决方法:
在回答我的评论时,您表示这是目标:
I want to allows users to select certain words in a poem and add annotations. I want to save each annotation as a tuple .
根据这个目标,我不会使用您在问题中提出的方法.我已经使用了几种方法来保存范围.哪一种适合您取决于您的项目的具体情况.
使用Rangy的选择保存和还原模块
文档记录为here.如果需要任何类型的持久性,则此方法将无效.如果以任何方式修改DOM都将删除Rangy放入的标记,这也将失败.例如,通过删除并重新显示它们刷新页面上的诗的操作将删除标记.例如,如果可以通过关键字动态过滤诗歌,则可能会发生这种情况.
在此情况下,很有可能不会有用. (在其他情况下很有用.)
使用Rangy的序列化器模块
记录为here.这允许以持久方式保存选择,并且以这种方式保存的选择将在DOM刷新后保留下来.
请注意,在序列化之前存在选择的DOM树的结构不得更改.如果DOM树更改了结构,则范围可能无法反序列化. (这取决于特定的情况.)
如果您以这种方式写诗:
<poem><title>Galaxy</title>Twinkle Twinkle Little Star</poem>
而且这种结构永远不变,那么您就很好.即使某些动态操作通过从页面中删除诗歌并重新显示它来刷新这首诗,只要其结构相同,序列化程序也可以反序列化选择.但是,如果保存选择,则决定添加如下作者:
<poem><title>Galaxy</title><author>John Doe</author>Twinkle Twinkle Little Star</poem>
则结构发生了变化,并且序列化程序将无法反序列化.
请注意,序列化程序能够记录相对于特定元素的序列化范围,就像您想要的一样.呼叫的格式如下:
rangy.serializeSelection(sel, false, root)
您将以sel的形式通过选择.第二个参数设置为false,以允许序列化程序计算校验和,以使其能够检测DOM在序列化和反序列化之间是否已更改.根参数将是您要针对其进行序列化的元素.
我建议始终使用与序列化和反序列化相同的元素.选择您最关心的元素.如果您只关心诗歌中的选集,那么大概就是诗歌.因此,给定诗歌中的所有注释都将针对这首诗的诗歌元素进行序列化.
将注释作为标记的一部分
如果将来需要更改数据结构,则必须将批注作为标记的一部分,因此,如果鲍勃添加批注,则可以这样编写代码:
<poem><title>Galaxy</title>Twinkle Twinkle <ann-start ann="#ANN.1"/>Little Star<ann-end ann="#ANN.1"/></poem>
<ann id="ANN.1" creator="Bob">In private correspondence, the author referred to his daughter as his "Little Star"</ann>
(以上假设采用XML表示法,并且仅出于说明目的.完整的解决方案在某些方面会有所不同.)
具有< ann-start>标记开始和< ann-end>在文本中标记注释的结尾是必要的,因为注释可以跨越其他注释或标记构造,但是XML(和HTML)不允许标签跨越. ann属性是一个ID引用,指示ann-start或an-end元素属于哪个注释.
通过使注释成为其引用的数据的一部分,您可以随意更改结构.因此,添加这样的作者:
<poem><title>Galaxy</title><author>John Doe</author>Twinkle Twinkle <ann-start ann="#ANN.1"/>Little Star<ann-end ann="#ANN.1"/></poem>
<ann id="ANN.1" creator="Bob">In private correspondence, the author referred to his daughter as his "Little Star"</ann>
这不是问题,因为您的应用程序仍然可以找到注释的开始和结束.
为什么不在问题中提出方法?
因为它非常脆弱.让我们来看第三个例子:
PAGETEXT: <poem><title>Galaxy</title>Twinkle Twinkle Little Star</poem>
3. SELECTION: Twinkle (the second one)
RELATIVETO: poem
RESULT: start = 28
如果发生以下任何情况,则偏移量28将变得不正确:
>在注解开始之前便发现了一个错字,并且该诗的文字是固定的.
>应用程序的开发者决定显示更多信息并改变这首诗的结构.例如,如上所示,在标题后添加作者姓名.
>标记已更改为支持更多功能.例如,如果有必要使用超链接引用标题:
<poem><title id="...">Galaxy</title>Twinkle Twinkle Little Star</poem>
一旦添加id,偏移量就变得不正确.其他示例包括脚注,样式(对于一次性的情况,不使用音符表),语言信息(这首诗是英语,但诗人决定使用法语单词作为标题).