我正在尝试突出显示我网站上的部分文字。将为数据库中的特定用户保存此突出显示的文本,并且当再次打开文档时,它将显示先前突出显示的文本。我以为我会使用javascript来突出显示文本,但我似乎无法找到一种方法来确定我突出显示的单词。
function getSelText()
{
var txt = '';
if (window.getSelection)
{
txt = window.getSelection();
}
else if (document.getSelection)
{
txt = document.getSelection();
}
else if (document.selection)
{
txt = document.selection.createRange().text;
}
else return "";
return txt;
}
我正在使用它来获取选择,但我无法弄清楚选择在文本中的位置。最大的烦恼是当我在行或文本中有重复时,所以如果我使用搜索,那么我会找到第一个实例而不是我想要的那个。
所以问题是:如何在整个文档中找出一个单词或一个选择?
答案 0 :(得分:4)
您可以使用我的Rangy库及其selection serialization module。 Rangy的核心为所有浏览器提供了一致的Selection和Range API,并且序列化模块通过将每个选择边界转换为文档中的路径来构建。有关详细信息,请参阅链接的文档。
答案 1 :(得分:3)
这当然不是一项微不足道的任务,因为您面临着在当前文档中查找文本,然后能够在后续页面加载时再次找到它的两个主要问题。如果您的页面内容可能会发生变化,则问题会更加复杂,因为您甚至无法依赖文本的相对位置来保持不变。
考虑到所需的努力,你可能想要考虑这是否是你想要完成的任何事情的最佳方法,但是这可能会让你开始朝着正确的方向前进:
function getSelection() {
var selection, position;
if (window.getSelection) {
selection = window.getSelection();
if (selection && !selection.isCollapsed) {
position = {
'offset': selection.anchorOffset,
'length': selection.toString().length,
// We're assuming this will be a text node
'node': selection.anchorNode.parentNode
};
}
} else if (document.selection) {
selection = document.selection.createRange();
if (selection && selection.text.length) {
var text = selection.parentElement().innerText,
range = document.body.createTextRange(),
last = 0, index = -1;
range.moveToElementText(selection.parentElement());
// Figure out which instance of the selected text in the overall
// text is the correct one by walking through the occurrences
while ((index = text.indexOf(selection.text, ++index)) !== -1) {
range.moveStart('character', index - last);
last = index;
if (selection.offsetLeft == range.offsetLeft && selection.offsetTop == range.offsetTop) {
break;
}
}
position = {
'offset': index,
'length': selection.text.length,
'node': selection.parentElement()
};
}
}
return position;
}
以及再次选择文本的方法:
function setSelection(position) {
if (!position || !position.node) {
return;
}
var selection, range, element;
if (document.createRange) {
element = position.node.childNodes[0];
range = document.createRange();
range.setStart(element, position.offset);
range.setEnd(element, position.offset + position.length);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
} else if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(position.node);
range.collapse(true);
range.move('character', position.offset);
range.moveEnd('character', position.length);
range.select();
}
}
这段代码做出了相当天真的假设,即所选文本都存在于同一个DOM元素中。如果用户选择任意文本,则情况可能很高。
鉴于Selection
object对anchorNode
和focusNode
属性进行了解释,您可以尝试解决此问题,但在Internet Explorer中处理TextRange
object可能会证明有点问题。
还存在如何跨页面请求跟踪position.node
值的问题。在我的 jsFiddle sample 中,我使用了稍微修改过的selector-generating jQuery function版本来生成一个选择器字符串,可以将其保存并用于稍后重新选择正确的节点。请注意,该过程相对简单,因此您可以轻松地在没有jQuery的情况下执行此操作 - 在这种情况下恰好可以节省一些工作。
当然,如果您在访问之间更改DOM,这种方法可能会相当不稳定。如果你不是,我觉得它可能是更可靠的选择之一。
答案 2 :(得分:1)
createRange创建一个textRange对象。它有各种有用的信息:
var range = document.selection.createRange();
var left = range.boundingLeft;
var top = range.boundingTop;