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

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

Используя jQuery здесь! Дэйв

Итак, я думаю, что завершение набора означает, что вы просто остановитесь на некоторое время, скажем, 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 иногда устанавливается несколько раз (нажатие клавиши дважды до нажатия клавиши для быстрого набора и т. Д.), Тогда оно не очищается должным образом.

Решение, приведенное ниже, решает эту проблему и вызывает 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 и функцию стрелки на обычную функцию.

Это просто одной строки . Это как окно, которое вы можете открыть с помощью Underscore.js функция debounce:

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

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

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

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

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

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

Marko

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/

Мне нравится ответ 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, но я новый пользователь и мне не хватает репутации. Сожалею!

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

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

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

var timeout = null;

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

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

Что ж, Строго говоря, нет, так как компьютер не может угадать, когда пользователь закончил печатать. Конечно, вы можете запустить таймер при нажатии клавиши up и сбросить его при каждом последующем нажатии клавиши. Если таймер истекает, пользователь не набрал длительность таймера — это можно назвать «законченным набором».

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

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

Я не думаю, что в этом случае необходимо событие 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)
    }

}

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

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

var typingTimer;
var doneTypingInterval = 500;

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

function doneTyping () {
    // code here
}

согласен с ответом @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);
});

Я выполнял поиск в моем листинге и хотел, чтобы он был основан на 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

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

Вы можете использовать событие 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>

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

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

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

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

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

javascript code

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

Объявите следующее 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);
});    

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

По истечении времени ожидания сделайте запрос ajax.

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

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

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

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

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

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

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

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

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

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

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

Для меня

Все остальные ответы работают только для

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

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

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

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

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

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

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

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

  1. events

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

  3. обязательно нужно использовать .val() или .value Вы можете использовать

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

  5. , чтобы легко получить доступ к doneTyping в setTimeout из n.4, но вам нужно сначала сохранить ее, как $(this) Создать хеш из строки в Javascript — Переполнение стека var $currentInput = $(this);