...

View Full Version : Grouping Checkboxes: How to make a "Heading" Checkbox control subordinate checkboxes?



FastCougar
06-17-2004, 06:18 PM
The title of this thread may seem confusing, but I can't think of a better of describing it. Basically, I need to have groups of checkboxes controlled by a parent checkbox. If I click the parent checkbox, the child checkboxes automatically check. Conversely, if I uncheck the partent checkbox, the child checkboxes uncheck. Finally, the parent checkbox should automatically uncheck if all child checkboxes are not checked. Please see the animation below.

Breakdown:
1) Checking parent checkbox checks all child checkboxes
2) Unchecking parent checkbox unchecks all child checkboxes
3) Parent checkbox should only be checked if all child checkboxes are checked

I'm fairly new to javascript and lack the skills currently to program such functionality. How would I go about programming this type of functionality? Thanks in advance for your help!!!

http://www.cavlog.com/misc/checkboxes.gif

NEExt
06-17-2004, 10:00 PM
I'm new to JS myself, but i like to read these boards cuz i learn alot. That being said, I took a stab at solving your problem because it seemed relatively straightforward.

Like i said, I don't know much about JS. But I do know that there is a far better way to do this than my gross mess of if/then's. However, this works (in IE at least)... and now im gonna go see if I can do it cleaner as further practice.



<html>
<head>
<script language="Jscript">
function checkChecks(el) {
var shortcut = document.box
if (el.name == "master0") {
if (el.checked) {
shortcut.slave00.checked = true
shortcut.slave01.checked = true
shortcut.slave02.checked = true
}
if (!el.checked) {
shortcut.slave00.checked = false
shortcut.slave01.checked = false
shortcut.slave02.checked = false
}
}
if (shortcut.slave00.checked == false || shortcut.slave01.checked == false || shortcut.slave02.checked == false) {
document.box.master0.checked = false
} else {
shortcut.master0.checked = true
}
if (el.name == "master1") {
if (el.checked) {
shortcut.slave10.checked = true
shortcut.slave11.checked = true
shortcut.slave12.checked = true
}
if (!el.checked) {
shortcut.slave10.checked = false
shortcut.slave11.checked = false
shortcut.slave12.checked = false
}
}
if (shortcut.slave10.checked == false || shortcut.slave11.checked == false || shortcut.slave12.checked == false) {
document.box.master1.checked = false
} else {
shortcut.master1.checked = true
}
}
</script>
</head>
<body>
<form name="box" method="" action="">
<p><input type="checkbox" name="master0" value="ON" onclick="checkChecks(this)">master<br>
<input type="checkbox" name="slave00" value="ON" onclick="checkChecks(this)">slave0<br>
<input type="checkbox" name="slave01" value="ON" onclick="checkChecks(this)">slave1<br>
<input type="checkbox" name="slave02" value="ON" onclick="checkChecks(this)">slave2<br></p>

<p><input type="checkbox" name="master1" value="ON" onclick="checkChecks(this)">master<br>
<input type="checkbox" name="slave10" value="ON" onclick="checkChecks(this)">slave0<br>
<input type="checkbox" name="slave11" value="ON" onclick="checkChecks(this)">slave1<br>
<input type="checkbox" name="slave12" value="ON" onclick="checkChecks(this)">slave2<br></p>
</form>
</body>
</html>

FastCougar
06-17-2004, 10:11 PM
Works great in IE/Opera, but I need a true cross browser solution. Time for me to start digging into why this will not work in Mozilla/Firefox. Anyone else have any suggestions/code that might be helpfull?

FastCougar
06-17-2004, 11:44 PM
I found a cross-browser solution on the web after much searching. It involves using a library and then calling it with a new function call. Pretty straight forward formatting. However, this is one catch. I need all my "grouped" values, regardless of which group they are in, to have the same name! This causes a problem with this solution since the name is passed to the library as an attribute. To see what I am talking about here, you will need to download this js source file and then link in in the test page (view code below). Can someone please take a look at the code and tell me if it's even possible to do what I want done? Below are my requirements:

1) All check boxes MUST have the same name attribute.
2) Selecting parent "group" will check all child "grouped" checkboxes.
3) Conversely, Deselecting will uncheck all the boxes FOR THAT GROUP ONLY.
4) If all child "grouped" checkboxes are checked, the parent "group" will be checked.


JS Source File: http://www.mattkruse.com/javascript/checkboxgroup/source.html

Testing Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Untitled</title>
<SCRIPT LANGUAGE="JavaScript" SRC="source/CheckBoxGroup.js"></script>
</head>

<body>
<form name="frmPermissions">
<table>
<tr>
<td colspan="3">Permissions:</td>
</tr>
<SCRIPT LANGUAGE="JavaScript">
var userSettingsGroup = new CheckBoxGroup();
userSettingsGroup.addToGroup("permissionID1");
userSettingsGroup.setControlBox("AllUser");
userSettingsGroup.setMasterBehavior("all");
</SCRIPT>
<tr>
<td><input type="checkbox" name="AllUser" onClick="userSettingsGroup.check(this)"></td>
<td colspan="2">User Settings</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="permissionID" value="1" onClick="userSettingsGroup.check(this)"></td>
<td>Change Password</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="permissionID" value="2" onClick="userSettingsGroup.check(this)"></td>
<td>Change Email Address</td>
</tr>
<SCRIPT LANGUAGE="JavaScript">
var inventoryModuleGroup = new CheckBoxGroup();
inventoryModuleGroup.addToGroup("permissionID2");
inventoryModuleGroup.setControlBox("AllInventory");
inventoryModuleGroup.setMasterBehavior("all");
</SCRIPT>
<tr>
<td><input type="checkbox" name="AllInventory" onClick="inventoryModuleGroup.check(this)"></td>
<td colspan="2">Inventory Module</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="permissionID" value="3" onClick="inventoryModuleGroup.check(this)"></td>
<td>Inquiry</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="permissionID" value="4" onClick="inventoryModuleGroup.check(this)"></td>
<td>Orders</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="checkbox" name="permissionID" value="5" onClick="inventoryModuleGroup.check(this)"></td>
<td>Receivings</td>
</tr>
</table>
</form>

</body>
</html>

sad69
06-18-2004, 01:00 AM
I spent a few hours working on this thing (in between other assignments at work and lunch... :D ) and so even though you've found your solution, I'm posting this one anyway!!

It only seems to work in IE though... but it seems to work well in IE!

If anyone knows how to change it to work in other browsers, I think it's a neat script. (Not sure how many people care about my opinion..)

Sadiq.

neofibril
06-18-2004, 04:19 AM
Breakdown:
1) Checking parent checkbox checks all child checkboxes
2) Unchecking parent checkbox unchecks all child checkboxes
3) Parent checkbox should only be checked if all child checkboxes are checked




<html>
<head>
<script type="text/javascript">

function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.parentNode.parentNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.parentNode.parentNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>

<style type="text/css">
.ckList
{
list-style-type:none;
}
</style>
</head>
<body>
<form>
<ul class="ckList">
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
</ul>
</form>
</body>
</html>



Ok, I've refined the code 5-times, now :D ... get the latest, above.

neofibril
06-18-2004, 02:45 PM
This is just for reference.

I experimented with an expando attribute to handle the state-accounting, instead of using the for() statement.
The extra code required for this will outweigh any efficiency gain, unless there are hundreds of checkboxes, I suspect.

So then, here's how it took shape:


<html>
<head>
<script type="text/javascript">
function ckSum(ckBx)
{
var pNode = ckBx.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckBx.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked,
ckd = pNode.getElementsByTagName("UL")[0].attributes["checkedcount"];
for(; i < boxes.length; i++)
boxes[i].checked = bool;
bool ? ckd.nodeValue = boxes.length - 1 : ckd.nodeValue = 0;
}
function backLash()
{
pNode = pNode.parentNode;
pNode.parentNode.getElementsByTagName("INPUT")[0].checked = false;
var counter = +pNode.getAttribute("checkedcount") - 1;
pNode.attributes["checkedcount"].nodeValue = counter;
}
function countLashings()
{
pNode = pNode.parentNode;
var counter = +pNode.getAttribute("checkedcount") + 1,
boxes = pNode.parentNode.getElementsByTagName("INPUT");
if(counter == boxes.length - 1)
boxes[0].checked = true;
pNode.attributes["checkedcount"].nodeValue = counter;
}
}
</script>
<style type="text/css">
.ckList
{
list-style-type:none;
}
</style>
</head>
<body>
<form>
<ul class="ckList">
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList" checkedcount="0">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList" checkedcount="2">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" checked onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" checked onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
<li master><input type="checkbox" checked onclick="ckSum(this)"><label>Master</label>
<ul class="ckList" checkedcount="3">
<li><input type="checkbox" checked onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" checked onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" checked onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
</ul>
</form>
</body>
</html>


