2009-09-15 10 views
4

J'utilise ce code pour rechercher environ 500 étiquettes li.Recherche rapide dans une grande liste avec jQuery

$(function() { 

    $.expr[":"].containsInCaseSensitive = function(el, i, m){ 
     var search = m[3]; 
     if (!search) return false; 
     return eval("/" + search + "/i").test($(el).text()); 
    }; 

    $('#query').focus().keyup(function(e){ 
     if(this.value.length > 0){ 
      $('ul#abbreviations li').hide(); 
      $('ul#abbreviations li:containsInCaseSensitive(' + this.value + ')').show(); 
     } else { 
      $('ul#abbreviations li').show();  
     } 
     if(e.keyCode == 13) { 
      $(this).val(''); 
      $('ul#abbreviations li').show(); 
     } 
    }); 

}); 

Et voici le HTML:

<input type="text" id="query" value=""/> 
<ul id="abbreviations"> 
<li>ABC<span>description</span></li> 
<li>BCA<span>description</span></li> 
<li>ADC<span>description</span></li> 
</ul> 

Ce script est très lent avec autant de balises li.

Comment est-ce que je peux le rendre plus rapide, et comment puis-je rechercher seulement le texte ABC dans le li, et pas les balises d'envergure (sans changer le html)?

Je connais les plugins existants, mais j'ai besoin d'une petite implémentation comme celle-ci.

Voici le code fini pour toute personne intéressée

var abbrs = {}; 

$('ul#abbreviations li').each(function(i){ 
    abbrs[this.firstChild.nodeValue] = i; 
}); 

$('#query').focus().keyup(function(e){ 
    if(this.value.length >= 2){ 
     $('ul#abbreviations li').hide(); 
     var filterBy = this.value.toUpperCase(); 
     for (var abbr in abbrs) { 
      if (abbr.indexOf(filterBy) !== -1) { 
       var li = abbrs[abbr]; 
       $('ul#abbreviations li:eq('+li+')').show(); 
      } 
     }  
    } else { 
     $('ul#abbreviations li').show();  
    } 
    if(e.keyCode == 13) { 
     $(this).val(''); 
     $('ul#abbreviations li').show(); 
    } 
}); 

Répondre

7

Cache tous les éléments dans un objet premier:

var abbrs = {}; 

$("ul#abbreviations li").each(function (i) { 
    abbrs[this.firstChild.nodeValue] = this; 
}); 

ensuite chercher le texte tapé dans votre objet:

var li = abbrs[this.value.toUpperCase()]; 
// show li, hide others 

Mise à jour: Pour les correspondances partielles, vous auriez à itérer à travers la collection:

var filterBy = this.value.toUpperCase(); 

for (var abbr in abbrs) { 
    if (abbr.indexOf(filterBy) !== -1) { 
     var li = abbrs[abbr]; 
     // show li 
    } 
} 
+1

+1 Bonne idée, mais cela ne fonctionne correctement que si les valeurs dans li sont uniques. Aussi, vous faites une correspondance exacte. –

+0

Ah ... match partiel ... Eh bien, je suppose que l'ajout de toutes les permutations de sous-chaînes acronyme serait une option laide. –

+0

Quelques erreurs dans le code, il devrait être: var abbrs = {}; \t $ ('abréviations ul n li') chacune (fonction (i) { \t \t abbrs [this.firstChild.nodeValue] = i; \t}). - Comment puis-je faire un match partiel? –

2

Pour commencer, j'utiliser new RegExp au lieu du eval et voir si cette amélioration des performances. Je suppose que vous remplissez dynamiquement les étiquettes li. Existe-t-il un moyen de rechercher la structure de données à partir de laquelle cette liste est remplie directement au lieu de rechercher des objets DOM? Si mon hypothèse n'est pas correcte, pouvez-vous parcourir la liste au début et construire un tableau de chaînes qui peuvent ensuite être recherchées?

Edit: Voici comment vous pouvez construire la liste des chaînes

var listTerms = []; 

$("ul#abbreviations li").each(function (li) { 
    listTerms.push({text : li.firstChild.nodeValue, elem : li}); 
}); 

Voilà comment vous pouvez rechercher (boucle simple, rien de fantaisie)

var exp = new RegExp(text, "i"); 
for(var i=0; i<listTerms.length; i++) { 
    if (exp.match(listTerms[i].text)) { 
     $(listTerms[i].elem).hide(); 
    } 
} 
+0

Je ne remplis pas dynamiquement les étiquettes li. Le contenu est simplement HTML, rien de plus. Pouvez-vous montrer un exemple pour la dernière question? –

0

Je ne suis pas un codeur javascript ou que Je connaissais bien jquery, mais j'ai eu un problème similaire il y a un certain temps avec un arborescence de répertoires js eye-candy pour une proposition de spécification de projet.

La regexp est évidemment votre goulot d'étranglement. Le javascript ne dispose-t-il pas de fonctions de gestion de tableaux efficaces, au lieu de la surcharge totale d'une expression rationnelle? La balise <li> n'est-elle pas déjà analysée dans le tableau DOM lorsque le code HTML est analysé lors du chargement du document? Il devrait être simple de parcourir l'arborescence DOM sur ces noeuds <li>, de les copier dans un tableau, puis d'utiliser une sorte de fonction 'find_value' sur le tableau résultant pour trouver la valeur.

+0

N'est pas le, en effet –

Questions connexes