6

Запуск функции JavaScript после завершения ввода пользователем, а не при отпускании клавиши?

1

Я хочу выполнить AJAX-запрос, когда пользователь завершит ввод в текстовом поле. Необходимо, чтобы функция не срабатывала при каждом введенном символе, так как это приведет к большому количеству AJAX-запросов, но и не хочу, чтобы пользователю приходилось нажимать кнопку "Enter" для этого.

Есть ли способ определить, когда пользователь завершил ввод, и затем выполнить AJAX-запрос?

Я использую jQuery.

5 ответ(ов)

8

Да, ваше предположение о том, что "завершение ввода" означает кратковременную паузу (например, 5 секунд), вполне верно. При этом мы можем установить таймер, когда пользователь отпускает клавишу, и сбросить его при нажатии клавиши. В примере ниже ввод, о котором идет речь, обозначен как #myInput.

Делаем несколько предположений...

// Инициализация переменных перед функциями
var typingTimer;                // идентификатор таймера
var doneTypingInterval = 5000;  // время в миллисекундах, например 5 секунд
var $input = $('#myInput');

// При отпускании клавиши запускаем обратный отсчет
$input.on('keyup', function () {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

// При нажатии клавиши сбрасываем обратный отсчет
$input.on('keydown', function () {
  clearTimeout(typingTimer);
});

// Пользователь "завершил ввод", выполняем нужное действие
function doneTyping () {
  // выполняем нужное действие
}

Таким образом, данный пример кода устанавливает таймер на 5 секунд после последнего ввода пользователя. Если пользователь начнет вводить текст снова (нажмет клавишу), таймер сбрасывается, и процесс начинается заново. Когда пользователь останавливается на 5 секунд, выполняется функция doneTyping, где можно реализовать необходимое действие.

4

Ответ, выбранный выше, не работает.

Проблема в том, что typingTimer иногда устанавливается несколько раз (например, если пользователь быстро нажимает клавиши — несколько раз keyup происходит до того, как сработает keydown), из-за чего таймер неправильно очищается.

Предложенное ниже решение устраняет эту проблему и вызывает функцию doneTyping через X секунд после окончания ввода, как и запрашивалось автором вопроса. Также больше не требуется излишняя функция keydown. Я добавил проверку, чтобы ваша функция не вызывалась в случае, если поле ввода пустое.

// Подготовка перед функциями
var typingTimer;                // идентификатор таймера
var doneTypingInterval = 5000;  // время в мс (5 секунд)

// При отпускании клавиши начинается обратный отсчет
$('#myInput').keyup(function() {
    clearTimeout(typingTimer);
    if ($('#myInput').val()) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

// Пользователь "закончил ввод", выполняем действие
function doneTyping () {
    // выполнить какое-то действие
}

И аналогичный код на чистом JavaScript:

// Подготовка перед функциями
let typingTimer;                // идентификатор таймера
let doneTypingInterval = 5000;  // время в мс (5 секунд)
let myInput = document.getElementById('myInput');

// При отпускании клавиши начинается обратный отсчет
myInput.addEventListener('keyup', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

// Пользователь "закончил ввод", выполняем действие
function doneTyping () {
    // выполнить какое-то действие
}

Это решение использует ES6, но это не обязательно. Просто замените let на var и стрелочную функцию на обычную функцию.

0

Это всего лишь одна строка с использованием функции debounce библиотеки underscore.js:

$('#my-input-box').keyup(_.debounce(doSomething, 500));

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

Для получения дополнительной информации, можно посетить: http://underscorejs.org/#debounce

0

Да, вы можете установить таймаут, скажем, в 2 секунды для каждого события key up, чтобы запускать AJAX-запрос. Также вы можете сохранить объект XHR и прервать его при последующих нажатиях клавиш, чтобы сэкономить больше трафика. Вот пример, который я написал для своего скрипта автозаполнения.

var timer;
var x;

$(".some-input").keyup(function () {
    if (x) { x.abort() } // Если существует текущий XHR, прерываем его.
    clearTimeout(timer); // Очищаем таймер, чтобы избежать дубликатов.
    timer = setTimeout(function() { // устанавливаем новый таймаут
        x = $.getJSON(...); // выполняем AJAX-запрос и сохраняем в переменной x (чтобы можно было отменить)
    }, 2000); // задержка 2000мс, измените для ускорения/замедления
});

Надеюсь, это поможет!

Марко

0

Ваш код предназначен для того, чтобы отслеживать ввод текста в элементе с id in и выполнять определенные действия с задержкой в 1000 мс (1 секунда) после последнего нажатия клавиши. Однако есть некоторые моменты, которые необходимо исправить. Вот исправленный и улучшенный вариант вашего кода:

var timer;
var timeout = 1000;

$('#in').keyup(function(){
    clearTimeout(timer);
    
    // Проверяем, что поле input не пустое
    if ($('#in').val()) {
        timer = setTimeout(function(){
            // Выполняем нужное действие здесь, например, AJAX-запрос и т.д.
            var v = $("#in").val();
            $("#out").html(v);
        }, timeout);
    }
});

Что было исправлено:

  1. Проверка значения: В вашем коде была ошибка в условии if ($('#in').val). Правильный способ проверки поля ввода на наличие значения - использовать if ($('#in').val()), так как val — это метод, который нужно вызывать, чтобы получить текущее значение поля.

  2. Описание работы кода: Я добавил комментарий, поясняющий, какие действия будут выполняться после задержки.

Общее объяснение:

Этот код использует свойство keyup, чтобы отслеживать нажатия клавиш в поле ввода. Если пользователь печатает, предыдущий таймер сбрасывается, и новый таймер запускается. Как только пользователь перестает печатать на одну секунду, текущее значение текстового поля #in берется и отображается в элементе #out.

Полный пример:

Вы можете найти полный пример вашего кода по следующей ссылке: jsfiddle.net

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