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

问题描述 投票:77回答:11

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

我尝试过:

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

但是此示例为每个键入的字符产生超时,如果键入20个字符,我将收到大约20个AJAX请求。

On this fiddle我用简单的警报而不是AJAX演示了相同的问题。

这是否有解决方案,或者我是否为此使用了错误的方法?

jquery timeout keypress typeahead debouncing
11个回答
164
投票

您必须像以前一样使用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()));
});
<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>

将在以下时间执行:

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

(以先到者为准)


0
投票

在HTML的<input>中使用属性onkeyup =“ myFunction()”。


-2
投票

根据我的想法,当用户不专注于输入内容时,他就会停止写作。为此,您有一个名为“ blur”的函数,该函数可以填充like


65
投票

解决方案:

这里是解决方案。用户停止输入指定的时间后执行功能:

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
  clearTimeout (timer);
  timer = setTimeout(callback, ms);
 };
})();

用法

$('input').keyup(function() {
  delay(function(){
    alert('Hi, func called');
  }, 1000 );
});

16
投票

您可以使用underscore.js“反跳”

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

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

有关其他信息,使用_.debounce(func,timer,true)将意味着将执行第一个功能,而其他所有带有后续500ms计时器的按键事件将被忽略。


9
投票

您需要去抖动!

这里是jQuery plugin,这是您需要了解的有关debounce的全部信息。如果您来自Google,而Underscore已发现进入您应用程序的JSoup的方式,则它会发生反跳baked right in


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

3
投票

我做了一些简单的plugin,确实可以做到这一点。它比拟议的解决方案所需的代码少得多,而且非常轻巧(〜0,6kb)

首先创建Bid对象,然后可以随时创建bumped。每个bump都会在触发下一个给定的时间延迟触发Bid回调。

var searchBid = new Bid(function(inputValue){
    //your action when user will stop writing for 200ms. 
    yourSpecialAction(inputValue);
}, 200); //we set delay time of every bump to 200ms

Bid对象准备好后,我们需要以某种方式将其bump。让我们将碰撞附加到keyup event

$("input").keyup(function(){
    searchBid.bump( $(this).val() ); //parameters passed to bump will be accessable in Bid callback
});

这里发生的是:

每次用户按下键,在接下来的200毫秒内“延迟”(突出)出价。如果200毫秒过去而又没有再次被“颠簸”,则将触发回调。

[此外,您还具有2个附加功能,用于停止出价(例如,如果用户按esc或单击外部输入)以及立即完成并触发回调(例如,当用户按Enter键时:]]]

searchBid.stop();
searchBid.finish(valueToPass);

2
投票

您应将setTimeout分配给变量,并在按键时使用clearTimeout清除它。


1
投票

我一直在寻找简单的HTML / JS代码,但未找到任何代码。然后,我使用onkeyup="DelayedSubmission()"编写了以下代码。


0
投票

为什么只想重设时钟呢?

© www.soinside.com 2019 - 2024. All rights reserved.