Links two select boxes together, so that making a selection in one will populate new options in another.
Options are TRIGGER_PREFIX and TARGET_PREFIX : a pattern to replace in the IDs of the two boxes to find which matches with which. The selector object should have an id of the form {trigger}_name Which tells us it relates to the element with id {target}_name found nearby on the page.
The source data lists are expected to be globally available, A big array of "ranges" which contains the data for the target and a small array of "selector_ranges" arrays which map the selected value to one or more of the named ranges.
/////////////////////////////////////////////////////////////////
// DEMO DATA
var selector_ranges = new Array();
// selector_ranges define how the list on the left maps to GROUPS of
// values that may go into the right.
selector_ranges['canines'] = new Array('doglist');
selector_ranges['felines'] = new Array('catlist');
selector_ranges['zoo'] = new Array('doglist','catlist');
selector_ranges['other'] = new Array('Literal');
var ranges = new Array();
ranges['doglist'] = new Array();
ranges['doglist']['Canus Canus'] = "Cross breed";
ranges['doglist']['Canus Familiarus'] = "Sheep Dog";
ranges['doglist']['Canus Domesticus'] = "Lap Dog";
ranges['catlist'] = new Array();
ranges['catlist']['Felix'] = "Moggy";
ranges['catlist']['Felis Domesticus'] = "Pussy";
ranges['catlist']['Felis Catus'] = "Cooking Fat";
function demo_list(){
var target = document.getElementById("target_xyz");
var list = new Array("monkeys","lions","tigers");
list["swallows"] = new Array("African","European");
target = change_element_to_select(target,list);
}
//
// The ranges and selector_ranges arrays
// should be over-ridden in your own page
// for yout own data.
// If neccessary, override the _PREFIXes as well.
/////////////////////////////////////////////////////////////////
var TRIGGER_PREFIX = 'trigger_';
var TARGET_PREFIX = 'target_';
/**
* Find partner with matching name and tell it what I've changed to
*/
function change_select_range(selector,target_name) {
var selected = selector.options[selector.selectedIndex].value;
if (!selected) return;
if(!target_name){
target_name = selector.id.replace(TRIGGER_PREFIX,TARGET_PREFIX);
}
change_select_range_to(target_name,selected);
}
/**
* Get options appropriate to the current selection
* from the global arrays and send them to the target.
*/
function change_select_range_to(target_name, range_name) {
var target = document.getElementById(target_name);
if (!target){
alert("Failed to locate target '"+target_name+"' when trying to repopulate the options. "+target); return;
}
var new_ranges = selector_ranges[range_name];
if((! new_ranges) || ! new_ranges[0] ){
new_ranges = selector_ranges["default"];
}
if(new_ranges[0] == "Literal" ){
// The only valid value is freetext. Change input to a text box
change_element_to_freetext(target);
return;
} else {
// retrieve the contents of the named ranges to insert into the option list.
var indexed_options = new Array();
for(var r in new_ranges){
// may be nested references to other sets. Expand them
var subset = selector_ranges[new_ranges[r]];
if(subset){
for(var ss in subset){
new_ranges[ss] = subset[ss];
}
}
}
for(var r in new_ranges){
var r_name = new_ranges[r];
if(! ranges[r_name]){
alert("Unknown range. The selector "+r_name+" is supposed to indicate targets of type \'"+new_ranges[r]+"\' but that data was unavailable.");
continue;
}
indexed_options[r_name] = ranges[r_name];
}
change_element_to_select(target,indexed_options);
return;
}
}
/**
* Destroy and re-create an input field as a select (retaining old value)
* Insert a structured array of values into it
*/
function change_element_to_select(element,indexed_options) {
var newField = document.createElement("select");
newField.setAttribute("name", element.getAttribute("name"));
newField.setAttribute("class", element.getAttribute("class"));
newField.setAttribute("className", element.getAttribute("className"));
newField.setAttribute("className", element.getAttribute("className"));
var currentval=element.getAttribute('value');
if(!currentval && (element.selectedIndex>-1) ){currentval = element.options[element.selectedIndex].value;}
for(o in indexed_options){
add_option_to_select(newField, o, indexed_options[o], currentval );
}
var id = element.id;
element.parentNode.replaceChild(newField,element);
newField.id = id;
if(typeof(init_combo_box)=='function')init_combo_box(newField);
return newField;
}
function add_option_to_select(select,label,list,selected) {
// allow recursive option groups
// IE doesn't display nested optgroups :(
if(typeof(list) == 'object'){
// the options are grouped
var og = document.createElement("optgroup");
og.setAttribute("label",label);
select.appendChild(og);
for(var varname in list)
{
add_option_to_select(og, varname, list[varname],selected);
}
} else {
var op = document.createElement("option");
op.setAttribute("value",label);
op.appendChild(document.createTextNode(list));
select.appendChild(op);
if(label == selected){op.setAttribute('selected','selected');op.selected=true;}
}
}
/////////////////////////////////////////////////////////////////
DOM by Dan