Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the fastest way to select a large amount of checkboxes and de/select them?

Since I use jQuery 1.3+ all except one timed test is using that. The other is plain javascript I found from back in 2000. I stopped going that route as it was taking around 150 seconds to run the test. I've read quite a few jQuery optimization web pages that relate to selecting a single element. A '#id' is the best case for using that, but now I have the issue of checking all checkboxes in one column in a rather large table that has multiple checkbox columns.

What I have done is setup a page the creates 20,000 table rows with two check box columns. The goal is to check the second column see how long that took, and then uncheck them and see how long that took. Obviously we want the lowest time. I'm only using IE6 and 7 and in my case all of my users will be doing the same.

20,000 rows you say? That's what I said too, but this is going to production (out of my hands) and it's too late to change now. I'm just trying to throw a hail mary with 1 second left on the clock. Besides, I've learned that input.chkbox isn't the fastest selector (for IE7)! :)

The question is, is there a better way to do this jQuery or otherwise? I'd love it to be running in less than half a second on my machine.

So you don't have to retype all the crap I've already done here's the test stuff I came up with:

Updated Morning 4/14 to include further time trials:

<form id="form1" runat="server">
    <div>
        <a href="#" id="one">input[id^='chkbox'][type='checkbox']</a><br />
        <a href="#" id="two">#myTable tr[id^='row'] input[id^='chkbox'][type='checkbox']</a><br />
        <a href="#" id="three">#myTable tr.myRow input[id^='chkbox'][type='checkbox']</a><br />
        <a href="#" id="four">tr.myRow input[id^='chkbox'][type='checkbox']</a><br />
        <a href="#" id="five">input[id^='chkbox']</a><br />
        <a href="#" id="six">.chkbox</a><br />
        <a href="#" id="seven">input.chkbox</a><br />
        <a href="#" id="eight">#myTable input.chkbox</a><br />

        <a href="#" id="nine">"input.chkbox", "tr"</a><br />
        <a href="#" id="nine1">"input.chkbox", "tr.myRow"</a><br />
        <a href="#" id="nine2">"input.chkbox", "#form1"</a><br />
        <a href="#" id="nine3">"input.chkbox", "#myTable"</a><br />

        <a href="#" id="ten">input[name=chkbox]</a><br />
        <a href="#" id="ten1">"input[name=chkbox]", "tr.myRow"</a><br />
        <a href="#" id="ten2">"input[name=chkbox]", "#form1"</a><br />
        <a href="#" id="ten3">"input[name=chkbox]", "#myTable"</a><br />

        <a href="#" id="ten4">"input[name=chkbox]", $("#form1")</a><br />
        <a href="#" id="ten5">"input[name=chkbox]", $("#myTable")</a><br />

        <a href="#" id="eleven">input[name='chkbox']:checkbox</a><br />
        <a href="#" id="twelve">:checkbox</a><br />
        <a href="#" id="twelve1">input:checkbox</a><br />
        <a href="#" id="thirteen">input[type=checkbox]</a><br />

        <div>
            <input type="text" id="goBox" /> <button id="go">Go!</button>
            <div id="goBoxTook"></div>
        </div>

        <table id="myTable">
            <tr id="headerRow"><th>Row #</th><th>Checkboxes o' fun!</th><th>Don't check these!</th></tr>
            <% for(int i = 0; i < 20000;i++) { %>
            <tr id="row<%= i %>" class="myRow">
                <td><%= i %> Row</td>
                <td>
                    <input type="checkbox" id="chkbox<%= i %>" name="chkbox" class="chkbox" />
                </td>
                <td>
                    <input type="checkbox" id="otherBox<%= i %>" name="otherBox" class="otherBox" />
                </td>
            </tr>
            <% } %>
        </table>
    </div>

    <script type="text/javascript" src="<%= ResolveUrl(" ~/") %>Javascript/jquery.1.3.1.min.js"></script>
    <script type="text/javascript">

        $(function () {
            function run(selectorText, el) {
                var start = new Date();
                $(selectorText).attr("checked", true);
                var end = new Date();
                var timeElapsed = end - start;
                $(el).after("<br />Checking Took " + timeElapsed + "ms");

                start = new Date();
                $(selectorText).attr("checked", false);
                end = new Date();
                timeElapsed = end - start;
                $(el).after("<br />Unchecking Took " + timeElapsed + "ms");
            }

            function runWithContext(selectorText, context, el) {
                var start = new Date();
                $(selectorText, context).attr("checked", true);
                var end = new Date();
                var timeElapsed = end - start;
                $(el).after("<br />Checking Took " + timeElapsed + "ms");

                start = new Date();
                $(selectorText, context).attr("checked", false);
                end = new Date();
                timeElapsed = end - start;
                $(el).after("<br />Unchecking Took " + timeElapsed + "ms");
            }

            $("#one").click(function () {
                run("input[id^='chkbox'][type='checkbox']", this);
            });

            $("#two").click(function () {
                run("#myTable tr[id^='row'] input[id^='chkbox'][type='checkbox']", this);
            });

            $("#three").click(function () {
                run("#myTable tr.myRow input[id^='chkbox'][type='checkbox']", this);
            });

            $("#four").click(function () {
                run("tr.myRow input[id^='chkbox'][type='checkbox']", this);
            });

            $("#five").click(function () {
                run("input[id^='chkbox']", this);
            });

            $("#six").click(function () {
                run(".chkbox", this);
            });

            $("#seven").click(function () {
                run("input.chkbox", this);
            });

            $("#eight").click(function () {
                run("#myTable input.chkbox", this);
            });

            $("#nine").click(function () {
                runWithContext("input.chkbox", "tr", this);
            });


            $("#nine1").click(function () {
                runWithContext("input.chkbox", "tr.myRow", this);
            });
            $("#nine2").click(function () {
                runWithContext("input.chkbox", "#form1", this);
            });
            $("#nine3").click(function () {
                runWithContext("input.chkbox", "#myTable", this);
            });

            $("#ten").click(function () {
                run("input[name=chkbox]", this);
            });

            $("#ten1").click(function () {
                runWithContext("input[name=chkbox]", "tr.myRow", this);
            });

            $("#ten2").click(function () {
                runWithContext("input[name=chkbox]", "#form1", this);
            });

            $("#ten3").click(function () {
                runWithContext("input[name=chkbox]", "#myTable", this);
            });

            $("#ten4").click(function () {
                runWithContext("input[name=chkbox]", $("#form1"), this);
            });

            $("#ten5").click(function () {
                runWithContext("input[name=chkbox]", $("#myTable"), this);
            });

            $("#eleven").click(function () {
                run("input[name='chkbox']:checkbox", this);
            });

            $("#twelve").click(function () {
                run(":checkbox", this);
            });

            $("#twelve1").click(function () {
                run("input:checkbox", this);
            });

            $("#thirteen").click(function () {
                run("input[type=checkbox]", this);
            });

            $('#go').click(function () {
                run($('#goBox').val(), this);
            });
        });
    </script>
