<script language=javascript src="test.js"></script>
<xml id="cascadeMenuDefinition">
<config-root>
<select-menu name="level1">
<item display="A" value="A"/>
<item display="B" value="B"/>
<item display="C" value="C"/>
</select-menu>
<select-menu name="level2">
<item display="A00" value="00" parentValue="A"/>
<item display="B01" value="01" parentValue="B"/>
<item display="C02" value="02" parentValue="C"/>
</select-menu>
<select-menu name="level3">
<item display="A0001" value="0001" parentValue="00"/>
<item display="B0102" value="0102" parentValue="01"/>
<item display="C0203" value="0203" parentValue="02"/>
</select-menu>
</config-root>
</xml>
<body>
<form>
<select id="menu1" useXmlBinding=true dataSource="level1" subMenus="menu2;menu3"></select>
<select id="menu2" useXmlBinding=true dataSource="level2" selectedValue="01"></select>
<select id="menu3" useXmlBinding=true dataSource="level2" subMenus="menu4"></select>
<select id="menu4" useXmlBinding=true dataSource="level3"></select>
</form>
</body>
test.js:
window.attachEvent("onload",initXMLCascadeMenu);
function $(id){
return document.getElementById(id);
}
/**
* XmlCascadeMenuHelper:用以维护一组select的dataSource定义,包括select items
*/
var XmlCascadeMenuHelper=new Object();
CascadeMenuConfig=new Array();//存储介质
/**
* initXMLCascadeMenu,页面onload时载入调用,用以管理异常和调用缓存数据、绑定数据的方法
*/
function initXMLCascadeMenu(){
window.status="初始化XML级联菜单";
try{
cacheXMLCascadeMenu();
bindXmlCascadeMenu();
}catch(e){
alert(e.message);
}
window.status=window.defaultStatus;
}
/**
* 将数据岛内的定义读入内存,数据岛的id必须为cascadeMenuDefinition
*/
function cacheXMLCascadeMenu(){
var xmlIsland=$("cascadeMenuDefinition");
//读入并封装到XMLDOM
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
xmldoc.async = false;
xmldoc.loadXML(xmlIsland.innerHTML);
var config=xmldoc.documentElement;
var menus=config.childNodes;
var menulen=menus.length;
for(var i=0;i<menulen;i++){
var menuNode=menus[i];
var menuName=XmlUtil.getProperty(menuNode,"name");
var menuObj=new CascadeMenu();
var items=menuNode.childNodes;
var itemlen=items.length;
for(var j=0;j<itemlen;j++){
var itemNode=items[j];
var itemObj=new CascadeMenu();
itemObj.display=XmlUtil.getProperty(itemNode,"display");
itemObj.value=XmlUtil.getProperty(itemNode,"value");
itemObj.parentValue=XmlUtil.getProperty(itemNode,"parentValue");
menuObj.addItem(itemObj);
}
CascadeMenuConfig[menuName]=menuObj;
}
}
/**
* 便利所有的表单select并绑定
*/
function bindXmlCascadeMenu(){
var forms=document.forms;
var formlen=forms.length;
for(var i=0;i<formlen;i++){
var form=forms[i];
var elems=form.elements;
var elemlen=elems.length;
for(var j=0;j<elemlen;j++){
var elem=elems[j];
if(elem.nodeName=="SELECT"&&elem.useXmlBinding&&elem.useXmlBinding=="true"&&elem.dataSource){
initXmlMenu(elem,true);
}
}
}
}
/**
* 绑定顶级菜单
*/
function initXmlMenu(elem,isInit){
elem.options.length=0;
var dataSource=elem.dataSource;
var menuObj=CascadeMenuConfig[dataSource];
var items=menuObj.items;
var itemlen=items.length;
for(var i=0;i<itemlen;i++){
var optionlen=elem.options.length;
var itemObj=items[i];
var option=new Option(itemObj.display,itemObj.value);
elem.options[elem.options.length]=option;
}
var subMenusStr=elem.subMenus;
if(subMenusStr){//递归初始化子菜单
var subMenuIds=subMenusStr.split(/[,|;]/);
var subMenuLen=subMenuIds.length;
for(var i=0;i<subMenuLen;i++){
var subMenu=$(subMenuIds[i]);
if(!subMenu){
throw new Error("绑定select失败,没有这个子菜单:"+subMenuIds[i]);
}
initSubXmlMenu(elem,subMenu,isInit);
}
}
if(isInit==true){
elem.attachEvent("onchange",onXmlCascadeMenuChange);
if(elem.selectedValue){//设置默认值
elem.value=elem.selectedValue;
elem.fireEvent("onchange");
}
}
}
/**
* 绑定子菜单
*/
function initSubXmlMenu(parent,elem,isInit){
elem.options.length=0;
var parentValue=parent.value;
var dataSource=elem.dataSource;
var menuObj=CascadeMenuConfig[dataSource];
var items=menuObj.items;
var itemlen=items.length;
for(var i=0;i<itemlen;i++){
var optionlen=elem.options.length;
var itemObj=items[i];
if(itemObj.parentValue!=parentValue){
continue;
}
var option=new Option(itemObj.display,itemObj.value);
elem.options[elem.options.length]=option;
}
var subMenusStr=elem.subMenus;
if(subMenusStr){//递归初始化子菜单
var subMenuIds=subMenusStr.split(/[,|;]/);
var subMenuLen=subMenuIds.length;
for(var i=0;i<subMenuLen;i++){
var subMenu=$(subMenuIds[i]);
if(!subMenu){
throw new Error("绑定select失败,没有这个子菜单:"+subMenuIds[i]);
}
initSubXmlMenu(elem,subMenu);
}
if(isInit==true){
elem.attachEvent("onchange",onXmlCascadeMenuChange);
}
}
if(isInit==true){
if(elem.selectedValue){//设置默认值
elem.value=elem.selectedValue;
elem.fireEvent("onchange");
}
}
}
/**
* 菜单onchange事件出发的动作
*/
function onXmlCascadeMenuChange(){
var elem=event.srcElement;
if(!elem)return;
var subMenusStr=elem.subMenus;
if(subMenusStr){//递归初始化子菜单
var subMenuIds=subMenusStr.split(/[,|;]/);
var subMenuLen=subMenuIds.length;
for(var i=0;i<subMenuLen;i++){
var subMenu=$(subMenuIds[i]);
if(!subMenu){
throw new Error("绑定select失败,没有这个子菜单:"+subMenuIds[i]);
}
initSubXmlMenu(elem,subMenu,false);
}
}
}
/**
* 封装javascript访问XML相关方法
*/
var XmlUtil=new Object();
XmlUtil.NULL=null;
/**
* 获得属性的值
*/
XmlUtil.getProperty=function(xmlNode,propertyName){
var attrs=xmlNode.attributes;
var attrlen=attrs.length;
for(var i=0;i<attrlen;i++){
var attr=attrs[i];
if(attr.name==propertyName){
return attr.value;
}
}
return XmlUtil.NULL;
}
/**
* 级联菜单对应的内存对象
*/
function CascadeMenu(){
this.items=new Array();
}
CascadeMenu.prototype.addItem=function(item){
this.items.push(item);
}
/**
* 菜单Option对应的对象
*/
function CascadeMenuItem(){
this.display=XmlUtil.NULL;
this.value=XmlUtil.NULL;
this.parentValue=XmlUtil.NULL;
}