首页 > Javascript > 原生JS实现搜索关键词高亮

原生JS实现搜索关键词高亮

在写搜索页面的时候,需要对匹配的内容进行高亮,往往采用后端的字符串替换实现。后来,通过这样一篇文章,我发现js同样可以实现关键词的高亮。

http://www.cnblogs.com/gogly/archive/2012/10/19/2731136.html

这篇文章实现的高亮正则我看的不是很明白,但确实能够满足一般高亮需求。

可是,当我们的高亮需求发生变化时,这段代码就不怎么灵活了。于是我稍微修改了一下源码:

//原生JS高亮
function Highlight(idVal, keywords) {
    var pucl = document.getElementById(idVal);
    var temp = pucl.innerHTML;
    var htmlReg = new RegExp("\<.*?\>", "i");
    var arrA = new Array();
    //替换HTML标签
    for (var i = 0; true; i++) {
        var m = htmlReg.exec(temp);
        if (m) {
            arrA[i] = m;
        } else {
            break;
        }
        temp = temp.replace(m, "{[(" + i + ")]}");
    }
    var i,
    word,
    style;
    for (i = 0; i < keywords.length; i++) {
        word = keywords[i].word;
        lable = keywords[i].lable;
        var r = new RegExp("(" + word.replace(/[(){}.+*?^$|\\\[\]]/g, "\\$&") + ")", "ig");
        temp = temp.replace(r, lable);
    }
    //恢复HTML标签
    for (var i = 0; i < arrA.length; i++) {
        temp = temp.replace("{[(" + i + ")]}", arrA[i]);
    }
    pucl.innerHTML = temp;
}

可以看出,这里的第二个参数keywords不再是字符串,而是一个对象数组,需要保证每一个元素有word属性(关键词),lable属性(标签名,使用$1代替关键词)。

后来,突然有这样一个需求:输入一个词高亮一次;再输入另一个词取消前面的高亮,高亮后面输入的词。

于是,经过摸索完成了去除高亮的代码:

//原生JS去除高亮
function removeHighlight(idVal, classname) {
    var pucl = document.getElementById(idVal);
    var temp = pucl.innerHTML;
    var classobj = new Array();
    var text,classnames,classArr;
    var tags = pucl.getElementsByTagName("*");
    for (var i in tags) { //对标签进行遍历
        if (tags[i].nodeType == 1) { //判断节点类型
            classnames = tags[i].getAttribute("class");
            if(classnames){
                classArr = classnames.split(" ");
                for(var j in classArr){
                    //判断和需要CLASS名字相同的,并组成一个数组
                    if (classArr[j] == classname){
                        
                        if(classnames == classname){
                            //去除html标签
                            temp = temp.replace(tags[i].outerHTML, tags[i].innerText || tags[i].textContent);
                        }else{
                            temp = temp.replace('class="'+classnames+'"', 'class="'+classnames.replace(classname,'')+'"');
                        }
                    }
                }
            }
        }
    }
    //恢复HTML标签
    pucl.innerHTML = temp;
}

经过测试,兼容IE,chrome,firefox等浏览器。

想必大家看到了“原生”二字,原因是很早以前就有人写了jquery的关键词高亮插件,这里和大家分享一下这两种高亮方式的源码。

原生高亮完整源码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>原生高亮关键词搜索 - phprm.com</title>
<style type="text/css">
.highlight {
    background-color: #fff34d;
    -moz-border-radius: 3px; /* FF1+ */
    -webkit-border-radius: 3px; /* Saf3-4 */
    border-radius: 3px; /* Opera 10.5, IE 9, Saf5, Chrome */
    -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.7); /* FF3.5+ */
    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.7); /* Saf3.0+, Chrome */
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.7); /* Opera 10.5+, IE 9.0 */
}

.highlight {
    padding:1px 4px;
    margin:0 -4px;
}
</style>

</head>

<body>

Search: <input type="text" id="text-search" />

