本人后端狗,接触过一些html、javascript,这个问题是组内前端小伙伴遇到的,帮他解决了这个问题
问题描述:将word文件转为html后在页面显示,需要对这部分html内容进行关键词搜索高亮,但转换后的文字被拆分,被包含在各种标签里,很多内容检索不到。
解决过程如下:
- 直接对html片段使用模糊匹配
*关键词在同一个标签内有效
-关键词被拆分到不同标签里,页面上可以看到这个关键词,但是搜索不到
-误匹配到html标签,造成页面显示异常 - 使用jquery插件(jquery.textSearch-1.0.js)插件原文链接
*关键词在同一个标签内有效
*解决误匹配html标签的问题
-关键词被拆分到不同标签里,页面上可以看到这个关键词,但是搜索不到 - 对jquery.textSearch插件进行改造
阅读了插件的源码,发现他是用正则将HTML代码支离为HTML片段和文字片段,其中文字片段用于正则替换处理,而HTML片段置之不理,处理好后再合并这些片段
拆分html的思路很棒,但是他只对单个文字片段进行替换,如果关键词包括了前后几个文字片段方法就失效了
于是我他的基础上补充了一部分代码,判断文字片段包含的关键词的开头部分,并且关键词包含了后面的连续文字片段,最后一个文字片段又包含关键词结尾部分,就可以匹配上跨标签的文字。
*关键词在同一个标签内有效
*解决误匹配html标签的问题
*关键词被拆分到不同标签里同样有效 - 实际使用中可以根据需要进行改造,比如使用正则表达式拆分出空格,这样即使原文片段里含有空格也不影响检索。
也可以将该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 "";
}
一句小心得:编程语言虽然有很多,但数据结构和算法是相通的