如何以编程方式将网页部分指定为“已选中”

时间:2014-05-30 04:52:39

标签: javascript jquery html ajax

我试图找出如何使用户能够突出显示和注释HTML文档,标记带有注释的部分并在屏幕上指示哪些文本已经如此标记。将其视为Kindle上提供的注释功能的一个非常简单的版本...用户选择一些文本,键入一个注释并单击"保存"然后文档突出显示该文本以及所有文本用户之前选择的其他文本。 AJAX调用可确保服务器了解选择。

简单的实现似乎是在文档中插入span标记,将类应用于用户选择的每个部分。这意味着文档将随着时间的推移而增长,但我怀疑差异是否显着(每页可能有8-10个选项)。这并不理想,因为我不想将整个文档存回,我只想为每个选定的区域发送/存储起始和结束字符索引(或类似的东西)。

复杂性的下一个逻辑级别是存储开始/结束索引列表,并在显示原始文档后使用jQuery将标记添加到HTML。我可以做到这一点,但逻辑和数学有点不稳定,我想尽可能避免它。当用户点击提交选择时,我只计算索引,如果文档中没有其他内容被选中,则使用AJAX发送,并将相应的span标记应用于标记文档。

不会有重叠的选定区域,因此保持逻辑合理......只是觉得应该有更好的方法。想法?

1 个答案:

答案 0 :(得分:1)

使用选择可能会非常痛苦,因为浏览器会将所有选择视为相对于封闭节点而不是文档,例如:

<p>An example <span>illustrating</span> sel|ections</p>
   01234567890      012345678901       012345678901

如果&#34; sel&#34;之后的管道字符代表插入符号,然后浏览器将其位置视为索引4进入&#34;选择&#34; text-node,而不是26个左右的字符进入包含段落,或者甚至更有用,作为其在包含文档中的索引。

由于这是一个很难处理的问题,我建议使用Tim Down的Rangy库并使用跨度突出显示内容。这里有关于类似要求的帖子:https://stackoverflow.com/a/5765574/3651800

简而言之,Rangy有一个跨浏览器突出显示模块,它将跨度应用于用户选择:

var highlightApplier;

window.onload = function() {
    rangy.init();
    highlightApplier = rangy.createCssClassApplier("highlighted ", true);
};

function applyHighlight() {
    highlightApplier.applyToSelection();
}

如果您以后想要删除文档中的所有突出显示并重新规范化,那么这样的事情应该可以解决问题:

function unwrap(root, tagname) {    
    var elements = root.getElementsByTagName(tagname);
    var len = elements.length;
    var i;
    for( i=len-1; i >= 0; i--) {
        // work backwards to avoid complications with nested spans
        while(elements[i].firstChild) {
            elements[i].parentNode.insertBefore(elements[i].firstChild, elements[i]);            
        }
        var parent = elements[i].parentNode;
        parent.removeChild(elements[i]);
        parent.normalize(); 
    }
}

并称之为:

unwrap(rootElement, "span");

真的希望能帮助你。