在我停止输入/写入后如何在输入文本中触发事件?

74 jquery timeout keypress typeahead debouncing

我想在输入文本框中停止输入(而不是在输入时)字符后触发事件.

我尝试过:

$('input#username').keypress(function() {
    var _this = $(this); // copy of this object for further usage

    setTimeout(function() {
        $.post('/ajax/fetch', {
            type: 'username',
            value: _this.val()
        }, function(data) {
            if(!data.success) {
                // continue working
            } else {
                // throw an error
            }
        }, 'json');
    }, 3000);
});
Run Code Online (Sandbox Code Playgroud)

但是这个例子会为每个类型字符生成一个超时,如果输入20个字符,我会得到大约20个AJAX请求.

在这个小提琴上,我用简单的警报而不是AJAX来演示同样的问题.

有没有解决方案,或者我只是使用一种不好的方法?

Bra*_*tie 163

你必须使用setTimeout(和你一样),但也存储引用,这样你就可以继续重置限制.就像是:

//
// $('#element').donetyping(callback[, timeout=1000])
// Fires callback when a user has finished typing. This is determined by the time elapsed
// since the last keystroke and timeout parameter or the blur event--whichever comes first.
//   @callback: function to be called when even triggers
//   @timeout:  (default=1000) timeout, in ms, to to wait before triggering event if not
//              caused by blur.
// Requires jQuery 1.7+
//
;(function($){
    $.fn.extend({
        donetyping: function(callback,timeout){
            timeout = timeout || 1e3; // 1 second default timeout
            var timeoutReference,
                doneTyping = function(el){
                    if (!timeoutReference) return;
                    timeoutReference = null;
                    callback.call(el);
                };
            return this.each(function(i,el){
                var $el = $(el);
                // Chrome Fix (Use keyup over keypress to detect backspace)
                // thank you @palerdot
                $el.is(':input') && $el.on('keyup keypress paste',function(e){
                    // This catches the backspace button in chrome, but also prevents
                    // the event from triggering too preemptively. Without this line,
                    // using tab/shift+tab will make the focused element fire the callback.
                    if (e.type=='keyup' && e.keyCode!=8) return;
                    
                    // Check if timeout has been set. If it has, "reset" the clock and
                    // start over again.
                    if (timeoutReference) clearTimeout(timeoutReference);
                    timeoutReference = setTimeout(function(){
                        // if we made it here, our timeout has elapsed. Fire the
                        // callback
                        doneTyping(el);
                    }, timeout);
                }).on('blur',function(){
                    // If we can, fire the event since we're leaving the field
                    doneTyping(el);
                });
            });
        }
    });
})(jQuery);

$('#example').donetyping(function(){
  $('#example-output').text('Event last fired @ ' + (new Date().toUTCString()));
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<input type="text" id="example" />
<p id="example-output">Nothing yet</p>
Run Code Online (Sandbox Code Playgroud)

这将在以下时间执行:

  1. 超时已过,或
  2. 用户切换字段(blur事件)

(以先到者为准)

  • 感谢这个插件 - 效果很好.我不得不进行一次调整,因为当有人将某些东西粘贴到输入字段时它不起作用.我编辑了以下行,包括`paste` - `$ el.is(':input')&& $ el.on('keyup keypress paste',function(e){` (3认同)
  • @Brad:这个jquery解决方案工作正常,除了在最新的chrome(38.0.2125.111)中没有检测到输入框中输入的退格键.只将它改为`keyup`才有效.您可能希望检查它并适当地修改代码. (2认同)

Ata*_*afa 62

解:

这是解决方案.在用户停止键入指定时间后执行函数:

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
  clearTimeout (timer);
  timer = setTimeout(callback, ms);
 };
})();
Run Code Online (Sandbox Code Playgroud)

用法

$('input').keyup(function() {
  delay(function(){
    alert('Hi, func called');
  }, 1000 );
});
Run Code Online (Sandbox Code Playgroud)

  • 我可以添加 N+ 票吗?这个使用 JavaScript 闭包的解决方案非常出色、简短且优雅。 (2认同)

Sco*_*2k5 16

你可以使用underscore.js"debounce"

$('input#username').keypress( _.debounce( function(){<your ajax call here>}, 500 ) );
Run Code Online (Sandbox Code Playgroud)

这意味着您的函数调用将在按下一个键500ms后执行.但是如果你在500ms之前按下另一个键(另一个按键事件被触发),前一个函数执行将被忽略(去抖动),新的将在新的500ms计时器之后执行.

有关额外信息,使用_.debounce(func,timer,true)将意味着将执行第一个函数,并且将忽略具有后续500ms计时器的所有其他按键事件.


Zig*_*ggy 9

你需要去抖!

这是一个jQuery插件,这里有关于去抖的所有知识.如果您是从谷歌和下划线来这里已经找到了它的方式进入您的应用程序的JSoup,它有反跳右出炉!


Gib*_*ias 6

您应该分配setTimeout给一个变量并用于clearTimeout在按键时清除它。

var timer = '';

$('input#username').keypress(function() {
  clearTimeout(timer);
  timer = setTimeout(function() {
    //Your code here
  }, 3000); //Waits for 3 seconds after last keypress to execute the above lines of code
});
Run Code Online (Sandbox Code Playgroud)

小提琴

希望这可以帮助。


Mat*_*rix 5

清洁液:

$.fn.donetyping = function(callback, delay){
  delay || (delay = 1000);
  var timeoutReference;
  var doneTyping = function(elt){
    if (!timeoutReference) return;
    timeoutReference = null;
    callback(elt);
  };

  this.each(function(){
    var self = $(this);
    self.on('keyup',function(){
      if(timeoutReference) clearTimeout(timeoutReference);
      timeoutReference = setTimeout(function(){
        doneTyping(self);
      }, delay);
    }).on('blur',function(){
      doneTyping(self);
    });
  });

  return this;
};
Run Code Online (Sandbox Code Playgroud)