7

Как задержать обработчик .keyup(), пока пользователь не перестанет вводить текст?

1

У меня есть поле для поиска. В текущей реализации поиск выполняется при каждом событии keyup. Таким образом, если пользователь вводит "Windows", то AJAX-поиск отправляется на каждом этапе ввода: "W", "Wi", "Win", "Wind", "Windo", "Window", "Windows".

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

В функции keyup нет возможности реализовать это поведение, и я уже пробовал использовать setTimeout, но это не сработало.

Как я могу решить эту задачу?

5 ответ(ов)

0

Если вы хотите осуществить поиск после завершения ввода, используйте глобальную переменную для хранения идентификатора таймера, возвращаемого вашим вызовом 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 миллисекунд с момента последнего нажатия клавиши.

0

Вот небольшое улучшение ответа 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); });

Таким образом, вы можете легко управлять задержками в зависимости от ваших потребностей.

0

Для реализации функционала, аналогичного приведенному коду на 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-код, чтобы дополнить оба примера. Это обеспечит правильный вывод значения, введенного в текстовое поле.

0

Это решение основано на ответе из 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) в функции, переданной в качестве параметра, не соответствует элементу ввода.

0

Задержка многократных вызовов функций с помощью меток

Вот решение, которое я разработал. Оно позволяет задерживать выполнение любой функции, которую вы хотите. Это может быть вызов при нажатии на клавишу для поиска, или же быстрый клик на кнопки "предыдущий" или "следующий" (которые в противном случае могут отправлять несколько запросов при быстром непрерывном нажатии и в итоге не использоваться). Этот код использует глобальный объект, который хранит время каждого вызова функции и сравнивает его с последним запросом.

В результате только последний клик/действие на самом деле будет вызвано, потому что эти запросы сохраняются в очереди, которую после 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); });

Это приведет к вызову одной и той же функции, но задержки будут независимыми благодаря разным меткам.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь