表格、列表关键字搜索且高亮显示的纯JavaScript实现

一、简介

之前看到在eclipse、intellij等ide编辑工具在搜索代码片段时,可以用到模糊匹配的快捷搜索,搜索到的关键字还可以高亮显示,感觉挺方便,用户体验不错,今天自己也想实现一个属于自己的高亮搜索组件,我用js来实现,可以用于table、ul列表;使用该组件时,可以绑定keyup事件,这样在你一边打字的同时,高亮匹配搜索一边就在进行,这个功能在网页上还是挺有用的,下面是具体的代码:

	/**
	* Highlight show for list search,默认支持UL->LI列表,可以通过在TR元素中设置class:hiddenRootElementClassName用于table
 	* @author zhangDa
 	* @param settingOptions 参数设置
 	*/
	function highLightShow(settingOptions){
		this.rootElement = settingOptions.rootElement;
		if(!this.rootElement){
			console.log("The rootElement do not exisits");
			return;
		}
		this.excludedElementsClassName = settingOptions.excludedElementsClassName;  //忽略隐藏的元素
		this.highLightColor = settingOptions.highLightColor?settingOptions.highLightColor:"yellow";
		this.hiddenRootElementClassName = settingOptions.hiddenRootElementClassName;
		this.highLightClassName = "zd-highlight";
		var replaceDom = "" + "$1" + "";
		var exp = "";
		var exp2 = "";
		
		/**
		 * 模糊搜索
		 * @param element 根元素
		 * @param matchObj  表示在某行元素中是否有与文本匹配上的关键字
		 * @return int 显示的行数
		 */
		this.search = function(queryContent){
			this.queryContent = queryContent;
			queryContent = queryContent.replace(/\./, "\\.");
			exp = new RegExp("(" + queryContent + ")", "g");
			exp2 = new RegExp(queryContent);
			this.recursionSearch(this.rootElement, {ifMatched: false});
			return $(this.rootElement).find("."+this.hiddenRootElementClassName+":visible").length;
		}
		
		/**
		 * 递归查找关键字
		 * @param element 相对根元素
		 * @return boolean  true表示要删除下一级
		 */
		this.recursionSearch = function(element, matchObj){
			if(typeof(this.excludedElementsClassName)!="undefined" && $.inArray(element.getAttribute("class"), this.excludedElementsClassName) != -1){
				return false;  // 对于不需匹配内容的元素直接返回,不删除行
			}
			
			if(element.childElementCount == 0){
				var text = element.innerText;
				// 若搜索内容为空的话也为true
				if(!matchObj.ifMatched){
					matchObj.ifMatched = exp2.test(text);
				}
				//如果在原来已经高亮的文本中没有匹配新的搜索内容,需要将高亮元素删掉重新加
				if($(element).hasClass(this.highLightClassName)){
					if(this.queryContent.length == text.length && matchObj.ifMatched){
						return false;
					}
					return true;  // 是指要将高亮元素删除
				}
				if(this.queryContent == ""){
					return false;  // 没有搜索内容,不需删除行
				}
				$(element).html(text.replace(exp, replaceDom));
			}else{
				var children = element.children;
				for (var i = 0; i < children.length; i++) {
					var shouldRemoveChildElement = this.recursionSearch(children[i], matchObj);
					if(shouldRemoveChildElement){
						var text = element.innerText;
						element.removeChild(children[i]);
						// 还要再匹配一次
						if(!matchObj.ifMatched){
							matchObj.ifMatched = exp2.test(text);
						}
						if(this.queryContent == ""){
							element.innerText = text;
						}else{
							$(element).html(text.replace(exp, replaceDom));
						}
					}
				}
			}
			
			// 若没有匹配上,确定是否要隐藏某行元素
			if($(element).hasClass(this.hiddenRootElementClassName)){
				var pattern = /\s+/;
				if(!pattern.test(this.queryContent)){
					if(!matchObj.ifMatched){
						element.style.display = "none";
					}else{
						matchObj.ifMatched = false;
						element.style.display = "";
					}
				}
			}
			
			return false;
		}
	}

二、应用

这里举一个应用在table上的例子

1、这是table的HTML代码

故障类型 故障代码 故障别名 原因描述 操作

2、定义dom变量
var searchBtn = document.getElementById("search-btn");   //搜索按钮
var searchInput = document.getElementById("search-input");  //搜索框
var tableLength = 2;
var tbodyList = [document.getElementById("testfault-table").getElementsByTagName("tbody")[0],document.getElementById("salefault-table").getElementsByTagName("tbody")[0]]; // 页面上有多个table,组成一个list


3、生成高亮搜索组件实例
var hls = [new highLightShow({
		rootElement : tbodyList[0],
		hiddenRootElementClassName: "hidden-root",
		highLightColor : "gold"
	}), new highLightShow({
		rootElement : tbodyList[1],
		hiddenRootElementClassName: "hidden-root",
		highLightColor : "gold"
	})]   //页面上有多个table,分别生成多个实例
该构造函数的配置参数主要有3个,rootElement是dom根元素,此处是tbody,hiddenRootElementClassName表示不需要参与搜索的元素class,highLightColor是高亮的颜色。


4、table样式处理及事件绑定

function initTbl(index){  // 该函数用于处理表格的隔行换色效果
	var tables = document.getElementsByTagName("table");
	for (var i = 0; i < tables.length; i++) {
		if(index==-1){
			var tbl = tables[i];
		}else{
			var tbl = tables[index];
		}
		var tbody = tbl.getElementsByTagName("tbody")[0];
		var trs = tbody.getElementsByTagName("tr");
		if(index==-1){
			trs = tbody.getElementsByTagName("tr");
		}else{
			trs = $(tbody).find("tr:visible");
		}
		
		if(trs.length == 0){
			var thLength = tbl.getElementsByTagName("th").length;
			$(tbody).append("查无数据");
		}else{
			var separateColor = "rgb(240,240,240)";
			for (var j = 0; j < trs.length; j++) {
				if(j%2==0){
					trs[j].style.backgroundColor=separateColor;
				}else{
					trs[j].style.backgroundColor="white";
				}
			}
		}
		if(index!=-1){
			break;
		}
	}
}

function showTbl(index){   // 该函数用于绑定、解绑keyup、click事件
 
	for (var i = 0; i < tableLength; i++) {
		if(index == i){
			var trs = tbodyList[index].getElementsByTagName("tr");
			if(trs.length == 1 && trs[0].classList.contains("no-data")){
				searchInput.onkeyup = function(){
					return ;
				}
				searchBtn.onclick = function(){
					return ;
				}
				return ;
			}
			searchInput.onkeyup = function(){
				searchEventCbk(index, this.value);
			}
			searchBtn.onclick = function(){
				searchEventCbk(index, searchInput.value);
			  }
			}
	}
}
	
function searchEventCbk(index, value){
	hls[index].search(value);
	var noDataTr = tbodyList[index].getElementsByClassName("no-data");
	var trs = $(tbodyList[index]).find("tr:visible:not(.no-data)").length;
	initTbl(index);
	if(noDataTr.length > 0 && trs > 0){
		noDataTr[0].parentElement.removeChild(noDataTr[0]);
	}
}

5、通过ajax从后台获取table数据、渲染数据

function refreshFaultType(index){
		$.get("setting/type",{index: index}, function(result){
			var data = result.data;
			var append = "";
			for (var i = 0, len = data.length; i < len; i++) {
				var reasonStr = isEmptyArray(data[i].faultReason)?" ":data[i].faultReason.join(",");
				append += ""+
				(index == 0 ? (""+(data[i].testType==1?"功能不良":"外观不良")+"") : "")+
				""+data[i].faultCode+""+
				""+data[i].desc+""+
				(index == 0 ? (""+data[i].faultReason+"") : "")+
				""+
				""+
				"";
			}
			$(tbodyList[index]).empty().append(append);
			if(index == currentType){
				initTbl(index);//初始化table
				showTbl(index);//
			}
		});
	}

效果如下:这里是将其用于table,这是搜索之前的数据记录

表格、列表关键字搜索且高亮显示的纯JavaScript实现_第1张图片


下面这是打出“电”字以后,即放下键盘以后的效果,有“电”字的记录显示出来,其他被隐藏,而"电"字也被高亮显示出来

表格、列表关键字搜索且高亮显示的纯JavaScript实现_第2张图片


如果搜索不到则显示查无数据

表格、列表关键字搜索且高亮显示的纯JavaScript实现_第3张图片


三、总结

这只是一个小小的不起眼的小组件,无非就是用到了一些基本的js功能、正则表达式匹配替换、递归等常见的东西,不过自己实现起来,还是花了一段时间,总的来说,比较有意思。









你可能感兴趣的:(前端)