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


84

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

我尝试过:

$('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请求。

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

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


1
恐怕javascript不会提供一个事件,当用户停止在输入字段中键入内容时,该事件将使您收到通知。你为什么需要那个?
Darin Dimitrov

3
从示例中可以看出吗?我想触发一个“当最终用户停止输入时”的事件,而不是发送20个请求

1
除非他们手动提交或更改字段,否则无法告诉用户实际上何时完成输入。您如何知道用户是否在句子中间停顿并等待5分钟再输入更多内容?一种可能的解决方案是使用.blur()并在用户焦点离开该字段时发送。
凯文M

14
上面的评论很愚蠢。这是一个常见的用例:当用户完成调整窗口大小,缩放地图,拖动,键入...时,我希望有一个事件。基本上,用户方面的任何连续动作都需要转换为我们的数字世界。即使是单个按键也遭受此问题的困扰:当您敲击某个按键时,它实际上会“弹跳”,不仅会产生一个按键事件,还会产生许多按键事件。您计算机的硬件或操作系统会删除这些额外的事件,这就是为什么我们会有离散按键事件的错觉。这称为“反跳”,这是OP所需要的。
Ziggy

Answers:


172

您必须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事件)

(以先到者为准)


1
是的,这可以节省我的夜晚。谢谢
新手

2
@Brad:此jquery解决方案工作正常,但在最新的chrome(38.0.2125.111)中未检测到输入框中键入的退格键。仅将其更改为keyup有效。您可能需要检查一下并适当地修改代码。
Palerdot 2014年

1
@palerdot:很高兴知道,谢谢。我将对其进行调查,并将所有更改发回。
布拉德·克里斯蒂

3
感谢您使用此插件-效果很好。我必须进行一次调整,因为当有人将某些内容粘贴到输入字段中时,它将无法工作。我编辑了以下线,其中包括paste -$el.is(':input') && $el.on('keyup keypress paste',function(e){
马特·

1
@ Sangar82:现在应该(尽管我有些困惑,但应该通过按键捕获ctrl + v -除非您右键单击->粘贴?)
Brad Christie

71

解:

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

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

1
user1386320-检查此解决方案,我也遇到类似的问题,并且它可以正常工作。您将添加代码代替alert()。
2013年

谢谢。效果很好。
user1919

2
我可以增加N +张投票吗?使用JavaScript闭包,此解决方案出色,简短而优雅。
Matteo Conta

1
@MatteoConta,谢谢您:)
Ata ul Mustafa

1
我不想为此仅将underscore.js包含到我的页面中。您的解决方案完美!谢谢
Skoempie '18

17

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

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

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

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


非常有用,如果您已经将下划线表示为lib,则简短。
Francesco Pasa


6

清洗液:

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

5

您应该分配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
});

小提琴

希望这可以帮助。


3

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

首先,您创建的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

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

1

我一直在寻找简单的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>

0

当您只想重设时钟时,为什么要这样做呢?

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

如果您正在使用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);
        });
});

如果您想扩展jquery并想在多个输入元素中使用此方法,那么批准的答案就是您要寻找的答案。
insCode


-1

在我看来,当用户不专注于输入内容时,他就会停止写作。为此,您有一个名为“ blur”的函数,其功能类似于


4
错误!当焦点丢失在特定输入字段上时,模糊是事件。我需要确定何时在我要触发事件的字段下不使用键盘。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.