zoukankan      html  css  js  c++  java
  • 搜索框键入提示并回显准确信息

    类似百度这种,大家应该也都清楚这个东西

    我提供一个网上大家都在用的一个方法,整理了一下分享出来。

    1.文本框和设置一个div,class=parentCls ,  搜索框的class设置:class=“inputElem”   , 为文本框设置一个oninput的属性。

    
    
    <div class="parentCls">
                        <input type="text" class="inputElem" id="inputName" name="name" value="${search}"
                               oninput="onChange(this.value)">
                        <input class="btn btn-dark" type="submit" value="搜索" style="margin-left: 15px;">
                        <input type="hidden" class="hiddenCls"/>
                    </div>

    在返回数据之前,我们先创建一个接受返回的json值的变量。

    var resultData;

    2.编写JS。

      1   /**
      2      * JS 模糊查询
      3      * @param 1.当前的input add targetCls
      4      * 2. 隐藏域里面统一增加同类名 叫 hiddenCls
      5      * 3. 在各个父级元素上 添加类名 parentCls
      6      */
      7     function AutoComplete(options) {
      8         this.config = {
      9             targetCls: '.inputElem',          // 输入框目标元素
     10             parentCls: '.parentCls',          // 父级类
     11             hiddenCls: '.hiddenCls',          // 隐藏域input
     12             searchForm: '.jqtransformdone',     //form表单
     13             hoverBg: 'hoverBg',             // 鼠标移上去的背景
     14             outBg: 'outBg',               // 鼠标移下拉的背景
     15             isSelectHide: true,                 // 点击下拉框 是否隐藏
     16             url: 'search',                    // url接口
     17             height: 0,                     // 默认为0 不设置的话 那么高度自适应
     18             manySelect: false,                 // 输入框是否多选 默认false 单选
     19             renderHTMLCallback: null,                  // keyup时 渲染数据后的回调函数
     20             callback: null,                  // 点击某一项 提供回调
     21             closedCallback: null                   // 点击输入框某一项x按钮时 回调函数
     22         };
     23 
     24         this.cache = {
     25             currentIndex: -1,
     26             oldIndex: -1,
     27             inputArrs: []                 // 多选时候 输入框值放到数组里面去
     28         };
     29         this.init(options);
     30     }
     31 
     32     AutoComplete.prototype = {
     33 
     34         constructor: AutoComplete,
     35         init: function (options) {
     36 
     37             this.config = $.extend(this.config, options || {});
     38             var self = this,
     39                 _config = self.config,
     40                 _cache = self.cache;
     41 
     42             // 鼠标点击输入框时候
     43             $(_config.targetCls).each(function (index, item) {
     44 
     45                 /*
     46                  *  禁止 ctrl+v 和 黏贴事件
     47                  */
     48                 $(item).unbind('paste');
     49                 $(item).bind('paste', function (e) {
     50                     e.preventDefault();
     51                     var target = e.target,
     52                         targetParent = $(target).closest(_config.parentCls);
     53                     $(this).val('');
     54                     $(_config.hiddenCls, targetParent) && $(_config.hiddenCls, targetParent).val('');
     55                 });
     56 
     57                 $(item).keyup(function (e) {
     58                     _cache.inputArrs = [];
     59                     var targetVal = $.trim($(this).val()),
     60                         keyCode = e.keyCode,
     61                         elemHeight = $(this).outerHeight(),
     62                         elemWidth = $(this).outerWidth();
     63 
     64                     // 如果输入框值为空的话 那么隐藏域的value清空掉
     65                     if (targetVal == '') {
     66                         var curParents = $(this).closest(_config.parentCls);
     67                         $(_config.hiddenCls, curParents).val('');
     68                     }
     69                     var targetParent = $(this).parent();
     70                     $(targetParent).css({'position': 'relative'});
     71 
     72                     if ($('.auto-tips', targetParent).length == 0) {
     73                         // 初始化时候 动态创建下拉框容器
     74                         $(targetParent).append($('<div class="auto-tips hidden"></div>'));
     75                         $('.auto-tips', targetParent).css({
     76                             'position': 'absolute',
     77                             'top': elemHeight,
     78                             'left': '0px',
     79                             'margin-left': '383px',
     80                             'z-index': 999,
     81                             'width': elemWidth,
     82                             'border': '1px solid #ccc'
     83                         });
     84                     }
     85 
     86 
     87                     var curIndex = self._keyCode(keyCode);
     88                     if (curIndex > -1) {
     89                         self._keyUpAndDown(targetVal, e, targetParent);
     90                     } else {
     91                         if (targetVal != '') {
     92                             self._doPostAction(targetVal, targetParent);
     93                         }
     94 
     95                     }
     96                 });
     97 
     98                 // 失去焦点时 如果没有点击 或者上下移时候 直接输入 那么当前输入框值情况 隐藏域值情况
     99                 $(item).blur(function (e) {
    100                     var target = e.target,
    101                         targetParent = $(target).closest(_config.parentCls);
    102                     if ($(this).attr('up') || $(this).attr('down')) {
    103                         return;
    104                     } else {
    105                         $(this).val('');
    106                         $(_config.hiddenCls, targetParent).val('');
    107                     }
    108                 });
    109 
    110             });
    111 
    112             // 阻止form表单默认enter键提交
    113             $(_config.searchForm).each(function (index, item) {
    114                 $(item).keydown(function (e) {
    115                     var keyCode = e.keyCode;
    116                     if (keyCode == 13) {
    117                         return false;
    118                     }
    119                 });
    120             });
    121 
    122             // 点击文档
    123             $(document).click(function (e) {
    124                 e.stopPropagation();
    125                 var target = e.target,
    126                     tagParent = $(target).parent(),
    127                     attr = $(target, tagParent).closest('.auto-tips');
    128 
    129                 var tagCls = _config.targetCls.replace(/^./, '');
    130 
    131                 if (attr.length > 0 || $(target, tagParent).hasClass(tagCls)) {
    132                     return;
    133                 } else {
    134                     $('.auto-tips').each(function (index, item) {
    135                         !$(item, tagParent).hasClass('hidden') && $(item, tagParent).addClass('hidden');
    136                     });
    137 
    138                 }
    139             });
    140 
    141             var stylesheet = '.auto-tips { margin: 0 1px; list-style: none;height:auto !important;padding: 0px;position:absolute; border:1px solid #ccc; top:27px; left:0; z-index:999; 100%;background:#fff !important;}' +
    142                 '.auto-tips p {overflow: hidden;margin: 1px 0;padding: 5px 5px;text-align:left;color: #666;text-decoration: none;line-height: 23px;white-space: nowrap;cursor: pointer;zoom: 1;}' +
    143                 '.auto-tips p img{ vertical-align:middle;float:left;}' +
    144                 '.auto-tips p.hoverBg {background-color: #669cb6;color: #fff;cursor: pointer;}' +
    145                 '.hidden {display:none;}';
    146 
    147             this._addStyleSheet(stylesheet);
    148 
    149         },
    150         /**
    151          * 键盘上下键操作
    152          */
    153         _keyUpAndDown: function (targetVal, e, targetParent) {
    154             var self = this,
    155                 _cache = self.cache,
    156                 _config = self.config;
    157 
    158             // 如果请求成功后 返回了数据(根据元素的长度来判断) 执行以下操作
    159             if ($('.auto-tips p', targetParent) && $('.auto-tips p', targetParent).length > 0) {
    160 
    161                 var plen = $('.auto-tips p', targetParent).length,
    162                     keyCode = e.keyCode;
    163                 _cache.oldIndex = _cache.currentIndex;
    164 
    165                 // 上移操作
    166                 if (keyCode == 38) {
    167                     if (_cache.currentIndex == -1) {
    168                         _cache.currentIndex = plen - 1;
    169                     } else {
    170                         _cache.currentIndex = _cache.currentIndex - 1;
    171                         if (_cache.currentIndex < 0) {
    172                             _cache.currentIndex = plen - 1;
    173                         }
    174                     }
    175                     if (_cache.currentIndex !== -1) {
    176 
    177                         !$('.auto-tips .p-index' + _cache.currentIndex, targetParent).hasClass(_config.hoverBg) &&
    178                         $('.auto-tips .p-index' + _cache.currentIndex, targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
    179                         var curAttr = $('.auto-tips .p-index' + _cache.currentIndex, targetParent).attr('data-html');
    180 //                            embId = $('.auto-tips .p-index'+_cache.currentIndex,targetParent).attr('embId');
    181 
    182                         // 判断是否是多选操作 多选操作 暂留接口
    183                         if (_config.manySelect) {
    184                             _cache.inputArrs.push(curAttr);
    185                             _cache.inputArrs = self._unique(_cache.inputArrs);
    186                             self._manySelect(targetParent);
    187                         } else {
    188                             $(_config.targetCls, targetParent).val(curAttr);
    189                             // 上移操作增加一个属性 当失去焦点时候 判断有没有这个属性
    190                             if (!$(_config.targetCls, targetParent).attr('up')) {
    191                                 $(_config.targetCls, targetParent).attr('up', 'true');
    192                             }
    193 
    194                             self._createDiv(targetParent, curAttr);
    195                             // hover
    196                             self._hover(targetParent);
    197                         }
    198 
    199                     }
    200 
    201                 } else if (keyCode == 40) { //下移操作
    202                     if (_cache.currentIndex == plen - 1) {
    203                         _cache.currentIndex = 0;
    204                     } else {
    205                         _cache.currentIndex++;
    206                         if (_cache.currentIndex > plen - 1) {
    207                             _cache.currentIndex = 0;
    208                         }
    209                     }
    210                     if (_cache.currentIndex !== -1) {
    211 
    212                         !$('.auto-tips .p-index' + _cache.currentIndex, targetParent).hasClass(_config.hoverBg) &&
    213                         $('.auto-tips .p-index' + _cache.currentIndex, targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
    214                         var curAttr = $('.auto-tips .p-index' + _cache.currentIndex, targetParent).attr('data-html');
    215 //                            embId = $('.auto-tips .p-index'+_cache.currentIndex,targetParent).attr('embId');
    216 
    217 
    218                         // 判断是否是多选操作 多选操作 暂留接口
    219                         if (_config.manySelect) {
    220                             _cache.inputArrs.push(curAttr);
    221                             _cache.inputArrs = self._unique(_cache.inputArrs);
    222                             self._manySelect(targetParent);
    223                         } else {
    224                             $(_config.targetCls, targetParent).val(curAttr);
    225 
    226                             // 下移操作增加一个属性 当失去焦点时候 判断有没有这个属性
    227                             if (!$(_config.targetCls, targetParent).attr('down')) {
    228                                 $(_config.targetCls, targetParent).attr('down', 'true');
    229                             }
    230 
    231                             var pCls = $(_config.targetCls, targetParent).closest(_config.parentCls);
    232 //                            $(_config.hiddenCls,pCls).val(embId);
    233                             self._createDiv(targetParent, curAttr);
    234                             self._closed(targetParent);
    235                             // hover
    236                             self._hover(targetParent);
    237                         }
    238 
    239                     }
    240                 } else if (keyCode == 13) { //回车操作
    241                     var curVal = $('.auto-tips .p-index' + _cache.oldIndex, targetParent).attr('data-html');
    242                     $(_config.targetCls, targetParent).val(curVal);
    243                     /*
    244                      if(_config.isSelectHide) {
    245                      !$(".auto-tips",targetParent).hasClass('hidden') && $(".auto-tips",targetParent).addClass('hidden');
    246                      }
    247                      */
    248 
    249                     _cache.currentIndex = -1;
    250                     _cache.oldIndex = -1;
    251 
    252                 }
    253             }
    254         },
    255         // 键码判断
    256         _keyCode: function (code) {
    257             var arrs = ['17', '18', '38', '40', '37', '39', '33', '34', '35', '46', '36', '13', '45', '44', '145', '19', '20', '9'];
    258             for (var i = 0, ilen = arrs.length; i < ilen; i++) {
    259                 if (code == arrs[i]) {
    260                     return i;
    261                 }
    262             }
    263             return -1;
    264         },
    265         _doPostAction: function (targetVal, targetParent) {
    266 
    267             var self = this,
    268                 _cache = self.cache,
    269                 _config = self.config,
    270                 url = _config.url;
    271 
    272             // 假如返回的数据如下:
    273             if (resultData != null) {
    274                 var result = JSON.parse(resultData);
    275                 if (result.length > 0) {
    276                     var results = result;
    277                     self._renderHTML(results, targetParent);
    278                     self._executeClick(results, targetParent);
    279                 } else {
    280                     !$('.auto-tips', targetParent).hasClass('hidden') && $('.auto-tips', targetParent).addClass("hidden");
    281                     $('.auto-tips', targetParent).html('');
    282                 }
    283             }
    284         },
    285 
    286         /*
    287          $.get(url+"?keyword="+targetVal+"&timestamp="+new Date().getTime(),function(data){
    288          var ret = $.parseJSON(data.content),
    289          results = ret.results;
    290          if(results.length > 0) {
    291          self._renderHTML(results,targetParent);
    292          self._executeClick(results,targetParent);
    293          }else {
    294          !$('.auto-tips',targetParent).hasClass('hidden') && $('.auto-tips',targetParent).addClass("hidden");
    295          $('.auto-tips',targetParent).html('');
    296 
    297          }
    298          });*/
    299         _renderHTML: function (ret, targetParent) {
    300             var self = this,
    301                 _config = self.config,
    302                 _cache = self.cache,
    303                 html = '';
    304 
    305             for (var i = 0, ilen = ret.length; i < ilen; i += 1) {
    306                 html += '<p  data-html = "' + ret[i].appname + '" class="p-index' + i + '">' +
    307                     '<span>' + ret[i].appname + '</span>' +
    308                     '</p>';
    309             }
    310             // 渲染值到下拉框里面去
    311             $('.auto-tips', targetParent).html(html);
    312             $('.auto-tips', targetParent).hasClass('hidden') && $('.auto-tips', targetParent).removeClass('hidden');
    313             $('.auto-tips p:last', targetParent).css({"border-bottom": 'none'});
    314 
    315 
    316             // 出现滚动条 计算p的长度 * 一项p的高度 是否大于 设置的高度 如是的话 出现滚动条 反之
    317             var plen = $('.auto-tips p', targetParent).length,
    318                 pheight = $('.auto-tips p', targetParent).height();
    319 
    320             if (_config.height > 0) {
    321                 if (plen * pheight > _config.height) {
    322                     $('.auto-tips', targetParent).css({'height': _config.height, 'overflow': 'auto'});
    323                 } else {
    324                     $('.auto-tips', targetParent).css({'height': 'auto', 'overflow': 'auto'});
    325                 }
    326             }
    327         }
    328         ,
    329         /**
    330          * 当数据相同的时 点击对应的项时 返回数据
    331          */
    332         _executeClick: function (ret, targetParent) {
    333             var self = this,
    334                 _config = self.config,
    335                 _cache = self.cache;
    336             $('.auto-tips p', targetParent).unbind('click');
    337             $('.auto-tips p', targetParent).bind('click', function (e) {
    338                 var dataAttr = $(this).attr('data-html');
    339 //                    embId = $(this).attr('embId');
    340 
    341                 // 判断是否多选
    342                 if (_config.manySelect) {
    343                     _cache.inputArrs.push(dataAttr);
    344                     _cache.inputArrs = self._unique(_cache.inputArrs);
    345                     self._manySelect(targetParent);
    346                 } else {
    347                     $(_config.targetCls, targetParent).val(dataAttr);
    348                     var parentCls = $(_config.targetCls, targetParent).closest(_config.parentCls),
    349                         hiddenCls = $(_config.hiddenCls, parentCls);
    350 //                    $(hiddenCls).val(embId);
    351                     self._createDiv(targetParent, dataAttr);
    352 
    353                     // hover
    354                     self._hover(targetParent);
    355 
    356 //                    !$(_config.targetCls,targetParent).hasClass('hidden') && $(_config.targetCls,targetParent).addClass('hidden');
    357                 }
    358                 self._closed(targetParent);
    359                 if (_config.isSelectHide) {
    360                     !$('.auto-tips', targetParent).hasClass('hidden') && $('.auto-tips', targetParent).addClass('hidden');
    361                 }
    362                 _config.callback && $.isFunction(_config.callback) && _config.callback();
    363             });
    364 
    365             // 鼠标移上效果
    366             $('.auto-tips p', targetParent).hover(function (e) {
    367                 !$(this, targetParent).hasClass(_config.hoverBg) &&
    368                 $(this, targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
    369             });
    370         }
    371         ,
    372         _hover: function (targetParent) {
    373             $('.create-input span', targetParent).hover(function () {
    374                 $(this).css({"background": '#ccc', 'padding-left': '0px'});
    375             }, function () {
    376                 $(this).css({"background": ''});
    377             });
    378         }
    379         ,
    380         // 动态的创建div标签 遮住input输入框
    381         _createDiv: function (targetParent, dataAttr) {
    382             var self = this,
    383                 _config = self.config;
    384             var iscreate = $('.create-input', targetParent);
    385 
    386             // 确保只创建一次div
    387             if (iscreate.length > 0) {
    388                 $('.create-input', targetParent).remove();
    389             }
    390             $(_config.targetCls, targetParent).val(dataAttr);
    391             $('.alink', targetParent).css({'float': 'left', 'background': 'none'});
    392         }
    393         ,
    394         // X 关闭事件
    395         _closed: function (targetParent) {
    396             var self = this,
    397                 _config = self.config;
    398             /*
    399              * 点击X 关闭按钮
    400              * 判断当前输入框有没有up和down属性 有的话 删除掉 否则 什么都不做
    401              */
    402             $('.alink', targetParent).click(function () {
    403                 $('.create-input', targetParent) && $('.create-input', targetParent).remove();
    404                 $(_config.targetCls, targetParent) && $(_config.targetCls, targetParent).hasClass('hidden') &&
    405                 $(_config.targetCls, targetParent).removeClass('hidden');
    406                 $(_config.targetCls, targetParent).val('');
    407                 //清空隐藏域的值
    408                 var curParent = $(_config.targetCls, targetParent).closest(_config.parentCls);
    409                 $(_config.hiddenCls, curParent).val('');
    410 
    411                 var targetInput = $(_config.targetCls, targetParent);
    412                 if ($(targetInput).attr('up') || $(targetInput).attr('down')) {
    413                     $(targetInput).attr('up') && $(targetInput).removeAttr('up');
    414                     $(targetInput).attr('down') && $(targetInput).removeAttr('down');
    415                 }
    416                 _config.closedCallback && $.isFunction(_config.closedCallback) && _config.closedCallback();
    417             });
    418         }
    419         ,
    420         /*
    421          * 数组去重复
    422          */
    423         _unique: function (arrs) {
    424             var obj = {},
    425                 newArrs = [];
    426             for (var i = 0, ilen = arrs.length; i < ilen; i++) {
    427                 if (obj[arrs[i]] != 1) {
    428                     newArrs.push(arrs[i]);
    429                     obj[arrs[i]] = 1;
    430                 }
    431             }
    432             return newArrs;
    433         }
    434         ,
    435         /*
    436          * 输入框多选操作
    437          */
    438         _manySelect: function (targetParent) {
    439             var self = this,
    440                 _config = self.config,
    441                 _cache = self.cache;
    442             if (_cache.inputArrs.length > 0) {
    443                 $(_config.targetCls, targetParent).val(_cache.inputArrs.join(','));
    444             }
    445         }
    446         ,
    447         /*
    448          * 判断是否是string
    449          */
    450         _isString: function (str) {
    451             return Object.prototype.toString.apply(str) === '[object String]';
    452         }
    453         ,
    454         /*
    455          * JS 动态添加css样式
    456          */
    457         _addStyleSheet: function (refWin, cssText, id) {
    458 
    459             var self = this;
    460             if (self._isString(refWin)) {
    461                 id = cssText;
    462                 cssText = refWin;
    463                 refWin = window;
    464             }
    465             refWin = $(refWin);
    466             var doc = document;
    467             var elem;
    468 
    469             if (id && (id = id.replace('#', ''))) {
    470                 elem = $('#' + id, doc);
    471             }
    472 
    473             // 仅添加一次,不重复添加
    474             if (elem) {
    475                 return;
    476             }
    477             //elem = $('<style></style>'); 不能这样创建 IE8有bug
    478             elem = document.createElement("style");
    479             // 先添加到 DOM 树中,再给 cssText 赋值,否则 css hack 会失效
    480             $('head', doc).append(elem);
    481 
    482             if (elem.styleSheet) { // IE
    483                 elem.styleSheet.cssText = cssText;
    484             } else { // W3C
    485                 elem.appendChild(doc.createTextNode(cssText));
    486             }
    487         }
    488         ,
    489         /*
    490          * 销毁操作 释放内存
    491          */
    492         destory: function () {
    493             var self = this,
    494                 _config = self.config,
    495                 _cache = self.cache;
    496             _cache.ret = [];
    497             _cache.currentIndex = 0;
    498             _cache.oldIndex = 0;
    499             _cache.inputArrs = [];
    500             _config.targetCls = null;
    501         }
    502     };
    503     // 初始化
    504     $(function () {
    505         var auto = new AutoComplete({});
    506     });
    507 </script>

    73行-83行,我手动设置了下他的位置,让他加载生成到我的搜索框下面。正好对准。

    3:编写ajax:

      如果监测到搜索框内容改变 就请求action

     function onChange(value) {
            var textValue = $("#inputName").val(); //文本框的值
            if ($.trim(textValue) == "") {  //判断文本框的值是否为空
                return;
            }
    
            $.ajax({
                dataType: "text",
                type: "POST",
                url: "/search", //请求地址
                data: {"search": textValue}, //附带参数
                success: function (result) {  //返回结果
                    var result = JSON.parse(result);  //将一个json字符串转换成对象
                    if (result.status == 1) { //判断返回值
                        resultData = result.data;  //将返回的json信息,赋值给我们上面定义好的变量resultData
                    }
                }
            });
        }

    4.返回:resutData:

    将返回的resultData,传给我们上面编写的js里面。(在273行有体现

    效果: 

     我的sql :

    select 搜索词 from 表名 where 搜索词 like  CONCAT('','${搜索词}','%' ) GROUP BY 搜索词 LIMIT 5


    我是以匹配以什么内容开头去查询的信息, limit 5 是控制显示条数。
  • 相关阅读:
    Linux基本知识
    Linux 基金会发起开源创新计划,为全球对抗 COVID-19 提供基础架构
    单片机程序设计有十层功力,你现在在哪一层?
    C语言太复杂?CUDA Python也能实现并行计算加速!
    Java 基础 子类赋值给父类问题
    SpringBlade AVUE 拖拽排序
    java 基础 Long类型 判断是否相等
    数字量输入模块和模拟量输入模块的区别是什么?
    模拟量输入模块和模拟量输出模块的应用范围
    NB-IOT关键技术分析
  • 原文地址:https://www.cnblogs.com/wdnnccey/p/6431317.html
Copyright © 2011-2022 走看看