...and that can be consolidated a bit:


<script type="text/javascript">
function ckSum(ckBx)
{
var pNode = ckBx.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
pNode = pNode.parentNode;
var counter = +pNode.getAttribute("checkedcount"),
boxes = pNode.parentNode.getElementsByTagName("INPUT");
if(ckBx.checked)
{
counter = counter + 1;
if(counter == boxes.length - 1)
boxes[0].checked = true;
}
else
{
boxes[0].checked = false;
counter = counter - 1;
}
pNode.attributes["checkedcount"].nodeValue = counter;
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked,
ckd = pNode.getElementsByTagName("UL")[0].attributes["checkedcount"];
for(; i < boxes.length; i++)
boxes[i].checked = bool;
bool ? ckd.nodeValue = boxes.length - 1 : ckd.nodeValue = 0;
}
}
</script>

FastCougar
06-18-2004, 03:36 PM
Great work! Thanks!!! Any way this could be done without using lists?

Just when you think that you got it figured out, along I come and change the assignment :eek:

:D




<html>
<head>
<script type="text/javascript">

function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.parentNode.parentNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.parentNode.parentNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>

<style type="text/css">
.ckList
{
list-style-type:none;
}
</style>
</head>
<body>
<form>
<ul class="ckList">
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
<li master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<ul class="ckList">
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
<li><input type="checkbox" onclick="ckSum(this)"><label>slave</label></li>
</ul>
</li>
</ul>
</form>
</body>
</html>



Ok, I've refined the code 5-times, now :D ... get the latest, above.

FastCougar
06-18-2004, 03:39 PM
I spent a few hours working on this thing (in between other assignments at work and lunch... :D ) and so even though you've found your solution, I'm posting this one anyway!!

It only seems to work in IE though... but it seems to work well in IE!

If anyone knows how to change it to work in other browsers, I think it's a neat script. (Not sure how many people care about my opinion..)

Sadiq.Thanks for working on this! However, I haven't found a solution. The library I linked to above doesn't support using the same name attribute in the checkbox input, which is my #1 requirement. I am using the string of returned values of checkbox (1,5,7,19) to populate a database. So, I MUST use the same checkbox name with different values.

neofibril
06-18-2004, 04:46 PM
Any way this could be done without using lists?
Is there a good reason not to use a list structure?

It seems to be ideal for this.

neofibril
06-18-2004, 05:13 PM
Well, regardless, just keep the relative parentNodes intact, and nothing need be changed.

Here's the same thing with divs:


<html>
<head>
<script type="text/javascript">

function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.parentNode.parentNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.parentNode.parentNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>
</head>
<body>
<form>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
</div>
</div>
<br>
<br>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
<div><input type="checkbox" onclick="ckSum(this)"><label>slave</label></div>
</div>
</div>
</form>
</body>
</html>

FastCougar
06-18-2004, 05:29 PM
Is there a good reason not to use a list structure?

It seems to be ideal for this.

Not really ... just easier to display the exact way I want. Lists hard code the indention spacing and impose unwanted line breaks. Using DIV instead works good, but they are followed by a line break. To ensure no formatting other than what I express, I simply converted all the DIV's to SPAN's and it works just fine.

I can't thank you enough! This works great in all the browsers I have tested in (Mozilla 1.7b/FireFox 0.8/Netscape 7.1/IE 6.0/Opera 7.5).

Quick Question: What version of Javascript is required to be supported to use this? I don't have the means to test this backwards.

neofibril
06-18-2004, 05:37 PM
I'd guess its a matter of browser support for DOM Level 1.

