Roelf
02-25-2003, 02:13 PM
Hi,
finally i created something which i think is useful, so i am going to post it here. I see a lot of questions about connecting dropdown elements together, where the options in the second dd are depending on the selection in the first. People even want to connect three of them together. My thinkin was, why not make it as flexible as possible. Imagine a hierarchy of choices, where neither branche of the hierarchy is as deep as another one. I want to make a dd with variable levels so a dd contains all the children of a certain level of the hierarchy. After a selection is made, the script checks if the hierarchy has children in the next level. When a selection is altered, the deeper dd's are removed and created again with the proper options.
All is based on a xml-file which holds the dropdowndata and a function in a html-file to read it and create the drop downs where they are needed
Points to improve:
- make it x-browser compatible (currently tested in IE5.5)
- perhaps the inputfile (xml) should be changed so the name and (if added) the value, or the caption shouldn't be attributes of an element, but a child-element
- code efficiency
- get the maxdepth variable dynamically, by analyzing the contents of the xml before processing
- create positions to put the captions and the dd's dynamically, based on the xml-data instead of fixing them in the html file
- make the xml more strict, add a dtd or something like that
- lay-out aspects
- whatever you can think of
I am not an xml-expert, neither am i a javascript expert. I managed to create this, it works the way i intended, i leave it up to you guys to improve it....
Improved versions will be used by me ofcourse :D
Roelf
file: dropdowndata.xml
<ddlevel0 name="geo" caption="Select a continent">
<ddlevel1 name="North America" caption="Select a country">
<ddlevel2 name="United States" caption="Select a state">
<ddlevel3 name="Arkansas" caption="Select a city">
<ddlevel4 name="City 1 in arkansas" />
<ddlevel4 name="City 2 in arkansas" />
<ddlevel4 name="City 3 in arkansas" caption="Perhaps you want to select a street">
<ddlevel5 name="Street1" />
<ddlevel5 name="Street2" />
<ddlevel5 name="Street3" />
</ddlevel4>
</ddlevel3>
<ddlevel3 name="Texas" caption="Select a city">
<ddlevel4 name="City 1 in Texas" />
<ddlevel4 name="City 2 in Texas" />
<ddlevel4 name="City 3 in Texas" />
</ddlevel3>
<ddlevel3 name="Another state" caption="Select a city">
<ddlevel4 name="City 1 in another state" />
<ddlevel4 name="City 2 in another state" />
<ddlevel4 name="City 3 in another state" />
<ddlevel4 name="City 4 in another state" />
<ddlevel4 name="City 5 in another state" />
<ddlevel4 name="City 6 in another state" />
</ddlevel3>
</ddlevel2>
<ddlevel2 name="Canada" caption="Select a city">
<ddlevel3 name="Montreal" />
<ddlevel3 name="Some city in Canada" />
<ddlevel3 name="Some other city" />
<ddlevel3 name="Yet another one in canada" />
</ddlevel2>
</ddlevel1>
<ddlevel1 name="Africa" caption="Select a county">
</ddlevel1>
<ddlevel1 name="Europe" caption="Select a country">
</ddlevel1>
<ddlevel1 name="Australia" caption="Select a city">
<ddlevel2 name="Sidney" />
<ddlevel2 name="Canberra" />
<ddlevel2 name="Another one in Australia" />
<ddlevel2 name="Aussie city" />
</ddlevel1>
</ddlevel0>
file: thehtml.html
<html>
<head>
<title>testdocument</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" language="JavaScript">
/*********************************************
* Dynamic connected dropdown menus Version 1.0
* Script created by Roelf Prakken
* email: r.prakken@home.nl
*********************************************/
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.load("dropdowndata.xml");
var maxlevel = 5;
function createdropdown (level, selectiontocreate) {
// first, delete all selects and captions from previously made selections in this hierarchy level
for (var d = level; d < maxlevel; d++) {
var caplocation = document.getElementById("caption" + d);
if (caplocation.childNodes.length > 1){
caplocation.removeChild(caplocation.childNodes[1]);
}
var ddlocation = document.getElementById("dd" + d);
if (ddlocation.childNodes.length > 1){
ddlocation.removeChild(ddlocation.childNodes[1]);
}
}
// now get the data for the new dropdown
var dd = xmlDoc.getElementsByTagName("ddlevel" + level)
var ddlength = dd.length
for (var i = 0; i < ddlength; i++) {
if (dd[i].getAttribute("name") == selectiontocreate) {
// the correct element is found
var numberofoptions = dd[i].childNodes.length;
if (numberofoptions > 0) {
// get the captiontext from the selected element
var capText = document.createTextNode(dd[i].getAttribute("caption"));
// create the dropdown with all the options
var selObj = document.createElement("select");
// first option is not a real option
selObj.options[0] = new Option(dd[i].getAttribute("caption"))
for (var j = 0; j < numberofoptions; j++){
selObj.options[selObj.options.length] = new Option(dd[i].childNodes[j].getAttribute("name"),
dd[i].childNodes[j].getAttribute("name"))
}
// add the eventhandler to the select, if the node has children
selObj.onchange = function () {
createdropdown((level + 1), this.options[this.selectedIndex].value);
}
// put the caption and the dropdown in the correct place
var caplocation = document.getElementById("caption" + level);
caplocation.appendChild(capText);
var ddlocation = document.getElementById("dd" + level);
ddlocation.appendChild(selObj);
}
}
}
}
</script>
</head>
<body onload="createdropdown(0, 'geo')">
<form name="dynamic">
<table border="1" width="50%">
<tr>
<td id="caption0"> </td><td id="dd0"> </td>
</tr>
<tr>
<td id="caption1"> </td><td id="dd1"> </td>
</tr>
<tr>
<td id="caption2"> </td><td id="dd2"> </td>
</tr>
<tr>
<td id="caption3"> </td><td id="dd3"> </td>
</tr>
<tr>
<td id="caption4"> </td><td id="dd4"> </td>
</tr>
</table>
</form>
</body>
</html>
finally i created something which i think is useful, so i am going to post it here. I see a lot of questions about connecting dropdown elements together, where the options in the second dd are depending on the selection in the first. People even want to connect three of them together. My thinkin was, why not make it as flexible as possible. Imagine a hierarchy of choices, where neither branche of the hierarchy is as deep as another one. I want to make a dd with variable levels so a dd contains all the children of a certain level of the hierarchy. After a selection is made, the script checks if the hierarchy has children in the next level. When a selection is altered, the deeper dd's are removed and created again with the proper options.
All is based on a xml-file which holds the dropdowndata and a function in a html-file to read it and create the drop downs where they are needed
Points to improve:
- make it x-browser compatible (currently tested in IE5.5)
- perhaps the inputfile (xml) should be changed so the name and (if added) the value, or the caption shouldn't be attributes of an element, but a child-element
- code efficiency
- get the maxdepth variable dynamically, by analyzing the contents of the xml before processing
- create positions to put the captions and the dd's dynamically, based on the xml-data instead of fixing them in the html file
- make the xml more strict, add a dtd or something like that
- lay-out aspects
- whatever you can think of
I am not an xml-expert, neither am i a javascript expert. I managed to create this, it works the way i intended, i leave it up to you guys to improve it....
Improved versions will be used by me ofcourse :D
Roelf
file: dropdowndata.xml
<ddlevel0 name="geo" caption="Select a continent">
<ddlevel1 name="North America" caption="Select a country">
<ddlevel2 name="United States" caption="Select a state">
<ddlevel3 name="Arkansas" caption="Select a city">
<ddlevel4 name="City 1 in arkansas" />
<ddlevel4 name="City 2 in arkansas" />
<ddlevel4 name="City 3 in arkansas" caption="Perhaps you want to select a street">
<ddlevel5 name="Street1" />
<ddlevel5 name="Street2" />
<ddlevel5 name="Street3" />
</ddlevel4>
</ddlevel3>
<ddlevel3 name="Texas" caption="Select a city">
<ddlevel4 name="City 1 in Texas" />
<ddlevel4 name="City 2 in Texas" />
<ddlevel4 name="City 3 in Texas" />
</ddlevel3>
<ddlevel3 name="Another state" caption="Select a city">
<ddlevel4 name="City 1 in another state" />
<ddlevel4 name="City 2 in another state" />
<ddlevel4 name="City 3 in another state" />
<ddlevel4 name="City 4 in another state" />
<ddlevel4 name="City 5 in another state" />
<ddlevel4 name="City 6 in another state" />
</ddlevel3>
</ddlevel2>
<ddlevel2 name="Canada" caption="Select a city">
<ddlevel3 name="Montreal" />
<ddlevel3 name="Some city in Canada" />
<ddlevel3 name="Some other city" />
<ddlevel3 name="Yet another one in canada" />
</ddlevel2>
</ddlevel1>
<ddlevel1 name="Africa" caption="Select a county">
</ddlevel1>
<ddlevel1 name="Europe" caption="Select a country">
</ddlevel1>
<ddlevel1 name="Australia" caption="Select a city">
<ddlevel2 name="Sidney" />
<ddlevel2 name="Canberra" />
<ddlevel2 name="Another one in Australia" />
<ddlevel2 name="Aussie city" />
</ddlevel1>
</ddlevel0>
file: thehtml.html
<html>
<head>
<title>testdocument</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" language="JavaScript">
/*********************************************
* Dynamic connected dropdown menus Version 1.0
* Script created by Roelf Prakken
* email: r.prakken@home.nl
*********************************************/
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.load("dropdowndata.xml");
var maxlevel = 5;
function createdropdown (level, selectiontocreate) {
// first, delete all selects and captions from previously made selections in this hierarchy level
for (var d = level; d < maxlevel; d++) {
var caplocation = document.getElementById("caption" + d);
if (caplocation.childNodes.length > 1){
caplocation.removeChild(caplocation.childNodes[1]);
}
var ddlocation = document.getElementById("dd" + d);
if (ddlocation.childNodes.length > 1){
ddlocation.removeChild(ddlocation.childNodes[1]);
}
}
// now get the data for the new dropdown
var dd = xmlDoc.getElementsByTagName("ddlevel" + level)
var ddlength = dd.length
for (var i = 0; i < ddlength; i++) {
if (dd[i].getAttribute("name") == selectiontocreate) {
// the correct element is found
var numberofoptions = dd[i].childNodes.length;
if (numberofoptions > 0) {
// get the captiontext from the selected element
var capText = document.createTextNode(dd[i].getAttribute("caption"));
// create the dropdown with all the options
var selObj = document.createElement("select");
// first option is not a real option
selObj.options[0] = new Option(dd[i].getAttribute("caption"))
for (var j = 0; j < numberofoptions; j++){
selObj.options[selObj.options.length] = new Option(dd[i].childNodes[j].getAttribute("name"),
dd[i].childNodes[j].getAttribute("name"))
}
// add the eventhandler to the select, if the node has children
selObj.onchange = function () {
createdropdown((level + 1), this.options[this.selectedIndex].value);
}
// put the caption and the dropdown in the correct place
var caplocation = document.getElementById("caption" + level);
caplocation.appendChild(capText);
var ddlocation = document.getElementById("dd" + level);
ddlocation.appendChild(selObj);
}
}
}
}
</script>
</head>
<body onload="createdropdown(0, 'geo')">
<form name="dynamic">
<table border="1" width="50%">
<tr>
<td id="caption0"> </td><td id="dd0"> </td>
</tr>
<tr>
<td id="caption1"> </td><td id="dd1"> </td>
</tr>
<tr>
<td id="caption2"> </td><td id="dd2"> </td>
</tr>
<tr>
<td id="caption3"> </td><td id="dd3"> </td>
</tr>
<tr>
<td id="caption4"> </td><td id="dd4"> </td>
</tr>
</table>
</form>
</body>
</html>