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

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

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

использование jQuery здесь! Дэйв!--1-->

22 ответов


Итак, я собираюсь догадаться, что закончить печатать означает, что вы просто остановитесь на некоторое время, скажем, 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
}

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

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

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

//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 vanilla:

//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 и функция стрелки с регулярной функцией.


Это просто одна строка С подчеркивания.js функция debounce:

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

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

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


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

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
});

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

Марко


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/


Мне нравится ответ сюрреалистического сна, но я обнаружил, что моя функция" doneTyping "будет срабатывать для каждого нажатия клавиши, т. е. если вы наберете" привет " очень быстро; вместо того, чтобы стрелять только один раз, когда вы прекратите печатать, функция будет срабатывать 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. Я хотел бы просто добавить это в качестве комментария к ответу сюрреалистического сна, но я новый пользователь и не имею достаточной репутации. Прости!


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

//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
}

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

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

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


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

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)
    }

}

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


устранение:

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

решение работало для меня-это:

$(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

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

Я уверен, что это поможет другим.

Ata


Я чувствую, что решение несколько проще с input событие:

var typingTimer;
var doneTypingInterval = 500;

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

function doneTyping () {
    // code here
}

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

var timeout = null;

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

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

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

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

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


Это простой код 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>

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

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


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

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

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

$('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 секунд) или переходит в другое поле (размывается из элемента)


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

$(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);
            }
        });  
    });
});    

согласен с ответом @going. Еще одно аналогичное решение, которое сработало для меня, - это приведенное ниже. Единственная разница в том, что я использую .на входе."..) вместо 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);
});

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

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

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


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

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

Шаг 2.триггер clear timeout для переменной define перед запуском события 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);
};

Вау, даже 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);