2010-04-06 16 views

Respuesta

40

Creo que he resuelto ambas características ...

Para facilitar las cosas, he usado una selector de costumbre común:

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

el resto del código:

$(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()); 
     } 
    }); 
}); 

Si ninguna de sus sugerencias de autocompletado contienen caracteres 'especiales' utilizados por expresión regular, que debe escapar de los personajes dentro de m [3] en el selector personalizado:

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

y cambiar el selector personalizado:

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

¿También pudo hacer funcionar el "autocompletar"? Tengo una pregunta aquí http://stackoverflow.com/questions/2933713/add-autofill-capabilities-to-jquery-ui-1-8-1 pero no puedo por mi vida hacer que Autocompletar funcione . –

+1

¿Cómo podría personalizar esto para usar el objeto ui que se pasa junto al parámetro de evento en el foco, seleccionar, etc. del complemento? – Gazillion

+0

Casi tengo esto para trabajar (solo lo de mustmatch) pero parece borrar el valor independientemente de si fue sugerido o no. ¿Algunas ideas? :/ –

3

Creo que tengo la mustMatch trabajar con el código ... necesitan probar a fondo sin embargo:

<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

Bueno, pero puedo enviar un valor vacío a la devolución. Creo que debes implementar una función de tecla. – CyberJunkie

2

Encontré esta pregunta para ser útil.

Pensé en publicar el código que estoy usando (adaptado de Esteban Feldman's answer).

He agregado mi propia opción mustMatch y una clase CSS para resaltar el problema antes de restablecer el valor del cuadro de texto.

 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 - tiene las imágenes en cualquier lugar autocompleteerror.gif – leora

+0

era solo una imagen de 16x16 que dibujé ... no una imagen de biblioteca. – GordonB

0

que estoy haciendo un poco diferente, almacenamiento en caché de los resultados y despejar el campo de texto si el número de resultados para un determinado término es cero:

<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

La solución que he usado para implementar '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

Descubrí un problema. Mientras la lista de sugerencias está activa, puede enviar su formulario incluso si el valor no coincide con la sugerencia. Para este dissallow añadí:

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

Esto evita que la forma de ser presentado y muestra un mensaje.

+0

Nota: esto parece ser un comentario en la respuesta aceptada por Doc Hoffiday. –

1

Esta demo oficial de jQuery-UI tiene mustMatch, entre otras cosas interesantes: http://jqueryui.com/demos/autocomplete/#combobox

He actualizado para añadir relleno automático, y algunas otras cosas.

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-cuadro combinado es un lapso de envoltura)

     
    .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;} 
    

    Nota: este código se actualiza y mantiene aquí: https://github.com/tablatom/hobo/blob/master/hobo_jquery_ui/vendor/assets/javascripts/combobox.js

    32

    utilicé algo tan simple como esto para mustMatch y funciona. Espero que esto ayude a alguien.

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

    Perfecto, gracias! ¿Has implementado autocompletar? Buscando eso también :) –

    +2

    Solo para notar que debes asegurarte de que tienes 'autoFocus: true' – Elliott

    +0

    esto es lo que estaba buscando –

    1

    tal vez es sólo porque se trata de una cuestión de edad, pero he encontrado que la solución más fácil es que ya existe en el plugin, sólo tiene que utilizar las funciones propias de las acceder a él.

    Este código se encargará de los casos cuando el autocompletar deja de estar seleccionado con un valor no válido:

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

    Y este código, al igual que la funcionalidad original de bassistance, se encargará de los casos en los que no hay coincidencias mientras escribe en el autocompletar:

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

    Esto funciona bien ya sea con una fuente matriz estática, o una fuente de datos JSON. Combinado con la opción autoFocus: true, parece hacer todo lo necesario de manera eficiente.

    El último caso que puede querer manejar es qué hacer cuando se presiona la tecla ESCAPE con un valor no válido en el cuadro de texto. Lo que hago es usar el valor del primer resultado coincidente. Y así es como lo hago ...

    Primero, declara una variable para mantener la mejor coincidencia. Haga esto fuera de su complemento de autocompletar.

    var bestMatch = ""; 
    

    A continuación, utilice la siguiente opción:

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

    Por último, añadir el siguiente evento al autocompletar:

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

    Usted sólo puede forzar fácilmente el campo para estar vacío cuando el se presiona la tecla de escape. Todo lo que tiene que hacer es establecer el valor en una cadena vacía cuando se presiona la tecla en lugar de la variable bestMatch (que no es necesaria en absoluto si elige vaciar el campo).

    0

    Sobre la base de la respuesta aceptada:

    Mis requisitos adicionales: múltiples validación completa automáticamente a, de error discreto.

    0

    ¡Respuesta tardía pero podría ayudar a alguien!

    Teniendo en cuenta los dos eventos en widget de autocompletar

    1) el cambio - desencadena cuando el campo es borrosa y se cambia el valor.

    2) respuesta: se activa cuando finaliza la búsqueda y se muestra el menú.

    modificar el eventos de cambio y la respuesta de la siguiente manera:

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

    Espero que esto ayude!

    Cuestiones relacionadas