2009-06-24 15 views
4

Dans mon formulaire, j'ai un ensemble de zones de saisie dans lesquelles un utilisateur peut entrer une valeur. En cas de changement d'une de ces cases, le formulaire est automatiquement envoyé.Formulaire de soumission automatique après x millisecondes de clavier inactif

Le problème est maintenant que l'utilisateur reste dans le dernier champ, prend la souris et appuie sur le bouton OK (d'une autre forme) sans quitter la zone de texte en premier. L'événement change n'est pas déclenché et les anciennes valeurs incorrectes sont passées à la page suivante.

Je souhaite déclencher l'événement onchange après quelques millisecondes de clavier inactif. Tout comme la plupart des plugins autocomplete.
Je pense que je pourrais implémenter une minuterie qui commence à chronométrer au moment où vous entrez dans un champ de saisie et qui est réinitialisée chaque fois qu'une touche est manipulée, puis quand elle atteint zéro, l'événement onchange est déclenché.

Je ne suis pas prêt à réinventer la roue et je me demandais si une telle fonction est disponible quelque part.
Suggestions?

Répondre

6

J'ai eu un problème similaire et créé un plugin jQuery actuellement utilisé dans une application interne. Il devrait déclencher l'événement de changement après que l'utilisateur a fini de taper.

Si vous n'utilisez pas jQuery, le code est toujours adaptable à toute autre chose.

jQuery.fn.handleKeyboardChange = function(nDelay) 
{ 
    // Utility function to test if a keyboard event should be ignored 
    function shouldIgnore(event) 
    { 
     var mapIgnoredKeys = { 
      9:true, // Tab 
      16:true, 17:true, 18:true, // Shift, Alt, Ctrl 
      37:true, 38:true, 39:true, 40:true, // Arrows 
      91:true, 92:true, 93:true // Windows keys 
     }; 
     return mapIgnoredKeys[event.which]; 
    } 

    // Utility function to fire OUR change event if the value was actually changed 
    function fireChange($element) 
    { 
     if($element.val() != jQuery.data($element[0], "valueLast")) 
     { 
      jQuery.data($element[0], "valueLast", $element.val()) 
      $element.trigger("change"); 
     } 
    } 

    // The currently running timeout, 
    // will be accessed with closures 
    var timeout = 0; 

    // Utility function to cancel a previously set timeout 
    function clearPreviousTimeout() 
    { 
     if(timeout) 
     { 
      clearTimeout(timeout); 
     } 
    } 

    return this 
    .keydown(function(event) 
    { 
     if(shouldIgnore(event)) return; 
     // User pressed a key, stop the timeout for now 
     clearPreviousTimeout(); 
     return null; 
    }) 
    .keyup(function(event) 
    { 
     if(shouldIgnore(event)) return; 
     // Start a timeout to fire our event after some time of inactivity 
     // Eventually cancel a previously running timeout 
     clearPreviousTimeout(); 
     var $self = $(this); 
     timeout = setTimeout(function(){ fireChange($self) }, nDelay); 
    }) 
    .change(function() 
    { 
     // Fire a change 
     // Use our function instead of just firing the event 
     // Because we want to check if value really changed since 
     // our previous event. 
     // This is for when the browser fires the change event 
     // though we already fired the event because of the timeout 
     fireChange($(this)); 
    }) 
    ; 
} 

Utilisation:

$("#my_input").handleKeyboardChange(300).change(function() 
{ 
    // value has changed! 
}); 
+0

bien. Vous avez pris en compte certaines situations Je n'ai pas –

+0

J'ai changé $ element.trigger ("Keyboard.change"); à $ element.trigger ("change"); Était beaucoup mieux alors ma mise en œuvre naïve. –

+0

Oh désolé pour cela, c'était un événement marqué pour cette application spécifique. Vous avez eu raison de le changer et je vais le changer le code ci-dessus. –

0

Je ne sais pas si une telle solution serait considérée comme "réinventant" quoi que ce soit. Comme vous l'avez dit, il semble que ce ne soit rien de plus qu'un simple setTimeout une fois la page chargée. Après environ 3000 millisecondes, il exécute form.submit().

Je recommencerais probablement le compte à rebours avec chaque touche, pour donner à l'utilisateur suffisamment de temps pour faire son entrée.

+0

Vous aviez raison, je l'ai fait. Je suis juste une fosse peur des différences de navigateur dans l'événement de la pression des touches. Jusqu'à présent, aucun problème. –

0

Cela ne fonctionne-t-il pas de faire un onBlur, donc à la fois lorsque l'utilisateur passe au champ suivant ou clique sur autre chose, la valeur est sauvegardée?

+0

le problème se produit lorsque l'utilisateur clique sur le bouton d'envoi qui utilise la valeur actuelle pour aller à une autre page. Il n'y aura pas le temps de soumettre d'abord le formulaire précédent avant de soumettre le formulaire qui va à la page suivante. –