neofibril
06-18-2004, 06:03 PM
To ensure no formatting other than what I express, I simply converted all the DIV's to SPAN's and it works just fine.

Alright, I took out one of the parentNode references, so you won't need to use so many unnecessary elements.


<html>
<head>
<script type="text/javascript">
function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.parentNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.parentNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>
</head>

<body>
<form>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<span>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<span>
</div>
<br>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<span>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<span>
</div>
</form>
</body>
</html>

FastCougar
06-18-2004, 06:44 PM
Alright, I took out one of the parentNode references, so you won't need to use so many unnecessary elements.


<html>
<head>
<script type="text/javascript">
function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(pNode.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.parentNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.parentNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>
</head>

<body>
<form>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<span>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<span>
</div>
<br>
<div master><input type="checkbox" onclick="ckSum(this)"><label>Master</label>
<span>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<span>
</div>
</form>
</body>
</html>

Actually, I reverted back to your original listing structure since I can't get this to work when the span's are seperated with structural eliments like tables and table rows and table data cells.

neofibril
06-18-2004, 07:11 PM
Well, the script can be reduced to a minimum reference level, without changing all code.

This places each checkbox group in a single element, if that makes any difference.


<html>
<head>
<script type="text/javascript">
function ckSum(ckb)
{
var pNode = ckb.parentNode;
if(ckb.getAttributeNode("master"))
return whipAll();
!ckb.checked ? backLash() : countLashings();
function whipAll()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
bool = boxes[0].checked;
for(; i < boxes.length; i++)
boxes[i].checked = bool;
}
function backLash()
{
var master = pNode.getElementsByTagName("INPUT")[0];
master.checked = false;
}
function countLashings()
{
var boxes = pNode.getElementsByTagName("INPUT"),
i = 1,
master = boxes[0];
for(; i < boxes.length; i++)
if(!boxes[i].checked)
break;
if(i == boxes.length)
master.checked = true;
}
}
</script>
</head>

<body>
<form>
<div>
<input master type="checkbox" onclick="ckSum(this)"><label>Master</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
</div>
<br>
<div>
<input master type="checkbox" onclick="ckSum(this)"><label>Master</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
<input type="checkbox" onclick="ckSum(this)"><label>slave</label>
</div>
</form>
</body>
</html>

adios
06-18-2004, 07:45 PM
Just an alternative... ;)


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>Untitled</title>
<style type="text/css">

body {
margin: 20px;
background: ghostwhite;
}
.controls th {
font: bold 12px arial;
text-align: left;
}
.controls td {
padding-left: 48px;
font: normal 11px arial;
}
.controls td.section {
padding: 8px 0 0 24px;
font: bold 11px arial;
}
.controls td.section .master {
width: 60px;
font: normal 9px arial;
background: #eee;
}

</style>
<script type="text/javascript">

onload = function()
{
var input, inputs, form, forms = document.getElementsByTagName('form');
var f = 0, i;
while (form = forms.item(f++))
{
inputs = form.getElementsByTagName('input');
i = 0;
while (input = inputs.item(i++))
{
if (input.className == 'master')
{
input.master_idx = i - 1;
input.onclick = function()
{
var idx = this.master_idx;
var bWhich = (this.value == 'check all');
while (inputs.item(++idx) && inputs.item(idx).className == 'slave')
inputs.item(idx).checked = bWhich;
this.value = (bWhich) ? 'uncheck all' : 'check all';
}
}
else if (input.className == 'slave')
{
var idx = i - 1;
while (inputs.item(idx).className != 'master')
--idx;
input.master_idx = idx;
input.onclick = function()
{
var idx = this.master_idx;
var master = inputs.item(idx);
var checked = unchecked = 0;
while (inputs.item(++idx) && inputs.item(idx).className == 'slave')
(inputs.item(idx).checked) ? ++checked : ++unchecked;
master.value = (checked == 0) ? 'check all' :
(unchecked == 0) ? 'uncheck all' :
master.value;
}
}
}
}
}

