1

I have a form with thousands of checkboxes, and when one is checked, I want to check all the boxes below it. This works:

<html>
<body>
<form name="myform">
<input type="checkbox" name="box1" onClick="redrawboxes(this);">1<br>
<input type="checkbox" name="box2" onClick="redrawboxes(this);">2<br>
...
</form>
</body>
</html>
<script>
function redrawboxes(obj){ 
 //check all boxes below 
 var foundit=false;
 for (e=0; e<document.myform.elements.length; e++){
 if (foundit==false){ //search for checked obj
 if(obj == document.myform.elements[e]){ 
 foundit=true; 
 }
 }else{ //continuing below checked box
 if(obj.checked){ //are we checking or unchecking
 document.myform.elements[e].checked = true;
 }else{
 document.myform.elements[e].checked = false;
 }
 }
 }
}
</script>

but for more than a few thousand boxes, IE is unacceptably slow. (Firefox works fine.) Is there a better way to find the original box besides iterating through the whole list?

asked Feb 2, 2009 at 21:06
3
  • My first question is what the hell are you doing with thousands of checkboxes on a form? :P Commented Feb 2, 2009 at 21:18
  • That was my first thought too... :D Commented Feb 2, 2009 at 21:33
  • It is actually a tree, of thousands of employees, divided by department, discipline, position. I am allowing selecting by any of these groups or individuals. In the actual tree, it doesn't select everything below the checked box, it stops when it jumps up a level on the tree. Commented Feb 3, 2009 at 3:46

5 Answers 5

4

Both of the jQuery suggestions are pretty good. For DOM wrangling like this, you're really better off using a good library.

And the comment about the dubious wisdom of putting thousands of checkboxes on a form is pretty good as well...

But, on the off-chance that you do have a good reason for doing this, and you can't use jQuery or similar, here's a fast, straight JS method:

function redrawboxes(obj)
{ 
 //check all boxes below 
 var next = obj;
 while ( (next = next.nextSibling) )
 {
 if ( next.nodeName.toLowerCase() == "input" 
 && next.type.toLowerCase() == "checkbox" )
 next.checked = obj.checked;
 }
}

tested in FF3, FF3.1, IE6, Chrome 1, Chromium 2

answered Feb 2, 2009 at 21:34
Sign up to request clarification or add additional context in comments.

3 Comments

Maybe one should compare the tagName using a case insensitive method or leave the comparison out if one knows that there are only checkboxes. (As the solution of the asker suggests.)
@gs: nextSibling will pick up all sorts of nodes, not just HTML elements. So even if there are only checkbox fields on the form, we still need to skip past the text nodes.
...as for the tag name comparison, it won't matter for HTML but it's probably a good idea just to be safe if used in XHTML - i'll update it.
3

i might get down voted for this, but try using jquery. it has selectors optimized for that.

answered Feb 2, 2009 at 21:09

Comments

2

Advertising inside !

If you are using jQuery, you can try my plugin to make your loop asynchronous, this will allow to run a long loop without freezing the browser.

http://mess.genezys.net/jquery/jquery.async.php

If you don't want to use jQuery, you can download the plugin and modify the code for your own needs, it does not really depend on jQuery.

answered Feb 2, 2009 at 21:10

Comments

2

You can read out the name of the selected checkbox like this:

function redrawboxes(obj) {
 var name = obj.name;
 var state = obj.checked;
 // get that index
 var index = name.substr(3) * 1; // just to be sure it's a number
 var length = document.myform.elements.length;
 var allElements = document.myform.elements
 // (un)check all elements below
 for (var i = index; i < length; i++) {
 allElements[i].checked = state;
 }
}

You could have sped up your code quite a bit by using local variables and there's an if-statement that can be replaced.

Edit: Actually that one-off-error isn't an error because that specific checkbox was (un)checked by the user himself.

answered Feb 2, 2009 at 21:33

4 Comments

You have an off-by-one error (since his numbering starts with 1). More seriously, this code won't let you uncheck a box by clicking it. And it unchecks every box above the one you clicked.
The off-by-one is my mistake :) The other I've corrected 7 minutes ago. And thanks for the last one, that command is not needed for the code at all, removed it.
Much better - and slightly faster than mine! :-)
That is a very fast method to solve the problem I posed. In my real code, I can't use the name of the field as an index because of the structure of the data, but I did pick up some pointers, like not testing it obj is checking in a loop (duh). Thank you.
2

Dunno how fast it is, but you could try the jQuery-way, grab jQuery from www.jquery.com and insert the following code on the page:

$(function(){
 $("input:checkbox").click(function(){
 $(this).nextAll("input:checkbox").each(function(){
 this.checked = true;
 });
 });
});
answered Feb 2, 2009 at 22:19

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.