2010-04-06 9 views

Odpowiedz

40

myślę rozwiązać obie funkcje ...

Aby ułatwić użyłem wspólny zwyczaj selektor:

$.expr[':'].textEquals = function (a, i, m) { 
    return $(a).text().match("^" + m[3] + "$"); 
}; 

reszta kodu:

$(function() { 
    $("#tags").autocomplete({ 
     source: '/get_my_data/', 
     change: function (event, ui) { 
      //if the value of the textbox does not match a suggestion, clear its value 
      if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) { 
       $(this).val(''); 
      } 
     } 
    }).live('keydown', function (e) { 
     var keyCode = e.keyCode || e.which; 
     //if TAB or RETURN is pressed and the text in the textbox does not match a suggestion, set the value of the textbox to the text of the first suggestion 
     if((keyCode == 9 || keyCode == 13) && ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0)) { 
      $(this).val($(".ui-autocomplete li:visible:first").text()); 
     } 
    }); 
}); 

Jeżeli którykolwiek z sugestiami autouzupełniania zawierać dowolne znaki „specjalne” używane przez regexp, trzeba uciec te znaki w obrębie m [3] w selektorze niestandardowe:

function escape_regexp(text) { 
    return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 
} 

i zmienić selektor niestandardowe:

$.expr[':'].textEquals = function (a, i, m) { 
    return $(a).text().match("^" + escape_regexp(m[3]) + "$"); 
}; 
+0

Czy udało Ci się również uruchomić funkcję "autoFill"? Mam pytanie tutaj: http://stackoverflow.com/questions/2933713/add-autofill-capabilities-to-jquery-ui-1-8-1, ale nie mogę do końca życia, aby uzyskać autouzupełnianie do pracy . –

+1

W jaki sposób można dostosować to, aby użyć obiektu interfejsu użytkownika, który jest przekazywany obok parametru zdarzenia w fokusie, wybierz itp wtyczki? – Gazillion

+0

Mam prawie to do pracy (tylko rzeczy mustmatch), ale wydaje się, aby wyczyścić wartość niezależnie od tego, czy zasugerowano, czy nie. Jakieś pomysły? :/ –

3

Chyba dostał mustMatch pracy z tym kodem ... trzeba gruntownie przetestować choć:

<script type="text/javascript"> 
    $(function() { 
     $("#my_input_id").autocomplete({ 
      source: '/get_my_data/', 
      minChars: 3, 
      change: function(event, ui) { 
       // provide must match checking if what is in the input 
       // is in the list of results. HACK! 
       var source = $(this).val(); 
       var found = $('.ui-autocomplete li').text().search(source); 
       console.debug('found:' + found); 
       if(found < 0) { 
        $(this).val(''); 
       } 
      } 
     }); 
    }); 
</script> 
+0

Dobrze, ale mogę przesłać pustą wartość po powrocie. Myślę, że musisz zaimplementować funkcję keydown. – CyberJunkie

2

Znalazłem to pytanie jako przydatne.

