代码之家  ›  专栏  ›  技术社区  ›  Nelson Rothermel

突出显示搜索项(仅选择叶节点)

  •  4
  • Nelson Rothermel  · 技术社区  · 15 年前

    $('.searchResult *').each(function() {
        $(this.html($(this).html().replace(new RegExp('(term)', 'gi'), '<span class="highlight">$1</span>'));
    )};
    

    然而, $('.searchResult *').each

    1. 如何仅匹配叶节点?
    2. 是否有一些内置jQuery RegEx函数来简化事情?比如: $(this).wrap('term', $('<span />', { 'class': 'highlight' }))
    3. 有没有办法做一个简单的字符串替换而不是正则表达式?

    非常感谢!

    7 回复  |  直到 15 年前
        1
  •  8
  •   galambalazs    14 年前

    [ See it in action

    // escape by Colin Snover
    // Note: if you don't care for (), you can remove it..
    RegExp.escape = function(text) {
        return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    }
    
    function highlight(term, base) {
      if (!term) return;
      base = base || document.body;
      var re = new RegExp("(" + RegExp.escape(term) + ")", "gi"); //... just use term
      var replacement = "<span class='highlight'>" + term + "</span>";
      $("*", base).contents().each( function(i, el) {
        if (el.nodeType === 3) {
          var data = el.data;
          if (data = data.replace(re, replacement)) {
            var wrapper = $("<span>").html(data);
            $(el).before(wrapper.contents()).remove();
          }
        }
      });
    }
    
    function dehighlight(term, base) {
      var text = document.createTextNode(term);
      $('span.highlight', base).each(function () {
        this.parentNode.replaceChild(text.cloneNode(false), this);
      });
    }
    
        2
  •  3
  •   Anurag    15 年前

    contents() 1 , 2 3 要获取包括文本节点在内的所有节点,请过滤掉非文本节点,最后替换 nodeValue

    function highlight(term) {
        var regex = new RegExp("(" + term + ")", "gi");
        var localRegex = new RegExp("(" + term + ")", "i");
        var replace = '<span class="highlight">$1</span>';
    
        $('body *').contents().each(function() {
            // skip all non-text nodes, and text nodes that don't contain term
            if(this.nodeType != 3 || !localRegex.test(this.nodeValue)) {
                return;
            }
            // replace text node with new node(s)
            var wrapped = $('<div>').append(this.nodeValue.replace(regex, replace));
            $(this).before(wrapped.contents()).remove();
        });
    }
    

    See example here .

        3
  •  2
  •   Chris Doggett    15 年前

    我会给你 Highlight

        4
  •  1
  •   Ryan    12 年前

    我花了几个小时在网络上搜索代码,这些代码可以根据用户的类型突出显示搜索词,但没有一个可以做我想做的事情,直到我把一堆东西组合在一起做这件事( jsfiddle demo here ):

    $.fn.replaceText = function(search, replace, text_only) {
        //http://stackoverflow.com/a/13918483/470749
        return this.each(function(){  
            var v1, v2, rem = [];
            $(this).find("*").andSelf().contents().each(function(){
                if(this.nodeType === 3) {
                    v1 = this.nodeValue;
                    v2 = v1.replace(search, replace);
                    if(v1 != v2) {
                        if(!text_only && /<.*>/.test(v2)) {  
                            $(this).before( v2 );  
                            rem.push(this);  
                        } else {
                            this.nodeValue = v2;  
                        }
                    }
                }
            });
            if(rem.length) {
                $(rem).remove();
            }
        });
    };
    
    function replaceParentsWithChildren(parentElements){
        parentElements.each(function() {
            var parent = this;
            var grandparent = parent.parentNode;
            $(parent).replaceWith(parent.childNodes);
            grandparent.normalize();//merge adjacent text nodes
        });
    }
    
    function highlightQuery(query, highlightClass, targetSelector, selectorToExclude){
        replaceParentsWithChildren($('.' + highlightClass));//Remove old highlight wrappers.
        $(targetSelector).replaceText(new RegExp(query, "gi"), function(match) {
            return '<span class="' + highlightClass + '">' + match + "</span>";
        }, false);
        replaceParentsWithChildren($(selectorToExclude + ' .' + highlightClass));//Do not highlight children of this selector.
    }
    
        5
  •  1
  •   jasonslyvia    11 年前

    我已经制作了一个纯JavaScript版本,并将其打包成一个Google Chrome插件,希望对一些人有所帮助。核心功能如下:

    GitHub Page for In-page Highlighter

    function highlight(term){
        if(!term){
            return false;
        }
    
        //use treeWalker to find all text nodes that match selection
        //supported by Chrome(1.0+)
        //see more at https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
        var treeWalker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null,
            false
            );
        var node = null;
        var matches = [];
        while(node = treeWalker.nextNode()){
            if(node.nodeType === 3 && node.data.indexOf(term) !== -1){
                matches.push(node);
            }
        }
    
        //deal with those matched text nodes
        for(var i=0; i<matches.length; i++){
            node = matches[i];
            //empty the parent node
            var parent = node.parentNode;
            if(!parent){
                parent = node;
                parent.nodeValue = '';
            }
            //prevent duplicate highlighting
            else if(parent.className == "highlight"){
                continue;
            }
            else{
                while(parent && parent.firstChild){
                    parent.removeChild(parent.firstChild);
                }
            }
    
            //find every occurance using split function
            var parts = node.data.split(new RegExp('('+term+')'));
            for(var j=0; j<parts.length; j++){
                var part = parts[j];
                //continue if it's empty
                if(!part){
                    continue;
                }
                //create new element node to wrap selection
                else if(part == term){
                    var newNode = document.createElement("span");
                    newNode.className = "highlight";
                    newNode.innerText = part;
                    parent.appendChild(newNode);
                }
                //create new text node to place remaining text
                else{
                    var newTextNode = document.createTextNode(part);
                    parent.appendChild(newTextNode);
                }
            }
    
        }
    }
    
        6
  •  0
  •   a7drew    15 年前

    下面是一个简单的实现,它只在HTML中爆炸任何匹配:

    <!DOCTYPE html>
    <html lang"en">
    <head>
        <title>Select Me</title>
        <style>
            .highlight {
                background:#FF0;
            }
        </style>
        <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js"></script>
        <script type="text/javascript">
    
            $(function () {
    
                hightlightKeyword('adipisicing');
    
            });
    
            function hightlightKeyword(keyword) {
    
                var replacement = '<span class="highlight">' + keyword + '</span>';
                var search = new RegExp(keyword, "gi");
                var newHtml = $('body').html().replace(search, replacement);
                $('body').html(newHtml);
            }
    
        </script>
    </head>
    <body>
        <div>
    
            <p>Lorem ipsum dolor sit amet, consectetur <b>adipisicing</b> elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p>Lorem ipsum dolor sit amet, <em>consectetur adipisicing elit</em>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    
        </div>
    </body>
    </html>
    
        7
  •  0
  •   Sbl musiKk    11 年前

    var start = new Date();
    // hightlighting code goes here ...
    var end = new Date();
    var ms = end.getTime() - start.getTime();
    jQuery("#time-ms").text(ms);
    

    我用这些线分叉了Anurag的溶液,结果平均为40-60ms。

    所以我把这把小提琴叉起来,做了一些改进来满足我的需要。一件事是RegEx转义(请参阅stackoverflow中CoolAJ86在“javascript RegEx中使用的转义字符串”中的答案)。

    在我的机器(chromium,linux)上,我有大约30-50ms的运行时 jsfiddle .

    我还添加了我的定时器到最高等级的galambalazs解决方案,你可以在这里找到这个 jsFiddle . 但是这个有60-100毫秒的运行时间。

    在运行时(例如,在Firefox中大约四分之一秒),以毫秒为单位的值变得更高,更重要。