Jack M.
Jack M.

Reputation: 2031

Speeding up jQuery/Javascript search function

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

Answers (4)

Victor Radu
Victor Radu

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

Offir
Offir

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:enter image description here.

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

Snake Eyes
Snake Eyes

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

MysterX
MysterX

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

Related Questions