Запустить javascript-функцию, когда пользователь заканчивает ввод, а не на клавише?

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

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

Использование jQuery здесь! Dave

Ответ 1

Итак, я собираюсь догадаться, что завершение ввода означает, что вы просто остановитесь на некоторое время, скажем, 5 секунд. Поэтому, имея в виду, давайте начнем таймер, когда пользователь выпустит ключ и очистит его, когда он нажмет один. Я решил, что входной вопрос будет #myInput.

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

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example
var $input = $('#myInput');

//on keyup, start the countdown
$input.on('keyup', function () {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$input.on('keydown', function () {
  clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

Ответ 2

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

Поскольку typingTimer иногда устанавливается несколько раз (нажатие клавиши дважды до нажатия клавиши для быстрого набора текста и т.д.), Тогда оно не очищается должным образом.

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

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on keyup, start the countdown
$('#myInput').keyup(function(){
    clearTimeout(typingTimer);
    if ($('#myInput').val()) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

И тот же код в ванильном решении JavaScript:

//setup before functions
let typingTimer;                //timer identifier
let doneTypingInterval = 5000;  //time in ms (5 seconds)
let myInput = document.getElementById('myInput');

//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

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

Ответ 3

Это просто одна строка с функцией underscore.js debounce:

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

В основном это говорит doSomething 500 миллисекунд после того, как я перестаю печатать.

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

Ответ 4

Да, вы можете установить тайм-аут, скажем, 2 секунды на каждом событии, на котором будет срабатывать ajax-запрос. Вы также можете сохранить XHR-метод и прервать его при последующих нажатиях клавиш, чтобы вы сохранили полосу пропускания еще больше. Вот что я написал для автозаполнения script.

var timer;
var x;

$(".some-input").keyup(function () {
    if (x) { x.abort() } // If there is an existing XHR, abort it.
    clearTimeout(timer); // Clear the timer so we don't end up with dupes.
    timer = setTimeout(function() { // assign timer a new timeout 
        x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
    }, 2000); // 2000ms delay, tweak for faster/slower
});

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

Марко

Ответ 5

var timer;
var timeout = 1000;

$('#in').keyup(function(){
    clearTimeout(timer);
    if ($('#in').val) {
        timer = setTimeout(function(){
            //do stuff here e.g ajax call etc....
             var v = $("#in").val();
             $("#out").html(v);
        }, timeout);
    }
});

полный пример здесь: http://jsfiddle.net/ZYXp4/8/

Ответ 6

Мне нравится ответ Surreal Dream, но я обнаружил, что моя функция "doneTyping" будет срабатывать для каждого нажатия клавиши, т.е. если вы быстро наберете "Hello"; вместо того, чтобы стрелять только один раз, когда вы перестали печатать, функция будет срабатывать 5 раз.

Проблема заключалась в том, что функция javascript setTimeout не переписывает или не убивает какие-либо старые тайм-ауты, которые были установлены, но если вы сделаете это самостоятельно, это сработает! Поэтому я просто добавил вызов clearTimeout непосредственно перед setTimeout, если установлен typingTimer. См. Ниже:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example

//on keyup, start the countdown
$('#myInput').on("keyup", function(){
    if (typingTimer) clearTimeout(typingTimer);                 // Clear if already set     
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$('#myInput').on("keydown", function(){
    clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

N.B. Мне бы хотелось только добавить это как комментарий к сюжету Surreal Dream, но я новый пользователь и не имею достаточной репутации. Извините!

Ответ 7

Изменение принятого ответа для обработки дополнительных случаев, таких как paste:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 2000;  //time in ms, 2 second for example
var $input = $('#myInput');

// updated events 
$input.on('input propertychange paste', function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);      
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

Ответ 8

Оба топ-2 ответа не работают для меня. Итак, вот мое решение:

var timeout = null;

$('#myInput').keyup(function() {
    clearTimeout(timeout);

    timeout = setTimeout(function() {
        //do stuff here
    }, 500);
});

Ответ 9

Я не думаю, что в этом случае необходимо событие keyDown (скажите, пожалуйста, если я ошибаюсь). В моем (не jquery) script подобное решение выглядит так:

var _timer, _timeOut = 2000; 



function _onKeyUp(e) {
    clearTimeout(_timer);
    if (e.keyCode == 13) {      // close on ENTER key
        _onCloseClick();
    } else {                    // send xhr requests
        _timer = window.setTimeout(function() {
            _onInputChange();
        }, _timeOut)
    }

}

Это мой первый ответ на Stack Overflow, поэтому я надеюсь, что это кому-то поможет когда-нибудь:)

Ответ 10

Ну, строго говоря, нет, поскольку компьютер не может догадаться, когда пользователь закончил печатать. Конечно, вы могли бы запустить таймер на клавиатуре и reset на каждом последующем ключе. Если таймер истекает, пользователь не набрал для длительности таймера - вы могли бы назвать это "завершенной типизацией".

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

(Если, конечно, вы не можете сказать по данным, когда они сделаны)

Ответ 11

Объявите следующую функцию delay:

var delay = (function () {
    var timer = 0;
    return function (callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
    };
})()

и затем используйте это:

let $filter = $('#item-filter');
$filter.on('keydown', function () {
    delay(function () {            
        console.log('this will hit, once user has not typed for 1 second');            
    }, 1000);
});    

Ответ 12

Я осуществлял поиск по своему списку, и мне нужно было, чтобы он был основан на ajax. Это означает, что при каждом изменении ключа результаты поиска должны обновляться и отображаться. Это приводит к тому, что на сервер отправляется так много вызовов ajax, что не очень хорошо.

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

Это решение сработало для меня:

$(document).ready(function() {
    $('#yourtextfield').keyup(function() {
        s = $('#yourtextfield').val();
        setTimeout(function() { 
            if($('#yourtextfield').val() == s){ // Check the value searched is the latest one or not. This will help in making the ajax call work when client stops writing.
                $.ajax({
                    type: "POST",
                    url: "yoururl",
                    data: 'search=' + s,
                    cache: false,
                    beforeSend: function() {
                       // loading image
                    },
                    success: function(data) {
                        // Your response will come here
                    }
                })
            }
        }, 1000); // 1 sec delay to check.
    }); // End of  keyup function
}); // End of document.ready

Вы заметите, что нет необходимости использовать таймер при реализации этого.

Ответ 13

Мне кажется, что решение несколько проще с событием input:

var typingTimer;
var doneTypingInterval = 500;

$("#myInput").on("input", function () {
    window.clearTimeout(typingTimer);
    typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});

function doneTyping () {
    // code here
}

Ответ 14

согласен с ответом @going. Другое подобное решение, которое сработало для меня, - это следующее. Единственное отличие состоит в том, что я использую .on( "input"...) вместо keyup. Это фиксирует изменения во входном сигнале. другие клавиши, такие как Ctrl, Shift и т.д., игнорируются.

var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on input change, start the countdown

$('#myInput').on("input", function() {    
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function(){
        // doSomething...
    }, doneTypingInterval);
});

Ответ 15

Я только что понял простой код, чтобы дождаться, пока пользователь закончит печатать:

шаг 1. установите время ожидания на ноль, а затем очистите текущее время ожидания, когда пользователь печатает.

шаг 2.trigger очистить тайм-аут для определения переменной до того, как будет запущено событие keyup.

шаг 3. определить время ожидания для переменной, объявленной выше;

<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>

код JavaScript

var textInput = document.getElementById('input');
var textdata = document.querySelector('.data');
// Init a timeout variable to be used below
var timefired = null;

// Listen for keystroke events
// Init a timeout variable to be used below
var timefired = null;// Listen for keystroke events
textInput.onkeyup = function (event) {
clearTimeout(timefired);
timefired = setTimeout(function () {
    textdata.innerHTML = 'Input Value:'+ textInput.value;
  }, 600);
};

Ответ 16

Вы можете использовать событие onblur, чтобы обнаружить, когда текстовое поле теряет фокус: https://developer.mozilla.org/en/DOM/element.onblur

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

Для этого я бы предложил привязать setTimeout к событию onclick и предположить, что после x времени без нажатий клавиш пользователь перестает печатать.

Ответ 17

Это простой JS-код, который я написал:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
    var date = new Date();
    initial_time = date.getTime();
    if (typeof setInverval_Variable == 'undefined') {
            setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
    } 
}
function DelayedSubmission_Check() {
    var date = new Date();
    check_time = date.getTime();
    var limit_ms=check_time-initial_time;
    if (limit_ms > 800) { //Change value in milliseconds
        alert("insert your function"); //Insert your function
        clearInterval(setInverval_Variable);
        delete setInverval_Variable;
    }
}

</script>
</head>
<body>

<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />

</body>
</html>

Ответ 18

Поздний ответ, но я добавляю его, потому что это 2019 год, и это вполне достижимо при использовании довольно ES6, без сторонних библиотек, и я считаю, что большинство высоко оцененных ответов громоздки и отягощены слишком большим количеством переменных.

Элегантное решение взято из этого отличного сообщения в блоге.

function debounce(callback, wait) {
  let timeout;
  return (...args) => {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => callback.apply(context, args), wait);
  };
}

window.addEventListener('keyup', debounce( () => {
    // code you would like to run 1000ms after the keyup event has stopped firing
    // further keyup events reset the timer, as expected
}, 1000))

Ответ 19

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

Когда тайм-аут завершен, выполните ваш запрос ajax.

Ответ 20

Если вы ищете определенную длину (например, поле zipcode):

$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
        //make ajax request here after.
    }
  });

Ответ 21

Не уверен, что мои потребности просто странны, но мне нужно что-то похожее на это, и именно это я и использовал:

$('input.update').bind('sync', function() {
    clearTimeout($(this).data('timer'));            
    $.post($(this).attr('data-url'), {value: $(this).val()}, function(x) {
        if(x.success != true) {
            triggerError(x.message);    
        }
    }, 'json');
}).keyup(function() {
    clearTimeout($(this).data('timer'));
    var val = $.trim($(this).val());
    if(val) {
        var $this = $(this);
        var timer = setTimeout(function() {
            $this.trigger('sync');
        }, 2000);
        $(this).data('timer', timer);
    }
}).blur(function() {
    clearTimeout($(this).data('timer'));     
    $(this).trigger('sync');
});

Что позволяет мне иметь такие элементы в моем приложении:

<input type="text" data-url="/controller/action/" class="update">

Которые обновляются, когда пользователь "набирает" (без действий в течение 2 секунд) или переходит в другое поле (размывается из элемента)

Ответ 22

Если вам нужно подождать, пока пользователь завершит ввод, просто используйте это:

$(document).on('change','#PageSize', function () {
    //Do something after new value in #PageSize       
});

Полный пример с вызовом ajax - это работает для моего пейджера - количество элементов в списке:

$(document).ready(function () {
    $(document).on('change','#PageSize', function (e) {
        e.preventDefault();
        var page = 1;
        var pagesize = $("#PageSize").val();
        var q = $("#q").val();
        $.ajax({
            url: '@Url.Action("IndexAjax", "Materials", new { Area = "TenantManage" })',
            data: { q: q, pagesize: pagesize, page: page },
            type: 'post',
            datatype: "json",
            success: function (data) {
                $('#tablecontainer').html(data);
               // toastr.success('Pager has been changed', "Success!");
            },
            error: function (jqXHR, exception) {
                ShowErrorMessage(jqXHR, exception);
            }
        });  
    });
});    

Ответ 23

Почему бы просто не использовать onfocusout?

https://www.w3schools.com/jsreF/event_onfocusout.asp

Если это форма, они всегда будут оставлять фокус для каждого поля ввода, чтобы щелкнуть кнопку отправки, чтобы вы не знали, что вход не будет пропущен при вызове обработчика события onfocusout.

Ответ 24

Несколько таймеров на страницу

Все остальные ответы работают только для одного элемента управления (мой другой ответ включен). Если у вас есть несколько элементов управления на странице (например, в корзине), будет вызван только последний элемент управления, где пользователь что-то набрал. В моем случае это, конечно, не желаемое поведение - у каждого элемента управления должен быть свой таймер.

Чтобы решить эту проблему, вам просто нужно передать идентификатор функции и поддерживать словарь timeoutHandles, как показано в следующем коде:

Объявление функции:

var delayUserInput = (function () {
    var timeoutHandles = {};    
    return function (id, callback, ms) {        
        if (timeoutHandles[id]) {
            clearTimeout(timeoutHandles[id]);
        }

        timeoutHandles[id] = setTimeout(callback, ms);             
    };
})();

Использование функции:

  delayUserInput('yourID', function () {
     //do some stuff
  }, 1000);

Ответ 25

Просто и легко понять.

var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
   clearTimeout(mySearchTimeout);
   var filter = $(this).val();
   mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
   return true;
});

Ответ 26

Для передачи параметров в вашу функцию вместе с синтаксисом ES6.

$(document).ready(() => {
    let timer = null;
     $('.classSelector').keydown(() => {
     clearTimeout(timer); 
     timer = setTimeout(() => foo('params'), 500);
  });
});

const foo = (params) => {
  console.log('In foo ${params}');
}

Ответ 27

Вау, даже 3 комментария довольно правильные!

  1. Пустой ввод не является причиной пропуска вызова функции, например, Я удаляю ненужный параметр из URL перед перенаправлением

  2. .on ('input', function() { ... }); следует использовать для запуска событий keyup, paste и change

  3. безусловно, следует использовать .val() или .value

  4. Вы можете использовать $(this) внутри функции события вместо #id для работы с несколькими входами

  5. (мое решение) Я использую анонимную функцию вместо doneTyping в setTimeout для легкого доступа к $(this) из n.4, но вам нужно сначала сохранить его, как var $currentInput = $(this);

ОБНОВЛЕНИЕ Я вижу, что некоторые люди не понимают направления без возможности скопировать и вставить готовый код. Здесь ты

var typingTimer;
//                  2
$("#myinput").on('input', function () {
    //             4     3
    var input = $(this).val();
    clearTimeout(typingTimer);
    //                           5
    typingTimer = setTimeout(function() {
        // do something with input
        alert(input);
    }, 5000);      
});