web-dev-qa-db-fra.com

Comment déclencher un événement dans le texte de saisie après avoir cessé de taper/écrire?

Je souhaite déclencher un événement juste après que j'arrête de taper (pas en cours de frappe) des caractères dans la zone de saisie.

J'ai essayé avec:

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

Mais cet exemple produit un délai d'attente pour chaque caractère saisi et je reçois environ 20 demandes AJAX si je saisis 20 caractères.

Sur ce violon Je démontre le même problème avec une alerte simple au lieu d'un AJAX.

Y a-t-il une solution pour cela ou j'utilise simplement une mauvaise approche pour cela?

70
user1386320

Vous devrez utiliser une variable setTimeout (comme ce que vous êtes), mais également stocker la référence afin que vous puissiez réinitialiser la limite. Quelque chose comme:

//
// $('#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>

Cela s'exécutera quand:

  1. Le délai a expiré, ou
  2. L'utilisateur a changé de champs (événement blur)

(Peu importe lequel vient en premier)

154
Brad Christie

SOLUTION:

Voici la solution. Exécution d'une fonction après que l'utilisateur a cessé de taper pendant un laps de temps spécifié

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 );
});
60
Ata ul Mustafa

Vous pouvez utiliser underscore.js "debounce"

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

Cela signifie que votre appel de fonction s’exécutera après 500 ms d’appui sur une touche. Mais si vous appuyez sur une autre touche (un autre événement de frappe est déclenché) avant les 500 ms, l'exécution de la fonction précédente sera ignorée (rebondie) et la nouvelle s'exécutera après un nouveau temporisateur de 500 ms.

Pour plus d’informations, utiliser ___bounce (func, timer, true ) signifierait que la première fonction sera exécutée et que tous les autres événements de pression de touche avec des temporisations de 500 ms seront ignorés.

15
ScorpionKing2k5

Vous avez besoin de debounce!

Voici un plugin jQuery , et voici tout ce que vous devez savoir sur debounce . Si vous venez de Google et que Underscore a trouvé sa place dans le groupe JSoup de votre application, il a rebondi cuit directement dans !

9
Ziggy

solution nettoyée:

$.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
Matrix

Il y a de simples plugins que j'ai créés qui font exactement cela. Il nécessite beaucoup moins de code que les solutions proposées et il est très léger (~ 0,6kb)

Tout d'abord, vous créez un objet Bid pouvant être bumped à tout moment. Chaque bosse retardera le tir rappel pour la prochaine période donnée.

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

Lorsque l'objet Bid est prêt, nous devons le bump en quelque sorte. Attachons bumping à keyupevent.

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

Ce qui se passe ici est:

Chaque fois que l'utilisateur appuie sur la touche, l'enchère est "retardée" pendant 200 ms. Si 200 ms passent sans être à nouveau «repoussé», le rappel est déclenché.

En outre, vous disposez de 2 fonctions supplémentaires pour arrêter l'enchère (si l'utilisateur a appuyé sur la touche Echap ou que l'utilisateur a cliqué en dehors de l'entrée, par exemple) et sur la finition et le rappel immédiat (par exemple lorsque l'utilisateur a appuyé sur la touche Entrée):

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

Je cherchais un code HTML/JS simple et je n’en ai trouvé aucun. Ensuite, j'ai écrit le code ci-dessous en utilisant 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>
1
Alfredo Lingoist Jr.

Vous devez affecter setTimeout à une variable et utiliser clearTimeout pour l'effacer lors de la frappe.

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

J'espère que cela t'aides.

0
Gibin Ealias

pourquoi faire cela quand vous voulez juste réinitialiser une horloge?

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

si vous travaillez sur wordpress, vous devez insérer tout ce code à l'intérieurun bloc 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);
        });
});
0
insCode