2012-06-14 17 views
12

Używam combo z autouzupełniania jquery ui i działa świetnie, ale teraz jestem trochę chciwy. Chciałbym móc dodać do niego kategorie. ComboBox jest generowana wyłączyć z menu, więc jeśli dodałam kategorie patrz przykład poniżej znacznika by pokazać się jak kategoriami są w jquery ui autocomplete categories versionjquery ui autouzupełnianie combobox z kategoriami

<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> 

stworzyłem http://jsfiddle.net/nH3b6/11/.

Dzięki za pomoc lub wskazówki.

Odpowiedz

11

Rozbudowując sugestię @ Jarry, zaktualizowałbym twój kod, aby określić, do której opcji należy ta opcja. Stamtąd można użyć kodu podobnego jak znaleźć na stronie internetowej 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(); 
    }); 
}); 

Przykład:http://jsfiddle.net/gB32r/

+1

To działa świetnie. Dzięki wielkie. –

+0

Hej, więc znalazłem mały błąd jako produkt uboczny dokonanej korekty. Jeśli upuszczę listę i wybiorę jedną z opcji z kategorii, wyświetli się komunikat "Brak dopasowań". Jeśli wybiorę opcję, która nie należy do kategorii, działa doskonale. Próbowałem to zrozumieć bezskutecznie. –

+0

Nevermind wymyślił to ... select.children ("optgroup"). Children ("option"). Each (function() { –

2

jak widać w jQueryUI docs, trzeba dostosować widget, aby to zrobić

_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); 
      }); 
     } 

to jej nie testowane, ale powinien być dobry początek:

_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); 
      }); 
     } 

jeśli tego nie robi działa, może powinieneś debugować, aby zobaczyć, co jest w tablicy items, która przychodzi jako parametr _renderMenu.

Uwaga: to się nazywa MonkeyPatching, nie polecam robić tego dużo, ale ponieważ dokumenty pokazują to, id powiedz, zrób to.

+0

Dzięki za Odpowiedź: Popraw mnie, jeśli się mylę, ale zaczynasz od kodu z "kategorii" wersji autoco mplete Zaczynam od wersji "combobox". Tak więc powyższy kod nie zadziała. –

+0

nie mylisz się. kod pochodzi z kategorii. nie jestem pewien, czy to zadziała, i nie mogę go przetestować teraz. myślę, że to zadziała, po prostu musisz przesłonić (AKA monkeypatch) funkcję _renderMenu.Założę się, że jego nazwa pochodzi od miejsca, z którego pochodzą przedmioty. – Jarry

3

Istnieje kilka cech z jQuery 10. biorę autouzupełniania combobox z internetowej jQuery UI : http://jqueryui.com/autocomplete/#combobox i dołącz do niego z odpowiedzią Andrew Whitakera.

(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

I'am pomocą jQueryUI widget autouzupełniania w moim webapp, z łatania combobox małpa, optgroup (kategorie), a także zdolność do wyszukaæ w nazwach kategorii. Termin wyszukiwania jest również podkreślony w zgodnej opcji i optgroup. Użyłem kilku odpowiedzi ze strony stackoverflow i jqueryui, aby dostać się do tego punktu, dzięki!

Uwielbiam pracować nad ostatnią wersją jqueryui. Jqueryui 1.9 i 1.11 wprowadziły przełomowe zmiany (w autouzupełnianiu i wtyczce menu, z których ostatnia była używana przez poprzednie) iw końcu udało mi się sprawić, by działała z najnowszą wersją jqueryui (1.11.0) i jquery (2.1.1)

jsbin here

ważny element: opcje widgetów menu zmiana nie rozważyć kategorie jak zwykłego łącza menu poprzez nową opcję egzemplarze (tak nowy, że nie wewnątrz doc ale w jQueryUI uaktualnić przypomnienie 1,11

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

To jest idealne! Z początku się wahałem, aby to wykorzystać, ale to zadziałało i rozwiązało mój problem, wielkie dzięki! – NinaNa

Powiązane problemy