JavaScript:如何检测单词是否被高亮显示

74
我正在编写一个Firefox插件,它会在单词被选中时触发。但是我需要一个脚本来检测单词何时被选中,不过我卡住了。例如,nytimes.com的文章中,当你选中一个单词时,参考图标就会弹出。然而,nytimes.com的脚本非常复杂。我只有16岁,也不是很擅长编程,所以那绝对超出了我的能力范围。
4个回答

106

最简单的方法是在文档上检测mouseupkeyup事件,并检查是否选择了任何文本。以下内容适用于所有主流浏览器。

示例:http://www.jsfiddle.net/timdown/SW54T/

function getSelectedText() {
    var text = "";
    if (typeof window.getSelection != "undefined") {
        text = window.getSelection().toString();
    } else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
        text = document.selection.createRange().text;
    }
    return text;
}

function doSomethingWithSelectedText() {
    var selectedText = getSelectedText();
    if (selectedText) {
        alert("Got selected text " + selectedText);
    }
}

document.onmouseup = doSomethingWithSelectedText;
document.onkeyup = doSomethingWithSelectedText;

4
如果您想检测特定单词是否已被选中,该怎么办呢?比如页面上有多个foo,用户选择了其中一个,您如何知道用户选择的是哪个单词? - Jespertheend
1
@Jespertheend 如果数据(foos)是动态生成的,那么您可以为每个foo分配一些唯一的ID,然后您可以使用window.getSelection().getRangeAt(0).startContainer.parentNode.id来获取特定foo的ID。 - Raghav Garg
太好了,谢谢!我想在输入框的 keypress 事件中实现自定义的最大长度功能,但如果输入框已经达到其最大长度,则仍应通过 keypress 事件,如果有任何文本被突出显示。您的函数完美地完成了这项工作。 - Jacob Stamm

6

这里有一段脚本:

<script>
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;
document.aform.selectedtext.value = txt;
}
</script>
<input type="button" value="Get selection" onmousedown="getSelText()"> 
<form name="aform">
<textarea name="selectedtext" rows="5" cols="20"></textarea>
</form>

由Code Toad提供:

http://www.codetoad.com/javascript_get_selected_text.asp

在您的情况下,您希望在选择时调用此脚本,然后您可以以任何您希望的方式进行处理,例如使用AJAX请求获取相关信息,就像NYtimes可能会做的那样。


6
我经常在 Stack Overflow 上看到这段代码,但它是错误的:window.getSelection() 返回一个 Selection 对象,而不是一个字符串。 - Tim Down
2
@tim down 并不是完全正确的。该对象具有toString()方法。当需要一个字符串时,将返回一个字符串,否则,就像你指出的那样,将返回一个对象。https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection - Ted Cohen
是的,该方法返回一个对象。如果它没有返回一个对象,那么我们都认同的“东西”如何有一个toString()方法呢?我不同意的是你的代码是错误的说法。你忘记了js语言经常隐式转换类型。有些人称之为弱类型语言。所有的js程序员都需要注意到这种转换并认识到它的本质。在浏览器返回对象后,js会隐式调用toString()方法并返回一个字符串。这适用于js中的任何对象,而不仅仅是getSelection()。代码是正确的。 - Ted Cohen
@tim down,这就是为什么你在SO上经常看到它的原因。请阅读我原始评论中的参考文献,因为它清楚地阐述了我的观点,可能比我自己说得更好。 - Ted Cohen
@tim down, 我并没有说你的评论是错的,只是它并不是全部的真相。我希望你能回去编辑一下你的初始评论,我们可以删除这个讨论部分。你提出了一个非常重要的观点,正如MDN页面所说,经常被误解(我在从记忆中转述,而不是引用)。 - Ted Cohen
显示剩余3条评论

4

在我的情况下,我希望能够在一行的文本中突出显示并单击该行,然后将我发送到其他路由,例如“/entity/:id”;

我创建了一个检测鼠标是否突出显示一些文本的函数:

export const isHighlighting = () => {
  // detects mouse is highlighting a text
  return window.getSelection && window.getSelection().type === 'Range';
};

然后我将这个添加到行中。
const handleClick = (id) => {
  if (!isHighlighting() {
     history.push(`/entity/${id}`)
  }
}

{data.map((item) => (
  <tr>
    <td onClick={() => handleClick(item.id)}>{item.name}</>
  </tr>
))}

通过这种方式,用户可以高亮名称字段,或单击其他位置进入 "/entity/:id"。


-1

使用 rangy.js 和 jQuery:

$('#elem').on('keyup mouseup', function(){
    var sel = rangy.getSelection()
    if (sel.rangeCount === 0 || sel.isCollapsed) return
    alert(sel.toString())
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接