使用jquery对html内容进行跨标签的关键词检索

本人后端狗,接触过一些html、javascript,这个问题是组内前端小伙伴遇到的,帮他解决了这个问题

问题描述:将word文件转为html后在页面显示,需要对这部分html内容进行关键词搜索高亮,但转换后的文字被拆分,被包含在各种标签里,很多内容检索不到。
解决过程如下:

  1. 直接对html片段使用模糊匹配
    *关键词在同一个标签内有效
    -关键词被拆分到不同标签里,页面上可以看到这个关键词,但是搜索不到
    -误匹配到html标签,造成页面显示异常
  2. 使用jquery插件(jquery.textSearch-1.0.js插件原文链接
    *关键词在同一个标签内有效
    *解决误匹配html标签的问题
    -关键词被拆分到不同标签里,页面上可以看到这个关键词,但是搜索不到
  3. 对jquery.textSearch插件进行改造
    阅读了插件的源码,发现他是用正则将HTML代码支离为HTML片段和文字片段,其中文字片段用于正则替换处理,而HTML片段置之不理,处理好后再合并这些片段
    拆分html的思路很棒,但是他只对单个文字片段进行替换,如果关键词包括了前后几个文字片段方法就失效了
    于是我他的基础上补充了一部分代码,判断文字片段包含的关键词的开头部分,并且关键词包含了后面的连续文字片段,最后一个文字片段又包含关键词结尾部分,就可以匹配上跨标签的文字。
    *关键词在同一个标签内有效
    *解决误匹配html标签的问题
    *关键词被拆分到不同标签里同样有效
  4. 实际使用中可以根据需要进行改造,比如使用正则表达式拆分出空格,这样即使原文片段里含有空格也不影响检索。
    也可以将该jquery插件用vue等方式重写,欢迎分享

附上修改后的代码,有点长


// update by vinci

(function($){
    $.fn.textSearch = function(str,options){
        var defaults = {
            divFlag: true,
            divStr: " ",
            markClass: "mark",
            markColor: "",
            cardColor: "",
            markType: "font",
            markBackground: "",
            nullReport: true,
            callback: function(){
                return false;   
            }
        };
        var sets = $.extend({}, defaults, options || {}), clStr;
        if(sets.markClass){
            clStr = "class='"+sets.markClass+"'";   
        }
        if(sets.cardColor){
            clStr += " style='color:"+sets.cardColor+"; cursor: pointer;text-decoration:underline;'";
        }
        if(sets.markColor){
            clStr += " style='color:"+sets.markColor+";'";
        }
        if(sets.markBackground){
            clStr += " style='background:"+sets.markBackground+";'";
        }
        
        
        
        //对前一次高亮处理的文字还原     
        // $("."+sets.markClass).each(function() {
        //  var text = document.createTextNode($(this).text()); 
        //  $(this).replaceWith($(text));
        // });
        
        
        //字符串正则表达式关键字转化
        $.regTrim = function(s){
            var imp = /[\^\.\\\|\(\)\*\+\-\$\[\]\?]/g;
            var imp_c = {};
            imp_c["^"] = "\\^";
            imp_c["."] = "\\.";
            imp_c["\\"] = "\\\\";
            imp_c["|"] = "\\|";
            imp_c["("] = "\\(";
            imp_c[")"] = "\\)";
            imp_c["*"] = "\\*";
            imp_c["+"] = "\\+";
            imp_c["-"] = "\\-";
            imp_c["$"] = "\$";
            imp_c["["] = "\\[";
            imp_c["]"] = "\\]";
            imp_c["?"] = "\\?";
            s = s.replace(imp,function(o){
                return imp_c[o];                       
            }); 
            return s;
        };
        $(this).each(function(){
            var t = $(this);
            str = $.trim(str);
            if(str === ""){
                alert("关键字为空"); 
                return false;
            }else{
                //将关键字push到数组之中
                var arr = [];
                if(sets.divFlag){
                    arr = str.split(sets.divStr);   
                }else{
                    arr.push(str);  
                }
            }
            var v_html = t.html();
            //删除注释
            v_html = v_html.replace(/<!--(?:.*)\-->/g,"");
            
            //将HTML代码支离为HTML片段和文字片段,其中文字片段用于正则替换处理,而HTML片段置之不理
            //var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g;
            //处理空格问题
            var tags = /[^<>\s]+|[\s]+|[]+|<(\/?)([A-Za-z]+)([^<>]*)>/g;

            var a = v_html.match(tags), test = 0;
            $.each(a, function(i, c){
                if(!/<(?:.|\s)*?>/.test(c)){//非标签
                    //开始执行替换
                    $.each(arr,function(index, con){
                        if(con === ""){return;}
                        var reg = new RegExp($.regTrim(con), "g");
                        if(reg.test(c)){
                            //正则替换
                            c = c.replace(reg,"♂"+con+"♀");
                            c = c.replace(/♂/g,"<"+sets.markType+" "+clStr+">").replace(/♀/g,"</"+sets.markType+">");
                            a[i] = c;
                            test = 1;
                        }else if(containStart(c, con)){
                            var testA = [];
                            var testI = [];
                            testA.push(c);
                            testI.push(i);
                            for(var j=i+1;j<a.length;j++){
                                var aj = a[j]
                                if(!/<(?:.|\s)*?>/.test(aj)){
                                    if(containEnd(aj,con)){
                                        testA.push(aj);
                                        testI.push(j);
                                        if(testA.join("").length >= con.length){
                                            break;
                                        }
                                    }else if(con.indexOf(aj)!=-1){
                                        testA.push(aj);
                                        testI.push(j);
                                    }else if(con.indexOf(aj)==-1){
                                        break;
                                    }
                                }
                            }
                            if(testA.join("").indexOf(con)!=-1){
                                for(var p=0;p<testI.length;p++){
                                    var ind = testI[p];
                                    var ti = testA[p];
                                    var c1;
                                    if(p==0){
                                        var start = getContainStart(ti, con)
                                        c1 = ti.replace(start,"♂"+start+"♀");
                                    }else if(p==testI.length-1){
                                        var end = getContainEnd(ti, con)
                                        c1 = ti.replace(end,"♂"+end+"♀");
                                    }else{
                                        c1 = ti.replace(ti,"♂"+ti+"♀");
                                    }
                                    c1 = c1.replace(/♂/g,"<"+sets.markType+" "+clStr+">").replace(/♀/g,"</"+sets.markType+">");
                                    a[ind] = c1;
                                }
                                test = 1;
                            }
                        }
                    });
                    
                }
            });
            //将支离数组重新组成字符串
            var new_html = a.join("");
            $(this).html(new_html);
            if(test === 0 && sets.nullReport){
                return false;
            }
            
            //执行回调函数
            sets.callback();
        });
    };
})(jQuery);

function confirmEnding(str, target) {
 let strLen = str.length;
 let targetLen = target.length;
 if(str.substring(strLen-targetLen) == target){
   return true;
 }
 return false;
}


function containStart(str, target) {
 var tarL = target.length;
 var strL = str.length;
 for(var i=strL;i>0;i--){
     var tarS = target.substring(0,i);
     if(confirmEnding(str,tarS)){
         return true;
     }
 }
 return false;
}


function getContainStart(str, target) {
 var tarL = target.length;
 var strL = str.length;
 for(var i=strL;i>0;i--){
     var tarS = target.substring(0,i);
     if(confirmEnding(str,tarS)){
         return tarS;
     }
 }
 return "";
}




function containEnd(str, target) {
 var tarL = target.length;
 var strL = str.length;
 for(var i=tarL-strL;i<tarL;i++){
     var tarS = target.substring(i,tarL);
     if(str.indexOf(tarS)==0){
         return true;
     }
 }
 return false;
}

function getContainEnd(str, target) {
 var tarL = target.length;
 var strL = str.length;
 for(var i=tarL-strL;i<tarL;i++){
     var tarS = target.substring(i,tarL);
     if(str.indexOf(tarS)==0){
         return tarS;
     }
 }
 return "";
}

一句小心得:编程语言虽然有很多,但数据结构和算法是相通的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容