1

I have a javascript function that filter dom elements based on a input text changes, so:

$(".input").keyup(function(e) {
    filter();
});

var cache = $(".dom");

var filter = function() {
     cache.each(function() {
         // if field contains some text show else hide
     }
};

My problem happens when there are many dom elements to filter, the whole pages gets inaccessible because of the synchronous processing (like the example above). Im trying to come out with a solution that dont locks the entire page with synchronous processing.

The problem is NOT related to the filter logic (it's completely trivial), it's NOT related to the jquery or javascript itslef, it's related to the synchronous processing and the quantity of dom elements.

0

5 Answers 5

1

As JavaScript is single threaded, the only real way to sort this out is to split the long-running job into a series of shorter jobs, and use setTimeout() with a short time delay at the end of each section to kick off the next one. This gives your UI and other JavaScript events a chance to update.

Sign up to request clarification or add additional context in comments.

Comments

0

You can update large set of dom nodes by placing them in a queue and process only a few elements on each setTimeout "tick". In pseudo-code:

on(event):
   queue = DOM nodes to be updated
   setTimeout(update)

update:
    queue.slice(0, limit).each(...update a node...)
    queue = queue.slice(limit) // remove processed nodes
    if (queue.length > 0) setTimeout(update) // repeat...

See http://jsfiddle.net/Etsmm/2/ for a complete working example.

Upd: The first version had problems with Chrome (related to its' "display" bug), adding a fix as per this answer appears to have done the trick.

3 Comments

Your jsFiddle example freezes the browser when I type just the number 3.
Your comment in the duplicate question stated "Some people seem to go crazy here. ... Details of the filter() function are irrelevant," But how did you just improve the performance between your first and second versions? Was it in the filter? Yes. Please tell me again that I've gone crazy.
thg, that solution does the same as the one I wrote, but does it in a smarter way, so I'm gonna use it. thank you.
0

Or doing it elsewhere through an ajax request if's really too long ? And, maybe, some kind of: first step, select all IDs to be hidden in an array, then, settimeout, then in a second step, hiding them like 50 per 50 ? Also, maybe processing that having the container of all those elements himself hidden, and then, once done, reshowing it may be faster ?

Comments

0

For this kind of purposes I generally prefer Ben Alman's message queuing library. It has also different alternatives. This one is quite successful on throttling.

https://github.com/cowboy/jquery-message-queuing/

Here below a throttling sample

http://benalman.com/code/projects/jquery-message-queuing/examples/throttling/

Comments

0

thank you all for your help. I came up with a solution based on Ben Clayton response, but Im still looking for ideas and investigating the thg435 solution. Any comments will be apreciated.

    <script type="text/javascript">

        $(document).ready(function () {

            var cache = $(".whatever");
            var wait = 0;
            var input = $("#input");
            var regex = null;

            input.keyup(function (e) {
                go.index = 0;
                clearTimeout(wait);
                wait = setTimeout(go.start, 500);
            });

            var filter = function (i) {
                var one = cache.eq(i - 1);
                one.text().match(regex) ? one.show() : one.hide();
                go.index++;
                setTimeout(go.filter, 10);
            };

            go = {
                index: 0,
                filter: function () {
                    go.index == 0 || go.index > cache.length ? null : filter(go.index);
                },
                start: function () {

                    go.index = 1;

                    var search = input.val();
                    search = search.replace(new RegExp("[a]", "gi"), "[aàáâã]");
                    search = search.replace(new RegExp("[e]", "gi"), "[eéê]");
                    search = search.replace(new RegExp("[i]", "gi"), "[ií]");
                    search = search.replace(new RegExp("[o]", "gi"), "[oóô]");
                    search = search.replace(new RegExp("[u]", "gi"), "[uú]");
                    search = search.replace(new RegExp("[c]", "gi"), "[cç]");
                    regex = new RegExp(search, "gi");

                    go.filter();

                }
            }

        });

    </script>

    <input type="text" id="input" />

    <span class="whatever">lalala</span>
    <span class="whatever">leléLÉ</span>
    <span class="whatever">lololo</span>
    <span class="whatever">lululu</span>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.