最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What's the fastest way to select a large amount of checkboxes and deselect them? - Stack Overflow

programmeradmin6浏览0评论

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>

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>
Share Improve this question edited Jan 24, 2020 at 4:51 ankitkanojia 3,1224 gold badges24 silver badges37 bronze badges asked Apr 13, 2009 at 23:09 rballrball 6,9557 gold badges51 silver badges78 bronze badges 2
  • I don't mean to be unhelpful, but 20k rows in one page is just bad design. You should fix THAT. :) – Paolo Bergantino Commented Apr 13, 2009 at 23:24
  • Well...no kidding. :) I didn't do it! Right now there isn't enough time to fix it for this release. It will be the first thing to do on the next release. This project has brought up many "interesting" challenges so far though. – rball Commented Apr 13, 2009 at 23:31
Add a ment  | 

4 Answers 4

Reset to default 9

input[name=chkbox] is ing 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 ing 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 puter. 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./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?

I haven't tested this, but you could try building an array[] of checkbox references on page load then simply iterate over that each time you want to make a change?

You'd pay the performance cost on page load, but it might be quicker than walking the DOM each time. Hey, at least you'd be performing the heavy lifting in user 'down time' (how long does it take for people to locate and click the unselect/select options).

My only suggestion probably wont work either. Switch browsers. But I've only had one pany actually agree to that. We had the pany switch to FireFox, and specific users move to Google Chrome. IE is just too slow with JavaScript.

Also, you can try pre-caching the jquery query list.

If all else fails, solve it with psychology. That means letting the user know that something is going to take a long time. Put up a "Please wait" div while the function is performing. That way the user knows that the browser isn't just locked up, and they know when they can get back to work. I have had many a slow page "solved" by doing just this.

Have you tried the jQuery selectors with a context to see if that improves performance? Presumably the controls will be inside of an ASP.NET form, and perhaps another uniquely identifiable element?

For example, where you have

$("input[id^='chkbox']")

Try with

$("input[id^='chkbox']", "#myFormID")

Here's a BeardScratchers article on context

EDIT:

Following your updates, it seems like 2.45-6 seconds might be the fastest that you can achieve, given your circumstances.

Just for pleteness, have you tried the following selectors?

$(':checkbox')
$('input[type=checkbox]')
发布评论

评论列表(0)

  1. 暂无评论