Ограничить результат в автозаполнении jQuery

Как установить ограничение на результат автозаполнения jQuery?

Это мой код:

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

Этот код возвращает все результаты в запросе, но я хочу ограничиться отображением 10 результатов. В старой версии автозаполнения для этого была опция, но теперь она устарела.

Пример 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>

person Martin    schedule 01.11.2010    source источник


Ответы (5)


Последнее обновление
после того, как я понял, что в своих предыдущих ответах я ограничивал весь набор результатов xml, а не результаты автозаполнения

Поскольку вы переопределили метод _renderItem по умолчанию, вы можете переопределить метод _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 );}
      });
}

ответ изменен из этого jQueryUI: как я могу отформатировать результаты плагина автозаполнения в произвольном формате? благодарим @cheeso ..


Исходный ответ

В вашем success обратном вызове используйте $("SearchModel:lt(10)", xmlResponse).map(...

:lt(10) получает элементы с индексом меньше 10. Таким образом, будет возвращено не более 10 результатов.

(Конечно, число 10 может быть любым)

Посмотрите на :lt() селектор на http://api.jquery.com/lt-selector/.

обновить

Хотя я не могу понять, почему первый ответ не работает, поскольку SearchModel - это тег, и мы нацелены на это ... мы можем переместить фильтрацию в метод карты ..

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

документация по карте ()

person Gabriele Petrioli    schedule 01.11.2010
comment
Предложение многообещающее, но оно не сработало. Не похоже, что SearchModel - это обычный селектор. - person Martin; 01.11.2010
comment
@Martin, я предположил, что это тег, используемый внутри xml. Можете ли вы опубликовать какой-нибудь контент из XML-файла? я опубликую альтернативные решения, используя метод map - person Gabriele Petrioli; 01.11.2010
comment
Спасибо, я обновил свой вопрос примером узла. - person Martin; 01.11.2010
comment
Спасибо, но это фактически ограничит источник данных XML и вернет только первые 10 результатов в файле XML. И это еще до того, как вы начнете поиски. XML-файл необходимо загрузить полностью. - person Martin; 01.11.2010
comment
@martin ... теперь я вижу свет ... оба моих случая (первый работает и в этом отношении) работают с исходными данными, а не с результатами после фильтрации автозаполнения ... ищу некоторые более .. - person Gabriele Petrioli; 01.11.2010
comment
Это решение, которое я искал, чем вы :) - person MarioRicalde; 04.05.2011

Почему бы не ограничить данные, которые ваш запрос возвращает из вашего источника xml?

Редактировать:

Вы должны помнить, что функция автозаполнения по существу использует регулярное выражение для сопоставления элементов в источнике данных. Наличие большого источника данных - это плохо, потому что ему приходится анализировать так много данных, чтобы просто найти правильный элемент.

person Achilles    schedule 01.11.2010
comment
Конечно, я бы с удовольствием это сделал, но как? Я искал варианты ограничений в jQuery .map() и .get(), но не нашел их, я вроде как застрял. - person Martin; 01.11.2010
comment
Уменьшите размер файла xml. Если вы не заинтересованы в отображении всех результатов, которые сопоставляются в файле, уменьшите размер файла (количество элементов в нем). - person Achilles; 01.11.2010
comment
Достаточно честно, но разве нет других способов сделать это без изменения файла XML? - person Martin; 01.11.2010
comment
@Martin, Ахиллес прав, зачем вам возвращать 100 записей xml, только чтобы показать 10. Имеет смысл ограничить до 10 на стороне генерации xml (mysql / sql / etc) - person Jakub; 01.11.2010
comment
Что ж, я получаю результаты от системы ERP, которая имеет медленную интеграцию. Поэтому вместо того, чтобы искать непосредственно в системе ERP, я делаю XML-файл кеша один раз в день. Этот файл cahce включает все продукты из системы ERP. И поиск в этом файле выполняется очень быстро, но поиск непосредственно в системе ERP очень медленный. - person Martin; 01.11.2010
comment
Нет, я понимаю ваш подход, проблема, с которой вы столкнулись, заключается в том, что 1. Производительность будет отстой, потому что данные оцениваются по регулярному выражению, чтобы найти каждый элемент, который соответствует. 2. Вы заставляете браузер обрабатывать данные, которые на самом деле не используются, и это не идеальный способ запроса к большому набору данных. - person Achilles; 01.11.2010

Это то, что я сделал на основе некоторого чтения документации API автозаполнения.

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

Следование этому шаблону избавляет от необходимости делать какие-либо забавные вещи в слое рендеринга.

person Paul Sheldrake    schedule 20.05.2014
comment
не имеет ли смысла ограничивать размер набора результатов на стороне сервера? например, с предложением LIMIT в запросе SQL? - person David; 11.11.2015
comment
Так было бы лучше, но у меня не было доступа к этому набору кода. - person Paul Sheldrake; 30.06.2016

Самый быстрый способ ограничить результаты - это сделать это во время «открытого» события. Мы можем удалить часть содержимого, динамически созданного jquery ui, уменьшив массив дочерних элементов.

Это решение решило ту же проблему для меня:

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

Вы можете добавить обработчик для события «open»:

    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]);
    }
person sorry    schedule 15.05.2012