Автозаполнение jQuery

У меня есть текстовое поле автозаполнения, которое должно отвечать на 2 события:

  • Когда пользователь набирает что-то в текстовом поле (в настоящее время я использую focusout, чтобы предположить, когда пользователь закончил ввод текста. Таким образом, если пользователь выходит из текстового поля, это означает, что пользователь выполнен типирование.)
  • Когда пользователь выбирает элемент в списке автозаполнения значений (я использую событие autocomplete select, чтобы определить это)

Проблема:

Когда пользователь выбирает элемент в списке значений автозаполнения, цепочка событий такова, что сначала вызывается focusout, затем select. Когда в focusout, у меня есть только доступ к тому, что пользователь вводил, а не то, что пользователь выбрал из списка автозаполнения значений, - и того, что мне действительно нужно. Как решить эту проблему?

Шаги по воспроизведению проблемы:

  • В текстовом поле введите букву a
  • Выберите ActionScript из списка автозаполнения значений
  • Соблюдайте сообщения console.debug:

    focusout event called
    a
    select event called
    ActionScript
    

Здесь код:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <link href="#" onclick="location.href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css'; return false;" rel="stylesheet" type="text/css"/>
        <title>Data Matching</title>
    </head>
    <body>
        <form>
            <input id="1" type="text"></input>
            <input id="2" type="submit"></input>
        </form>

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

        <script>
        $('#1').autocomplete(
        {
            select: function (event, ui)
            {
                "use strict";
                console.debug('select event called');
                console.debug(ui.item.value);
            },
            source: ["ActionScript", "AppleScript", "Asp", "BASIC", "C", "C++", "Clojure", "COBOL", "ColdFusion", "Erlang", "Fortran", "Groovy", "Haskell", "Java", "JavaScript", "Lisp", "Perl", "PHP", "Python", "Ruby", "Scala", "Scheme"],

            minLength: 1
        });

        $('#1').focusout(function ()
        {
            "use strict";
            console.debug('focusout event called');
            console.debug($(this).attr('value')); //  At this point, I need the value that was selected from autocomplete. I only get the value that the user typed, though
        });
        </script>
    </body>
</html>

Ответ 1

Именно поэтому jQueryUI внедрил специальное событие change для autocomplete:

Запущено, когда поле размыто, если значение изменилось; ui.item относится к выбранному элементу.

Это событие может выполнять двойную работу для обоих ваших требований:

$("#1").autocomplete({
    /* snip */
    change: function(event, ui) {
        if (ui.item) {
            console.log("ui.item.value: " + ui.item.value);
        } else {
            console.log("ui.item.value is null");
        }
        console.log("this.value: " + this.value);
    }
});
  • ui.item не будет определяться, когда пользователь не выберет значение из списка кандидатов автозаполнения.
  • С другой стороны, this.value всегда будет правильным.

Вот пример: http://jsfiddle.net/33GJb/

Ответ 2

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

Один: создайте приложение, чтобы несколько значений, выбранных пользователем (тип или выбранный), не мешали. Например, если приложение выполняет автоматическое исправление орфографии, а кто-то набрал "orphanag" при фокусировке, код, который искал ближайшую орфографию, заменил бы значение "приютом для сиротства", чем если бы кто-то действительно выбрал "детские дома", он заменил бы значение с выбранным значением. Там, скорее всего, здесь не проблема, кроме стремления к оптимизации.

Два: есть помеченное значение либо в Javascript, либо в Html Element ( "data-corrected = false" ), который существует. На FocusOut установите SetTimeout для ожидания продолжительности времени. Затем, если пользователи выбрали значение, установите значение флага равным true. Когда продолжительность увеличивается, проверьте отмеченное значение, если оно истинно, ничего не делайте, иначе используйте значение в поле ввода для чего-то.