我试图找出如何使用户能够突出显示和注释HTML文档,标记带有注释的部分并在屏幕上指示哪些文本已经如此标记。将其视为Kindle上提供的注释功能的一个非常简单的版本...用户选择一些文本,键入一个注释并单击"保存"然后文档突出显示该文本以及所有文本用户之前选择的其他文本。 AJAX调用可确保服务器了解选择。
简单的实现似乎是在文档中插入span标记,将类应用于用户选择的每个部分。这意味着文档将随着时间的推移而增长,但我怀疑差异是否显着(每页可能有8-10个选项)。这并不理想,因为我不想将整个文档存回,我只想为每个选定的区域发送/存储起始和结束字符索引(或类似的东西)。
复杂性的下一个逻辑级别是存储开始/结束索引列表,并在显示原始文档后使用jQuery将标记添加到HTML。我可以做到这一点,但逻辑和数学有点不稳定,我想尽可能避免它。当用户点击提交选择时,我只计算索引,如果文档中没有其他内容被选中,则使用AJAX发送,并将相应的span标记应用于标记文档。
不会有重叠的选定区域,因此保持逻辑合理......只是觉得应该有更好的方法。想法?
答案 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");
真的希望能帮助你。