【问题标题】:Highlight text inside html with jQuery使用 jQuery 突出显示 html 中的文本
【发布时间】:2012-02-28 09:14:28
【问题描述】:

我想做一些类似于这个插件http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

但是我面临的问题是上面的插件不允许你在html中突出显示单词。

所以如果你正在寻找my text

在html里面喜欢

this is <a href="#">my</a> text that needs highlighting

您不会得到任何突出显示。

有没有办法在忽略中间的任何 html 标签的同时突出显示文本?

【问题讨论】:

  • 以这种方式跨多个 html 节点匹配文本几乎是不可能的。
  • 假设您想保留锚标记的位置。

标签: jquery highlight


【解决方案1】:

我修改了一些允许 HTML 标记位于空白字符位置的正则表达式:

<div id="test">this is <a href="#">my</a> text that needs highlighting</div>

JavaScript:

var src_str = $("#test").html();
var term = "my text";
term = term.replace(/(\s+)/,"(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("("+term+")", "i");

src_str = src_str.replace(pattern, "<mark>$1</mark>");
src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/,"$1</mark>$2<mark>$4");

$("#test").html(src_str);

在这里试试:http://jsfiddle.net/UPs3V/

【讨论】:

  • 这看起来不错,但是如果您在“my”和“term”之间添加一个空格,它不会突出显示。我指的是 JSFiddle
  • 我修复了该错误,但出现了一个新错误。因为脚本输出类似&lt;a href="#"&gt;&lt;mark&gt;my&lt;/a&gt; text&lt;/mark&gt; 的内容,浏览器引擎会自动将其更正为&lt;a href="#"&gt;&lt;mark&gt;my&lt;/mark&gt;&lt;/a&gt; text。有任何想法吗? ://
  • 哎呀,这看起来像一些严肃的正则表达式。我将通过振铃器运行它,看看它是如何执行的。速度是我关心的问题。我确实可以选择在服务器端执行此操作,因此将其转换为 php 也可能有意义。我做了一些阅读,有些人推荐了一个 php Dom Parser,但我不知道从哪里开始。
  • 如果在 JavaScript 的第二行中将 my text 替换为 href 会破坏逻辑。你觉得你有时间看吗?这对我有很大帮助。
  • 尽管我们对这项工作深表感谢,但必须注意的是,使用正则表达式解析 HTML 往往会打开地狱之门,并引发大量食肉怪物,它们会摧毁一切美好的事物和漂亮。
【解决方案2】:

我尝试了公认的解决方案,但它似乎在复杂页面上中断,例如这个(无限递归)。另外,我并没有真正看到依赖 jQuery 的好处,所以我重写了代码以独立于 jQuery(它也大大缩短并且不支持花哨的选项)。

如果您愿意,可以很容易地重新添加选项并使用类。

function highlight(re, node, depth, maxdepth){
    node = node || document.body;
    depth = depth || 0;
    maxdepth = maxdepth || 10;

    if( node.nodeType === 3 ){
        var match = node.data.match(re);
        if(match){
            var span = document.createElement('span');
            span.style.backgroundColor = '#ffa';
            var wordNode = node.splitText(match.index);
            wordNode.splitText(match[0].length);
            var wordClone = wordNode.cloneNode(true);
            span.appendChild(wordClone);
            wordNode.parentNode.replaceChild(span, wordNode);
            return 1;
        }
    } else if( depth === maxdepth ){
        console.log( 'Reached max recursion depth!', node );
    } else if( (node.nodeType === 1 && node.childNodes) && !/(script|style)/i.test(node.tagName) ) {
        for( var i = 0; i < node.childNodes.length; i++ ){
            i += highlight(re, node.childNodes[i], depth + 1, maxdepth);
        }
    }
    return 0;
}

【讨论】:

    【解决方案3】:

    我想发表评论,但堆栈不允许我,或者我似乎找不到它的按钮,所以必须在答案中这样做。 脚本有问题。 例如: 在以下字符串中突出显示 fox:

    <img src="brown fox.jpg" title="The brown fox" /><p>some text containing fox.</p>
    

    会破坏 img 标签:

    var term = "fox";
    term = term.replace(/(\s+)/,"(<[^>]+>)*$1(<[^>]+>)*");
    var pattern = new RegExp("("+term+")", "i");
    src_str ='<img src="brown fox.jpg" title="The brown fox" />'
        +'<p>some text containing fox.</p>'
    src_str = src_str.replace(pattern, "<mark>$1</mark>");
    src_str = src_str.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/,"$1</mark>$2<mark>$4");
    src_str
    

    我正在编写一个高亮脚本并解决了这个问题,但我没有意识到脚本可能必须在多个标签上高亮显示。 这是我如何通过尝试突出显示标签中的内容来避免破坏标签的方法,该脚本也突出显示内容中的多个实例,但不会突出多个标签:

    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>");
    })
    

    不确定如何组合这些脚本并突出显示多个标签,但我会继续关注这个线程。

    【讨论】:

      猜你喜欢
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      相关资源
      最近更新 更多