Search code examples
jqueryperformancesearchmobilelivesearch

jQuery filter optimization (slow performance on mobile devices)


I have a list of about 200 items (in table rows):

<tr><td><h5>Title</h5></td>
    <td class="nazwa">some text</td>
    <td>Some additional stuff</td>
</tr>

I created a jQuery function which filters (shows or hides) the items if they match searched string

jQuery.fn.filterItems = function(str){
    var title = jQuery(this).find("h5").text().toLowerCase();
    var name = jQuery(this).find(".nazwa").text().toLowerCase();
    if( title.search( str ) < 0 && name.search( str ) < 0 ){
        jQuery(this).hide().removeClass("visible");
    }
    else{
        jQuery(this).show().addClass("visible");
    }
    return this;
}

Every time user types something into search input it automatically filters the items and shows those matching the input:

jQuery("#search_items").on("input", function(){
        var s = jQuery(this).val();
        if(s != ""){
           jQuery('.list-of-items tr').each(function(){
               jQuery(this).filterItems( s.toLowerCase() );
           });
        }
        else{
            jQuery('.list-of-items tr').show().addClass("visible");
        }
    });

This works fine on PCs, but I have some performance issues on mobile devices. Sometimes there's quite a delay between input and filter reaction.

How can I optimize this live-search in terms of performance/usage of resources?


Solution

  • This could help a bit : https://davidwalsh.name/javascript-debounce-function.

    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    function debounce(func, wait, immediate) {
        var timeout;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
    

    You have to wrap the event function (in your case input) with debounce() from above.

    Just read more about debounce and throttle

    If you have a project which uses angular it will be much more easier and faster : https://docs.angularjs.org/api/ng/filter/filter .