S
Stewart
Dear comp.lang.javascript,
I have more than once wanted to manipulate the contents of select boxes
dynamically, whilst the boxes contain <optgroup> tags.
Manipulation of a select box containing only <option> tags is fairly
easy and there is plenty of material on the net to assist with this.
However, I have searched long and found the material on the subject of
<optgroup> to be sparse, with a few posts here & there, but basically
you're on your own.
After much trial & error regarding techniques for this, I have a fairly
generic solution, which I decided to share, and the code is below. Two
different scenarios I have come across are (1) altering the contents of
one <select> dynamically depending upon another, and (2) being able
click 'up' and 'down' buttons to alter the sequence of the listing
(whilst keeping each <option> within its respective <optgroup>) I tried
various solutions for both of these which tended to either trash the
screen, alter which <optgroup> an <option> was under or trash the
<optgroup>s altogether.
Both these situations can be handled with the solution here. Basically
I keep the <optgroup>s and <option>s stored in an Array(), and then use
the Array() to reconstruct the <select>.
To use, just manipulate the Array() in memory - which I find very easy
- and then call the function to reconstruct.
I like to build the <select> <optgroup> <option> set using HTML as
normal and then create the Array() with <body onload=""> as this makes
it usable where javascript is unavailable, rather than have the Array()
as a hard-coded start point.
Reasonably tested on IE6, known to be buggy on Opera 8 - not sure why.
Constructive comments, insights, additions etc, are welcome.
Thank you,
Stewart
<html>
<head>
<script type="text/javascript">
var selectOptions = new Array(
new Array('Group One',
new Array('Option One', 21),
new Array('Option Two', 22),
new Array('Option Three', 23)),
new Array('Group Two',
new Array('Option Four', 24),
new Array('Option Five', 25),
new Array('Option Six', 26)),
new Array('Group Three',
new Array('Option Seven', 27),
new Array('Option Eight', 28),
new Array('Option Nine', 29)));
function constructArray(list)
{
selectOptions = new Array();
var optgroups = list.childNodes;
var m = 0;
for(i = 0 ; i < optgroups.length ; i++)
{
var n = 1;
if(optgroups.nodeName == 'OPTGROUP')
{
selectOptions[m] = new Array(optgroups.label);
var options = optgroups.childNodes;
for(j = 0 ; j < options.length ; j++)
{
if(options[j].nodeName == 'OPTION')
{
selectOptions[m][n++] =
new Array(options[j].text, options[j].value);
}
}
m++;
}
}
reConstructSelectBox(list);
}
function reConstructSelectBox(list)
{
// Javascript re-indexs after each null or removeChild()
// so we have to count backwards
for(i = list.options.length - 1 ; i >= 0 ; i--)
{
list.options = null;
}
var optgroups = list.childNodes;
for(i = optgroups.length - 1 ; i >= 0 ; i--)
{
list.removeChild(optgroups);
}
var k = 0;
for(i = 0 ; i < selectOptions.length ; i++)
{
var group = selectOptions;
var optgroup = document.createElement('optgroup');
optgroup.label = group[0];
list.appendChild(optgroup);
for(j = 1 ; j < group.length ; j++)
{
var option = new Option(group[j][0], group[j][1]);
list.options[k++] = option;
}
}
}
</script>
</head>
<body onload="constructArray(this.form.list);">
<form method="post" action="" name="form">
<select name="list" size="15" id="list">
<optgroup label="Group One">
<option value="21">Option One</option>
<option value="22">Option Two</option>
<option value="23">Option Three</option>
</optgroup>
<optgroup label="Group Two">
<option value="24">Option Four</option>
<option value="25">Option Five</option>
<option value="26">Option Six</option>
</optgroup>
<optgroup label="Group Three">
<option value="27">Option Seven</option>
<option value="28">Option Eight</option>
<option value="29">Option Nine</option>
</optgroup>
</select>
</body>
</html>
I have more than once wanted to manipulate the contents of select boxes
dynamically, whilst the boxes contain <optgroup> tags.
Manipulation of a select box containing only <option> tags is fairly
easy and there is plenty of material on the net to assist with this.
However, I have searched long and found the material on the subject of
<optgroup> to be sparse, with a few posts here & there, but basically
you're on your own.
After much trial & error regarding techniques for this, I have a fairly
generic solution, which I decided to share, and the code is below. Two
different scenarios I have come across are (1) altering the contents of
one <select> dynamically depending upon another, and (2) being able
click 'up' and 'down' buttons to alter the sequence of the listing
(whilst keeping each <option> within its respective <optgroup>) I tried
various solutions for both of these which tended to either trash the
screen, alter which <optgroup> an <option> was under or trash the
<optgroup>s altogether.
Both these situations can be handled with the solution here. Basically
I keep the <optgroup>s and <option>s stored in an Array(), and then use
the Array() to reconstruct the <select>.
To use, just manipulate the Array() in memory - which I find very easy
- and then call the function to reconstruct.
I like to build the <select> <optgroup> <option> set using HTML as
normal and then create the Array() with <body onload=""> as this makes
it usable where javascript is unavailable, rather than have the Array()
as a hard-coded start point.
Reasonably tested on IE6, known to be buggy on Opera 8 - not sure why.
Constructive comments, insights, additions etc, are welcome.
Thank you,
Stewart
<html>
<head>
<script type="text/javascript">
var selectOptions = new Array(
new Array('Group One',
new Array('Option One', 21),
new Array('Option Two', 22),
new Array('Option Three', 23)),
new Array('Group Two',
new Array('Option Four', 24),
new Array('Option Five', 25),
new Array('Option Six', 26)),
new Array('Group Three',
new Array('Option Seven', 27),
new Array('Option Eight', 28),
new Array('Option Nine', 29)));
function constructArray(list)
{
selectOptions = new Array();
var optgroups = list.childNodes;
var m = 0;
for(i = 0 ; i < optgroups.length ; i++)
{
var n = 1;
if(optgroups.nodeName == 'OPTGROUP')
{
selectOptions[m] = new Array(optgroups.label);
var options = optgroups.childNodes;
for(j = 0 ; j < options.length ; j++)
{
if(options[j].nodeName == 'OPTION')
{
selectOptions[m][n++] =
new Array(options[j].text, options[j].value);
}
}
m++;
}
}
reConstructSelectBox(list);
}
function reConstructSelectBox(list)
{
// Javascript re-indexs after each null or removeChild()
// so we have to count backwards
for(i = list.options.length - 1 ; i >= 0 ; i--)
{
list.options = null;
}
var optgroups = list.childNodes;
for(i = optgroups.length - 1 ; i >= 0 ; i--)
{
list.removeChild(optgroups);
}
var k = 0;
for(i = 0 ; i < selectOptions.length ; i++)
{
var group = selectOptions;
var optgroup = document.createElement('optgroup');
optgroup.label = group[0];
list.appendChild(optgroup);
for(j = 1 ; j < group.length ; j++)
{
var option = new Option(group[j][0], group[j][1]);
list.options[k++] = option;
}
}
}
</script>
</head>
<body onload="constructArray(this.form.list);">
<form method="post" action="" name="form">
<select name="list" size="15" id="list">
<optgroup label="Group One">
<option value="21">Option One</option>
<option value="22">Option Two</option>
<option value="23">Option Three</option>
</optgroup>
<optgroup label="Group Two">
<option value="24">Option Four</option>
<option value="25">Option Five</option>
<option value="26">Option Six</option>
</optgroup>
<optgroup label="Group Three">
<option value="27">Option Seven</option>
<option value="28">Option Eight</option>
<option value="29">Option Nine</option>
</optgroup>
</select>
</body>
</html>