<div class="result" id="result"> 
<p>一个和尚挑水吃、两个和尚抬水吃、三个和尚没水吃。总寺的方丈大人得知情况后,就派来了一名主持和一名书记,共同负责解决这一问题。主持上任后,发现问题的关键是管理不到位,于是就招聘一些和尚成立了寺庙管理部来制定分工流程。为了更好地借鉴国外的先进经验,寺庙选派唐僧等领导干部出国学习取经;此外,他们还专门花钱请了天主教、基督教的神父传授MBA。神父呆了不久留下几个东东就走了,一个叫BPR,一个叫ERP。</p>
<p> </p>
<p>书记也没闲着,他认为问题的关键在于人才没有充分利用、寺庙文化没有建设好,于是就成立了人力资源部和寺庙工会等等,并认认真真地走起了竞聘上岗和定岗定编的过场。</p>
<p> </p>
<p>几天后成效出来了,三个和尚开始拼命地挑水了,可问题是怎么挑也不够喝。不仅如此,小和尚都忙着挑水、寺庙里没人念经了,日子一长,来烧香的客人越来越少,香火钱也变得拮据起来。为了解决收入问题,寺庙管理部、人力资源部等连续召开了几天的会,最后决定,成立专门的挑水部负责后勤和专门的烧香部负责市场前台。同时,为了更好地开展工作,寺庙提拔了十几名和尚分别担任副主持、主持助理,并在每个部门任命了部门小主持、副小主持、小主持助理。</p>
<p> </p>
<p>老问题终于得到缓解了,可新的问题跟着又来了。前台负责念经的和尚总抱怨口渴水不够喝,后台挑水的和尚也抱怨人手不足、水的需求量太大而且没个准儿,不好伺候。</p>
<p> </p>
<p>为了更好地解决这一矛盾,经开会研究决定,成立一个新的部门:喝水响应部,专门负责协调前后台矛盾。为了便于沟通、协调,每个部门都设立了对口的联系和尚。   协调虽然有了,但效果却不理想,仔细一研究,原来是由于水的需求量不准、水井数量不足等原因造成的。于是各部门又召开了几次会,决定加强前台念经和尚对饮用水的预测和念经和尚对挑水和尚满意度测评等,让前后台签署协定、相互打分,健全考核机制。为了便于打分考核,寺院特意购买了几个计算机系统,包括挑水统计系统、烧香统计系统、普通香客捐款分析系统、大香客捐款分析系统、挨上必死系统(简称IBS系统)、马上就死系统(简称MS系统)等,同时成立香火钱管理部、香火钱出账部、打井策略研究部、打井建设部、打井维护部等等。由于各个系统出来的数总不准确、都不一致,于是又成立了技术开发中心,负责各个系统的维护、二次开发。由于部门太多、办公场地不足,寺院专门成立了综合部来解决这一问题,最后决定把寺院整个变成办公区,香客烧香只许在山门外烧。 </p>
<p> </p>
<p>部门多、当官的多档和开会自然就多,为了减少文山会海,综合办牵头召开了N次关于减少开会的会,并下达了“关于减少档的档”。同时,为了精简机构、提高效率,寺院还成立了精简机构办公室、机构改革研究部等部门。 </p>
<p> </p>
<p>一切似乎都合情合理,但香火钱和喝水的问题还是迟迟不能解决。问题在哪呢?有的和尚提出来每月应该开一次分析会,于是经营分析部就应运而生了。分析需要很多数据和报表,可系统总是做不到,于是每个部门都指派了一些和尚手工统计、填写报表、给系统打工。</p>
<p> </p>
<p>寺院空前地热闹起来,有的和尚在拼命挑水、有的和尚在拼命念经、有的和尚在拼命协调、有的和尚在拼命分析……忙来忙去,水还是不够喝、香火钱还是不够用。什么原因呢?这个和尚说流程不顺、那个和尚说任务分解不合理,这个和尚说部门界面不清、那个和尚说考核力度不够。只有三个人最清楚问题之关键所在,那三个人就是最早的那三个和尚。说来说去,就是***闲人太多了!他们说:“整天瞎分析个屁!什么***流程问题、职责问题、接口问题、考核问题,明明就是机构臃肿问题!早知今日,还不如当初咱们仨自觉自律一点算了!如今倒好,招来了这么一大帮傻B,一个个不干正经事还***人五人六的,跟屎盆子一样甩都甩不掉!”</p>
<p> </p>
<p>又过了一年,寺院黄了,和尚们也都死了。人们在水井边发现了几具尸体,是累死的;在寺院里发现了几千具尸体,是渴死的。</p>
</div> 

