2009-09-15 79 views
4

我正在使用此代码来搜索约500个li标签。用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(); 
     } 
    }); 

}); 

这里是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> 

这个脚本是用这么多的李标签很慢。

我该如何加快速度,以及如何在li中搜索槽只有ABC文本,而不是span标签(不更改html)?

我知道现有的插件,但我需要一个像这样的小实现。

这里有兴趣的人

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(); 
    } 
}); 

回答

7

缓存中的所有物品放入一个对象第一:

var abbrs = {}; 

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

然后寻找你的对象中键入的文本:

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

更新:部分匹配,你必须遍历通过收集:

var filterBy = this.value.toUpperCase(); 

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

+1正确的想法,但只有当li内部的值是唯一的时,这才能正确工作。你也正在做一个完全匹配。 – 2009-09-15 21:39:04

+0

啊...部分匹配...嗯,我想添加所有首字母缩略词子串的排列将是一个丑陋的选择。 – 2009-09-15 22:18:59

+0

代码中的一些错误,应该是:var abbrs = {}; \t $( 'UL#缩写立')每个(函数(I){ \t \t abbrs [this.firstChild.nodeValue] = I; \t})。 - 我怎样才能进行部分比赛? – 2009-09-16 18:33:48

2

对于初学者完成的代码,我会用new RegExp代替eval,看看是否有更好的性能。

我假设你是动态填充li标签。有没有一种方法可以直接从这个列表中搜索数据结构,而不是搜索DOM对象?如果我的假设不正确,您是否可以在开始时循环查看列表并构建一组字符串,然后可以搜索这些字符串?

编辑:这里是你如何构建字符串列表

var listTerms = []; 

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

这里是你如何寻找(简单的循环,没有什么花哨)

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

我没有动态填充锂标签。内容只是简单的HTML,仅此而已。你能举出最后一个问题的例子吗? – 2009-09-15 18:45:53

0

我不是一个JavaScript编码器或熟悉jquery,但是前一段时间我有一个类似的问题,那就是针对项目规范提案的js eye-candy目录树。

正则表达式显然是您的瓶颈。 JavaScript没有高效的数组处理函数,而不是正则表达式的全部开销?在文档加载时解析HTML时,<li>标记是否已经解析到DOM数组中?在这些<li>节点上遍历DOM树,将它们复制到数组中,然后在生成的数组上使用'find_value'类型的函数来查找值应该很简单。

+0

是不是,的确, – 2009-09-15 18:17:08