使用Javascript获取所点击单词的句子

13

这是一个我遇到的问题,我不太确定如何解决它。

假设我有一个段落:

"This is a test paragraph. I love cats. Please apply here"

我希望用户能够点击句子中的任意单词,然后返回包含该单词的整个句子。


nextSibling() 和 previousSibling() - freedomflyer
4
句子边界检测是一个中等难度的自然语言处理问题,由于缩写和标点符号的不完整性而变得更加困难。不适合使用Javascript进行处理。 - bmargulies
1
看看[Rangy](http://code.google.com/p/rangy/)。这是一个非常稳定的文本选择库,我已经使用了相当长一段时间。它应该有助于抽象出很多在查找文本边界时遇到的痛苦,例如句子、单词等。 - Matthew Blancarte
3
这怎么可能被投票为“离题”? - Denys Séguret
我查看了Rangy,但似乎找不到任何句子方法,只有针对单词或更小的选择。有什么指导吗?那是一个有趣的库。 - freedomflyer
显示剩余3条评论
5个回答

11

你首先需要将你的段落拆分成元素,因为没有元素,你无法(轻松地)检测到点击文本的操作:

$('p').each(function() {
    $(this).html($(this).text().split(/([\.\?!])(?= )/).map(
      function(v){return '<span class=sentence>'+v+'</span>'}
   ));
});

请注意,它会正确地分割像这样的段落:

<p>I love cats! Dogs are fine too... Here's a number : 3.4. Please apply here</p>​

然后你需要绑定点击事件:

$('.sentence').click(function(){
    alert($(this).text());
});

演示

我不知道在英语中:是否是句子之间的分隔符。 如果是,当然可以将其添加到正则表达式中。


2
“.” 并不总是用来分割句子的。 - bmargulies
1
@JustinMorgan 为什么不试试?你会发现标点符号并没有从段落中删除。最后的调整可能是将第i个和第i+1个句子合并,但考虑到我在这个答案上得到的建设性或积极的评论越来越少,我不会自己这样做。 - Denys Séguret
看起来这对我的使用情况完全不实用:用户浏览网页,阅读故事,并添加他/她遇到的单词。换句话说,这似乎是很多额外工作。 - freedomflyer
还有,那些不在<p>标签中的文本怎么办? - freedomflyer
1
然后你只需要更改初始选择器。你不需要为此提供新的答案... - Denys Séguret
显示剩余3条评论

5
首先,准备接受一定程度的不准确性。表面看起来这似乎很简单,但试图解析自然语言就像是一种疯狂的练习。因此,让我们假设所有句子都以?!作为结尾标点。我们可以暂时忘记感叹号和其他标点符号。另外,让我们忽略引用标点符号,比如"!",它并不是句子的结尾。
另外,让我们尝试获取标点符号后面的引号,这样"Foo?"最终会被解析为"Foo?"而不是"Foo?
最后,为了简单起见,我们假设段落中没有嵌套的标签。虽然这并不是一个安全的假设,但它会简化代码,处理嵌套标签是一个单独的问题。
$('p').each(function() {
    var sentences = $(this)
        .text()
        .replace(/([^.!?]*[^.!?\s][.!?]['"]?)(\s|$)/g, 
                 '<span class="sentence">$1</span>$2');
    $(this).html(sentences);
});

$('.sentence').on('click', function() { 
    console.log($(this).text()); 
});​

这并不是完美的(例如,引号内的标点符号会破坏它),但它能在99%的情况下工作。


这个很好用。唯一的小问题是要包括 ;: 字符,因为它们也是自然的写作分隔符。正则表达式应该是 /(((?![.!?;:]['"]?\s).)*[.!?;:]['"]?)(\s|$)/g - iwasrobbed

2
  1. 匹配句子。您可以使用类似于/[^!.?]+[!.?]/g的正则表达式来实现。
  2. 用包含点击事件的span标签替换每个句子,以便弹出整个标签。

0

不确定如何获得完整的句子。但是,如果您通过空格拆分每个单词,可以尝试这样做以逐个获取单词。

     <div id="myDiv" onmouseover="splitToSpans(this)" onclick="alert(event.target.innerHTML)">This is a test paragraph. I love cats. Please apply here</div>
function splitToSpans(element){
    if($(element).children().length) 
        return;
    var arr = new Array();
    $($(element).text().split(' ')).each(function(){
    arr.push($('<span>'+this+' </span>'));
    });
    $(element).text('');
    $(arr).each(function(){$(element).append(this);});
}

0

我建议你看一下JavaScript中的选择和范围

没有解析方法可以获取当前选定的句子,所以你必须自己编写代码...

一个跨浏览器基于范围选择的Javascript库是Rangy


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