前戏

原cn域名已经很久不续费了,现在打算用hisune.com来继续写博客,之前的博客日志就不保留了,直接弄新的,内容全部原创不追求访问量,纯粹为了提升自身技术。

最近要用到ajax的带下拉菜单的搜索功能,原本项目使用的是multiselect,看了一下api文档,没有ajax功能,于是谷歌了一番,也没有现成的解决办法,但找到一个插件,https://github.com/truckingsim/Ajax-Bootstrap-Select

下载下来后试用了一下,放弃了,原因有以下几点:

  1. 原本项目使用multiselect,这个插件基于bootstrap-select插件,且试了一下,不支持multiselect;
  2. 如果格外使用bootstrap-select插件,为了这个功能得加多两个插件,不划算;
  3. 插件对中文支持不好;
  4. 由于基于bootstrap-select,不支持多选

解决

于是去multiselect的git项目出发了个question,隔日后没有收到解决办法,决定自己动手了。先更新了multiselect插件到最新版本,然后大概看了一下代码开始动工:

  1. Multiselect.prototypedefault里面新增一个参数: ajaxUrl: '',
  2. buildFilter函数中加入判断:

    if (this.query !== event.target.value) {
     this.query = event.target.value;
     if(this.options.ajaxUrl != ''){
         var _t = this;
         $.ajax({
             type: 'POST',
             data: {name: event.target.value},
             url: this.options.ajaxUrl,
             timeout: 20000,
             dataType: "json",
             success: function(json){
                 var _option = '';
                 $.each(json, function(i, n){
                     _option += '' + n + '';
                 });
                 _t.$select.html(_option);
                 _t.$ul.find('li:not(.filter)').remove(); // 清空除搜索框外的li
                 _t.buildSelectAll();
                 _t.buildDropdownOptions();
    
                 _t.updateButtonText();
                 _t.updateSelectAll();
                 _t.$filter.find('input').focus();
             }
         });
     }else{
         $.each($('li', this.$ul), $.proxy(function(index, element) {
             var value = $('input', element).val();
             var text = $('label', element).text();
    
             var filterCandidate = '';
             if ((this.options.filterBehavior === 'text')) {
                 filterCandidate = text;
             }
             else if ((this.options.filterBehavior === 'value')) {
                 filterCandidate = value;
             }
             else if (this.options.filterBehavior === 'both') {
                 filterCandidate = text + 'n' + value;
             }
    
             if (value !== this.options.selectAllValue && text) {
                 // by default lets assume that element is not
                 // interesting for this search
                 var showElement = false;
    
                 if (this.options.enableCaseInsensitiveFiltering && filterCandidate.toLowerCase().indexOf(this.query.toLowerCase()) > -1) {
                     showElement = true;
                 }
                 else if (filterCandidate.indexOf(this.query) > -1) {
                     showElement = true;
                 }
    
                 if (showElement) {
                     $(element).show().removeClass("filter-hidden");
                 }
                 else {
                     $(element).hide().addClass("filter-hidden");
                 }
             }
         }, this));
     }
    }

    为什么ajax返回后不直接用rebuild?由于使用rebuild后,每次输入,下拉select都会还原,search的input框在每次输入后会清空。如果_t.$filter.find('input').val(_t.query);这样在英文输入法下是OK的,但中文输入法下,例如输入:"测试",会变成"ceshi测试"。

  3. 为了防止输入其他非可见数字字母键也进行查询,在buildFilter函数的.on('input onkeyup', $.proxy(function(event) {下加入:
    var specialKeyCodeMap = {
    9: "tab",
    13: "enter",
    16: "shift",
    17: "ctrl",
    18: "alt",
    27: "esc",
    37: "left",
    39: "right",
    38: "up",
    40: "down",
    229: "unknown"  //Returned if it can't get the virtual key number per w3 spec: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html
    };
    if(specialKeyCodeMap[event.keyCode]){
    return true;
    }

    这个是参考了Ajax-Bootstrap-Select的代码。

  4. 8月28日补充,修复一个小bug:
    $('li input', this.$ul).on('change', $.proxy(function(event) {

    改为:

    $('li input:not([type=text])', this.$ul).on('change', $.proxy(function(event) {

    防止change绑定到了搜索框的input

  5. 8月28日补充,multiselect在ie8下搜索是无效的,只支持ie9+,修复方法:
    this.$filter.val(this.query).on('click', function(event) {
    event.stopPropagation();
    }).on('input onkeyup', $.proxy(function(event) {

    改为:

    this.$filter.val(this.query).on('click', function(event) {
    event.stopPropagation();
    }).on('input keyup', $.proxy(function(event) {

    最后关于服务端的返回:返回的数据必须是json格式,key为option的name,value为option的value

至此,搞定!

如果您觉得您在我这里学到了新姿势,博主支持转载,姿势本身就是用来相互学习的。同时,本站文章如未注明均为 hisune 原创 请尊重劳动成果 转载请注明 转自: 为bootstrap的multiselect插件增加ajax搜索功能 - hisune.com