Comment puis-je faire ma recherche jQuery en direct, attendez une seconde avant d'effectuer la recherche?

J'ai une entrée de recherche qui envoie des données d'une entrée à un fichier php lorsque je tape. Le fichier php effectue une recherche sur ma base de données et affiche une liste d'options de recherche. Vous savez, le style ajax recherche en direct.

Mon problème est que, si vous tapez quelque chose de très rapidement, il pourrait simplement effectuer une recherche sur les 1 ou 2 premières lettres, même si 10 autres ont été tapés. Cela pose quelques problèmes.

Mon jquery ressemble un peu comme ceci:

$(document).ready(function(){ $('#searchMe').keyup(function(){ lookup(this.value); }); }); 

et

 function lookup(searchinput) { if(searchinput.length == 0) { // Hide the suggestion box. $("#suggestions").hide(); } else { $('#loading').fadeIn(); $.post("/RPCsearch.php", {queryString: ""+searchinput+""}, function(data){ if(data.length > 0) { $("#suggestions").html(data).show(); $('#loading').fadeOut(); } }); } } // lookup 

Je suis juste curieux, comment puis-je faire pour que mon script attend jusqu'à ce que j'ai fini de taper avant d'exécuter la fonction? Ma logique indique quelque chose comme si une clé n'a pas été pressée pendant 200 secondes, exécutez la fonction, sinon maintenez un peu.

Comment cela se fait-il?

Facile, en utilisant setTimeout . Bien sûr, vous ne voulez qu'un temporisateur aller à la fois, il est donc important d'utiliser clearTimeout au début de la fonction …

 $(function() { var timer; $("#searchMe").keyup(function() { clearTimeout(timer); var ms = 200; // milliseconds var val = this.value; timer = setTimeout(function() { lookup(val); }, ms); }); }); 

Vous pouvez être intéressé par mon mini-plugin jQuery bindDelayed . Il:

  • Permet de spécifier un délai avant de lancer la requête
  • Annule automatiquement toutes les demandes précédentes qui devaient être annulées
  • Annule automatiquement toutes les demandes XHR en direct qui étaient en cours lorsque vous faites votre demande
  • Invoque seulement votre rappel pour la dernière demande
    • Si l'utilisateur tape "s", attend le temps suffisant pour que la demande se déclenche, puis tapez "a", et la réponse pour "s" revient avant la réponse pour "sa", vous ne devrez pas y faire face .

La réponse à la question originale utilisant bindDelayed ressemblerait à ceci:

 // Wait 200ms before sending a request, // avoiding, cancelling, or ignoring previous requests $('#searchMe').bindDelayed('keyup',200,'/RPCsearch.php',function(){ // Construct the data to send with the search each time return {queryString:this.value}; },function(html){ // Use the response, secure in the knowledge that this is the right response $("#suggestions").html(html).show(); },'html','post'); 

Dans le cas où mon site est en panne, voici le code de plugin pour la postérité de Déploiement de Stack:

 (function($){ // Instructions: http://phrogz.net/jquery-bind-delayed-get // Copyright: Gavin Kistner, [email protected] // License: http://phrogz.net/js/_ReuseLicense.txt $.fn.bindDelayed = function(event,delay,url,dataCallback,callback,dataType,action){ var xhr, timer, ct=0; return this.on(event,function(){ clearTimeout(timer); if (xhr) xhr.abort(); timer = setTimeout(function(){ var id = ++ct; xhr = $.ajax({ type:action||'get', url:url, data:dataCallback && dataCallback(), dataType:dataType||'json', success:function(data){ xhr = null; if (id==ct) callback.call(this,data); } }); },delay); }); }; })(jQuery); 

Vous devez vraiment regarder l'utilisation du plugin jQuery autocomplete . Je trouve que ce plugin est très utile et il fait déjà ce dont vous avez besoin. Regardez particulièrement l' option de délai, que vous pouvez personnaliser pour modifier la durée pendant laquelle le plug-in attend après une frappe à exécuter.

1 solution dans psuedocode:

 OnKeyPress() txt = getTxt sleep(200) newTxt = getTxt if (txt == newTxt) // nothing has been typed so do something run my thing 

Celui-ci est content

  $(document).ready(function(){ $("#searchMe").keyup(function () { try{window.clearTimeout(timeoutID);}catch(e){} timeoutID = window.setTimeout(run, 2000); //delay function run() { //dowhatev var text = $("#searchMe").val(); //$("#showit").html(text); } }); }); 

J'ai trouvé le meilleur succès lors de la connexion de l'événement aux entrées de touche, de décompte et de clavier. Safari / FireFox / IE semblent gérer des touches spéciales (suppression, backspace, etc.) un peu différemment, mais l'utilisation de tous les événements ensemble semble le couvrir. La seule façon d'exécuter tous les événements fonctionne cependant est d'utiliser setTimeout afin que, lorsqu'ils déclenchent tous, ils réinitialisent simplement la minuterie et finalement, le rappel ne s'exécute qu'une seule fois.

 var delay = 200; var search_timer = null; $("#searchMe").keydown(function(e) { if(search_timer) { clearTimeout(search_timer); } search_timer = setTimeout(lookup, delay); }); $("#searchMe").keypress(function(e) { if(search_timer) { clearTimeout(search_timer); } search_timer = setTimeout(lookup, delay); }); $("#searchMe").keyup(function(e) { if(search_timer) { clearTimeout(search_timer); } search_timer = setTimeout(lookup, delay); });