jQuery 停止打字/书写后如何触发输入文本中的事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14042193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 13:12:41  来源:igfitidea点击:

How to trigger an event in input text after I stop typing/writing?

jquerytimeoutkeypresstypeaheaddebouncing

提问by Brad Christie

I want to trigger an event just after I stop typing (not while typing) characters in my input textbox.

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

I've tried with:

我试过:

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

But this example produces a timeout for every typed character and I get about 20 AJAX requests if I type-in 20 characters.

但是这个例子会为每个输入的字符产生一个超时,如果我输入 20 个字符,我会收到大约 20 个 AJAX 请求。

On this fiddleI demonstrate the same problem with a simple alert instead of an AJAX.

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

Is there a solution for this or I'm just using a bad approach for this?

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

回答by Brad Christie

You'll have to use a setTimeout(like you are) but also store the reference so you can keep resetting the limit. Something like:

您必须使用 a 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>

That will execute when:

这将在以下情况下执行:

  1. The timeout has elapsed, or
  2. The user switched fields (blurevent)
  1. 超时已过,或
  2. 用户切换字段(blur事件)

(Whichever comes first)

(以先到者为准)

回答by Ata ul Mustafa

SOLUTION:

解决方案:

Here is the solution. Executing a function after the user has stopped typing for a specified amount of time:

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

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

Usage

用法

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

回答by ScorpionKing2k5

You can use underscore.js "debounce"

您可以使用 underscore.js “去抖动”

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

This means that your function call will execute after 500ms of pressing a key. But if you press another key (another keypress event is fired) before the 500ms, the previous function execution will be ignored (debounced) and the new one will execute after a fresh 500ms timer.

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

For extra info, using _.debounce(func,timer,true) would mean that the first function will execute and all other keypress events withing subsequent 500ms timers would be ignored.

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

回答by Ziggy

You need debounce!

你需要去抖!

Here is a jQuery plugin, and here is all you need to know about debounce. If you are coming here from Google and Underscore has found its way into the JSoup of your app, it has debounce baked right in!

这是一个jQuery 插件,这里是关于debounce 的所有信息。如果您是从 Google 来到这里的,并且 Underscore 已经进入您的应用程序的 JSoup 中,那么它已经!

回答by Matrix

cleaned solution :

清洁溶液:

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

回答by pie6k

There is some simple pluginI've made that does exacly that. It requires much less code than proposed solutions and it's very light (~0,6kb)

我制作了一些简单的插件,可以做到这一点。它需要的代码比提议的解决方案少得多,而且非常轻(~0,6kb)

First you create Bidobject than can be bumpedanytime. Every bumpwill delay firing Bidcallback for next given ammount of time.

首先,您Bid可以bumped随时创建对象。每次碰撞都会在下一个给定的时间内延迟触发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

When Bidobject is ready, we need to bumpit somehow. Let's attach bumping to keyupevent.

Bid对象准备好时,我们需要以bump某种方式。让我们将碰撞附加到keyupevent.

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


What happens here is:

这里发生的是:

Everytime user presses key, bid is 'delayed' (bumped) for next 200ms. If 200ms will pass without beeing 'bumped' again, callback will be fired.

每次用户按下键时,出价会在接下来的 200 毫秒内“延迟”(碰撞)。如果 200 毫秒过去了而没有再次“碰撞”,则将触发回调。

Also, you've got 2 additional functions for stopping bid (if user pressed esc or clicked outside input for example) and for finishing and firing callback immediately (for example when user press enter key):

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

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

回答by Gibin Ealias

You should assign setTimeoutto a variable and use clearTimeoutto clear it on keypress.

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

var timer = '';

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

Fiddle

小提琴

Hope this helps.

希望这可以帮助。

回答by Alfredo Lingoist Jr.

I've been searching for a simple HTML/JS code and I did not found any. Then, I wrote the code below using onkeyup="DelayedSubmission()".

我一直在寻找一个简单的 HTML/JS 代码,但没有找到。然后,我使用onkeyup="DelayedSubmission()".

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
    var date = new Date();
    initial_time = date.getTime();
    if (typeof setInverval_Variable == 'undefined') {
            setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
    } 
}
function DelayedSubmission_Check() {
    var date = new Date();
    check_time = date.getTime();
    var limit_ms=check_time-initial_time;
    if (limit_ms > 800) { //Change value in milliseconds
        alert("insert your function"); //Insert your function
        clearInterval(setInverval_Variable);
        delete setInverval_Variable;
    }
}

</script>
</head>
<body>

<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />

</body>
</html>

回答by insCode

why do that much when you just want to reset a clock ?

当您只想重置时钟时,为什么要做那么多?

var clockResetIndex = 0 ;
// this is the input we are tracking
var tarGetInput = $('input#username');

tarGetInput.on( 'keyup keypress paste' , ()=>{
    // reset any privious clock:
    if (clockResetIndex !== 0) clearTimeout(clockResetIndex);

    // set a new clock ( timeout )
    clockResetIndex = setTimeout(() => {
        // your code goes here :
        console.log( new Date() , tarGetInput.val())
    }, 1000);
});

if you are working on wordpress , then you need to wrap all this code inside an jQuery block :

如果您正在使用 wordpress ,那么您需要将所有这些代码包装在一个 jQuery 块中:

jQuery(document).ready(($) => {
    /**
     * @name 'navSearch' 
     * @version 1.0
     * Created on: 2018-08-28 17:59:31
     * GMT+0530 (India Standard Time)
     * @author : ...
     * @description ....
     */
        var clockResetIndex = 0 ;
        // this is the input we are tracking
        var tarGetInput = $('input#username');

        tarGetInput.on( 'keyup keypress paste' , ()=>{
            // reset any privious clock:
            if (clockResetIndex !== 0) clearTimeout(clockResetIndex);

            // set a new clock ( timeout )
            clockResetIndex = setTimeout(() => {
                // your code goes here :
                console.log( new Date() , tarGetInput.val())
            }, 1000);
        });
});

回答by HesamJafarian

Use the attribute onkeyup="myFunction()" in the <input>of your html.

<input>您的 html 中使用属性 onkeyup="myFunction()" 。