当用户完成输入而不是按键时运行 javascript 函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4220126/
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-23 11:26:20  来源:igfitidea点击:

Run javascript function when user finishes typing instead of on key up?

javascriptjquerykeyboard

提问by David Zorychta

I want to trigger an ajax request when the user has finished typing in a text box. I don't want it to run the function on every time the user types a letter because that would result in A LOT of ajax requests, however I don't want them to have to hit the enter button either.

当用户在文本框中输入完成时,我想触发一个 ajax 请求。我不希望它在每次用户键入字母时都运行该函数,因为这会导致大量的 ajax 请求,但是我也不希望他们必须点击输入按钮。

Is there a way so I can detect when the user has finished typing and then do the ajax request?

有没有办法让我可以检测到用户何时完成输入然后执行 ajax 请求?

Using jQuery here! Dave

在这里使用jQuery!戴夫

回答by Surreal Dreams

So, I'm going to guess finish typing means you just stop for a while, say 5 seconds. So with that in mind, lets start a timer when the user releases a key and clear it when they press one. I decided the input in question will be #myInput.

所以,我猜想完成打字意味着你只是停下来,比如 5 秒。因此,考虑到这一点,让我们在用户释放一个键时启动一个计时器,并在他们按下一个键时清除它。我决定有问题的输入将是#myInput。

Making a few assumptions...

做一些假设...

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example
var $input = $('#myInput');

