2010-03-21 4 views
5

J'ai une zone de texte sur une page Web, dont la valeur que je veux envoyer à un XMLHttpRequest. Maintenant, je veux que l'utilisateur tape simplement la valeur, sans appuyer sur un bouton. Mais si je viens d'envoyer la requête dans les événements du clavier, il se déclenchera à chaque pression sur une touche.Javascript: Traitement lorsque l'utilisateur a cessé de taper

Donc, fondamentalement, je veux quelque chose liek ce

function KeyUpEvent() 
{ 
    if (user is still typing) 
    return; 
    else 
    //do processing 
} 

Ce serait bien si la solution pourrait venir de la plaine ou javascript Mootools. Je ne veux pas utiliser une autre bibliothèque.

+0

Une minuterie ne suffira jamais. L'utilisateur peut simplement être distrait ou taper plus lentement que n'importe quelle fois que vous choisissez comme délai d'expiration. Ma solution est la seule solution raisonnable et c'est la façon dont les utilisateurs s'attendent à interagir avec les champs et elle ne nécessite aucun bouton. Si vous ne connaissez pas la longueur de la valeur, vous n'avez aucune idée si l'utilisateur a terminé. Alors vous risquez de transmettre une valeur que l'utilisateur ne voulait pas ou n'attendait pas et son expérience est simplement frustrée par votre minuterie, pas améliorée. En ce qui concerne l'expérience de l'interface utilisateur, il vaut mieux s'en tenir aux scénarios d'utilisation standard. – nicerobot

Répondre

9

La façon habituelle de procéder est de redémarrer un temporisateur sur l'événement keyup. Quelque chose comme ceci:

var keyupTimer; 
function keyUpEvent(){ 
    clearTimeout(keyupTimer); 
    keyupTimer = setTimeout(sendInput,1000); // will activate when the user has stopped typing for 1 second 
} 

function sendInput(){ 
    alert("Do AJAX request"); 
} 
+0

vous oubliez le clavier, et s'ils décidaient de recommencer à taper dans 30 secondes? votre événement déclenche toujours –

+1

qui n'est pas une réponse valide, qui déclenchera l'événement [nombre de caractères tapés] nombre de fois –

9

Fondamentalement, vous voulez démarrer un minuteur sur KeyUp, et lorsque KeyUp redémarre, réinitialisez le minuteur. Lorsque l'utilisateur arrête de taper, le délai expire et votre requête peut être exécutée à ce moment-là.

Exemple:

var timout_id; 

function keyup_handler(event) { 
    if (timout_id) { 
    clearTimeout(timout_id); 
    } 

    timout_id = setTimeout(function(){ 
    alert('sending data: \n' + event.target.value) 
    }, 800); 
} 

attach Juste la fonction à l'entrée en utilisant votre méthode préférée, et remplacer le alert avec votre action préférée.

Bien sûr, il y a plusieurs façons de généraliser cette approche et de la rendre plus réutilisable, etc., mais je pense que cela illustre l'idée de base.

2

Vous ne savez jamais quand un utilisateur est vraiment "fini" en tapant. L'utilisateur peut prendre une pause d'éternuement, une pause d'étirement ou une pause café, puis continuer à taper. Cependant, si vous implémentez quelque chose comme un mécanisme de saisie semi-automatique, vous pouvez définir un temporisateur (voir window.setTimeout(...)) pour voir si l'utilisateur n'a rien saisi depuis un certain temps. Si vous obtenez un autre événement pendant que la minuterie est en cours d'exécution, vous pouvez recommencer la minuterie.

-1

Utilisez onBlur et peut-être un onKeyDown pour vérifier que l'utilisateur appuie sur la touche Entrée/Retour.

+0

Seriously !? Down-vote ceci quand c'est le seul vrai moyen de savoir quand un utilisateur a fini de taper ?! Autrement dit, ils ont quitté le champ ou appuyé sur une touche indiquant qu'ils veulent soumettre. Sinon, il n'y a aucun moyen de savoir. Pas une minuterie parce qu'ils peuvent avoir été simplement distraits. – nicerobot

5

J'utilise toujours cette fonction simple à manipuler une minuterie, qui déclenche une fonction de rappel, après que l'utilisateur a cessé de taper pendant un laps de temps:

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

Utilisation (exemple avec MooTools):

$('textInput').addEvent('keyup', function(e){ 
    typewatch(function() { 
    // executed only 500 ms after the last keyup event 
    // make Ajax request 
    }, 500); 
}); 

la principale différence entre cette solution et les solutions d'autres réponses est que tous la logique de la minuterie est gérée par la fonction elle-même typewatch, le gestionnaire d'événements n'a pas besoin de connaître un Tout au sujet de la minuterie, il appelle simplement la fonction. De plus, il n'y a pas de variables globales à prendre en compte (l'identificateur de temporisateur est et non stocké dans une variable globale).

1
var keyTimer; 
function onKeyUp(){ 
clearTimeout(keyTimer); 
setTimeout(stoppedTyping,1500); 
} 
function stoppedTyping(){ 
// Profit! $$$ 
} 

EDIT: Bon sang ninjas

0

J'ai écrit un événement jQuery personnalisé parce que j'utilise cette logique beaucoup:

jQuery.event.special.stoppedtyping = { 
    setup: function(data, namespaces) { 
    jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler); 
    }, 
    teardown: function(namespaces) { 
    jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler); 
    }, 
    keyuphandler: function(e) { 
    var interval = 1000; 
    var el = this; 

    if (jQuery.data(this, 'checklastkeypress') != null) { 
     clearTimeout(jQuery.data(this, 'checklastkeypress')); 
    } 

    var id = setTimeout(function() { 
     jQuery(el).trigger('stoppedtyping'); 
    }, interval); 
    jQuery.data(this, 'checklastkeypress', id); 
    } 
}; 

Vous pouvez l'utiliser comme ceci:

$('input.title').bind('stoppedtyping', function() { 
    // run some ajax save operation 
}); 

Pour une raison quelconque, je ne pourrais jamais le faire fonctionner avec .live (...). Je ne sais pas pourquoi ...

Questions connexes