2010-11-01 31 views
10

¿Cómo se puede establecer un límite en el resultado de la autocompletar de jQuery?Limite el resultado en jQuery Autocompletar

Este es mi código:

 $.ajax({ 
      url: "/cache/search/SearchModels.xml", 
      dataType: "xml", 
      success: function(xmlResponse) { 
       var data = $("SearchModel", xmlResponse).map(function() { 
        return { 
         value: $("Name", this).text() + ", " + $("Description", this).text(), 
         id: $("No", this).text(), 
         name: $("Name", this).text(), 
         url: $("URL", this).text() 
        }; 
       }).get(); 
       $("#txtTopSearch").autocomplete({ 
        source: data, 
        minLength: 2, 
        select: function(event, ui) { 
         BlockUI(); 
         if (typeof (ui.item.url) != 'undefined') { 
          window.location = ui.item.url; 
         } 
         else { 
          alert('Page not found!'); 
          $.unblockUI(); 
         } 
        }, 
        search: function(event, ui) { 
         $('#txtTopSearch').addClass('searchInProgress'); 
        }, 
        close: function(event, ui) { 
         $('#txtTopSearch').removeClass('searchInProgress'); 
        } 
       }).data("autocomplete")._renderItem = function(ul, item) { 
        return $("<li></li>") 
        .data("item.autocomplete", item) 
        .append("<a><span style='font-size:.9em; font-weight:bold;'>" + item.id + "</span><br /><span style='font-size:.8em;'>" + item.name + "</span></a>") 
        .appendTo(ul); 
       }; 
      }, 
      error: function(xhr, textStatus, errorThrown) { 
       alert('Error: ' + xhr.statusText); 
      } 
     }); 

Este código de retorno todos los resultados de la consulta, pero quiero limitar esta a solo 10 muestra los resultados. En la versión antigua de autocompletar existía una opción para esto, pero ahora está en desuso.

Ejemplo del XML:

<?xml version="1.0"?> 
<ArrayOfSearchModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <SearchModel> 
    <No>1</No> 
    <Name>My product</Name> 
    <Description>My description</Description> 
    <Tags>blue;brown;</Tags> 
    <URL>/Products/1</URL> 
    </SearchModel> 
</ArrayOfSearchModel> 

Respuesta

11

Informe final de actualización
después de entender que en mis respuestas anteriores, estaba limitando su conjunto el resultado XML establecido y no a los resultados de la función de autocompletar

Como se ha anulado el método predeterminado _renderItem, puede anular el predeterminado _renderMenu.

$.ui.autocomplete.prototype._renderMenu = function(ul, items) { 
    var self = this; 
    $.each(items, function(index, item) { 
     if (index < 10) // here we define how many results to show 
     {self._renderItem(ul, item);} 
     }); 
} 

respuesta se modifica a partir de este jQueryUI: how can I custom-format the Autocomplete plug-in results? así que gracias ir a @cheeso ..


respuesta original

En que success devolución de llamada utilizan $("SearchModel:lt(10)", xmlResponse).map(...

El :lt(10) obtiene elementos con un índice de menos de 10. Entonces max 10 resu lts serán devueltos ..

(, por supuesto, el número 10 podría ser cualquier cosa que desee)

Mira :lt() selector en http://api.jquery.com/lt-selector/

actualización

aunque no puedo entender por qué la primera respuesta no funciona, ya que SearchModel es una etiqueta y apostamos a eso ... podemos mover el filtrado en el método del mapa ...

success: function(xmlResponse) { 
       var data = $("SearchModel", xmlResponse).map(function(index) { 
        if (index<10) 
         { 
         return { 
          value: $("Name", this).text() + ", " + $("Description", this).text(), 
          id: $("No", this).text(), 
          name: $("Name", this).text(), 
          url: $("URL", this).text() 
           }; 
         } 
         else 
         { return null; } 
       }).get(); 

documentation of map()

+0

sugerencia prometedora, pero no funcionó. No parece que 'SearchModel' sea un selector regular. – Martin

+0

@Martin, supuse que era una etiqueta utilizada dentro del xml. ¿Puedes publicar algo de contenido del archivo XML? Voy a publicar soluciones alternativas utilizando el método 'map' –

+0

Gracias, he actualizado mi pregunta con un ejemplo de un nodo. – Martin

3

Por qué no limitar los datos que la consulta devuelve desde su origen XML?

Editar:

Hay que recordar que la funcionalidad de autocompletar es esencialmente usando una expresión regular para que coincida con los elementos de la fuente de datos. Tener una fuente de datos grande es malo porque tiene que analizar tantos datos simplemente para encontrar el elemento correcto.

+0

Claro, me encantaría hacer eso, pero ¿cómo? He buscado opciones de limitación en jQuery '.map()' y '.get()' pero no he encontrado ninguna, estoy un poco bloqueado. – Martin

+0

Reduce el tamaño del archivo xml. Si no está interesado en mostrar todos los resultados que coinciden en el archivo, reduzca el tamaño del archivo (el número de elementos). – Achilles

+0

Lo suficiente, pero ¿no hay otras maneras de hacerlo sin cambiar el archivo XML? – Martin

1

puede agregar un controlador para el evento "abierta":

open:function(event,ui){ 
    var maxListLength=10; 
    var ul = jQuery("#txtTopSearch").autocomplete("widget")[0]; 
    while(ul.childNodes.length > maxListLength) 
      ul.removeChild(ul.childNodes[ul.childNodes.length-1]); 
    } 
2

Esto es lo que hice basado en una lectura de los documentos de la API de autocompletar

$input.autocomplete({ 
    source: function(request, response) { 
    $.getJSON('search.php', request, function(data, status, xhr) { 
     // return a max of 10 results. 
     response(data.slice(0, 9)); 
    }); 
    } 
}) 

Seguir este patrón ahorra tener que hacer cualquier cosa funky en la capa de renderizado.

+0

¿No tendría más sentido limitar el tamaño del conjunto de resultados en el lado del servidor? por ejemplo, con una cláusula LIMIT en una consulta SQL? – David

+0

Eso hubiera sido mejor, pero no tuve acceso a ese conjunto de código. –

1

La forma más rápida de limitar los resultados es hacerlo durante el evento "abrir". Podemos eliminar parte del contenido creado dinámicamente por jquery ui, reduciendo la matriz de elementos secundarios.

Esta solución resuelto el mismo problema para mí:

var maxResults = 10; 
$input.autocomplete({ 
    source: somefile.json, 
    open: function(event,ui){ 
      $(this).data("uiAutocomplete").menu.element.children().slice(maxResults).remove(); 
     } 
}) 
Cuestiones relacionadas