如何延迟.keyup()处理程序,直到用户停止键入?
我有一个search字段。 现在它search每个键盘。 因此,如果有人input“Windows”,它将使用AJAXsearch每个键盘:“W”,“Wi”,“Win”,“Wind”,“Windo”,“Window”,“Windows”。
我想有一个延迟,所以只有当用户停止input200毫秒时才进行search。
在这个keyup
函数中没有这个选项,我尝试了setTimeout
,但是没有成功。
我怎样才能做到这一点?
我使用这个函数来达到同样的目的,在用户停止键入指定的时间之后执行一个函数:
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插件。
如果要在types完成后search,请使用全局variables来保存从setTimout
调用返回的超时,如果尚未发生,则使用clearTimeout
将其取消,以便除最后一次提示之外不会触发超时事件
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); }
你也可以看看underscore.js ,它提供了像debounce这样的实用方法:
var lazyLayout = _.debounce(calculateLayout, 300); $(window).resize(lazyLayout);
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);});
基于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);
小心:作为parameter passing的函数中的$(this)variables与input不匹配
使用标签延迟多function呼叫
这是我工作的解决scheme。 它会延迟任何你想要的function的执行 。 它可以是keydownsearch查询,也许是快速点击上一个或下一个button(否则,如果连续快速点击,会发送多个请求,毕竟不会被使用)。 这使用一个全局对象来存储每个执行时间,并将其与最新的请求进行比较。
所以结果是只有最后一次点击/动作才会真正被调用,因为这些请求被存储在一个队列中,如果在队列中不存在具有相同标签的其他请求,则在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毫秒)。 并以“closures方式”发送你的函数参数。
例如,如果你想调用波纹pipefunction:
function send_ajax(id){console.log(id);}
要防止多个send_ajax请求,可以使用以下命令来延迟它们:
delay_method( "check date", function(){ send_ajax(2); } ,600);
只有在600毫秒的时间内没有其他请求才会触发使用“检查date”标签的每个请求。 这个参数是可选的
标签独立性(调用相同的目标函数),但同时运行:
delay_method("check date parallel", function(){send_ajax(2);}); delay_method("check date", function(){send_ajax(2);});
结果是调用相同的函数,但由于它们的标签不同而延迟了它们
我很惊讶,没有人提到CMS的非常好的剪切多input的问题。
基本上,你将不得不为每个input单独定义延迟variables。 否则,如果sb将文本放入第一个input并快速跳转到其他input并开始input,则不会调用第一个input的callback。
看到下面的代码基于其他答案来:
(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);
该解决scheme在input的delayTimervariables中保留setTimeout引用。 它也传递元素的引用作为fazzyxbuild议。
testing了IE6,8(comp – 7),8和Opera 12.11。
这工作对我来说,我拖延search逻辑操作,并作出检查,如果值是相同的input文本字段。 如果值相同,则继续执行与search值有关的数据的操作。
$('#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); });
这个函数从Gaten的回答中稍微扩展一下函数来获取元素:
$.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);
延迟function可以调用每个键盘。 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,并且没有外部variables,他可以使用下一个脚本:
function MyFunction() { //Delaying the function execute if (this.timer) { window.clearTimeout(this.timer); } this.timer = window.setTimeout(function() { //Execute the function code here... }, 500); }
使用
mytimeout = setTimeout( expression, timeout );
其中expression式是要运行的脚本,超时是在运行之前等待的时间(以毫秒为单位) – 这不会影响脚本,只是延迟执行该部分,直到超时完成。
clearTimeout(mytimeout);
会重置/清除超时,所以只要尚未执行,就不会在expression式中运行脚本(如取消)。
这是一个沿着CMS的解决scheme,但为我解决了一些关键问题:
- 支持多个input,延迟可以同时运行。
- 忽略不改变值的关键事件(如Ctrl,Alt + Tab)。
- 解决争用条件(执行callback时,值已经改变)。
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) }) })
代码是以我喜欢的风格编写的,您可能需要添加一堆分号。
需要注意的是:
- 一个唯一的ID是基于表单ID和input名称生成的,所以它们必须被定义和唯一,或者可以根据自己的情况进行调整。
- 延迟返回一个对象,可以根据自己的需要轻松扩展。
- 用于延迟的原始元素绑定到callback函数,所以
this
函数按照预期的方式工作(如下例)。 - 在第二次validation中,空值将被忽略。
- 注意排队 ,它预计毫秒首先,我更喜欢,但你可能想切换参数匹配
setTimeout
。
我使用的解决scheme增加了另一个层次的复杂性,例如允许您取消执行,但是这是一个很好的基础。
根据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 ); })
超级简单的方法,用于在用户input文本字段后运行function…
<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>
使用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 };
这是我写的一个build议,它负责处理表单中的多个input。
这个函数获取input字段的对象,放入你的代码中
function fieldKeyup(obj){ // what you want this to do } // fieldKeyup
这是实际的delayCall函数,负责多个input字段
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的答案和米格尔的 答案产生一个强大的解决scheme,允许同时延迟。
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'); });
看看自动完成插件。 我知道它允许你指定一个延迟或最小数量的字符。 即使你没有使用这个插件,通过代码来看看如何自己实现它也会给你一些想法。
那么,我也做了一个由Keyup / Keydown引起的限制高频ajax请求的代码。 看一下这个:
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 */ }); });
今天看到这个迟了一点,但只是想把这个在这里以防别人需要。 只是分开function,使其可重复使用。 下面的代码将在打字停止后等待1/2秒。
var timeOutVar $(selector).on('keyup', function() { clearTimeout(timeOutVar); timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500); });