2015-08-09 3 views
2

Я испытываю странный образец в моем текущем проекте. Я попытался найти SO и Google, однако я не уверен, что именно искать. Подводя итог моей проблеме:Странный шаблон события щелчка с полем ввода и неупорядоченным списком

Я создал репликацию JSFiddle here. Я испытал следующее поведение в (Windows) Chrome, Waterfox и Edge. В принципе, у меня есть текстовый ввод, который служит в качестве поля поиска. Когда изменяется значение ввода, выполняется поиск базы данных и добавляются действительные ответы в виде элементов списка в неупорядоченный список. В скрипте бэкэнд базы данных заменяется массивом.

При вводе изменений весь список очищается, а затем пополняется на основе поискового запроса. Проблема возникает, когда я использую список как «меню» - я слушаю событие click на каждом ли. Когда я ввожу что-то в поле, затем щелкните элемент списка, событие click не запускается. Когда я снова нажимаю элемент списка, клик запускается с, и каждый щелчок после этого работает (пока я не введу другой запрос). Вот странная часть: после того, как были вызваны события клика для определенного поискового запроса, если я очистил ввод и снова набрал тот же запрос, элементы списка мгновенно кликаются, хотя они только что были очищены и восстановлены.

Чтобы повторить такое поведение:

  1. Enter «мы» на вход
  2. Нажмите один из результатов один раз (ничего не печатается на консоль)
  3. Click один из вновь результатов (Clicked! печатается на консоль)
  4. Очистить ввод и ввести что-то еще, но не нажимайте никаких результатов
  5. Очистить ввод и ввести «ma» снова
  6. Нажмите один из результатов. Он должен быть немедленно интерактивным
  7. Ввода другого запроса будет сделать результаты не сразу «интерактивные»

Я делаю сравнение без учета регистра с поисковым запросом, но набрав «Мы» (или «MA» или «мА») на шаге 5 не приведет к мгновенным нажатиям результатов.

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

  1. Почему событие click не запускается в первый раз (для «нового» запроса)? Я предполагаю, что это связано с потерей фокуса ввода.
  2. Почему событие click срабатывает мгновенно, когда запрос, который стал последним кликабельным, вводится даже после того, как неупорядоченный список несколько раз очищается и повторно заполняется?

Кроме того, есть ли что-то иное, чем неупорядоченные списки, которые я должен использовать, чтобы предоставить список интерактивных результатов поиска?

Заранее благодарен!

По просьбе редактора сообщений о переполнении стека, вот это код репликации:

HTML:

<body> 
    <form> 
     <input type="text" id="text-input" /> 
    </form> 
    <ul id="results-list"> 
    </ul> 
</body> 

JS:

var entries = ["Jason Stewart", "George Bacon", "Martha Stewart", "Cliff Mandarin", "Luke Barnes", "Spandex Assassin"]; 

$(function() { 
    $("#text-input").on("keyup change", function() { 
     $("#results-list").html(""); 
     if ($(this).val().length <= 0) { 
      return; 
     } 
     var query = $(this).val().toUpperCase(); 
     for (var i = 0; i < entries.length; i++) { 
      var entry = entries[i]; 
      if (entry.toUpperCase().indexOf(query) >= 0) { 
       $("#results-list").html($("#results-list").html() + "<li>" + entry + "</li>"); 
      } 
     } 
    }); 

    $("#results-list").on("click", "li", function(evt) { 
     console.log("Clicked!"); 
    }); 

}); 

ответ

3

Почему событие щелчка не запускаться в первый раз (для «нового» запроса)? Я предполагаю, что это связано с потерей фокуса ввода.

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

Почему событие click активируется мгновенно, когда запрос, который стал последним кликабельным, вводится даже после того, как неупорядоченный список несколько раз очищается и повторно заполняется?

Потому что change не срабатывает в этом случае; значение не изменилось.

Вы можете исправить это, просто вспомнив последнее обработанное значение и не заменив список, если он не изменился. Таким образом, то keyup обновляет список и change не: Updated Fiddle

var entries = ["Jason Stewart", "George Bacon", "Martha Stewart", "Cliff Mandarin", "Luke Barnes", "Spandex Assassin"]; 

$(function() { 
    var lastValue = undefined;       // ** 
    $("#text-input").on("keyup change", function() { 
     var thisValue = $(this).val();     // ** 
     if (lastValue == thisValue) {     // ** 
      return;         // ** 
     }            // ** 
     lastValue = thisValue;       // ** 
     $("#results-list").html(""); 
     if (thisValue.length <= 0) {     // ** 
      return; 
     } 
     var query = $(this).val().toUpperCase(); 
     for (var i = 0; i < entries.length; i++) { 
      var entry = entries[i]; 
      if (entry.toUpperCase().indexOf(query) >= 0) { 
       $("#results-list").html($("#results-list").html() + "<li>" + entry + "</li>"); 
      } 
     } 
    }); 

    $("#results-list").on("click", "li", function(evt) { 
     console.log("Clicked!"); 
    }); 

}); 

Вы также можете добавить input и paste события в списке событий.


Если вы хотите, чтобы получить лучшее понимание того, почему это происходит, добавив название события к элементам при заполнении их могут помочь: Просто обновить оригинальную скрипку (не мое исправление выше), чтобы принять e аргумент функции обработчика и изменить строку, добавив элемент списка включить e.type в тексте: Example

$("#results-list").html($("#results-list").html() + "<li>" + entry + " [" + e.type + "]</li>"); 

Если вы наберете ma, вы увидите keyup, но при попытке нажать кнопку, вы увидите записи заменены на change объявление.

Смежные вопросы