Автозаполнение jQuery проверяет выбранное значение

Мы используем подключаемый модуль автозаполнения jQuery, написанный Jörn Zaefferer, и пытаемся проверить допустимый вариант. вводится.

Плагин имеет событие result(), которое срабатывает при выборе. Это нормально, но мне нужно проверить значение в текстовом поле, когда пользователь также щелкает. Итак, мы попробовали события .change() и .blur(), но оба они создают проблему: когда вы нажимаете на запись в div результатов (список «предложить»), .change() и .blur() события срабатывают, и это происходит до того, как плагин запишет значение в текстовое поле, поэтому на этом этапе проверять нечего.

Может ли кто-нибудь помочь мне настроить события, чтобы всякий раз, когда кто-то щелкает мышью, но не в поле результатов, я мог проверить действительное значение в поле. Если это неправильный подход, сообщите мне о правильном. Изначально мы выбрали этот плагин из-за его опции «mustMatch». Этот вариант работает не во всех случаях. Много раз действительная запись будет записана в текстовое поле, а затем очищена плагином как недействительная, я не смог определить, почему.

Пример основного кода:

<html>
<head>
<title>Choose Favorite</title>
<script language="JavaScript" src="jquery-1.3.2.min.js" ></script>
<script language="JavaScript" src="jquery.autocomplete.min.js" ></script>
<script>
    $(".suggest").autocomplete("fetchNames.asp", {
        matchContains:false,
        minChars:1, 
        autoFill:false,
        mustMatch:false,
        cacheLength:20,
        max:20
    });

    $(".suggest").result(function(event, data, formatted) {
        var u = this;
        // Check value here

    });

    /* OR */

    $(".suggest").change(function(me) {
        //check value here
    });

</script>
</head>
<body>
    <label for="tbxName">Select name (I show 10):</label><br />
    <INPUT type="text" id="tbxName" name="tbxName" class="suggest"><br />
</body>
</html>

person Brettski    schedule 28.04.2009    source источник
comment
Я нашел здесь лучший ответ Виктора stackoverflow.com/questions/4952094/   -  person dis.iz.peez    schedule 04.11.2011
comment
Это достойное решение. Я должен буду попробовать это в следующий раз, когда мне понадобится эта функция.   -  person Brettski    schedule 04.11.2011
comment
см. это: stackoverflow.com/questions/1267149/   -  person    schedule 08.03.2012


Ответы (4)


Я думаю, что вместо того, чтобы писать собственную функцию для проверки совпадения данных, вы можете просто вызвать search(). Если result() вызывается с нулевым параметром data, то вы знаете, что автозаполнение не использовалось, и, вызывая search() при размытии, вы гарантированно вызовете result() хотя бы один раз.

Я разместил этот код для аналогичного вопроса, это может помочь и здесь.

autocompleteField.result(function(event, data, formatted) {
    if (data) {
        //auto-complete matched
        //NB: this might get called twice, but that's okay
    }
    else {
        //must have been triggered by search() below
        //there was no match
    }
});

autocompleteField.blur(function(){
    autocompleteField.search(); //trigger result() on blur, even if autocomplete wasn't used
});
person npdoty    schedule 16.10.2009
comment
Хороший ответ! Может быть, вы знаете, как предотвратить двойное срабатывание события результата? Это проблема, если это событие выполняет какую-то сложную логику, например, проверяет ввод на сервере через запрос ajax. - person Kamarey; 06.11.2009
comment
Если вы выполняете много операций в .result(), вы можете попытаться сохранить флаг, чтобы увидеть, была ли уже вызвана ваша ветвь if (data). Я могу предупредить вас, что это будет нетривиально: вы можете легко установить флаг в конце if (data), но вам нужно будет снять его в тех случаях, когда пользователь редактирует автозаполненное предложение. Я бы попробовал использовать .change() для этого. Удачи! - person npdoty; 06.11.2009

ОБНОВЛЕНИЕ: это должно работать. Я загружаю список имен в массив с именем ListOfNames, он используется в событии onBlur() для проверки введенного имени по данным. Возможно, вам придется сделать некоторые настройки, но я думаю, что он должен делать то, что вы ищете.

var listOfNames = [];
$(document).ready(function(){
   $.get("fetchNames.asp", function(data){
     listOfNames = data.split("\r\n");    
   });
   $(".suggest").autocomplete("fetchNames.asp", {
        matchContains:false,
        minChars:1, 
        autoFill:false,
        mustMatch:false,
        cacheLength:20,
        max:20
    });
    $("#tbxName").blur(function(){
        if(!listOfNames.containsCaseInsensitive(this.value)){
          alert("Invalid name entered");
        }
    });        
});

