2010-02-08 3 views
33

Voici jQuery pour une zone de recherche que je pense est en fait un antimodèle, et je suis sûr qu'il ya une bien meilleure solution pour que j'aimerais être pointé vers:Evénement idiomatique jQuery retardé (seulement après une courte pause lors de la frappe)? (Aka TimeWatch/typewatch/keywatch)

I le décrira dans les commentaires alors donnez simplement le code, puisque les commentaires peuvent être plus clairs et simples que le code:

  • // configurer un appel de fonction à la touche.
  • // l'appel de fonction a un délai avant que l'événement principal ne se produise.
  • // Lorsque vous appuyez sur la touche, effacez tous les événements précédemment mis en file d'attente et créez-en un nouveau au taux de retard standard.
  • // Utilisez un global pour stocker le pointeur setTimeout.
  • // clearTimeout les pointeurs préexistants.
  • // Démarrer un nouveau délai.

Le code:

   // set up a filter function call on keypress. 
       $('#supplier-select-filter').keypress(function(){ 
        // Currently, resets a delay on an eventual filtering action every keypress. 
        filterSuppliers(.3, this); 
       }); 

       // Delayed filter that kills all previous filter request. 
       function filterSuppliers(delay, inputbox){ 
        if(undefined != typeof(document.global_filter_trigger)){ 
         clearTimeout(document.global_filter_trigger); 
         // clearTimeout any pre-existing pointers. 
        } 
        // Use a global to store the setTimeout pointer. 
        document.global_filter_trigger = setTimeout(function(){ 
         var mask = $(inputbox).val(); 
         $('#user_id').load("supplier.php?action=ajax_getsuppliers_html&mask="+escape(mask)); 
        }, 1000*delay); 
        // Finally, after delay is reached, display the filter results.    
       } 

Les problèmes:

Sur une boîte d'entrée où un terme de recherche peut se composer de 10 caractères en moyenne, soit 10 appels à setTimeout dans une demi-seconde, ce qui semble être lourd pour le processeur, et lors de mes tests, cela pose des problèmes de performance, alors j'espère qu'il y a une alternative plus propre? .12 (

.load() est plus simple que de prendre JSON, puis de générer du code HTML à partir de json, mais peut-être qu'il existe un meilleur outil?

.keypress() ne semble pas toujours déclencher sur des choses comme la suppression de retour arrière et d'autres éléments essentiels, alors peut-être que l'utilisation de keypress() sur cette boîte de saisie n'est pas l'idéal?

+0

Petit commentaire - « 10 appels à setTimeout dans une demi-seconde » est pas vraiment un problème de performance, je ne vous en inquiéter du tout. –

Répondre

96

J'utilise souvent l'approche suivante, une fonction simple pour exécuter un rappel, après que l'utilisateur a arrêté la saisie d'une quantité de temps ::

$(selector).keyup(function() { 
    typewatch(function() { 
    // executed only 500 ms after the last keyup event. 
    }, 500); 
}); 

Mise en œuvre:

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

I pense que cette approche est très simple et n'implique aucune variable globale.

Pour des utilisations plus sophistiquées, jetez un oeil à la jQuery TypeWatch Plugin.

+10

Je recommande également de vérifier si current_value! == previous_value dans la fonction de rappel, avant d'aller chercher de nouvelles données via AJAX. Pourrait être que l'utilisateur utilise simplement les touches fléchées, etc –

+0

Huh.Ça a l'air sympa et propre, même si je ne comprends pas vraiment comment le pointeur setTimeout peut être non-global mais toujours accessible plus tard comme un var statique est en php, même si je suis sûr que ça marche. Comment appelle-t-on cela? – Kzqai

+1

@Tchalvak: La variable reste dans la portée de la fonction retournée même si la première fonction a fini son exécution, car une ** fermeture ** est créée, c'est l'une des fonctionnalités les plus puissantes de JavaScript ... Jetez un oeil à cet article: http://www.jibbering.com/faq/faq_notes/closures.html – CMS

3

Jetez un oeil à l'excellent plugin Text Change Event de Zurb, fournisseurs de produits jQuery de la plus haute qualité.

+0

L'OP voulait un rappel après une pause lors de la frappe, ce qui n'est pas le cas du plugin Text Change Event. –

+0

Cela peut aider l'OP à implémenter la fonctionnalité qu'il souhaite. Il _does_ fournit un meilleur événement sur lequel déclencher le rappel retardé. Je ne suis pas le seul sur cette page à suggérer que le rappel ne devrait probablement pas être appelé si le contenu de l'entrée n'a pas changé. –

0

Ceci est une autre bonne façon de le faire, sans utiliser le plug-in:

var timeout; 
$('input[type=text]').keypress(function() { 
if(timeout) { 
    clearTimeout(timeout); 
    timeout = null; 
} 

timeout = setTimeout(myFunction, 5000) 
}) 
Questions connexes