</form>
like image 340
rball Avatar asked Apr 13 '09 23:04

rball


1 Answers

input[name=chkbox] is coming in as the fastest jQuery selector on my machine under IE7.

Unchecking Took 2453ms
Checking Took 2438ms
Unchecking Took 2438ms
Checking Took 2437ms
Unchecking Took 2453ms
Checking Took 2438ms

input.chkbox and...

Unchecking Took 2813ms
Checking Took 2797ms
Unchecking Took 2797ms
Checking Took 2797ms
Unchecking Took 2813ms
Checking Took 2797ms

input:checkbox.chkbox seem tied

Unchecking Took 2797ms
Checking Took 2797ms
Unchecking Took 2813ms
Checking Took 2781ms

.chkbox almost takes twice as long as the input.chkbox

Unchecking Took 4031ms
Checking Took 4062ms
Unchecking Took 4031ms
Checking Took 4062ms

The javascript for loop is by far the worst coming in at:

Checking Took 149797ms

150 seconds! It locks the browser too. This just makes me really impressed with jQuery. I honestly didn't expect it to be that slow. Probably because I'm passing across each individual element which it's then having to find...

This was pretty interesting to me as well:

input[id^='chkbox']

Unchecking Took 3031ms
Checking Took 3016ms

took less time than:

input[id^='chkbox'][type='checkbox']

Unchecking Took 3375ms
Checking Took 3344ms

I thought since I posted more filters it'd be faster. Nope!

Specifying even more paths to the checkbox makes it way slower:

#myTable tr[id^='row'] input[id^='chkbox'][type='checkbox']

Checking Took 10422ms

It didn't even run the second uncheck as it asked me if I wanted to continue running scripts on my computer. Crazy! :P

Update Morning 4/14:

Someone brought up setting the context: I actually did a few of those and much to my suprise and against what a lot of people have said on the web on IE7 these were slower! Here are the times I got with a few different context's specified paired with the quicker selector's above:

"input.chkbox", "tr"

Checking Took 8546ms

"input.chkbox", "tr.myRow"

Checking Took 8875ms

"input.chkbox", "#form1"

Unchecking Took 3032ms
Checking Took 3000ms

"input.chkbox", "#myTable"

Unchecking Took 2906ms
Checking Took 2875ms

Current winner (still): input[name=chkbox]

Unchecking Took 2469ms
Checking Took 2453ms

"input[name=chkbox]", "tr.myRow"

Checking Took 9547ms

"input[name=chkbox]", "#form1"

Unchecking Took 3140ms
Checking Took 3141ms

"input[name=chkbox]", "#myTable"

Unchecking Took 2985ms
Checking Took 2969ms

Update 2 Morning 4/14

Thought I might have had a better one after I noticed a syntax difference from http://beardscratchers.com/journal/jquery-its-all-about-context. It seems that these are NOT the same as they are giving slightly better times, but still doesn't beat the non-contexted selector - darn.

"input[name=chkbox]", $("#form1")

Unchecking Took 3078ms
Checking Took 3000ms
Unchecking Took 3078ms
Checking Took 3016ms

"input[name=chkbox]", $("#myTable")

Unchecking Took 2938ms
Checking Took 2906ms
Unchecking Took 2938ms
Checking Took 2921ms

Update 3 Morning 4/14

Russ wanted me to try these out, they de/select ALL the boxes but again it was interesting:

:checkbox

Unchecking Took 8328ms
Checking Took 6250ms

input:checkbox

Unchecking Took 5016ms
Checking Took 5000ms

-> Fastest?!?! input[type=checkbox]

Unchecking Took 4969ms
Checking Took 4938ms

The fact that the third up there is the fastest is quite interesting as that goes against what I would have thought. Why wouldn't (for IE7 at least) the :checkbox just use the type=checkbox to achieve a faster time? These are really close scores but the checking took 62ms less time. Also, why are the first two different at all? Is there a different element besides an input that can take have a checkbox?

like image 121
rball Avatar answered Oct 18 '22 19:10

rball