花了半天時間實現(xiàn)一個多級聯(lián)動下拉框,目的是對某一植物進行“門綱目科屬”的歸類。使用的技術(shù)是javascript+xml,之所以不用數(shù)據(jù)庫,一來這方面的數(shù)據(jù)雖然量大但都是固定不變的,二來不希望加重服務(wù)器的負擔(dān),第三是因為這種多級從屬關(guān)系的數(shù)據(jù)不太適合放在數(shù)據(jù)庫里。
這是大概的思路:
1、讀取xml文件
2、當(dāng)一個下拉框選中某選項時,根據(jù)該選項,當(dāng)前節(jié)點指向下一層,進入下一層下拉框的設(shè)置
3、取消當(dāng)前下拉框的禁用,禁用下一層的下拉框
4、清空當(dāng)前下拉框的選項
5、根據(jù)當(dāng)前節(jié)點讀取xml的數(shù)據(jù),設(shè)置下拉框選項
6、返回步驟2
代碼:
JavaScript
//載入xml文件var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");xmlDoc.async = false;xmlDoc.load("classify.xml");var currentNode;//當(dāng)前所在節(jié)點//讀取xml文件數(shù)據(jù)并設(shè)置門、綱、目、科、屬的下拉框//設(shè)置“門”的下拉框function setPhylum(){currentNode=xmlDoc.documentElement;var phylums = currentNode.childNodes;for(var i=0;i<phylums.length;i++){//從門到屬,都有name屬性標簽,并且所有下拉框選項索引都是從1開始var phylumName=phylums(i).selectNodes("name")(0).text;document.forms[0].phylum.options[i+1]=new Option(phylumName,phylumName);}}//設(shè)置“綱”的下拉框function setClazz(selectedIndex){//取消下拉框的禁用//后面的下拉框禁用,這是因應(yīng)各下拉框的無序選擇可能產(chǎn)生的錯誤//比如選了“科”又回頭重新選“目”,或更改同一個下拉框選項)document.forms[0].clazz.disabled=null;document.forms[0].order.disabled="disabled";document.forms[0].family.disabled="disabled";document.forms[0].genus.disabled="disabled";//將選中的門節(jié)點作為當(dāng)前節(jié)點,注意這里需要將索引回減1//因為門的父節(jié)點沒有name屬性標簽,而下拉框的索引又是從1開始//currentNode的賦值應(yīng)使用絕對定位,也是因應(yīng)各下拉框的無序選擇//currentNode=currentNode.childNodes(selectedIndex-1);currentNode=xmlDoc.documentElement.childNodes(selectedIndex-1);var clazzes=currentNode.childNodes;clearOption(document.forms[0].clazz);//因為門節(jié)點的第一個子節(jié)點為name屬性標簽,故循環(huán)時索引從1開始//相應(yīng)的下拉框的索引就與綱節(jié)點的索引同步(不需要options[i+1]),目、科、屬也是一樣for(var i=1;i<clazzes.length;i++){var clazzName=clazzes(i).selectNodes("name")(0).text;document.forms[0].clazz.options[i]=new Option(clazzName,clazzName);}}//設(shè)置“目”的下拉框function setOrder(selectedIndex){//取消下拉框的禁用//后面的下拉框禁用,這是因應(yīng)各下拉框的無序選擇可能產(chǎn)生的錯誤(比如選了“科”又回頭重新選“目”)document.forms[0].order.disabled=null;document.forms[0].family.disabled="disabled";document.forms[0].genus.disabled="disabled";//currentNode的賦值應(yīng)使用絕對定位var phylumSI=document.forms[0].phylum.selectedIndex; //phylum selected indexcurrentNode=xmlDoc.documentElement.childNodes(phylumSI-1).childNodes(selectedIndex);var orders=currentNode.childNodes;clearOption(document.forms[0].order);for(var i=1;i<orders.length;i++){var orderName=orders(i).selectNodes("name")(0).text;document.forms[0].order.options[i]=new Option(orderName,orderName);}}//設(shè)置“科”的下拉框function setFamily(selectedIndex){document.forms[0].family.disabled=null;//取消下拉框的禁用document.forms[0].genus.disabled="disabled";//后面的下拉框禁用//currentNode的賦值應(yīng)使用絕對定位var phylumSI=document.forms[0].phylum.selectedIndex;//phylum selected indexvar clazzSI=document.forms[0].clazz.selectedIndex; //clazz selected indexcurrentNode=xmlDoc.documentElement.childNodes(phylumSI-1).childNodes(clazzSI).childNodes(selectedIndex);var families=currentNode.childNodes;clearOption(document.forms[0].family);for(var i=1;i<families.length;i++){var familyName=families(i).selectNodes("name")(0).text;document.forms[0].family.options[i]=new Option(familyName,familyName);}}//設(shè)置“屬”的下拉框function setGenus(selectedIndex){document.forms[0].genus.disabled=null;//取消下拉框的禁用//currentNode的賦值應(yīng)使用絕對定位var phylumSI=document.forms[0].phylum.selectedIndex;//phylum selected indexvar clazzSI=document.forms[0].clazz.selectedIndex; //clazz selected indexvar orderSI=document.forms[0].order.selectedIndex; //order selected indexcurrentNode=xmlDoc.documentElement.childNodes(phylumSI-1).childNodes(clazzSI).childNodes(orderSI).childNodes(selectedIndex);var genuses=currentNode.childNodes;clearOption(document.forms[0].genus);for(var i=1;i<genuses.length;i++){//屬為葉節(jié)點var genusName=genuses(i).text;document.forms[0].genus.options[i]=new Option(genusName,genusName);}}//清空下拉框選項function clearOption(selectElement){for(var i=1;i<selectElement.options.length;i++){selectElement.options[i]=null;}}
html
<form id="plantForm" action="plant" method="post"><select id="phylum" name="plantForm.phylum"onchange="setClazz(this.selectedIndex)"><option selected="selected">———門———</option></select><select id="clazz" name="plantForm.clazz" disabled="disabled"onchange="setOrder(this.selectedIndex)"><option selected="selected">———綱———</option></select><select id="order" name="plantForm.order" disabled="disabled"onchange="setFamily(this.selectedIndex)"><option selected="selected">———目———</option></select><select id="family" name="plantForm.family" disabled="disabled"onchange="setGenus(this.selectedIndex)"><option selected="selected">———科———</option></select><select id="genus" name="plantForm.genus" disabled="disabled"><option selected="selected">———屬———</option></select></form><script type="text/javascript">setPhylum();//設(shè)置第一個下拉框</script>
最后是xml文件的內(nèi)容
<?xml version="1.0" encoding="UTF-8"?><plant><phylum><name>被子植物門</name><clazz><name>雙子葉植物綱</name><order><name>菊目</name><family><name>菊科</name><genus>菊屬</genus></family><family><name>桔梗科</name><genus>同鐘花屬</genus><genus>刺萼參屬</genus></family></order><order><name>胡椒目</name><family><name>胡椒科</name><genus>胡椒屬</genus><genus>草胡椒屬</genus><genus>齊頭絨屬</genus></family></order></clazz></phylum><phylum><name>蕨類植物門</name><clazz><name>石松綱</name><order><name>石松目</name><family><name>石松科</name><genus>石松屬</genus></family></order></clazz></phylum></plant>
可以實現(xiàn)上下級下拉框的聯(lián)動,支持無序選擇,若向上重新選擇,下下層下拉框?qū)⒆詣颖唤?,下層下拉框選項也會相應(yīng)改變。
有一點不足是,因為數(shù)據(jù)量實在太大,這樣5個下拉框仍然可能出現(xiàn)某下拉框有幾百甚至幾千個選項,此時就失去了下拉框的意義,因此正在考慮是否應(yīng)該做成輸入框的形式,或者像搜索引擎那樣帶有輸入提示功能,研究中,歡迎拍磚。