//on keyup, start the countdown
$input.on('keyup', function () {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$input.on('keydown', function () {
  clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

回答by going

The chosen answer above does not work.

上面选择的答案不起作用。

Because typingTimer is occassionaly set multiple times (keyup pressed twice before keydown is triggered for fast typers etc.) then it doesn't clear properly.

因为 TypingTimer 偶尔会设置多次(在为快速打字机等触发 keydown 之前按两次 keyup),所以它不能正确清除。

The solution below solves this problem and will call X seconds after finished as the OP requested. It also no longer requires the redundant keydown function. I have also added a check so that your function call won't happen if your input is empty.

下面的解决方案解决了这个问题,并会在完成 OP 请求后调用 X 秒。它也不再需要冗余的 keydown 功能。我还添加了一个检查,以便在您的输入为空时不会发生您的函数调用。

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on keyup, start the countdown
$('#myInput').keyup(function(){
    clearTimeout(typingTimer);
    if ($('#myInput').val()) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

And the same code in vanilla JavaScript solution:

和 vanilla JavaScript 解决方案中的相同代码:

//setup before functions
let typingTimer;                //timer identifier
let doneTypingInterval = 5000;  //time in ms (5 seconds)
let myInput = document.getElementById('myInput');

//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

This solution does use ES6 but it's not necessary here. Just replace letwith varand the arrow function with a regular function.

这个解决方案确实使用了 ES6,但这里没有必要。只需将letwithvar和箭头函数替换为常规函数即可。

回答by bit2pixel

It's just one linewith underscore.jsdebounce function:

它只是带有underscore.js去抖动功能的一行

$('#my-input-box').keyup(_.debounce(doSomething , 500));

This basically says doSomething500 milliseconds after I stop typing.

这基本上是说在我停止打字后 500 毫秒执行doSomething

For more info: http://underscorejs.org/#debounce

更多信息:http: //underscorejs.org/#debounce

回答by Marko

Yes, you can set a timeout of say 2 seconds on each and every key up event which will fire an ajax request. You can also store the XHR method and abort it on subsequent key press events so that you save bandwith even more. Here's something I've written for an autocomplete script of mine.

是的,您可以在每个按键事件上设置 2 秒的超时时间,这将触发 ajax 请求。您还可以存储 XHR 方法并在随后的按键事件中中止它,以便您节省更多带宽。这是我为我的自动完成脚本编写的内容。

var timer;
var x;

$(".some-input").keyup(function () {
    if (x) { x.abort() } // If there is an existing XHR, abort it.
    clearTimeout(timer); // Clear the timer so we don't end up with dupes.
    timer = setTimeout(function() { // assign timer a new timeout 
        x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
    }, 2000); // 2000ms delay, tweak for faster/slower
});

Hope this helps,

希望这可以帮助,

Marko

马可

回答by azzy81

var timer;
var timeout = 1000;

$('#in').keyup(function(){
    clearTimeout(timer);
    if ($('#in').val) {
        timer = setTimeout(function(){
            //do stuff here e.g ajax call etc....
             var v = $("#in").val();
             $("#out").html(v);
        }, timeout);
    }
});

full example here: http://jsfiddle.net/ZYXp4/8/

完整示例:http: //jsfiddle.net/ZYXp4/8/

回答by YSFKBDY

Both top 2 answers doesn't work for me. So, here is my solution:

前两个答案对我都不起作用。所以,这是我的解决方案:

var timeout = null;

$('#myInput').keyup(function() {
    clearTimeout(timeout);

    timeout = setTimeout(function() {
        //do stuff here
    }, 500);
});

回答by Liam Flanagan

I like Surreal Dream's answer but I found that my "doneTyping" function would fire for every keypress, i.e. if you type "Hello" really quickly; instead of firing just once when you stop typing, the function would fire 5 times.

我喜欢超现实梦的回答,但我发现我的“doneTyping”功能会在每次按键时触发,也就是说,如果你真的很快地输入“Hello”;当您停止输入时,该函数将触发 5 次,而不是仅触发一次。

The problem was that the javascript setTimeout function doesn't appear to overwrite or kill the any old timeouts that have been set, but if you do it yourself it works! So I just added a clearTimeout call just before the setTimeout if the typingTimer is set. See below:

问题是 javascript setTimeout 函数似乎不会覆盖或终止已设置的任何旧超时,但是如果您自己这样做,它就可以工作!因此,如果设置了 TypingTimer,我只是在 setTimeout 之前添加了一个 clearTimeout 调用。见下文:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example

//on keyup, start the countdown
$('#myInput').on("keyup", function(){
    if (typingTimer) clearTimeout(typingTimer);                 // Clear if already set     
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$('#myInput').on("keydown", function(){
    clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

N.B. I would have liked to have just added this as a comment to Surreal Dream's answer but I'm a new user and don't have enough reputation. Sorry!

注意,我本来希望将其添加为对超现实梦的答案的评论,但我是新用户并且没有足够的声誉。对不起!

回答by Jecoms

Modifying the accepted answer to handle additional cases such as paste:

修改接受的答案以处理其他情况,例如粘贴:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 2000;  //time in ms, 2 second for example
var $input = $('#myInput');

// updated events 
$input.on('input propertychange paste', function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);      
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

回答by Rafal Pastuszak

I don't think keyDown event is necessary in this case (please tell me why if I'm wrong). In my (non-jquery) script similar solution looks like that:

我认为在这种情况下不需要 keyDown 事件(如果我错了,请告诉我为什么)。在我的(非 jquery)脚本中,类似的解决方案如下所示:

var _timer, _timeOut = 2000; 



function _onKeyUp(e) {
    clearTimeout(_timer);
    if (e.keyCode == 13) {      // close on ENTER key
        _onCloseClick();
    } else {                    // send xhr requests
        _timer = window.setTimeout(function() {
            _onInputChange();
        }, _timeOut)
    }

}

It's my first reply on Stack Overflow, so I hope this helps someone, someday:)

这是我对 Stack Overflow 的第一个回复,所以我希望这对某人有帮助,有一天:)

回答by Fabian Bigler

Declare the following delayfunction:

声明以下delay函数:

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

and then use it:

然后使用它:

let $filter = $('#item-filter');
$filter.on('keydown', function () {
    delay(function () {            
        console.log('this will hit, once user has not typed for 1 second');            
    }, 1000);
});