Javascript 如何延迟.keyup()处理程序直到用户停止键入?

Javascript 如何延迟.keyup()处理程序直到用户停止键入?,javascript,jquery,Javascript,Jquery,我有一个搜索栏。现在它搜索每一个关键点。因此,如果有人键入“Windows”,它将使用AJAX搜索每个键:“W”、“Wi”、“Win”、“Wind”、“Windo”、“Window”、“Windows” 我希望有一个延迟,所以它只在用户停止键入200毫秒时进行搜索 在keyup函数中没有此选项,我尝试了setTimeout,但没有成功 我该怎么做呢?看看这个插件。我知道它允许您指定延迟或最小字符数。即使你最终没有使用插件,查看代码将为您提供一些关于如何自己实现它的想法。如果您想在类型完成后进行搜

我有一个搜索栏。现在它搜索每一个关键点。因此,如果有人键入“Windows”,它将使用AJAX搜索每个键:“W”、“Wi”、“Win”、“Wind”、“Windo”、“Window”、“Windows”

我希望有一个延迟,所以它只在用户停止键入200毫秒时进行搜索

keyup
函数中没有此选项,我尝试了
setTimeout
,但没有成功


我该怎么做呢?

看看这个插件。我知道它允许您指定延迟或最小字符数。即使你最终没有使用插件,查看代码将为您提供一些关于如何自己实现它的想法。

如果您想在类型完成后进行搜索,请使用一个全局变量来保存从
settimeout
调用返回的超时,如果尚未发生,则使用
cleartimout
取消超时,以便它不会触发超时,除非在最后一次调用
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);  
}   
使用

其中expression是要运行的脚本,timeout是在运行之前等待的时间(以毫秒为单位)——这不会拖拽脚本,只是简单地延迟该部分的执行,直到超时完成

clearTimeout(mytimeout);

将重置/清除超时,以便只要脚本尚未执行,它就不会在表达式中运行脚本(如取消)。

我使用此小函数也是为了同样的目的,在用户停止键入指定的时间后或在高速率触发的事件中执行函数,如
resize

函数延迟(回调,毫秒){
var定时器=0;
返回函数(){
var context=this,args=arguments;
清除超时(计时器);
定时器=设置超时(函数(){
apply(上下文,args);
},ms | | 0);
};
}
//用法示例:
$(“#输入”).keyup(延迟)(函数(e){
console.log('timepassed!',this.value);
}, 500));

试试看:
您还可以查看,它提供了以下实用方法:

使用jQuery插件:

element.bindWithDelay(eventType, [ eventData ], handler(eventObject), timeout, throttle)

根据CMS的回答,我做了以下几点:

将下面的代码放在include 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)变量与每次键控时调用的输入

延迟函数不匹配。 jQuery 1.7.1或更高版本

jQuery.fn.keyupDelay=函数(cb,延迟){
如果(延迟==null){
延迟=400;
}
var定时器=0;
返回$(this).on('keyup',function()){
清除超时(计时器);
定时器=设置超时(cb,延迟);
});
}

用法:
$('#searchBox').keyupDelay(cb)

此函数从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);

我很惊讶,在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中进行了测试。

这是一个与CMS类似的解决方案,但为我解决了几个关键问题:

  • 支持多个输入,延迟可以并发运行
  • 忽略未更改值的关键事件(如Ctrl、Alt+Tab)
  • 解决竞争条件(当执行回调且值已更改时)
var delay=(函数(){
变量计时器={}
,值={}
返回函数(el){
变量id=el.form.id+'.'+el.name
返回{
排队:功能(ms、cb){
if(values[id]==el.value)返回
如果(!el.value)返回
var原始=值[id]=el.value
clearTimeout(计时器[id])
计时器[id]=设置超时(函数(){
if(original!=el.value)返回//解决竞争条件
cb.应用(el)
},ms)
}
}
}
}())
用法:

$("#username").on("keyup",function(){
    delayCall($(this),500,fieldKeyup);
});
$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000, this);
});
signup.key.addEventListener('keyup',function()){
延迟(this).排队(300,函数(){
console.log(this.value)
})
})
代码是以我喜欢的风格编写的,您可能需要添加一些分号

要记住的事情:

  • 唯一id是基于表单id和输入名称生成的,因此它们必须是定义的和唯一的,或者您可以根据自己的情况进行调整
  • delay返回一个易于扩展以满足您自己需要的对象
  • 用于延迟的原始元素绑定到回调,因此
    这个
    按预期工作(如示例中所示)
  • 在第二次验证中忽略空值
  • 注意排队,它首先需要毫秒,我更喜欢这样,但您可能希望切换参数以匹配
    设置超时

我使用的解决方案增加了另一个层次的复杂性,例如,允许您取消执行,但这是一个很好的基础。

根据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 );


})

在我延迟搜索逻辑操作并检查值是否与在文本字段中输入的值相同的情况下,这对我很有效。如果值相同,则继续执行与搜索值相关的数据的操作

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

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);});
如果你想要sepa
$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});
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
};
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 fieldKeyup(obj){
    //  what you want this to do

} // fieldKeyup
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);
});
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{  delayed_methods[label]=""; callback();}}, time||500);
  }
function send_ajax(id){console.log(id);}
delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});
function MyFunction() {

    //Delaying the function execute
    if (this.timer) {
        window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(function() {

        //Execute the function code here...

    }, 500);
}
    var timeOutVar
$(selector).on('keyup', function() {

                    clearTimeout(timeOutVar);
                    timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500);
                });
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);
});
changeName: _.debounce(function (val) {
  console.log(val)                
}, 1000)
// Get an global variable isApiCallingInProgress

//  check isApiCallingInProgress 
if (!isApiCallingInProgress) {
// set it to isApiCallingInProgress true
      isApiCallingInProgress = true;

      // set timeout
      setTimeout(() => {
         // Api call will go here

        // then set variable again as false
        isApiCallingInProgress = false;     
      }, 1000);
}
// declare the timeout variable out of the event listener or in global scope
var timeout = null;

$("#some-id-to-bind-event").keyup(function() {
    clearTimeout(timout); // this will clear the recursive unneccessary calls
    timeout = setTimeout(() => {
         // do something: send an ajax or call a function here
    }, 2000);
    // wait two seconds

});