</script>
</head>
<body>
<form name="frmPermissions">
<table class="controls">
<thead>
<tr>
<th>Permissions</th>
</tr>
</thead>
<tbody>
<tr>
<td class="section">User Settings_____<input type="button" class="master" value="check all" /></td>
</tr><tr>
<td><input type="checkbox" class="slave" name="permissionID" value="1" />Change Password</td>
</tr><tr>
<td><input type="checkbox" class="slave" name="permissionID" value="2" />Change Email Address</td>
</tr><tr>
<td><input type="checkbox" class="slave" name="permissionID" value="3" />Change Preferences</td>
</tr><tr>
<td class="section">Inventory Module_____<input type="button" class="master" value="check all" /></td>
</tr><tr>
<td><input type="checkbox" class="slave" name="flagelID" value="1" />Inquiry</td>
</tr><tr>
<td><input type="checkbox" class="slave" name="flagelID" value="2" />Orders</td>
</tr><tr>
<td><input type="checkbox" class="slave" name="flagelID" value="3" />Receivings</td>
</tr>
</table>
</form>
</body>
</html>

Microserf
09-01-2005, 02:24 AM
It's been a while since this checkbox group solution was posted but in searching the threads it's a solution to a problem I'm working on that has had me stumped. My checkboxes are in tables which is why this post has helped me a lot over the previous ones in the thread.

Ideally I'd like the parent as a checkbox to control the slave checkboxes instead of a button and I'm trying to work that out now.

Here's a summary:
1) Checking parent checkbox checks all child checkboxes
2) Unchecking parent checkbox unchecks all child checkboxes
3) Parent checkbox should only be checked if all child checkboxes are checked

I'm pretty new to javascript and will eventually figure it out but any help would be great.


Thanks

ca_redwards
09-02-2005, 04:05 AM
checkboxes together with the same name?

Well, even when checkboxes have different names, it can still be done with an alias array.

Consider my form with duplicate name checkboxes...



<form name="myForm">
<input type="checkbox" name="duplicate" />
<input type="checkbox" name="duplicate" />
<input type="checkbox" name="duplicate" />
<input type="checkbox" name="duplicate" />
</form>


In the DOM, document.forms.myForm.duplicate is actually an array. Whenever the first one is clicked, you can just iterate over the others to make them do as the first one does. When any other one is clicked, check the first one, but clear it if any others are found clear.



document.forms.myForm.duplicate[0].onclick=function(){
with(this.form){
for(var i=1;i<duplicate.length;i++)
duplicate[i].checked=this.checked;
}
}
with(document.forms.myForm){
for(var i=1;i<duplicate.length;i++)
duplicate[i].onclick=function(){
with(this.form){
duplicate[0].checked=true;
for(var i=1;i<duplicate.length;i++)
duplicate[0].checked &= duplicate[i].checked;
}
}
}


Of course, you may not be able to name all of your checkboxes alike in your form. Perhaps they are numbered (or named by their meaning) so that each has its own unique name...



<form name="yourForm">
<input type="checkbox" name="unique0" />
<input type="checkbox" name="unique1" />
<input type="checkbox" name="unique2" />
<input type="checkbox" name="unique3" />
</form>


Fortunately, you can still use my same basic code, if you'll just introduce an alias array to effectively name them all the same.



with(document.forms.yourForm)
var duplicate=[unique0,unique1,unique2,unique3];
duplicate[0].onclick=function(){
for(var i=1;i<duplicate.length;i++)
duplicate[i].checked=this.checked;
}
for(var i=1;i<duplicate.length;i++)
duplicate[i].onclick=function(){
duplicate[0].checked=true;
for(var i=1;i<duplicate.length;i++)
duplicate[0].checked &= duplicate[i].checked;
}


But of course, you might not know how many numbered checkboxes you have...



var duplicate=[];
with(document.forms)
while(typeof(yourForm['unique'+duplicate.length])!='undefined')
duplicate[duplicate.length]=yourForm['unique'+duplicate.length];
duplicate[0].onclick=function(){
for(var i=1;i<duplicate.length;i++)
duplicate[i].checked=this.checked;
}
for(var i=1;i<duplicate.length;i++)
duplicate[i].onclick=function(){
duplicate[0].checked=true;
for(var i=1;i<duplicate.length;i++)
duplicate[0].checked &= duplicate[i].checked;
}


I hope this helps.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum