Обнаружение отсутствия результатов при автозаполнении интерфейса jQuery

Прежде чем вы укажете мне на них, да, я просмотрел полдюжины сообщений на эту тему, но я все еще не понимаю, почему это не работает.

Моя цель - определить, когда автозаполнение дает 0 результатов. Вот код:

 $.ajax({
   url:'sample_list.foo2',
   type: 'get',
   success: function(data, textStatus, XMLHttpRequest) {
      var suggestions=data.split(",");

  $("#entitySearch").autocomplete({ 
    source: suggestions,
    minLength: 3,
    select: function(e, ui) {  
     entityAdd(ui.item.value);
     },
    open: function(e, ui) { 
     console.log($(".ui-autocomplete li").size());
     },
    search: function(e,ui) {
     console.log("search returned: " + $(".ui-autocomplete li").size());

    },
    close: function(e,ui) {  
     console.log("on close" +  $(".ui-autocomplete li").size());    
     $("#entitySearch").val("");
    }
   }); 

  $("#entitySearch").autocomplete("result", function(event, data) {

   if (!data) { alert('nothing found!'); }

  })
 }
}); 

Сам поиск работает нормально, я могу получить результаты без проблем. Насколько я понимаю, я должен иметь возможность перехватывать результаты с помощью обработчика автозаполнения ("результата"). В этом случае он никогда не срабатывает. (Даже общее предупреждение или console.log, которое не ссылается на количество результатов, никогда не срабатывает). Обработчик события open показывает правильное количество результатов (если они есть), а обработчики событий поиска и закрытия сообщают о размере результата, который всегда на один шаг позади.

Я чувствую, что упускаю что-то очевидное и бросаю в глаза, но просто не вижу этого.

88 голосов | спросил ScottyDont 18 Jam1000000amTue, 18 Jan 2011 02:21:05 +030011 2011, 02:21:05

8 ответов


0

jQueryUI 1.9

jQueryUI 1.9 благословил виджет автозаполнения событием response, которое мы можем использовать, чтобы обнаружить, если результаты не были возвращены:

  

Срабатывает после завершения поиска, до отображения меню. Полезно для локальных манипуляций с данными предложений, когда обратный вызов пользовательской опции источника не требуется. Это событие всегда вызывается при завершении поиска, даже если меню не будет отображаться, поскольку результатов нет или автозаполнение отключено.

Итак, с учетом этого взлом, который мы должны были сделать в jQueryUI 1.8, заменяется на:

$(function() {
    $("input").autocomplete({
        source: /* */,
        response: function(event, ui) {
            // ui.content is the array that's about to be sent to the response callback.
            if (ui.content.length === 0) {
                $("#empty-message").text("No results found");
            } else {
                $("#empty-message").empty();
            }
        }
    });
});​

Пример: http://jsfiddle.net/andrewwhitaker/x5q6Q/


jQueryUI 1.8

Я не смог найти простой способ сделать это с помощью jQueryUI API, однако вы могли бы заменить функцию autocomplete._response на own, а затем вызовите функцию jQueryUI по умолчанию ( обновлено для расширения объекта prototype объекта автозаполнения) :

var __response = $.ui.autocomplete.prototype._response;
$.ui.autocomplete.prototype._response = function(content) {
    __response.apply(this, [content]);
    this.element.trigger("autocompletesearchcomplete", [content]);
};

А затем привяжите обработчик события к событию autocompletesearchcomplete (содержимое - это результат поиска, массив):

$("input").bind("autocompletesearchcomplete", function(event, contents) {
    $("#results").html(contents.length);
});

Здесь происходит то, что вы сохраняете функцию response автозаполнения в переменную (__response), а затем с помощью apply , чтобы позвонить снова. Я не могу представить никаких побочных эффектов от этого метода, так как вы вызываете метод по умолчанию. Поскольку мы модифицируем прототип объекта, это будет работать для всех виджетов автозаполнения.

Вот рабочий пример : http://jsfiddle.net/andrewwhitaker/VEhyV /

Мой пример использует локальный массив в качестве источника данных, но я не думаю, что это должно иметь значение.


Обновление . Вы также можете обернуть новую функциональность в свой собственный виджет, расширяя функцию автозаполнения по умолчанию:

$.widget("ui.customautocomplete", $.extend({}, $.ui.autocomplete.prototype, {

  _response: function(contents){
      $.ui.autocomplete.prototype._response.apply(this, arguments);
      $(this.element).trigger("autocompletesearchcomplete", [contents]);
  }
}));

Изменение вашего звонка с .autocomplete({...}); на:

$("input").customautocomplete({..});

А затем привяжите к пользовательскому событию autocompletesearchcomplete позже:

$("input").bind("autocompletesearchcomplete", function(event, contents) {
    $("#results").html(contents.length);
});

См. пример здесь : http://jsfiddle.net/andrewwhitaker/VBTGJ /


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

var src = [...];

$("#auto").autocomplete({
    source: function (request, response) {
        var results = $.ui.autocomplete.filter(src, request.term);

        if (!results.length) {
            $("#no-results").text("No results found!");
        } else {
            $("#no-results").empty();
        }

        response(results);
    }
});

Внутри if вы разместите свою собственную логику для выполнения, когда результаты не обнаружены.

Пример: http://jsfiddle.net/qz29K/ р>

Если вы используете удаленный источник данных, скажите что-то вроде этого:

$("#auto").autocomplete({
    source: "my_remote_src"
});

Затем вам нужно изменить свой код, чтобы самому вызывать AJAX и определять, когда возвращается 0 результатов:

$("#auto").autocomplete({
    source: function (request, response) {
        $.ajax({
            url: "my_remote_src", 
            data: request,
            success: function (data) {
                response(data);
                if (data.length === 0) {
                    // Do logic for empty result.
                }
            },
            error: function () {
                response([]);
            }
        });
    }
});
ответил Andrew Whitaker 18 Jam1000000amTue, 18 Jan 2011 05:03:53 +030011 2011, 05:03:53
0

Кажется, что все игнорируют простой, встроенный способ: используйте событие messages: noResults.

$('#field_name').autocomplete({
  source: $('#field_name').data('autocomplete-source'),
  messages: {
    noResults: function(count) {
      console.log("There were no matches.")
    },
    results: function(count) {
      console.log("There were " + count + " matches")
    }
  }
})

Эта функция была добавлена ​​в jQuery 1.9 как экспериментальная ( описан здесь ). По состоянию на июль 2017 года он еще не документирован в API .

ответил Mike Bethany 15 J000000Wednesday15 2015, 19:10:01
0

Если вы используете удаленный источник данных (например, базу данных MySQL, PHP или любой другой на стороне сервера) есть несколько других более чистых способов справиться с ситуацией, когда нет данных для возврата клиенту (без необходимости каких-либо хаков или изменений кода пользовательского кода ядра).

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

if (preg_match("/^[a-zA-Z0-9_]*$/", $_GET['callback'])) {//sanitize callback name
    $callback = $_GET['callback'];
} else { die(); }

die($callback . "([])");

Другим способом было бы вернуть флаг в ответе от сервера, чтобы указать, что нет соответствующих данных, и выполнить действия на стороне клиента на основе наличия (и /или значения) флага в ответе. В этом случае ответ сервера будет примерно таким:

die($callback . "([{'nodata':true}])");

Затем на основании этого флага могут быть выполнены действия на стороне клиента:

$.getJSON('response.php?callback=?', request, function (response) {
    if (typeof response[0].nodata !== 'undefined' && response[0].nodata === true) {
        alert('No data to display!');
    } else {
        //Do whatever needs to be done in the event that there is actually data to display.
    }
});
ответил Zappa 31 Jam1000000amTue, 31 Jan 2012 03:50:33 +040012 2012, 03:50:33
0

После инициализации элемента автозаполнения установите параметр сообщений, если вы хотите использовать диапазоны по умолчанию для индикации сообщений:

$(<yourselector>).autocomplete('option', 'messages', {
    noResults: 'myKewlMessage',
    results: function( amount ) {
        return amount + ( amount > 1 ? " results were" : " result was" ) + " found.";
    }
});

ПРИМЕЧАНИЕ . Это экспериментальный API (не задокументирован). Разработчики пользовательского интерфейса jQuery все еще изучают полное решение для работы со строками и интернационализации.

ответил Guntram 27 Maypm14 2014, 12:39:48
0

После нескольких часов игры я наконец нашел способ показать No match found в автозаполнении jQuery. Посмотрите на приведенный выше код и просто добавьте div, в моем случае #ulNoMatch и его стиль установлен в displap:none. В методе успеха обратного вызова проверьте, имеет ли возвращенный массив length == 0. Если это там, вы идете, вы сделали свой день! :)

<pre><div class="ui-widget1" style="width: auto;">
    <asp:TextBox ID="txtSearch" class="tb" runat="server" Width="150px">
    </asp:TextBox>
    <ul id="ulNoMatch" class="ui-autocomplete ui-menu ui-widget1 ui-widget1-content ui-corner-all"
        role="listbox" aria-activedescendant="ui-active-menuitem" style="z-index: 16;
        display: none; width: 150px;">
        <li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">No Matches
            Found</a></li>
    </ul>
    </div><pre>
<b>
<b>

Enter code here

<script>
    $(function () {
        $("input[id$='txtSearch']").autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: "splah.aspx/GetByName",
                    data: "{ 'strName': '" + request.term.trim() + "' }",
                    dataType: "json",
                    type: "POST",
                    //cacheLength: 1,
                    contentType: "application/json; charset=utf-8",
                    dataFilter: function (data) {
                        return data; },
                    success: function (data) {
                        var found = $.map(data.d, function (item) {
                            return {
                                value: item.Name,
                                id: item.id
                            }
                         });

                         if (found.length == 0)
                         {
                             $("#ulNoMatch").show();
                         }
                         else
                         {
                             $("#ulNoMatch").hide();
                         }
                         response(found);
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            },
            select: function (event, ui) {
                $("input[id$='txtSearch']").val(ui.item.label);
                $("input[id$='txtID']").val(ui.item.id);
                return false;
            },
            minLength: 1
        });
    });
</script>
ответил Umar Malik 29 Maypm12 2012, 18:17:42
0

Я не понимаю, почему для параметра source с пользовательским обратным вызовом недостаточно :

$("#autocomplete").autocomplete({
    source: function (request, response) {
        $.ajax({
            url: "http://example.com/service.json",
            data: {
                q: this.term
            },
            success: function (data, textStatus, jqXHR) {
                // data would be an array containing 0 or more items
                console.log("[SUCCESS] search returned " + data.length + " item(s)");
                response(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // triggered when AJAX failed because of, for example, malformed JSON
                console.log("[FAILURE] search returned error");
                response([]);
            }
        });
    }
});
ответил Salman A 2 MonEurope/Moscow2013-12-02T14:00:40+04:00Europe/Moscow12bEurope/MoscowMon, 02 Dec 2013 14:00:40 +0400 2013, 14:00:40
0
function SearchText() {
 $(".autosuggest").autocomplete({
   source: function (request, response) {
    $.ajax({
     type: "POST",
     contentType: "application/json; charset=utf-8",
      url: "Default.aspx/GetAutoCompleteData",
      data: "{'username':'" + document.getElementById('txtSearch').value + "'}",
        dataType: "json",
        success: function (data.d) {
        if ((data.d).length == 0) {
         alert("no result found");
          }
           response(data.d);
         },
         error: function (result) {
              alert("Error");
         }
         });
        }
     });
  }
ответил selvin john 27 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 27 Sep 2013 15:34:52 +0400 2013, 15:34:52
0
The easiest straight forward way to do it.

$("#search-box").autocomplete({
                    minLength: 2,
                    source:function (request, response) {
                        $.ajax({
                            url: urlPref + "/Api/SearchItems",
                            data: {
                                term: request.term
                            },
                            success: function (data) {
                                if (data.length == 0) {
                                    data.push({
                                        Id: 0,
                                        Title: "No results found"
                                    });
                                }
                                response(data);
                            }
                            });
                        },
ответил Bishoy Hanna 9 Jam1000000amThu, 09 Jan 2014 09:21:05 +040014 2014, 09:21:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132