2012-06-14 61 views
12

我正在使用jquery ui自動完成組合框,它運行良好,但現在我變得有點貪婪。我希望能夠添加類別。因此,如果我加入類別參見實施例的標籤的正下方會出現像的類別是在jquery ui autocomplete categories versionjquery ui與類別的自動完成組合框

<select> 
<optgroup name="Cat 1">  
<option value="1a">One A</option> 
<option value="1b">One B</option> 
<option value="1c">One C</option> 
</optgroup> 
<optgroup name="Cat 2">  
<option value="2a">Two A</option> 
<option value="2b">Two B</option> 
<option value="2c">Two C</option> 
</optgroup> 
</select> 

我創建了一個http://jsfiddle.net/nH3b6/11/組合框被關閉的菜單的生成。

感謝您的任何幫助或方向。

回答

11

擴展@ Jarry的建議,我會更新您的代碼,以確定該選項屬於optgroup。從那裏,你可以使用類似的代碼jQueryUI的網站上爲找到:

(function($) { 
    $.widget("ui.combobox", { 
     _create: function() { 
      var input, self = this, 
       select = this.element.hide(), 
       selected = select.children(":selected"), 
       value = selected.val() ? selected.text() : "", 
       wrapper = this.wrapper = $("<span>").addClass("ui-combobox").insertAfter(select); 

      input = $("<input>").appendTo(wrapper).val(value).addClass("ui-state-default ui-combobox-input").autocomplete({ 
       delay: 0, 
       minLength: 0, 
       source: function(request, response) { 
        var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); 

        response(select.find("option").map(function() { 
         var text = $(this).text(); 
         if (this.value && (!request.term || matcher.test(text))) return { 
          label: text.replace(
          new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(request.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"), 
          value: text, 
          option: this, 
          category: $(this).closest("optgroup").attr("label") 
         }; 
         //MK 
         $('#test').attr('style', 'display: none;'); 
        }).get()); 
       }, 
       select: function(event, ui) { 
        ui.item.option.selected = true; 
        self._trigger("selected", event, { 
         item: ui.item.option 
        }); 
       }, 
       change: function(event, ui) { 
        if (!ui.item) { 
         var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"), 
          valid = false; 
         select.children("option").each(function() { 
          if ($(this).text().match(matcher)) { 
           this.selected = valid = true; 
           return false; 
          } 
         }); 
         if (!valid) { 
          $('#test').attr('style', 'display: block;'); 
          // remove invalid value, as it didn't match anything 
          //$(this).val(""); 
          //select.val(""); 
          //input.data("autocomplete").term = ""; 
          //return false;      
         } 
        } 
       } 
      }).addClass("ui-widget ui-widget-content ui-corner-left"); 

      input.data("autocomplete")._renderItem = function(ul, item) { 
       return $("<li></li>").data("item.autocomplete", item).append("<a>" + item.label + "</a>").appendTo(ul); 
      }; 

      input.data("autocomplete")._renderMenu = function(ul, items) { 
       var self = this, 
        currentCategory = ""; 
       $.each(items, function(index, item) { 
        if (item.category != currentCategory) { 
         if (item.category) { 
          ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>"); 
         } 
         currentCategory = item.category; 
        } 
        self._renderItem(ul, item); 
       }); 
      }; 

      $("<a>").attr("tabIndex", -1).attr("title", "Show All Items").appendTo(wrapper).button({ 
       icons: { 
        primary: "ui-icon-triangle-1-s" 
       }, 
       text: false 
      }).removeClass("ui-corner-all").addClass("ui-corner-right ui-combobox-toggle").click(function() { 
       // close if already visible 
       if (input.autocomplete("widget").is(":visible")) { 
        input.autocomplete("close"); 
        return; 
       } 

       // work around a bug (likely same cause as #5265) 
       $(this).blur(); 

       // pass empty string as value to search for, displaying all results 
       input.autocomplete("search", ""); 
       input.focus(); 
      }); 
     }, 

     destroy: function() { 
      this.wrapper.remove(); 
      this.element.show(); 
      $.Widget.prototype.destroy.call(this); 
     } 
    }); 
})(jQuery); 

$(function() { 
    $("#combobox").combobox(); 
    $("#toggle").click(function() { 
     $("#combobox").toggle(); 
    }); 
}); 

例子:http://jsfiddle.net/gB32r/

+1

這很好。非常感謝。 –

+0

嘿所以我發現了一個小錯誤,作爲你所做調整的副產品。如果我下拉列表並從類別中選擇一個選項,則顯示「無匹配」。如果我選擇一個不屬於某個類別的選項,它的效果會很好。我試圖想出它無濟於事。 –

+0

不知道如何計算出來... select.children(「optgroup」)。children(「option」)。each(function(){ –

2

,你可以在jQueryUI docs看到,用戶還可自定義窗口小部件做

_renderMenu: function(ul, items) { 
      var self = this, 
       currentCategory = ""; 
      $.each(items, function(index, item) { 
       if (item.category != currentCategory) { 
        ul.append("<li class='ui-autocomplete-category'>" + item.category + "</li>"); 
        currentCategory = item.category; 
       } 
       self._renderItem(ul, item); 
      }); 
     } 

本公司沒有測試,但應該是一個良好的開端:

_renderMenu: function(ul, items) { 
      var self = this, 
       currentCategory = ""; 
      $.each(items, function(index, item) { 
       if (item.parent.attr('label') != currentCategory) { 
        ul.append("<li class='ui-autocomplete-category'>" + item.parent.attr('label') + "</li>"); 
        currentCategory = item.parent.attr('label'); 
       } 
       self._renderItem(ul, item); 
      }); 
     } 

如果這並不工作,也許你應該調試,看看items陣列是什麼進入_renderMenu的參數。

一個側面說明:這被稱爲MonkeyPatching,我不會推薦這麼做,但自從文檔顯示它,ID說這樣做。

+0

謝謝如果我錯了,糾正我,但是你從「類別」版本的autoco代碼開始完整我從「組合框」版本開始。所以上面的代碼不起作用。 –

+0

你沒有錯。代碼來自類別。即時通訊不知道它是否會工作,我現在不能測試它。我認爲它會起作用,你只需重寫(AKA monkeypatch)_renderMenu函數。我敢打賭,儘管物品來自哪裏,但它被稱爲 – Jarry

3

有與jQuery 10 的一些功能我需要自動完成組合框從jQuery用戶界面的網站:http://jqueryui.com/autocomplete/#combobox 並加入它與安德魯惠特克答案。

(function($) { 
$.widget("custom.combobox_with_optgroup", { 
    _create: function() { 
     this.wrapper = $("<span>") 
      .addClass("custom-combobox") 
      .insertAfter(this.element); 
     this.element.hide(); 
     this._createAutocomplete(); 
     this._createShowAllButton(); 
    }, 
    _createAutocomplete: function() { 
     var selected = this.element.find(":selected"), 
      value = selected.val() ? selected.text() : ""; 
     this.input = $("<input>") 
      .appendTo(this.wrapper) 
      .val(value) 
      .attr("title", "") 
      .addClass("custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left") 
      .autocomplete({ 
       delay: 0, 
       minLength: 0, 
       source: $.proxy(this, "_source") 
      }) 
      .tooltip({ 
       tooltipClass: "ui-state-highlight" 
      }); 
     this._on(this.input, { 
      autocompleteselect: function(event, ui) { 
       ui.item.option.selected = true; 
       this._trigger("select", event, { 
        item: ui.item.option 
       }); 
      }, 
      autocompletechange: "_removeIfInvalid" 
     }); 

     this.input.data("uiAutocomplete")._renderMenu = function(ul, items) { 
      var self = this, 
       currentCategory = ""; 
      $.each(items, function(index, item) { 
       if (item.category != currentCategory) { 
        if (item.category) { 
         ul.append("<li class='custom-autocomplete-category'>" + item.category + "</li>"); 
        } 
        currentCategory = item.category; 
       } 
       self._renderItemData(ul, item); 
      }); 
     }; 
    }, 
    _createShowAllButton: function() { 
     var input = this.input, 
      wasOpen = false; 
     $("<a>") 
      .attr("tabIndex", -1) 
      .attr("title", "Показать все") 
      .tooltip() 
      .appendTo(this.wrapper) 
      .button({ 
       icons: { 
        primary: "ui-icon-triangle-1-s" 
       }, 
       text: false 
      }) 
      .removeClass("ui-corner-all") 
      .addClass("custom-combobox-toggle ui-corner-right") 
      .mousedown(function() { 
       wasOpen = input.autocomplete("widget").is(":visible"); 
      }) 
      .click(function() { 
       input.focus(); 

       if (wasOpen) { 
        return; 
       } 

       input.autocomplete("search", ""); 
      }); 
    }, 
    _source: function(request, response) { 
     var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); 
     response(this.element.find("option").map(function() { 
      var text = $(this).text(); 
      if (this.value && (!request.term || matcher.test(text))) 
       return { 
        label: text, 
        value: text, 
        option: this, 
        category: $(this).closest("optgroup").attr("label") 
       }; 
     })); 
    }, 
    _removeIfInvalid: function(event, ui) { 

     if (ui.item) { 
      return; 
     } 

     var value = this.input.val(), 
      valueLowerCase = value.toLowerCase(), 
      valid = false; 
     this.element.find("option").each(function() { 
      if ($(this).text().toLowerCase() === valueLowerCase) { 
       this.selected = valid = true; 
       return false; 
      } 
     }); 

     if (valid) { 
      return; 
     } 

     this.input 
      .val("") 
      .attr("title", value + " не существует") 
      .tooltip("open"); 
     this.element.val(""); 
     this._delay(function() { 
      this.input.tooltip("close").attr("title", ""); 
     }, 2500); 
     this.input.data("ui-autocomplete").term = ""; 
    }, 
    _destroy: function() { 
     this.wrapper.remove(); 
     this.element.show(); 
    } 
}); 
})(jQuery); 
1

我'使用我的webapp jQueryUI的自動完成構件,具有ComboBox猴子修補,OPTGROUP(類別),並且還SEACH在類別名稱的能力。在兼容選項和optgroup中也強調了這個術語。我用了幾個來自stackoverflow和jqueryui網站的答案來達到這一點,謝謝!

我喜歡讓它在最後一個版本的jqueryui上工作。 Jqueryui 1.9和1.11引入了突破性變化(在自動完成和菜單插件中,前者使用的是最新版本),並且我最終成功地使用最新版本的jqueryui(1.11.0)和jquery(2.1.1)

jsbin here

重要組成部分:改變菜單控件選項,不考慮類別,通過新項目的選擇(正常菜單鏈接,以便新的,並非商務部內部,而是在jQueryUI的升級指南,以1.11

$.extend($.ui.menu.prototype.options, { 
    items: "> :not(.aureltime-autocomplete-category)" 
}); 
+0

這很完美!我一開始很猶豫,使用這個,但這實際上工作,並解決了我的問題,非常感謝! – NinaNa