突出显示HTML文本中的单词(但不是标记)

时间:2012-05-24 01:20:00

标签: javascript regex

我正在尝试突出显示正文中所有匹配的单词,而不是任何html标记内的单词。例如,给定的关键字是'para'。这是段落:

<p class="para"> Example of paragraph. Lorem ipsum dolor sit amet. </p>

导致:

<p class="para">
Example of <strong>para</strong>graph. Lorem ipsum dolor sit amet.
</p>

我知道这可以通过JavaScript replace()实现,但我对regex不太了解。

3 个答案:

答案 0 :(得分:13)

演示:http://jsfiddle.net/crgTU/7/

highlightWord(document.body,'para');

function highlightWord(root,word){
  textNodesUnder(root).forEach(highlightWords);

  function textNodesUnder(root){
    var n,a=[],w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,null,false);
    while(n=w.nextNode()) a.push(n);
    return a;
  }

  function highlightWords(n){
    for (var i; (i=n.nodeValue.indexOf(word,i)) > -1; n=after){
      var after = n.splitText(i+word.length);
      var highlighted = n.splitText(i);
      var span = document.createElement('span');
      span.className = 'highlighted';
      span.appendChild(highlighted);
      after.parentNode.insertBefore(span,after);
    }
  }
}
​

您也可以考虑调用类似......

function removeHighlights(root){     
  [].forEach.call(root.querySelectorAll('span.highlighted'),function(el){
    el.parentNode.replaceChild(el.firstChild,el);
  });
}

...在你找到新的亮点之前(从DOM中删除旧的亮点)。

答案 1 :(得分:6)

为什么使用自制高亮功能是一个坏主意

从头开始构建自己的突出显示功能可能是一个坏主意的原因是因为你肯定会遇到其他人已经解决的问题。挑战:

  • 您需要删除包含HTML元素的文本节点,以突出显示您的匹配,而不会破坏DOM事件并反复触发DOM重新生成(例如innerHTML就是这种情况)
  • 如果要删除突出显示的元素,则必须删除包含其内容的HTML元素,并且还必须组合拆分的文本节点以进行进一步搜索。这是必要的,因为每个荧光笔插件都会在文本节点内搜索匹配项,如果您的关键字将被拆分为多个文本节点,则无法找到它们。
  • 您还需要构建测试以确保您的插件能够在您没有考虑过的情况下工作。我正在谈论跨浏览器测试!

听起来很复杂?如果你想要一些功能,比如忽略突出显示,变音符号映射,同义词映射,iframe内搜索,分离词搜索等一些元素,这就变得越来越复杂。

使用现有插件

使用现有的,实施良好的插件时,您不必担心上面提到的内容。 Sitepoint上的文章 10 jQuery text highlighter plugins 比较了流行的荧光笔插件。

查看mark.js

mark.js是一个用纯JavaScript编写的插件,但也可以作为jQuery插件使用。它的开发目的是提供比其他插件更多的机会,可以选择:

  • 分别搜索关键字而不是完整的字词
  • map diacritics(例如,如果“justo”也应匹配“justò”)
  • 忽略自定义元素内的匹配
  • 使用自定义突出显示元素
  • 使用自定义突出显示类
  • 映射自定义同义词
  • 也在iframe内搜索
  • 收到未找到的条款

<强> DEMO

或者,您可以看到this fiddle

使用示例

// Highlight "keyword" in the specified context
$(".context").mark("keyword");

// Highlight the custom regular expression in the specified context
$(".context").markRegExp(/Lorem/gmi);

它是免费的,并在GitHub(project reference)上开发了开源。

答案 2 :(得分:0)

您可以使用正则表达式方式,但它还不会突出显示几个标签。 例如,我的亮点&#34;我的亮点&#34;不会突出显示。

以下是代码:

str='<img src="brown fox.jpg" title="The brown fox" />'
    +'<p>some text containing fox. And onother fox.</p>'
var word="fox";
word="(\\b"+ 
    word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
        + "\\b)";
var r = new RegExp(word,"igm")
str.replace(/(>[^<]+)/igm,function(a){
    return a.replace(r,"<span class='hl'>$1</span>");
})