Как оттянуть свое.keyup () обработчик, пока пользователь не перестанет печатать?
у меня есть поле поиска. Прямо сейчас он ищет каждый ключ. Поэтому, если кто-то наберет "Windows", он выполнит поиск с помощью AJAX для каждого ключа: "W", "Wi", "Win", "Wind", "Windo", "Window", "Windows".
Я хочу иметь задержку, поэтому он ищет только тогда, когда пользователь перестает печатать на 200 мс.
нет опции для этого в и setTimeout, но это не сработало.
Как я могу это сделать?
24 ответов:
Я использую эту функцию для той же цели, выполняя функцию после того, как пользователь перестал вводить в течение определенного периода времени:
var delay = (function(){ var timer = 0; return function(callback, ms){ clearTimeout (timer); timer = setTimeout(callback, ms); }; })();использование:
$('input').keyup(function() { delay(function(){ alert('Time elapsed!'); }, 1000 ); });для чего-то более сложного, посмотрите на jQuery Typewatch плагин.
если вы хотите выполнить поиск после завершения типа, используйте глобальную переменную для хранения таймаута, возвращенного из вашего
setTimoutпозвоните и отмените его с помощьюclearTimeoutесли это еще не произошло, чтобы он не запускал тайм-аут, кроме последнегоkeyupсобытиеvar globalTimeout = null; $('#id').keyup(function(){ if(globalTimeout != null) clearTimeout(globalTimeout); globalTimeout =setTimeout(SearchFunc,200); } function SearchFunc(){ globalTimeout = null; //ajax code }или с анонимной функцией:
var globalTimeout = null; $('#id').keyup(function() { if (globalTimeout != null) { clearTimeout(globalTimeout); } globalTimeout = setTimeout(function() { globalTimeout = null; //ajax code }, 200); }
еще одно небольшое улучшение в ответе 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);});
вы также можете посмотреть на подчеркивания.js, который предоставляет служебные методы, как debounce:
var lazyLayout = _.debounce(calculateLayout, 300); $(window).resize(lazyLayout);
основываясь на ответе CMS, я сделал это:
поместите код ниже после включения jQuery:
/* * delayKeyup * http://code.azerti.net/javascript/jquery/delaykeyup.htm * Inspired by CMS in this post : http://stackoverflow.com/questions/1909441/jquery-keyup-delay * Written by Gaten * Exemple : $("#input").delayKeyup(function(){ alert("5 secondes passed from the last event 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 secondes passed from the last event keyup."); }, 5000);осторожно: переменная $(this) в функции, переданной в качестве параметра, не соответствует input
задержка вызовов нескольких функций с помощью меток
это решение, с которым я работаю. это задержит выполнение любой функции, которую вы хотите. Это может быть поисковый запрос keydown, возможно , быстрый щелчок по предыдущим или следующим кнопкам ( которые в противном случае отправили бы несколько запросов, если бы быстро нажимали непрерывно и не использовались в конце концов). При этом используется глобальный объект, который сохраняет каждое время выполнения и сравнивает его с самым последним запросом.
таким образом, в результате будет вызван только последний щелчок / действие, потому что эти запросы хранятся в очереди, которая после 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{ 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);});результаты в вызове же функция, но задерживает их независимо из-за того, что их метки отличаются
эта функция немного расширяет функцию из ответа Гатена, чтобы вернуть элемент:
$.fn.delayKeyup = function(callback, ms){ var timer = 0; var el = $(this); $(this).keyup(function(){ clearTimeout (timer); timer = setTimeout(function(){ callback(el) }, ms); }); return $(this); }; $('#input').delayKeyup(function(el){ //alert(el.val()); // Here I need the input element (value for ajax call) for further process },1000);
Я удивлен, что никто не упоминает о проблеме с несколькими входами в CMS очень хорошо обрезан.
в принципе, вы должны определить переменную задержки индивидуально для каждого входа. В противном случае, если sb помещает текст на первый вход и быстро переходит к другому входу и начинает печатать, обратный вызов для первого НЕ назовешь!
смотрите код ниже я пришел с на основе других ответов:
(function($) { /** * KeyUp with delay event setup * * @link http://stackoverflow.com/questions/1909441/jquery-keyup-delay#answer-12581187 * @param function callback * @param int ms */ $.fn.delayKeyup = function(callback, ms){ $(this).keyup(function( event ){ var srcEl = event.currentTarget; if( srcEl.delayTimer ) clearTimeout (srcEl.delayTimer ); srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms); }); return $(this); }; })(jQuery);Это решение сохраняет ссылку setTimeout внутри входная переменная delayTimer. Он также передает ссылку элемента на обратный вызов, как предложил fazzyx.
протестировано в IE6, 8 (comp - 7), 8 и Opera 12.11.
это сработало для меня, когда я задерживаю логическую операцию поиска и проверяю, совпадает ли значение, введенное в текстовое поле. Если значение такое же, то я иду вперед и выполняю операцию для данных, связанных с значением поиска.
$('#searchText').on('keyup',function () { var searchValue = $(this).val(); setTimeout(function(){ if(searchValue == $('#searchText').val() && searchValue != null && searchValue != "") { // logic to fetch data based on searchValue } else if(searchValue == ''){ // logic to load all the data } },300); });
функция задержки для вызова на каждом keyup. jQuery 1.7.1 или выше требуется
jQuery.fn.keyupDelay = function( cb, delay ){ if(delay == null){ delay = 400; } var timer = 0; return $(this).on('keyup',function(){ clearTimeout(timer); timer = setTimeout( cb , delay ); }); }использование:
$('#searchBox').keyupDelay( cb );
Если кому-то нравится задерживать ту же функцию, и без внешней переменной он может использовать следующий скрипт:
function MyFunction() { //Delaying the function execute if (this.timer) { window.clearTimeout(this.timer); } this.timer = window.setTimeout(function() { //Execute the function code here... }, 500); }
супер простой подход, предназначенный для запуска функции после того, как пользователь закончил вводить текстовое поле...
<script type="text/javascript"> $(document).ready(function(e) { var timeout; var delay = 2000; // 2 seconds $('.text-input').keyup(function(e) { console.log("User started typing!"); if(timeout) { clearTimeout(timeout); } timeout = setTimeout(function() { myFunction(); }, delay); }); function myFunction() { console.log("Executing function for user!"); } }); </script> <textarea name="text-input" class="text-input"></textarea>
использовать
mytimeout = setTimeout( expression, timeout );где expression-это сценарий для запуска, а timeout - это время ожидания в миллисекундах до его запуска-это не вызывает сценарий, а просто задерживает выполнение этой части до тех пор, пока тайм-аут не будет выполнен.
clearTimeout(mytimeout);сбросит / очистит тайм-аут, чтобы он не запускал скрипт в выражении (например, отмена), пока он еще не был выполнен.
это решение по линии CMS, но решает несколько ключевых вопросов для меня:
- поддерживает несколько входов, задержки могут выполняться одновременно.
- игнорирует ключевые события, которые не изменили значение (например, Ctrl, Alt+Tab).
- решает условие гонки (когда обратный вызов выполняется и значение уже изменено).
var delay = (function() { var timer = {} , values = {} return function(el) { var id = el.form.id + '.' + el.name return { enqueue: function(ms, cb) { if (values[id] == el.value) return if (!el.value) return var original = values[id] = el.value clearTimeout(timer[id]) timer[id] = setTimeout(function() { if (original != el.value) return // solves race condition cb.apply(el) }, ms) } } } }())использование:
signup.key.addEventListener('keyup', function() { delay(this).enqueue(300, function() { console.log(this.value) }) })код написан в стиле, который мне нравится, вам может понадобиться добавить кучу точек с запятой.
вещи, чтобы иметь в виду:
- уникальный идентификатор создается на основе идентификатора формы и имени ввода, поэтому они должны быть определены и уникальны, или вы можете настроить его в соответствии с вашей ситуацией.
- задержка возвращает объект, который легко расширить для собственных нужд.
- исходный элемент, используемый для задержки привязан к девайсу, так
thisработает, как ожидалось (как в Примере).- пустой значение игнорируется во второй проверке.
- следи за в очередь, он ожидает миллисекунд сначала, я предпочитаю это, но вы можете переключить параметры, чтобы соответствовать
setTimeout.решение, которое я использую, добавляет еще один уровень сложности, позволяя, например, отменить выполнение, но это хорошая база для построения.
основываясь на ответе CMS, он просто игнорирует ключевые события, которые не изменяют значение.
var delay = (function(){ var timer = 0; return function(callback, ms){ clearTimeout (timer); timer = setTimeout(callback, ms); }; })(); var duplicateFilter=(function(){ var lastContent; return function(content,callback){ content=$.trim(content); if(content!=lastContent){ callback(content); } lastContent=content; }; })(); $("#some-input").on("keyup",function(ev){ var self=this; delay(function(){ duplicateFilter($(self).val(),function(c){ //do sth... console.log(c); }); }, 1000 ); })
основываясь на ответе CMS вот новый метод задержки, который сохраняет "это" в его использовании:
var delay = (function(){ var timer = 0; return function(callback, ms, that){ clearTimeout (timer); timer = setTimeout(callback.bind(that), ms); }; })();использование:
$('input').keyup(function() { delay(function(){ alert('Time elapsed!'); }, 1000, this); });
использовать bindWithDelay jQuery плагин:
element.bindWithDelay(eventType, [ eventData ], handler(eventObject), timeout, throttle)
var globalTimeout = null; $('#search').keyup(function(){ if(globalTimeout != null) clearTimeout(globalTimeout); globalTimeout =setTimeout(SearchFunc,200); }); function SearchFunc(){ globalTimeout = null; console.log('Search: '+$('#search').val()); //ajax code };
вот предложение, которое я написал, что заботится о нескольких входных данных в вашей форме.
эта функция получает объект поля ввода, помещенный в ваш код
function fieldKeyup(obj){ // what you want this to do } // fieldKeyupэто фактическая функция delayCall, заботится о нескольких полях ввода
function delayCall(obj,ms,fn){ return $(obj).each(function(){ if ( typeof this.timer == 'undefined' ) { // Define an array to keep track of all fields needed delays // This is in order to make this a multiple delay handling function this.timer = new Array(); } var obj = this; if (this.timer[obj.id]){ clearTimeout(this.timer[obj.id]); delete(this.timer[obj.id]); } this.timer[obj.id] = setTimeout(function(){ fn(obj);}, ms); }); }; // delayCallиспользование:
$("#username").on("keyup",function(){ delayCall($(this),500,fieldKeyup); });
объединение CMS ответ С Мигель один дает надежное решение, позволяющее одновременные задержки.
var delay = (function(){ var timers = {}; return function (callback, ms, label) { label = label || 'defaultTimer'; clearTimeout(timers[label] || 0); timers[label] = setTimeout(callback, ms); }; })();когда вам нужно отложить различные действия независимо, используйте третий аргумент.
$('input.group1').keyup(function() { delay(function(){ alert('Time elapsed!'); }, 1000, 'firstAction'); }); $('input.group2').keyup(function() { delay(function(){ alert('Time elapsed!'); }, 1000, '2ndAction'); });
посмотри автозаполнение плагин. Я знаю, что он позволяет указать задержку или минимальное количество символов. Даже если вы не используете плагин, Просмотр кода даст вам некоторые идеи о том, как реализовать его самостоятельно.
Ну, я также сделал кусок кода для ограничения высокочастотного ajax-запроса, вызванного Keyup / Keydown. Проверьте это:
https://github.com/raincious/jQueue
сделайте свой запрос следующим образом:
var q = new jQueue(function(type, name, callback) { return $.post("/api/account/user_existed/", {Method: type, Value: name}).done(callback); }, 'Flush', 1500); // Make sure use Flush mode.и привязать событие, как это:
$('#field-username').keyup(function() { q.run('Username', this.val(), function() { /* calling back */ }); });
видел это сегодня немного поздно, но просто хочу поставить это здесь, если кому-то еще нужно. просто отделите функцию, чтобы сделать ее многоразовой. приведенный ниже код будет ждать 1/2 секунды после ввода stop.
var timeOutVar $(selector).on('keyup', function() { clearTimeout(timeOutVar); timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500); });
С ES6 можно использовать стрелка функция синтаксис как хорошо.
В этом примере кода задержки
keyupсобытие для 400 мс после того, как пользователи закончат набирать перед вызовомsearchFuncсделать запрос.const searchbar = document.getElementById('searchBar'); const searchFunc = // any function // wait ms (milliseconds) after user stops typing to execute func const delayKeyUp = (() => { let timer = null; const delay = (func, ms) => { timer ? clearTimeout(timer): null timer = setTimeout(func, ms) } return delay })(); searchbar.addEventListener('keyup', (e) => { const query = e.target.value; delayKeyUp(() => {searchFunc(query)}, 400); })
Comments