Pomyślałem, że mogę opublikować kod, którego teraz używam (dostosowane z Esteban Feldman's answer).

Dodałem własną opcję mustMatch i klasę CSS, aby podświetlić problem przed zresetowaniem wartości pola tekstowego.

 change: function (event, ui) { 
      if (options.mustMatch) { 
      var found = $('.ui-autocomplete li').text().search($(this).val()); 

      if (found < 0) { 
       $(this).addClass('ui-autocomplete-nomatch').val(''); 
       $(this).delay(1500).removeClass('ui-autocomplete-nomatch', 500); 
      } 
      } 
     } 

CSS

.ui-autocomplete-nomatch { background: white url('../Images/AutocompleteError.gif') right center no-repeat; } 
+0

@GordonB - czy masz obrazy gdziekolwiek autocompleteerror.gif – leora

+0

to był tylko obraz 16x16, który narysowałem ... a nie obraz biblioteki. – GordonB

0

robię to trochę inaczej, buforowanie wyników i wyczyszczenie pola tekstowego, gdy liczba wyników dla pewnej perspektywie wynosi zero:

<script type='text/javascript'> 
function init_autocomplete(args) 
{ 
    var resultCache = {}; 
    var currentRequestTerm = null; 

    var closeCallback = function() 
    { 
     // Clear text field if current request has no results 
     if(resultCache[currentRequestTerm].length == 0) 
      $(args.selector).val(''); 
    }; 

    var sourceCallback = function(request, responseCallback) 
    { 
     // Save request term 
     currentRequestTerm = request.term; 

     // Check for cache hit 
     // ... 
     // If no cache hit, fetch remote data 
     $.post(
      dataSourceUrl, 
      { ... }, // post data 
      function(response) 
      { 
       // Store cache 
       resultCache[request.term] = response; 

       responseCallback(response); 
      } 
    }; 

    $(args.selector).autocomplete({ 
     close: closeCallback, 
     source: sourceCallback 
    }); 
} 
</script> 
1

Rozwiązanie, którego używałem do wdrożenia "mustMatch":

<script type="text/javascript"> 
... 

$('#recipient_name').autocomplete({ 
    source: friends, 
    change: function (event, ui) { 
     if ($('#message_recipient_id').attr('rel') != $(this).val()) { 
      $(this).val(''); 
      $('#message_recipient_id').val(''); 
      $('#message_recipient_id').attr('rel', ''); 
     } 
    }, 
    select: function(event, ui) { 
     $('#message_recipient_id').val(ui.item.user_id); 
     $('#message_recipient_id').attr('rel', ui.item.label); 
    } 
}); 

... 
</script> 
1

Odkryłem jeden problem. Podczas gdy lista sugestii jest aktywna, możesz przesłać swój formularz, nawet jeśli jego wartość nie pasuje do sugestii. Aby odrzucić to, dodałem:

$('form').submit(function() { 
     if ($(".ui-autocomplete li:textEquals('" + $(this).val() + "')").size() == 0) { 
      $(this).val(''); 
      $("span").text("Select a valid city").show(); 
      return false; 
     } 
}); 

Zapobiega to przesyłaniu formularza i wyświetla komunikat.

+0

Uwaga: wydaje się, że jest to komentarz do zaakceptowanej odpowiedzi Doca Hoffidaya. –

1

Ten oficjalny demo jQuery UI posiada mustMatch, pośród innych fajnych rzeczy: http://jqueryui.com/demos/autocomplete/#combobox

zaktualizowałem go dodać Autouzupełnianie i kilka innych rzeczy.

Javascript:

 


/* stolen from http://jqueryui.com/demos/autocomplete/#combobox 
* 
* and these options added. 
* 
* - autoFill (default: true): select first value rather than clearing if there's a match 
* 
* - clearButton (default: true): add a "clear" button 
* 
* - adjustWidth (default: true): if true, will set the autocomplete width the same as 
* the old select. (requires jQuery 1.4.4 to work on IE8) 
* 
* - uiStyle (default: false): if true, will add classes so that the autocomplete input 
* takes a jQuery-UI style 
*/ 
(function($) { 
    $.widget("ui.combobox", { 
     options: { 
      autoFill: true, 
      clearButton: true, 
      adjustWidth: true, 
      uiStyle: false, 
      selected: null, 
     }, 
    _create: function() { 
     var self = this, 
      select = this.element.hide(), 
      selected = select.children(":selected"), 
      value = selected.val() ? selected.text() : "", 
       found = false; 
     var input = this.input = $("") 
       .attr('title', '' + select.attr("title") + '') 
     .insertAfter(select) 
     .val(value) 
     .autocomplete({ 
      delay: 0, 
      minLength: 0, 
      source: function(request, response) { 
       var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); 
         var resp = select.children("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" 
         ), "$1"), 
         value: text, 
         option: this 
        }; 
       }); 
         found = resp.length > 0; 
       response(resp); 
      }, 
      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 || input.data("autocomplete").term=="") { 
        // set to first suggestion, unless blank or autoFill is turned off 
           var suggestion; 
           if(!self.options.autoFill || input.data("autocomplete").term=="") found=false; 
           if(found) { 
            suggestion = jQuery(input.data("autocomplete").widget()).find("li:first")[0]; 
            var option = select.find("option[text="+suggestion.innerText+"]").attr('selected', true); 
            $(this).val(suggestion.innerText); 
         input.data("autocomplete").term = suggestion.innerText; 
          self._trigger("selected", event, { item: option[0] }); 
           } else { 
            suggestion={innerText: ''}; 
            select.find("option:selected").removeAttr("selected"); 
            $(this).val(''); 
         input.data("autocomplete").term = ''; 
            self._trigger("selected", event, { item: null }); 
           } 
        return found; 
        } 
       } 
      } 
     }); 

      if(self.options.adjustWidth) { input.width(select.width()); } 

      if(self.options.uiStyle) { 
       input.addClass("ui-widget ui-widget-content ui-corner-left"); 
      } 


     input.data("autocomplete")._renderItem = function(ul, item) { 
      return $("
  • ") .data("item.autocomplete", item) .append("" + item.label + "") .appendTo(ul); }; this.button = $(" ") .attr("tabIndex", -1) .attr("title", "Show All Items") .insertAfter(input) .button({ icons: { primary: "ui-icon-triangle-1-s" }, text: false }) .removeClass("ui-corner-all") .addClass("ui-corner-right ui-button-icon") .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(); }); if(self.options.clearButton) { this.clear_button = $(" ") .attr("tabIndex", -1) .attr("title", "Clear Entry") .insertAfter(input) .button({ icons: { primary: "ui-icon-close" }, text: false }) .removeClass("ui-corner-all") .click(function(event, ui) { select.find("option:selected").removeAttr("selected"); input.val(""); input.data("autocomplete").term = ""; self._trigger("selected", event, { item: null }); // work around a bug (likely same cause as #5265) $(this).blur(); }); } }, destroy: function() { this.input.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call(this); } }); })(jQuery);

    CSS (.hjq-combobox jest rozpiętość owijania)

     
    .hjq-combobox .ui-button { margin-left: -1px; } 
    .hjq-combobox .ui-button-icon-only .ui-button-text { padding: 0; } 
    .hjq-combobox button.ui-button-icon-only { width: 20px; } 
    .hjq-combobox .ui-autocomplete-input { margin-right: 0; } 
    .hjq-combobox {white-space: nowrap;} 
    

    Uwaga: kod ten jest aktualizowany i utrzymywany tutaj: https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

    32

    Kiedyś coś tak proste jak to dla mustMatch i działa. Mam nadzieję, że to pomoże komuś.

     change: function (event, ui) { 
          if (!ui.item) { 
           $(this).val(''); 
          } 
         } 
    
    +0

    Doskonały, dzięki! Czy zaimplementowałeś autouzupełnianie? Poszukujesz tego też :) –

    +2

    Pamiętaj, że powinieneś się upewnić, że masz 'autoFocus: true' – Elliott

    +0

    to właśnie szukałem –

    1

    Może to tylko dlatego, że jest to stary problem, ale okazało się, że najprostszym rozwiązaniem jest już tam wtyczki, wystarczy użyć odpowiednich funkcji do Uzyskać dostęp do niego.

    Kod ten będzie obsługiwać przypadki, gdy autouzupełnianie traci fokus z niepoprawną wartość:

    change: function(e, ui) { 
        if (!ui.item) { 
         $(this).val(""); 
        } 
    } 
    

    i ten kod, podobnie jak oryginalny funkcjonalności z bassistance, zajmie się przypadki, gdy nie znaleziono żadnego meczu podczas pisania w autouzupełnieniu:

    response: function(e, ui) { 
        if (ui.content.length == 0) { 
         $(this).val(""); 
        } 
    } 
    

    Działa to dobrze ze statycznym źródłem tablicy lub ze źródłem danych JSON. W połączeniu z opcją autoFocus: true, wydaje się, że wszystko, co potrzebne, wykonuje się w efektywny sposób.

    Ostatnim przypadkiem, który możesz obsłużyć, jest to, co zrobić, gdy klawisz ESCAPE zostanie naciśnięty z nieprawidłową wartością w polu tekstowym. Używam wartości pierwszego dopasowanego wyniku. I tak to robię ...

    Najpierw zadeklaruj zmienną, która będzie najlepiej pasować. Zrób to poza pluginem autouzupełniania.

    var bestMatch = ""; 
    

    Następnie użyj następującej opcji:

    open: function(e, ui) { 
        bestMatch = ""; 
    
        var acData = $(this).data('uiAutocomplete'); 
        acData.menu.element.find("A").each(function() { 
         var me = $(this); 
    
         if (me.parent().index() == 0) { 
          bestMatch = me.text(); 
         } 
        }); 
    } 
    

    Wreszcie, należy dodać następujące wydarzenie do autouzupełniania:

    .on("keydown", function(e) { 
        if (e.keyCode == 27)  // ESCAPE key 
        { 
         $(this).val(bestMatch); 
        } 
    }) 
    

    Można tak łatwo zmusić boiska i być pusty, gdy klawisz Escape jest wciśnięty. Wszystko, co musisz zrobić, to ustawić wartość pustego łańcucha po naciśnięciu klawisza zamiast zmiennej bestMatch (która nie jest w ogóle potrzebna, jeśli zdecydujesz się opróżnić pole).

    0

    podstawie zaakceptowanej odpowiedzi:

    Moi dodatkowe wymagania: wiele Autouzupełnianie walidacji, błąd dyskretny.

    change: function() { 
        var target = $(this), 
         widget = target.autocomplete('widget'), 
         cond = widget.find('li:textEquals("' + target.val() + '")').length === 0; 
    
        target.toggleClass('input-validation-error', cond); 
    } 
    
    0

    Późna odpowiedź, ale może pomóc komuś!

    Biorąc pod uwagę te dwa wydarzenia w widget autouzupełniania

    1) zmiana - wyzwalane, gdy pole jest zamazany i wartość ulega zmianie.

    2) odpowiedź - aktywowana po zakończeniu wyszukiwania i wyświetleniu menu.

    Modyfikacja zdarzenia zmian i reagowania w sposób następujący:

    change : function(event,ui) 
    { 
    if(!ui.item){ 
    $("selector").val(""); 
    } 
    }, 
    
    response : function(event,ui){ 
    if(ui.content.length==0){ 
        $("selector").val(""); 
    } 
    } 
    

    Nadzieja to pomaga!

    Powiązane problemy