var cascadeSelects = new Array(); function registerCascadeSelect( name, containerId, data, defaultSelectId ) { if( !defaultSelectId ) defaultSelectId = null; cascadeSelects[ cascadeSelects.length ] = new Array( name, containerId, data, new Array(), defaultSelectId ); } function cascadeSelectInitialise() { // +++ We will check if we have a decent DOM implementation if( !document.implementation || !document.implementation.hasFeature || !document.implementation.hasFeature("html", "1.0" ) ) return; if( ( navigator.userAgent.indexOf('MSIE') != -1 ) && ( navigator.userAgent.indexOf('Mac') != -1 ) ) return; // --- for( var i = 0; i < cascadeSelects.length; i++ ) { cascadeSelects[ i ][ 1 ] = document.getElementById( cascadeSelects[ i ][ 1 ] ); // +++ Clear out the container first var children = cascadeSelects[ i ][ 1 ].childNodes; for( var j = 0; j < children.length; j++ ) cascadeSelects[ i ][ 1 ].removeChild( children[ j ] ); // --- if( cascadeSelects[ i ][ 4 ] ) { var indices = cascadeSelectFindId( cascadeSelects[ i ][ 2 ], cascadeSelects[ i ][ 4 ] ); var innerData = cascadeSelects[ i ][ 2 ]; for( var j = 0; j < indices.length; j++ ) { cascadeSelects[ i ][ 3 ][ j ] = innerData; cascadeSelectAddLevel( i, indices[ j ] ); innerData = innerData[ indices[ j ] ][ 2 ]; } } else { cascadeSelects[ i ][ 3 ][ 0 ] = cascadeSelects[ i ][ 2 ]; cascadeSelectAddLevel( i ); } } } function cascadeSelectChange( event, selectId, level ) { // +++ IE incompliance workaround if (!event) event = window.event; if (event.target) element = event.target; else element = event.srcElement; // --- cascadeSelectDeleteFromLevel( selectId, level ); // +++ Find the children of the element which has been selected var level = cascadeSelects[ selectId ][ 3 ].length; var children = cascadeSelects[ selectId ][ 3 ][ level - 1 ]; for( var i = 0; i < children.length; i++ ) { if( children[ i ][ 0 ] == element.options[ element.selectedIndex ].value ) { if( children[ i ][ 2 ].length > 0 ) { cascadeSelects[ selectId ][ 3 ][ level ] = children[ i ][ 2 ]; cascadeSelectAddLevel( selectId ); } break; } } // --- } function cascadeSelectDeleteFromLevel( selectId, level ) { // Deletes all the element from a specified level upmards var oldLevel = cascadeSelects[ selectId ][ 3 ].length; for( var i = oldLevel; i > level; i-- ) { cascadeSelects[ selectId ][ 1 ].removeChild( document.getElementById( cascadeSelects[ selectId ][ 0 ] + "_" + i ) ); cascadeSelects[ selectId ][ 1 ].removeChild( document.getElementById( cascadeSelects[ selectId ][ 0 ] + "_break_" + i ) ); } cascadeSelects[ selectId ][ 3 ].length = level; } function cascadeSelectAddLevel( selectId, selectedIndex ) { var level = cascadeSelects[ selectId ][ 3 ].length; var children = cascadeSelects[ selectId ][ 3 ][ level - 1 ]; // Create a new select element var newSelect = document.createElement( "select" ); newSelect.setAttribute( "id", cascadeSelects[ selectId ][ 0 ] + "_" + level ); newSelect.setAttribute( "name", cascadeSelects[ selectId ][ 0 ] + "_" + level ); newSelect.setAttribute( "class", "required" ); // Add the onchange event var onchange = new Function( "evt", "cascadeSelectChange( evt, " + selectId + ", " + level + " );" ); // +++ IE incompliance workaround if (newSelect.addEventListener) newSelect.addEventListener("change", onchange, false); else newSelect.onchange = onchange; // --- // Add the 'Select...' option to the beginning of the select box var newOption = document.createElement( "option" ); newOption.setAttribute( "value", "" ); newOption.appendChild( document.createTextNode( "Select..." ) ); newSelect.appendChild( newOption ); // And add the data options into it for( var i = 0; i < children.length; i++ ) { newOption = document.createElement( "option" ); newOption.setAttribute( "value", children[ i ][ 0 ] ); newOption.appendChild( document.createTextNode( children[ i ][ 1 ] ) ); if( i == selectedIndex ) newOption.selected = true; newSelect.appendChild( newOption ); } // Add the select box to the container element cascadeSelects[ selectId ][ 1 ].appendChild( newSelect ); // And add a break tag to it too! var newBreak = document.createElement( "br" ); newBreak.setAttribute( "id", cascadeSelects[ selectId ][ 0 ] + "_break_" + level ); cascadeSelects[ selectId ][ 1 ].appendChild( newBreak ); } function cascadeSelectFindId( data, id ) { var path = new Array(); for( var i = 0; i < data.length; i++ ) { if( data[ i ][ 0 ] == id ) { path[ path.length ] = i; break; } else { var subPath = cascadeSelectFindId( data[ i ][ 2 ], id ); if( subPath.length > 0 ) { path[ path.length ] = i; for( var j = 0; j < subPath.length; j++ ) path[ path.length ] = subPath[ j ]; break; } } } return path; } registerOnLoad(window, cascadeSelectInitialise);