zoukankan      html  css  js  c++  java
  • 搜索提示的实现(仿百度):附源码和在线demo

    智能搜索提示的功能大家都用过,百度搜索的时候一边输入一边会有搜索提示,这样的jQuery做的ajax智能搜索提示很方便,我也决定在我的个人网站上实现一下。不过我比百度更加提升一步,那就是不仅仅出搜索提示,而是结果不多的直接出搜索结果,当用户鼠标点击或键盘上下键选择以后回车自动到结果页面而不是搜索结果页面。出来的效果类似下图:

     

    而且还有一个功能,那就是支持空格和第二列重叠搜索,例如以上的示意图,我如果输入“IBM大连”,或者“大连IBM” ,或者“大连 IBM”照样能找到我需要的结果,更加智能,效果见下图:

     

    在线demo地址:请点击此处的google链接,点击第一个结果即可打开。

    功能实现思路:首先服务器端需要一个service,当前端keyup事件发生的时候检查关键词,并把匹配的智能提示结果返回前端。需要注意的是,后端的数据如果是需要从数据库取,那会非常消耗资源,因为并非人多,keyup事件也很多,很可能你的后台就撑不住。解决思路是从缓存取数据,不要从数据库取,数据库更新数据的时候自动更新缓存,匹配算法优化,提升匹配速度。前端可以输入完keyup一秒你再发送请求道服务器端,以防止用户接连输入,频繁发送请求。这些都是你可以考虑的。

    前端jQuery实现源代码

    JS Code
    $(document).ready(function() {
    //加onkeyp事件,IE和firefox浏览器兼容的写法:--------------
    if(document.addEventListener){
            document.addEventListener(
    "keyup",kuhandler, false);
    }
    else{
            document.attachEvent(
    "onkeyup",kuhandler);
      }
    });   
    //处理keyup事件,注意上下键的处理来选择结果,回车键的处理
    //
    注意特殊按键等不触发智能搜索提示---------------------------------
    function kuhandler(event){
        
    if($("#q_qsearch").attr("value")=='') $(".gac_m").remove();
        
    if(event.keyCode==27) $(".gac_m").remove();
        
    else if(event.keyCode==40)
        {
             
    if(menuFocusIndex >= $(".gac_a").length)
                 
    return true;
             
    else {
              forceMenuItem( menuFocusIndex
    +1"#q_qsearch");
              givNumber(menuFocusIndex, 
    "#q_qsearch");
            }
        }
    else if(event.keyCode==38)
        {
             
    if(menuFocusIndex == 1){
               forceMenuItem(menuFocusIndex
    -1"#q_qsearch"); 
             } 
    else{
              forceMenuItem(menuFocusIndex
    -1"#q_qsearch");
              givNumber(menuFocusIndex,
    "#q_qsearch");
            }
        } 
    else if(event.keyCode==8){
          $(
    ".gac_m").remove();}
        
    else if(!event.ctrlKey && (event.keyCode == 32 || (event.keyCode>=48 && event.keyCode<=57|| (event.keyCode>=65 && event.keyCode<=90))) {
              sug($(
    "#q_qsearch").attr("value"),"wide");}
    }
    //从服务器端webservice取得智能搜索提示结果并显示--------------------------------
    //
    getPosition函数取得相对位置,结果框能粘牢搜索框-----------------------
    function sug(k, wide) {
        
    if (k.length<= 1return;
        $.get(
    "companyquicksearch.asmx", { f: k }, function(result) {
            
    if (result.length > 0) {
                $(
    ".gac_m").remove();
                
    if ($("#q_qsearch").val().length == k.length) {
                    $(
    "#foot").before(result);
                    
    var txt = document.getElementById('q_qsearch');
                    
    var left_new = getPosition(txt)[1];
                    
    var top_new = getPosition(txt)[0];
                    $(
    ".gac_m").css({ left: left_new + "px", top: (top_new + txt.clientHeight + 2+ "px" });
                    menuFocusIndex 
    = 0;
                }
            } 
    else { $(".gac_m").remove(); }
       });
     }
    //getPosition函数取得相对位置,结果框能粘牢搜索框-----------------------
     function getPosition( obj )

        
    var top = 0,left = 0;
        
    do{
          top 
    += obj.offsetTop;
          left 
    += obj.offsetLeft;
        }
        
    while ( obj = obj.offsetParent );     

        
    var arr = new Array();     
        arr[
    0= top;
        arr[
    1= left;      
        
    return arr;   
    }
    var menuFocusIndex=0;
    //键盘上下键选择结果的效果,鼠标经过结果的效果-----------------------
    function forceMenuItem(index, id)
    {
          
    var lastMenuItem = document.getElementById( "menuItem" + menuFocusIndex )

           
    if ( lastMenuItem != null )
           {
              lastMenuItem.bgColor
    ="";
              lastMenuItem.childNodes[
    0].style.color="#000";
              lastMenuItem.childNodes[
    1].style.color="#666";
           }  
           
           
    var menuItem = document.getElementById( "menuItem" + index );

           
    if ( menuItem == null )
             $(id).focus();
           
    else
           {
             menuItem.bgColor
    ="#D2EAEC";
             menuItem.childNodes[
    0].style.color="#FFF";
             menuItem.childNodes[
    1].style.color="#333";
        
             menuFocusIndex 
    = index;
          }
    }
    //鼠标经过结果的效果-----------------------
    function MouseOver(Tr){
      $(
    "#"+Tr.id).css("background-color","#D2EAEC");
      $(
    "#q_qsearch").val($("#"+Tr.id+" a").text());
      $(
    "#rjbtn").attr("role", $("#"+Tr.id+" a").attr("href"));
      $(
    "#q_qsearch").focus(); 
    }
    function MouseOut(Tr){ $("#"+Tr.id).css("background-color","#fff");}
    //选中结果的效果-----------------------
    function givNumber(index, id)
    {
        
    if(index <= 0return;
        
    var t = document.getElementById( "menuItem" + index );
        
    if(t){
        $(
    "#q_qsearch").val($("#menuItem"+index+" a").text());
         $(
    "#rjbtn").attr("role", $("#menuItem"+index+" a").attr("href"));
         $(id).focus(); 
        }
    }


    CSS里面注意一点:table列的固定宽度问题 - 因为我的智能搜索提示是两列的table布局,有时候第一列某些结果很长,我设定了两列的宽度width和table的width但是在IE下没有用,后来发现table需要加一个css属性:table-layout:fixed;这样设置各个列的宽度有作用了,有时候第一列某些结果很长也会自动overflow:hidden。

    服务端端实现源码: 随便你用啥语言实现一个webservice即可,或者一个动态页面也行啊,很基本的,菜鸟都会的,你就不用问我源码了吧。还不会的话,自己google一下“webservice源码实现”去吧,bless you。

  • 相关阅读:
    烟大课表PC端-不仅仅是浏览器和手机APP
    关于51单片机电子时钟精度的问题
    第十二周项目4-点、圆的关系
    Git on Windows 一些问题
    vi 的使用
    Git 账户认证的一些问题
    [Windows] win7 配置Java开发环境
    Velocity 局部定制模板
    [Storm] Storm与asm的恩恩怨怨
    [Storm] No data flows into bolt
  • 原文地址:https://www.cnblogs.com/Mainz/p/1916396.html
Copyright © 2011-2022 走看看