Как вызвать событие onkeyup, которое задерживается до тех пор, пока пользователь не остановит их ввод?

У меня есть текстовое поле, где люди вводят какой-то текст (естественно), и я хочу сделать так, чтобы запрос AJAX делался время от времени, чтобы получить некоторые предложения относительно того, что такое textarea (например, переполнение стека) но для текстового поля, а не для ввода текста). Проблема в том, что я не могу выполнить запрос AJAX на каждом нажатии клавиши (это было бы бесполезно и очень ресурсоемким), и я не уверен, что было бы самым эффективным способом сделать это (каждые X слов? Каждые X секунд? или что-то еще?).

Каким будет лучший способ сделать это?

Спасибо заранее.

Ответ 1

Вы можете объединить обработчик событий keypress с setTimeout, чтобы вы отправили Ajax-запрос определенное количество времени после нажатия клавиши, отмены и перезапуска таймера, если другое нажатие клавиши происходит до окончания таймера. Предполагая, что у вас есть текстовое поле с id 'myTextArea' и функция обратного вызова Ajax, называемая doAjaxStuff:

function addTextAreaCallback(textArea, callback, delay) {
    var timer = null;
    textArea.onkeypress = function() {
        if (timer) {
            window.clearTimeout(timer);
        }
        timer = window.setTimeout( function() {
            timer = null;
            callback();
        }, delay );
    };
    textArea = null;
}

addTextAreaCallback( document.getElementById("myTextArea"), doAjaxStuff, 1000 );

Ответ 2

Другой альтернативой является использование небольшого плагина jQuery под названием bindWithDelay. Он использует тот же метод setTimeout, что и принятый ответ, но прозрачно обрабатывает таймауты, поэтому ваш код немного легче читать. Исходный код можно увидеть на github.

$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)

Ответ 3

То, что вы ищете, называется debouncing. Вот общий алгоритм в языке JavaScript:

function debounce(fn, duration) {
  var timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(fn, duration)
  }
}

И вот пример того, как использовать его с событием onkeyup:

function debounce(fn, duration) {
  var timer;
  return function(){
    clearTimeout(timer);
    timer = setTimeout(fn, duration);
  }
}

$(function(){
  
  $('#txtSearch').on('keyup', debounce(function(){
  
    alert('You paused your typing!');
    
  }, 500));
  
});
input{
  padding:.5em;
  font-size:16px;
  width:20em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="txtSearch" placeholder="Type here" />

Ответ 4

Если вы используете underscore.js, вы можете использовать функцию debounce.

Пример (jQuery, используемый для keyup):

$('#myTextArea').keyup(_.debounce(function(){
    alert('hello');
}, 500));

Ответ 5

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

Ответ 6

Если вас интересуют решения jQuery, jQuery Suggest является хорошей реализацией.

Нет смысла изобретать колесо каждый раз.

Ответ 7

Если вы используете эту функцию много вокруг сайта и не хотите отслеживать все ссылки setTimeout и т.д., тогда я упаковал это в плагин, доступный .

Плагин добавляет несколько параметров в обычный метод $.ajax для буферизации и отмены предыдущих вызовов ajax.