I am trying to implement a function which will uncheck other checkboxes when a new one is clicked. I am doing this instead of using radio because I want the possibility to uncheck by clicking on the subject.
function uncheck(obj) {
var ch = document.getElementsByName('ch');
for (var i = 0; i < ch.length; i++) {
if (ch[i].id != obj.id) {
ch[i].checked = !obj.checked;
break;
}
}
}
<input type="checkbox" name="ch" id="Chapter 1" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 2" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 3" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 4" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 5" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 6" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 7" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 8" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 9" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 10" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 11" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 12" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 13" onclick="uncheck(this)">
<input type="checkbox" name="ch" id="Chapter 14" onclick="uncheck(this)">
However, as the function works now, for some reason, if I check chapter 4, and then check chapter 1, it won’t uncheck chapter 4. And when I uncheck chapter 1, for some reason it checks chapter 2, and if I uncheck chapter 2, it checks chapter 1.
5
Answers
Try this one…
In the code you provided, you are trying to check/uncheck all of the boxes except the one that is clicked but the break makes it only toggle one.
This way, it loops through the entire code setting each checkbox to false except for the one the user clicks on.
If i understand your problem. Then your code is perfectly alright.
JUST REMOVE BREAK FROM YOUR CODE!
Like:
Hope it will help….
Regards
Shawpnendu
coderstechzone
You have a
break
statement in the body of theif
: this will stop the loop on the first element that isn’t the clicked one.Removing that reveals another issue: all the checkboxes will be set when one is clicked, to the inverse of the clicked one’s state. Checking one unchecks all the others, but unchecking one checks all the others. This is because they are set to the inverse of the clicked boxes state, not to unchecked.
A not so consequential issue is using
var
; I will uselet
/const
. Also, for the sake of clarity, I am going to make variable and function names more clear. And reduce the number of boxes.Fixing those yields us this:
That works.
Simplify using iterators
But it can be improved using iterators! The
getElementsByName
method returns aNodeList
, which is iterable; because of this, we can use afor...of
loop.Tada! Much simpler and clearer.
Alternative algorithm
This is the alternative algorithm I suggested: save the state of the clicked box, clear everything, and then set the state of the clicked box.
That satisfies me as to the core algorithm code.
Some other improvements
Some other improvements…
Move the definition of
boxes
out of the handler, so it isn’t recalculated on every click:Use
addEventListener
instead of event attributes (assuming the HTML is static):Use the proper
change
event instead ofclick
.All in all:
Just use radios
Instead of the above, why not use radios? They’re designed for your use case. You said that you "want the possibility to uncheck by clicking on the subject." You can add that to radios. Maybe not easier for you, but less confusing for your users.
This does mean you’ll have to use the
click
event instead of thechange
orinput
events (as far as I can tell). But that is insignificant.You will need to record the previous state to detect if the click is on an already selected radio.
Quoting the OP …
From my above comment …
The next provided example code implements a generic approach for unchecking any radio-group’s last checked radio-control …