Как задержать обработчик .keyup(), пока пользователь не перестанет вводить текст?
У меня есть поле для поиска. В текущей реализации поиск выполняется при каждом событии keyup
. Таким образом, если пользователь вводит "Windows", то AJAX-поиск отправляется на каждом этапе ввода: "W", "Wi", "Win", "Wind", "Windo", "Window", "Windows".
Я хочу добавить задержку, чтобы поиск выполнялся только в том случае, если пользователь перестал вводить текст на 200 мс.
В функции keyup
нет возможности реализовать это поведение, и я уже пробовал использовать setTimeout
, но это не сработало.
Как я могу решить эту задачу?
5 ответ(ов)
Если вы хотите осуществить поиск после завершения ввода, используйте глобальную переменную для хранения идентификатора таймера, возвращаемого вашим вызовом setTimeout
, и отменяйте его с помощью clearTimeout
, если это ещё не произошло. Это гарантирует, что таймер сработает только по последнему событию keyup
.
Вот пример кода:
var globalTimeout = null;
$('#id').keyup(function(){
if(globalTimeout != null) clearTimeout(globalTimeout);
globalTimeout = setTimeout(SearchFunc, 200);
});
function SearchFunc(){
globalTimeout = null;
// AJAX код
}
Также можно использовать анонимную функцию:
var globalTimeout = null;
$('#id').keyup(function() {
if (globalTimeout != null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function() {
globalTimeout = null;
// AJAX код
}, 200);
});
В этом коде мы устанавливаем таймер, который запускает функцию поиска через 200 миллисекунд после последнего ввода. Если пользователь продолжает вводить текст, таймер сбрасывается, и поиск не выполняется до тех пор, пока не пройдет 200 миллисекунд с момента последнего нажатия клавиши.
Вот небольшое улучшение ответа CMS. Чтобы упростить использование различных задержек, вы можете воспользоваться следующим кодом:
function makeDelay(ms) {
var timer = 0;
return function(callback){
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
};
Если вы хотите использовать одно и то же значение задержки, просто сделайте так:
var delay = makeDelay(250);
$(selector1).on('keyup', function() { delay(someCallback); });
$(selector2).on('keyup', function() { delay(someCallback); });
Если же вам нужны разные задержки, вы можете сделать так:
$(selector1).on('keyup', function() { makeDelay(250)(someCallback); });
$(selector2).on('keyup', function() { makeDelay(250)(someCallback); });
Таким образом, вы можете легко управлять задержками в зависимости от ваших потребностей.
Для реализации функционала, аналогичного приведенному коду на jQuery, с использованием чистого JavaScript, вы можете использовать следующий пример.
Пример с jQuery
var timeout = null;
$('#input').keyup(function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
console.log($(this).val());
}, 1000);
});
Здесь мы создаем переменную timeout
, которая будет использоваться для задержки. При каждом срабатывании события keyup
мы очищаем предыдущий таймер и устанавливаем новый, который выполнит вывод значения через 1 секунду после последнего нажатия клавиши.
Пример с чистым JavaScript
let input = document.getElementById('input');
let timeout = null;
input.addEventListener('keyup', function (e) {
clearTimeout(timeout);
timeout = setTimeout(function () {
console.log('Value:', input.value);
}, 1000);
});
В этом примере мы делаем то же самое, но используем методы чистого JavaScript. Мы получаем элемент input
по его ID, а затем добавляем обработчик события keyup
. Как и в случае с jQuery, мы очищаем таймер и устанавливаем новый задержанный вывод значения через 1 секунду.
HTML
<input type="text" id="input" placeholder="Type here..."/>
Используйте данный HTML-код, чтобы дополнить оба примера. Это обеспечит правильный вывод значения, введенного в текстовое поле.
Это решение основано на ответе из CMS. Я сделал следующее:
Вставьте приведенный ниже код после подключения jQuery:
/*
* delayKeyup
* http://code.azerti.net/javascript/jquery/delaykeyup.htm
* Вдохновлено CMS в этом посте: http://stackoverflow.com/questions/1909441/jquery-keyup-delay
* Написано Gaten
* Пример: $("#input").delayKeyup(function(){ alert("5 секунд прошло с последнего события keyup."); }, 5000);
*/
(function ($) {
$.fn.delayKeyup = function(callback, ms){
var timer = 0;
$(this).keyup(function(){
clearTimeout(timer);
timer = setTimeout(callback, ms);
});
return $(this);
};
})(jQuery);
И просто используйте его следующим образом:
$('#input').delayKeyup(function(){ alert("5 секунд прошло с последнего события keyup."); }, 5000);
Внимание: переменная $(this)
в функции, переданной в качестве параметра, не соответствует элементу ввода.
Задержка многократных вызовов функций с помощью меток
Вот решение, которое я разработал. Оно позволяет задерживать выполнение любой функции, которую вы хотите. Это может быть вызов при нажатии на клавишу для поиска, или же быстрый клик на кнопки "предыдущий" или "следующий" (которые в противном случае могут отправлять несколько запросов при быстром непрерывном нажатии и в итоге не использоваться). Этот код использует глобальный объект, который хранит время каждого вызова функции и сравнивает его с последним запросом.
В результате только последний клик/действие на самом деле будет вызвано, потому что эти запросы сохраняются в очереди, которую после X миллисекунд вызовут, если в очереди не существует другого запроса с той же меткой!
function delay_method(label, callback, time) {
if (typeof window.delayed_methods == "undefined") {
window.delayed_methods = {};
}
delayed_methods[label] = Date.now();
var t = delayed_methods[label];
setTimeout(function() {
if (delayed_methods[label] != t) {
return;
} else {
delayed_methods[label] = "";
callback();
}
}, time || 500);
}
Вы можете установить собственное время задержки (это необязательно, по умолчанию 500 мс). И передавать аргументы вашей функции в формате "замыкания".
Например, если вы хотите вызвать следующую функцию:
function send_ajax(id) {
console.log(id);
}
Чтобы предотвратить множественные вызовы send_ajax
, вы задерживаете их с помощью:
delay_method("check date", function() { send_ajax(2); }, 600);
Каждый запрос, использующий метку "check date", будет запущен только если не будет сделан другой запрос в течение 600 миллисекунд. Этот аргумент является необязательным.
Независимость меток (вызов одной и той же целевой функции), но с независимыми задержками:
delay_method("check date parallel", function() { send_ajax(2); });
delay_method("check date", function() { send_ajax(2); });
Это приведет к вызову одной и той же функции, но задержки будут независимыми благодаря разным меткам.
Как перенаправить на другую веб-страницу?
Прокрутка к элементу с использованием jQuery
jQuery: Получение Выбранного Значения Из Выпадающего Списка
Существует ли ссылка на "последнюю" библиотеку jQuery в Google APIs?
Потеряно HTML-кодирование при чтении атрибута из поля ввода