Reputation: 2031
I have a list of over 3000 items with unique names. They are all wrapped inside UL tag like this:
<ul>
<li><a href="#"> Item_ID125167</a></li>
<li><a href="#"> Item_ID146324</a></li>
</ul>
Then I have a search input like this:
<input type="text" id="searchfield" class="form-control" placeholder="Search">
<span class="input-group-addon">
<button type="submit" id="searchButton" onclick="filterByName()">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
And finally a function to hide/show the matching items:
function filterByName() {
$("li").each(function(index) {
if ($(this).children('a').text().toUpperCase().indexOf($("#searchfield").val().toUpperCase()) > -1) {
$(this).css('display', "");
} else {
$(this).css('display', "none");
}
});
}
This feels kind of slow with over 3000 items while using oldish android phone. Is there a better solution for the search function?
Upvotes: 0
Views: 253
Reputation: 2292
speeding it up means you should reuse resources as much as possible
var $list = {}; // initialize an empty global scope variable to keep your elements in
function filterByName(searchString) {
//reusing $list will prefent you from walking the dom each time
$list.each(function(index, el) {
el.style.display = el.title.indexOf(searchString) > -1 ? "list-item" : "none";
});
}
function loadList() {
$list = $('#results').find('li'); //faster than $('#results > li');
$list.each(function(index, el) {
//save the uppercase search values in a propery to search faster
//this saves you from running .toUpperCase() on every search
var text = el.textContent || el.innerText;
el.setAttribute('title', text.trim().toUpperCase()); //using title makes a faster search later
$list[index]=el;
});
}
$(function() {
loadList();
$('#searchButton').click(function(e){
e.preventDefault();
//prepariung the search sring here saves processing during search
filterByName($("#searchfield").val().trim().toUpperCase());
return false;
});
//if your list is build dynamicly simple run loadList() every time changes to the list content may happen
});
see a working fiddle https://jsfiddle.net/q1x7ujex/
Upvotes: 1
Reputation: 3491
From what I tested find
will work faster than children
in this case.
You can run it by your self with Test selectors, or look at the results:.
If you don't feel any improvement in your eyes, you can see the results using the console.time
I added to your function, It will log the time the operation took to the browser.
function filterByName() {
//Instead of selecting the search field + getting it's value + toUpperCase
//*3000 times this way it will only happen once.
var searchVal = $("#searchfield").val().toUpperCase();
//measures the time it takes for the operation
console.time("test");
$("li").each(function() {
//find is faster than children
if ($(this).find("a").text().toUpperCase().indexOf(searchVal >-1)) {
this.style.display = '';
} else {
this.style.display = 'none';
}
});
//Will write to the console the time it the operation took.
console.timeEnd("test");
}
Upvotes: 1
Reputation: 16764
Accordingly with this page: https://learn.jquery.com/performance/optimize-selectors/
You've to use find
instead of children
(it says super-fast)
Other thing you can do is to create an array from that list and use jQuery.inArray
Upvotes: 0
Reputation: 2368
I hope this code will be working a little bit faster then your's. Try it
function filterByName() {
var searchVal = $("#searchfield").val.toUpperCase();
$("li").each(function() {
if (this.children[0].textContent.toUpperCase().match(searchVal)) {
this.style.display = '';
} else {
this.style.display = 'none';
}
});
}
Upvotes: 0