Array.prototype.containsCaseInsensitive = function(obj) {
  var i = this.length;
  while (i--) {
    if (this[i].toUpperCase() === obj.toUpperCase()) {
      return true;
    }
  }
  return false;
}
person Jose Basilio    schedule 28.04.2009
comment
Благодарю за ваш ответ. Это не совсем так. Если я выберу значение, оно заполнится правильно, как только я щелкну его, появятся ошибки, недействительные. Если я ввожу пару символов, а затем нажимаю кнопку, ошибка не возникает, хотя мне нужно добавить проверку базы данных. - person Brettski; 28.04.2009
comment
Что запускается первым, .blur() или .change()? - person Brettski; 28.04.2009
comment
Еще раз спасибо за ваш ответ. Возможные имена, которые могут вернуться из fetchnames.asp, составляют 32 000, не уверен, что хочу хранить все эти данные в массиве. Хотя подход мне нравится - person Brettski; 29.04.2009
comment
В этом случае правильный подход состоял бы в том, чтобы ваш файл fetchNames.asp принимал параметр строки запроса, равный имени для проверки. Пример: searchNames.asp?name=John .... вернуть имя, если оно найдено, иначе пустую строку. Это можно добавить в событие onBlur(). Имеет ли это смысл? - person Jose Basilio; 29.04.2009
comment
this.value события .blur() будет содержать только элементы, которые я ввел в поле, а не элемент, который я пытаюсь выбрать. Так никогда не совпадет. Я ввожу текст в текстовое поле и получаю свои предложения, как только я нажимаю, чтобы выбрать один, срабатывает .blur(), но событие щелчка для записи значения в текстовое поле еще не произошло. Имеет ли это смысл? - person Brettski; 29.04.2009
comment
@Brettski - я думаю, что с таким подходом это может быть даже невозможно. Вот аналогичный пост: stackoverflow.com/questions/328430/ - person Jose Basilio; 29.04.2009
comment
Однако, если в форме есть другие поля ввода, вы можете активировать проверку, когда пользователь вводит другое поле ввода. Хотя это и не идеально, это может быть единственным способом. - person Jose Basilio; 29.04.2009

Это код, который я использовал в прошлом. Очень чистый и простой.

var availableTags = [
  "ActionScript",
  "AppleScript",
  "Asp",
  "BASIC",
  "C",
  "C++",
  "Clojure",
  "COBOL",
  "ColdFusion",
  "Erlang",
  "Fortran",
  "Groovy",
  "Haskell",
  "Java",
  "JavaScript",
  "Lisp",
  "Perl",
  "PHP",
  "Python",
  "Ruby",
  "Scala",
  "Scheme"
];
$( "#currentSelectedLevel" ).autocomplete({
  source: availableTags,
  change: function( event, ui ) {
        val = $(this).val();
        exists = $.inArray(val,availableTags);
        if (exists<0) {
          $(this).val("");
          return false;
        }
      }
});
person JoBaxter    schedule 11.04.2016
comment
Самое чистое решение на сегодняшний день. Обратите внимание, что вы должны убедиться, что val пишется с заглавной буквы в соответствии с вашим источником данных, иначе он не будет совпадать. Например. actionscript не то же самое, что ActionScript. - person Optimae; 05.08.2017

Я использую глобальную структуру данных для отслеживания найденных значений.

var ac_sent = {};

обработчик события .result() вызывается перед обработчиком события .change(), поэтому в .result(event, data, formatted) я добавляю данные в структуру:

ac_sent[ data ] = true;

затем в обработчике событий .change(event) я проверяю, есть ли элемент в ac_sent[data], и если его нет, я знаю, что слово не найдено:

$( "#textbox" ).change( function( event ) {

  var data = event.target.value;

  if ( !ac_sent[ data ] ) {
    // result was not found in autocomplete, do something...
    ac_sent[ data ] = true;  // remember that we processed it
  }

  return false;
});
person Jay    schedule 29.01.2010
comment
Событие result(), инициированное перед событием change(), не является точным на 100%. Это происходит в таком порядке, если клавиша Enter используется для выбора элемента из списка. Однако, если используется мышь, то порядок событий меняется на противоположный — сначала происходит change(), а затем результат(). - person Jason; 27.03.2010