花了半天時(shí)間實(shí)現(xiàn)一個(gè)多級(jí)聯(lián)動(dòng)下拉框,目的是對(duì)某一植物進(jìn)行“門綱目科屬”的歸類。使用的技術(shù)是javascript+xml,之所以不用數(shù)據(jù)庫,一來這方面的數(shù)據(jù)雖然量大但都是固定不變的,二來不希望加重服務(wù)器的負(fù)擔(dān),第三是因?yàn)檫@種多級(jí)從屬關(guān)系的數(shù)據(jù)不太適合放在數(shù)據(jù)庫里。
這是大概的思路:
1、讀取xml文件
2、當(dāng)一個(gè)下拉框選中某選項(xiàng)時(shí),根據(jù)該選項(xiàng),當(dāng)前節(jié)點(diǎn)指向下一層,進(jìn)入下一層下拉框的設(shè)置
3、取消當(dāng)前下拉框的禁用,禁用下一層的下拉框
4、清空當(dāng)前下拉框的選項(xiàng)
5、根據(jù)當(dāng)前節(jié)點(diǎn)讀取xml的數(shù)據(jù),設(shè)置下拉框選項(xiàng)
6、返回步驟2
代碼:
JavaScript
//載入xml文件var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");xmlDoc.async = false;xmlDoc.load("classify.xml");var currentNode;//當(dāng)前所在節(jié)點(diǎn)//讀取xml文件數(shù)據(jù)并設(shè)置門、綱、目、科、屬的下拉框//設(shè)置“門”的下拉框function setPhylum(){currentNode=xmlDoc.documentElement;var phylums = currentNode.childNodes;for(var i=0;i<phylums.length;i++){//從門到屬,都有name屬性標(biāo)簽,并且所有下拉框選項(xiàng)索引都是從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)生的錯(cuò)誤//比如選了“科”又回頭重新選“目”,或更改同一個(gè)下拉框選項(xiàng))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é)點(diǎn)作為當(dāng)前節(jié)點(diǎn),注意這里需要將索引回減1//因?yàn)殚T的父節(jié)點(diǎn)沒有name屬性標(biāo)簽,而下拉框的索引又是從1開始//currentNode的賦值應(yīng)使用絕對(duì)定位,也是因應(yīng)各下拉框的無序選擇//currentNode=currentNode.childNodes(selectedIndex-1);currentNode=xmlDoc.documentElement.childNodes(selectedIndex-1);var clazzes=currentNode.childNodes;clearOption(document.forms[0].clazz);//因?yàn)殚T節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)為name屬性標(biāo)簽,故循環(huán)時(shí)索引從1開始//相應(yīng)的下拉框的索引就與綱節(jié)點(diǎn)的索引同步(不需要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)生的錯(cuò)誤(比如選了“科”又回頭重新選“目”)document.forms[0].order.disabled=null;document.forms[0].family.disabled="disabled";document.forms[0].genus.disabled="disabled";//currentNode的賦值應(yīng)使用絕對(duì)定位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)使用絕對(duì)定位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)使用絕對(duì)定位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é)點(diǎn)var genusName=genuses(i).text;document.forms[0].genus.options[i]=new Option(genusName,genusName);}}//清空下拉框選項(xiàng)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è)置第一個(gè)下拉框</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>桔???lt;/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>
可以實(shí)現(xiàn)上下級(jí)下拉框的聯(lián)動(dòng),支持無序選擇,若向上重新選擇,下下層下拉框?qū)⒆詣?dòng)被禁用,下層下拉框選項(xiàng)也會(huì)相應(yīng)改變。
有一點(diǎn)不足是,因?yàn)閿?shù)據(jù)量實(shí)在太大,這樣5個(gè)下拉框仍然可能出現(xiàn)某下拉框有幾百甚至幾千個(gè)選項(xiàng),此時(shí)就失去了下拉框的意義,因此正在考慮是否應(yīng)該做成輸入框的形式,或者像搜索引擎那樣帶有輸入提示功能,研究中,歡迎拍磚。
聯(lián)系客服