ASP+XML+JavaScript实现动态无限级联动菜单
我做某个项目时,有需求的是做一个动态的无限级的联动菜单。由于本人比较懒于是上网找找有关的代码,但很多都没有满足需求,其中有一编文章是用JavaScript对XML文件操作来实现无限级联动菜单的,我们可结合ASP来完成对数据库值的读取,然后写入XML文件,再用JavaScript读出来并且控制它的联动。 这儿的关键是把数据库内的N层数据类读出来: 我的数据库表结构是这样的: ’tbl_Class 列名 数据类型 长度 说明 ClassID int 4 类ID ModuleID int 4 模块ID GroupID int 2 标识一个组 ClassName nvarchar 50 类别名称 ParentID int 2 连接到组(0表示是父类) ’####################################我的ASP代码如下########################################## ’我把连接数据库的代码忽略。 ’函数名字:OpenXml(FileName) ’入口参数: filename 需要连接或打开的xml文件名 ’返回值 :XmlDoc就是一个成功装载XML文档的对象了。 ’ 有错误则打印错误信息strError ’------------------------------------------------ function OpenXml(filename) dim strSourceFile ,XmlDoc,strError strSourceFile = filename Set XmlDoc = Server.CreateObject("Microsoft.XMLDOM") ’创建XMLDOM实例 XmlDoc.async = false XmlDoc.load(strSourceFile) OpenXml=XmlDoc.parseerror.errorcode if XmlDoc.parseerror.errorcode<>0 then strError="<h2>error"&XmlDoc.parseerror.errorcode&"</h2>" strError=strError&XmlDoc.parseerror.reason&"<br>" strError=strError&XmlDoc.parseerror.url&"<br>" strError=strError&XmlDoc.parseerror.line&"<br>" strError=strError&XmlDoc.parseerror.filepos&"<br>" strError=strError&XmlDoc.parseerror.srcText&"<br>" response.write strError ’输出错误 else set OpenXml=XmlDoc ’返回实例 end if end function ’------------------------------------------------ ’函数名字:CloseXml() ’参数: XmlDoc XML组件实例 ’------------------------------------------------ function CloseXml(XmlDoc) if IsObject(XmlDoc) then set XmlDoc=nothing end if end function ’------------------------------------------------ ’函数名字:SelectXmlNode ’参数:XmlDoc XML组件实例 ’ e 元素的名字 ’返回元素实例 ’------------------------------------------------ function SelectXmlNode(XmlDoc,e) dim n set n=XmlDoc.selectSingleNode("//" & e ) set selectXmlNode= n end function Dim n,np,MaxGroup,root,xmlDoc,nt,filename,s,ss,TorF filename=server.mappath("demo.xml") set xmlDoc=openXML(filename)’打开XML RemoveAllNodes xmlDoc,"Root"’把Root和它下面的子项清除,这样可以多次方便读写 set root= xmlDoc.createElement("Root") xmlDoc.appendChild root’创建一个顶层元素 sql="select Max(GroupID) from tbl_Class " ’读出最大的层次 set rs=cn.execute(sql) if isnull(rs(0)) then MaxGroup=0 else MaxGroup=rs(0) ’如果为null 表示没有数据 s="":ss="" set nt=xmldoc.createElement("item") nt.setAttribute "text", "请选择" root.appendChild nt ’创建一个元素 for i=1 to MaxGroup ’开始循环 sql="select * from tbl_Class where GroupID=" & i ’由底层向顶层读取 set rs=cn.execute(sql) TorF=False ’为了每一个层上都创建一个“请选择”的空取。 do while rs.eof =false ’开始读取下层的数据 Set n = xmlDoc.createElement("item" & rs("ClassID")) ’创建一个命名为item + ID号的标记元素 n.setAttribute "text",rs("ClassName")’把它的属性“text”设置为数据库表内的 ClassName n.setAttribute "value",rs("ClassID")’把它的属性“value”设置为数据库表内的 ClassID if rs("ParentID")>0 then ’是有上层数据的 set np=selectXmlNode(xmlDoc,"item" & rs("ParentID")) ’把它的上层数据元素先读出保存在np if TorF=false then ’如果TorF为False值时 set nt=xmldoc.createElement("item") ’创建一个元素保存在nt nt.setAttribute "text", "请选择"’把它的text属性设置为“请选择” np.appendChild nt ’np把它加为子元素 end if TorF=true ’设置true np.appendChild n ’np 把n加为子元素 else root.appendChild n ’如果是第一层数据就把它加入为root下的一个子元素 end if rs.movenext ’下一条指针 loop ss=ss & "<SELECT id=Select" & i & " width=1 ></SELECT></span>" ’每有一层就创建一个 <select> s=s & ",’Select" & i & "’" ’把每个<select>的id 保存在变量s,它的格式为:id1,id2,id3,id4 next xmlDoc.save filename ’正式保存Xml文件 CloseXml xmlDoc ’关闭Xml文件 response.write ss ’直接把<select>输出到文档 s=mid(s,2) //在HTM文件内调用xmlselect.js <SCRIPT language=JavaScript src="xmlselect.js"></SCRIPT> <SCRIPT language=JavaScript> <!--//** power by fason function init() { var Sel = [<%=s%>]; attachSelect("demo.xml", Sel,["论坛导航"]); };//--> </SCRIPT> init(); //#########我把它的JS代码贴出来,作者叫:蒲佛信,http://fason.nease.net/samples/xmlselect/这儿有示例和代码。 //-----------------------------xmlselect.js文件开始------------------------------- //-----------------------------------------------------/ // NichName :fason // Autho :Forbes Pu(蒲佛信) // Email :fason_pfx@hotmail.com // HomePage :http://fason.nease.net // Blog :http://blog.mvpcn.net/fason/ // http://blog.csdn.net/fason/ // // function :attachSelect(sXMLSrc, aSel[, sStore]) // param1 :sXMLSrc(URL of XML data source) // param2 :aSel(array of SELECT controls’s ID) // param3 :array of default value when display //-----------------------------------------------------/ function attachSelect(sXMLSrc, aSel, sStore) { var oXML = CreateXmlDocument(); var oDocument = null; var store = sStore ? sStore : []; var Sel = new Array(); for (var i=0; i<aSel.length; i++) Sel[i] = document.getElementById(aSel[i]); if (!oXML){ throw new Error(’Not support!\nplease install a XML parser’);return; } oXML.onreadystatechange = function () { if (oXML.readyState == 4) { attachXML(); } }; oXML.load(sXMLSrc); function CreateXmlDocument() { if (document.implementation && document.implementation.createDocument) { var doc = document.implementation.createDocument("", "", null); if (doc.readyState == null) { doc.readyState = 1; doc.addEventListener("load", function () { doc.readyState = 4; if (typeof doc.onreadystatechange == "function") doc.onreadystatechange(); }, false); } return doc; } else if (window.ActiveXObject) { var prefix = ["MSXML3","MSXML2","MSXML","Microsoft"]; for (var i=0;i<prefix.length;i++) { try { var doc = new ActiveXObject(prefix[i] + ".DomDocument"); doc.setProperty("SelectionLanguage","XPath"); return doc; } catch (e) {} } } return null; }; function attachXML() { oDocument = oXML.documentElement; if (!oDocument) { throw new Error(’No XML data!’); return; } for (var i=0;i<aSel.length-1;i++){ addEvent(Sel[i], "onchange", function(x) { return function () { doChange(x); } }(i+1)); } doChange(0); }; function selectXMLNode(x) { var sPath = "/*"; var oDoc = oDocument; for (var i=0;i<x;i++) sPath += "/*[" + (Sel[i].selectedIndex+1) + "]"; if (typeof(oDoc.selectSingleNode)!=’undefined’) return oDoc.selectSingleNode(sPath); else { var doc=oDoc.nodeType==9?oDoc:oDoc.ownerDocument; var res = doc.createNSResolver(oDoc.nodeType==9? oDoc.documentElement:oDoc); return doc.evaluate(sPath,oDoc, res, 9, null).singleNodeValue; } }; function addEvent(el, sHandler, fnc) { if (el.attachEvent) { el.attachEvent(sHandler, fnc); } else if (el.addEventListener) { el.addEventListener(sHandler.replace(/on/i, ’’), fnc, false); } else { el[sHandler] = fnc; } }; function doChange(n) { var el = selectXMLNode(n); var nodes = el ? el.childNodes :[]; var s = Sel[n]; var f = 0; if (nodes.length>0) { with (s){ length = 0; for (var i = 0,j = 0;i<nodes.length;i++) { if (nodes[i].nodeType!=1)continue; var t = nodes[i].getAttribute("text"); var v = nodes[i].getAttribute("value") ? nodes [i].getAttribute("value") : t; if (v == store[n]) f = j; options[j++] = new Option(t, v); } options[f].selected = true; } if (++n<Sel.length) doChange(n); } else { for (var i=n; i<Sel.length; i++) { with (Sel[i]) { length = 0; options[0] = new Option(’--’); options[0].selected = true; } } } }; }; //-----------------------------xmlselect.js文件结束------------------------------- 由于Xml的操作简便直接,使用起来得心应手。 本人只知一些XML的皮毛知识,如有错误请大家指出。我认为不用什么去了解XML等好多的专业知识,但可以满足我们使用就已经足够了。 |