입력 / 쓰기를 중지 한 후 입력 텍스트에서 이벤트를 트리거하는 방법은 무엇입니까?


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
사용자가 입력 필드에 입력하는 것을 중지 할 때 알림을받을 수있는 이벤트를 자바 스크립트가 제공하지 않는 것이 두렵습니다. 왜 필요합니까?
Darin Dimitrov

3
예에서 분명하지 않습니까? 20 개의 요청을 보내는 대신 "최종 사용자가 입력을 중지 할 때"이벤트를 트리거하고 싶습니다

1
사용자가 필드를 수동으로 제출하거나 변경하지 않는 한 사용자가 실제로 입력을 완료했는지 알 수있는 방법이 없습니다. 사용자가 문장 중간을 멈추고 5 분 동안 기다렸다가 더 입력하는지 어떻게 알 수 있습니까? 가능한 해결책은 .blur ()를 사용하고 사용자가 포커스를 필드에서 벗어날 때 전송하는 것입니다.
Kevin M

14
위의 댓글은 어리 석습니다. 이것은 일반적인 사용 사례입니다. 사용자가 창 크기 조정,지도 확대 / 축소, 끌기, 입력 ... 기본적으로 사용자가 수행하는 모든 지속적인 작업을 디지털 세계로 변환해야 할 때 하나의 이벤트를 원합니다. 키를 한 번만 입력해도이 문제가 발생합니다. 키를 치면 실제로 "바운스"되어 하나의 키 입력 이벤트가 아니라 여러 번 생성됩니다. 컴퓨터의 하드웨어 또는 OS는 이러한 추가 이벤트를 제거하기 때문에 이산 키 입력 이벤트의 착각이 발생합니다. 이것을 "디 바운싱"이라고하며 이것이 OP에 필요한 것입니다.
Ziggy 2011

사용자 반응에 대한 경고 : stackoverflow.com/a/28046731/57883
매스로 우는

답변:


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 솔루션은 입력 상자에 입력 된 백 스페이스 키가 최신 크롬 (38.0.2125.111)에서 감지되지 않는 것을 제외하고는 잘 작동합니다. keyup작동 하도록 변경 합니다. 이를 검사하고 코드를 적절하게 수정할 수 있습니다.
palerdot 2014 년

1
@palerdot : 알아서 감사합니다. 나는 그것을 조사하고 변경 사항을 다시 게시하겠습니다.
Brad Christie

3
이 플러그인에 감사드립니다-훌륭하게 작동합니다. 누군가 입력 필드에 무언가를 붙여 넣으면 작동하지 않기 때문에 한 번 조정해야했습니다. 나는 포함하는 다음 행을 편집 paste -$el.is(':input') && $el.on('keyup keypress paste',function(e){
매트

1
@ Sangar82 : 나는 혼란 좀 해요 비록한다 이제 (Ctrl + V 키 누르기에 의해 캡처되어야한다 -하지 않는 한있는 거 마우스 오른쪽 클릭 -> 붙여 넣기?
브래드 크리스티

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 () 대신 코드를 추가합니다.
Ata ul Mustafa

감사. 잘 작동합니다.
user1919

2
N + Up 투표를 추가해도됩니까? 이 솔루션은 JavaScript 클로저를 사용하여 훌륭하고 짧으며 우아합니다.
Matteo Conta 16.10.14

1
@MatteoConta, 감사합니다 :)
Ata ul Mustafa

1
나는 이것을 위해 underscore.js를 내 페이지에 포함하고 싶지 않았습니다. 솔루션이 완벽하게 작동합니다! 감사합니다
Skoempie 2018

17

underscore.js "debounce"를 사용할 수 있습니다.

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

즉, 500ms의 키를 누른 후에 함수 호출이 실행됩니다. 그러나 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. 모든 범프 는 다음 주어진 시간 동안 입찰 콜백 실행을 지연 시킵니다.

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

여기서 일어나는 일은 다음과 같습니다.

사용자가 키를 누를 때마다 입찰은 다음 200ms 동안 '지연'(범프)됩니다. 다시 '충돌'하지 않고 200ms가지나 가면 콜백이 실행됩니다.

또한 입찰 중지 (예 : 사용자가 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
잘못된! 흐림은 특정 입력 필드에서 포커스를 잃을 때 발생하는 이벤트입니다. 내가 필요한 것은 이벤트를 트리거하려는 해당 필드에서 키보드가 사용되지 않는 경우를 결정하는 것입니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.