<script type="text/javascript">
    var addEvent = (function () {
        if (document.addEventListener) {
            return function (el, type, fn) {
                el.addEventListener(type, fn, false);
            };
        } else {
            return function (el, type, fn) {
                el.attachEvent('on' + type, function () {
                    return fn.call(el, window.event);
                });
            }
        }
    })();
    
    addEvent(document.getElementById("text-search"),'keyup', function(){
        var searchTerm = document.getElementById("text-search").value;
        if(searchTerm){
            removeHighlight("result", "highlight");
            var keywords = [{word:searchTerm,lable:'<span class="highlight">$1</span>'}];
            Highlight("result", keywords);
        }
    });
    addEvent(document.getElementById("text-search"),'change', function(){
        console.log(document.getElementById("text-search"));
        var searchTerm = document.getElementById("text-search").value;
        if(searchTerm){
            removeHighlight("result", "highlight");
            var keywords = [{word:searchTerm,lable:'<span class="highlight">$1</span>'}];
            Highlight("result", keywords);
        }
    })
    
    //原生JS高亮
    function Highlight(idVal, keywords) {
        var pucl = document.getElementById(idVal);
        var temp = pucl.innerHTML;
        var htmlReg = new RegExp("\<.*?\>", "i");
        var arrA = new Array();
        //替换HTML标签
        for (var i = 0; true; i++) {
            var m = htmlReg.exec(temp);
            if (m) {
                arrA[i] = m;
            } else {
                break;
            }
            temp = temp.replace(m, "{[(" + i + ")]}");
        }
        var i,
        word,
        style;
        for (i = 0; i < keywords.length; i++) {
            word = keywords[i].word;
            lable = keywords[i].lable;
            var r = new RegExp("(" + word.replace(/[(){}.+*?^$|\\\[\]]/g, "\\$&") + ")", "ig");
            temp = temp.replace(r, lable);
        }
        //恢复HTML标签
        for (var i = 0; i < arrA.length; i++) {
            temp = temp.replace("{[(" + i + ")]}", arrA[i]);
        }
        pucl.innerHTML = temp;
    }

    //原生JS去除高亮
    function removeHighlight(idVal, classname) {
        var pucl = document.getElementById(idVal);
        var temp = pucl.innerHTML;
        var classobj = new Array();
        var text,classnames,classArr;
        var tags = pucl.getElementsByTagName("*");
        for (var i in tags) { //对标签进行遍历
            if (tags[i].nodeType == 1) { //判断节点类型
                classnames = tags[i].getAttribute("class");
                if(classnames){
                    classArr = classnames.split(" ");
                    for(var j in classArr){
                        //判断和需要CLASS名字相同的,并组成一个数组
                        if (classArr[j] == classname){
                            if(classnames == classname){
                                //去除html标签
                                temp = temp.replace(tags[i].outerHTML, tags[i].innerText || tags[i].textContent);
                            }else{
                                temp = temp.replace('class="'+classnames+'"', 'class="'+classnames.replace(classname,'')+'"');
                            }
                        }
                    }
                }
            }
        }
        //恢复HTML标签
        pucl.innerHTML = temp;
    }
</script>
</body>
</html>

jquery方式,已经打包提供下载地址:

jQuery高亮关键词搜索.zip


本文地址:http://blog.zhengshuiguang.com/js/js-highlight.html

转载随意,但请附上文章地址:-)

标签:js 高亮 搜索 关键词 jquery插件

相关文章

评论已关闭