Discuz!NT控件剖析 之 左侧导航控件 [原创: 附源码]

其实这个控件的核心基本都在JS上,而相关的数据绑定和显示却非常简单。而需要说明的是在Discuz!NT的1.0和2.0正式版,这个控件做过一些调整,当然改动也基本上是在JS上,今天给大家的源码是1.0正式版的代码,虽然有些“旧”,但程序本身的思想没变,大家只要明白了这里的源码,有了这碗酒垫底,相信再看即将开源的2.0代码,就会一目了然了。

好了,废话到此,马上开始今天的话题!

先请大家看一下这个控件运行时的效果图:

效果图1:

效果图2: 首先将相应的C#代码放出来:

1PropertyScriptPath#regionPropertyScriptPath23/**////<summary>4///Javascript脚本文件所在目录。5///</summary>6[Description(“Javascript脚本文件所在目录。”),DefaultValue(“./”)]7publicstringScriptPath8{9get10{11objectobj=ViewState[“NavMenuScriptPath”];12returnobj==null?”js/Navbar.js”:(string)obj;13}14set15{16ViewState[“NavMenuScriptPath”]=value;17}18}1920#endregion212223PropertyImageUrl#regionPropertyImageUrl24[Bindable(true),Category(“Appearance”),DefaultValue(“”)]25publicstringImageUrl26{27get28{29if(base.ViewState[“NavMenuimageurl”]!=null)30{31return(String)base.ViewState[“NavMenuimageurl”];32}33else34{35return”images/”;//String.Empty;36}37}38set39{40base.ViewState[“NavMenuimageurl”]=value;41}42}4344#endregion454647PropertyCssPath#regionPropertyCssPath4849/**////<summary>50///Css文件所在目录。51///</summary>52[Description(“Javascript脚本文件所在目录。”),DefaultValue(“./”)]53publicstringCssPath54{55get56{57objectobj=ViewState[“NavMenuCssPath”];58returnobj==null?”styles/nav.css”:(string)obj;59}60set61{62ViewState[“NavMenuCssPath”]=value;63}64}6566#endregion676869PropertyXmlFileFullPathName#regionPropertyXmlFileFullPathName7071/**////<summary>72///Xml文件所在目录。73///</summary>74[Description(“Xml文件所在目录。”),DefaultValue(“./”)]75publicstringXmlFileFullPathName76{77get78{79objectobj=ViewState[“NavMenuXmlFileFullPathName”];80returnobj==null?”xml/navmenu.xml”:(string)obj;81}82set83{84ViewState[“NavMenuXmlFileFullPathName”]=value;85}86}8788#endregion8990protectedoverridevoidOnPreRender(EventArgse)#regionprotectedoverridevoidOnPreRender(EventArgse)91/**////<summary>92///重写<seecref=”System.Web.UI.Control.OnPreRender”/>方法。93///</summary>94///<paramname=”e”>包含事件数据的<seecref=”EventArgs”/>对象。</param>95protectedoverridevoidOnPreRender(EventArgse)96{97StringBuildersb=newStringBuilder();9899sb.Append(“<scripttype=\”text/javascript\”src=\””+this.ScriptPath+”\”></script>\r\n”);100sb.Append(“<linkrel=\”stylesheet\”type=\”text/css\”href=\””+this.CssPath+”\”/>\r\n”);101sb.Append(“<scripttype=\”text/javascript\”>varimgpath='”+this.ImageUrl+”‘;</script>\r\n”);102sb.Append(“<scriptlanguage=\”javascript\”src=\””+this.ScriptPath+”\”></script>\r\n”);103#ifNET1104if(!Page.IsClientScriptBlockRegistered(“NavMenu”))105{106Page.RegisterClientScriptBlock(“NavMenu”,sb.ToString());107}108#else109if(!Page.ClientScript.IsClientScriptBlockRegistered(“NavMenu”))110{111Page.ClientScript.RegisterClientScriptBlock(this.GetType(),”NavMenu”,sb.ToString());112}113#endif114115base.OnPreRender(e);116}117118#endregion119120/**////<summary>121///将此控件呈现给指定的输出参数。122///</summary>123///<paramname=”output”>要写出到的HTML编写器</param>124protectedoverridevoidRender(HtmlTextWriteroutput)125{126127output.Write(“<divclass=\”sdmenu\”>\r\n”);128129System.Data.DataSetdsSrc=newSystem.Data.DataSet();130dsSrc.ReadXml(Page.Server.MapPath(this.XmlFileFullPathName));131132intcount=0;133foreach(System.Data.DataRowdrindsSrc.Tables[0].Rows)134{135输出主菜单#region输出主菜单136output.Write(“<table>\r\n”);137output.Write(“<tr>\r\n”);138if(count==0)139{140output.Write(“<tdwidth=\”196px\”><spanclass=\”title\”id=\”top\”>”+141dr[“menutitle”]+”</span></td>\r\n”);142}143else144{145output.Write(“<tdwidth=\”196px\”><spanclass=\”title\”>”+146dr[“menutitle”]+”</span></td>\r\n”);147}148output.Write(“<td><imgsrc=\””+this.ImageUrl+”/top_level_ico1.gif\”149class=\”arrow\”/></td>\r\n”);150output.Write(“</tr>\r\n”);151output.Write(“</table>\r\n”);152#endregion153154输出子菜单#region输出子菜单155output.Write(“<divclass=\”submenu\”>\r\n”);156output.Write(“<table>\r\n”);157foreach(System.Data.DataRowdrsindsSrc.Tables[1].Select(“menuparentid='”+158dr[“menuid”]+”‘”))159{160161output.Write(“<tr>\r\n”);162if(drs[“imgurl”].ToString().Trim()!=””)163{164output.Write(“<tdclass=\”lefttd\”><imgsrc=\””+165drs[“imgurl”].ToString().Trim()+”\”166class=\”submenuimg\”align=\”absmiddle\”/></td>”);167}168else169{170output.Write(“<tdclass=\”lefttd\”></td>”);171}172if((drs[“frameid”].ToString().Trim()==”top”)||(drs[“frameid”].ToString().173Trim()==””))174{175output.Write(“<td><ahref=\”javascript:void(0);\”176onclick=\”javascript:top.location.href='”+177drs[“link”].ToString().Trim()+”‘;\”178onfocus=\”this.blur();\”>”+179drs[“menutitle”].ToString().Trim()+”</a></td>\r\n”);180}181else182{183output.Write(“<td><ahref=\””+drs[“link”].ToString().Trim()+”\”184target=”+drs[“frameid”].ToString().Trim()+”185onfocus=\”this.blur();\”>”+186drs[“menutitle”].ToString().Trim()+”</a></td>\r\n”);187}188output.Write(“</tr>\r\n”);189}190output.Write(“</table>\r\n”);191output.Write(“</div>\r\n”);192#endregion193194//打印分割符195output.Write(“<divclass=\”splitter\”>&nbsp;</div>\r\n”);196count++;197}198199output.Write(“</div>\r\n”);200}201}202203204205

上面的代码因为太简单,就不多做介绍了。而XML的结构如下:

其中的submain表(这里暂且这样说)的menuparentid(子菜单的父menuid),是关联mainmenu表的menuid,这样就能够这这两个表有一个主从结构了。当前如果将这两个表合成“一个”也可以,前提是要减少数据冗余,因为mainmenu表里是不包含link(点击子菜单跳转地址),frameid(子菜单跳转的frameid)这样的信息的。 最后要说明的是这个控件的JS,代码如下(详情见注释):

12varremember=false;//记录当前菜单状态,当下次访问时使用3varcontractall_default=1;//系统菜单项状态1:只显示第一项2:展开所有项3:收缩所有的菜单项45varmenu,titles,submenus,arrows,bypixels;//定义指定的菜单数组变量6varheights=newArray();7varspeed=10;//加载菜单项的速度89varn=navigator.userAgent;1011if(/Opera/.test(n))12{13bypixels=2;14}15elseif(/Firefox/.test(n))16{17bypixels=3;18}19elseif(/MSIE/.test(n))20{21bypixels=2;22}232425//展开所有菜单项26functionslash_expandall()27{28if(typeofmenu!=”undefined”)29{30for(i=0;i<Math.max(titles.length,submenus.length);i++)31{32titles[i].className=”title”;33arrows[i].src=imgpath+”/top_level_ico1.gif”;34submenus[i].style.display=””;35submenus[i].style.height=heights[i]+”px”;36}37}38}394041//收缩所有菜单项42functionslash_contractall()43{44if(typeofmenu!=”undefined”)45{46for(i=0;i<Math.max(titles.length,submenus.length);i++)47{48titles[i].className=”titlehidden”;49arrows[i].src=imgpath+”/top_level_ico2.gif”;50submenus[i].style.display=”none”;51submenus[i].style.height=0;52}53}54}55565758//初始化函数59functioninit(){60menu=getElementsByClassName(“sdmenu”,”div”,document)[0];61titles=getElementsByClassName(“title”,”span”,menu);62submenus=getElementsByClassName(“submenu”,”div”,menu);63arrows=getElementsByClassName(“arrow”,”img”,menu);64for(i=0;i<Math.max(titles.length,submenus.length);i++)65{66titles[i].onclick=gomenu;67arrows[i].onclick=gomenu;68heights[i]=submenus[i].offsetHeight;69submenus[i].style.height=submenus[i].offsetHeight+”px”;70/**//*alert(i);*/7172if(i>0)73{74titles[i].className=”titlehidden”;75arrows[i].src=imgpath+”/top_level_ico2.gif”;76submenus[i].style.display=”none”;77submenus[i].style.height=0;78//alert(‘123’);79}80}8182if(remember)83{84restore();85}8687//根据菜单项状态设置,显示菜单88switch(contractall_default)89{90case1:91{92break;93}94case2:95{96slash_expandall();break;97}98case3:99{100slash_contractall();101}102default:103{104break;105}106}107}108109//存储菜单项状态110functionrestore(){111if(getcookie(“menu”)!=null){112varhidden=getcookie(“menu”).split(“,”);113for(variinhidden){114115titles[hidden[i]].className=”titlehidden”;116submenus[hidden[i]].style.height=”0px”;117submenus[hidden[i]].style.display=”none”;118arrows[hidden[i]].src=imgpath+”/top_level_ico2.gif”;119}120}121}122123//定向到指定的菜单项进行相应操作124functiongomenu(e)125{126if(!e)127{128e=window.event;129}130131varce=(e.target)?e.target:e.srcElement;132133varsm;134135//找到当前菜单项在数组中的位置,用于下面显示或隐藏判断136for(variintitles)137{138if(titles[i]==ce||arrows[i]==ce)139{140sm=i;141}142}143144//当前菜单项是展示状态时145if(parseInt(submenus[sm].style.height)>parseInt(heights[sm])-2)146{147hidemenu(sm);148}149elseif(parseInt(submenus[sm].style.height)<2)//当是收缩状态150{151titles[sm].className=”title”;152153//当菜单只能展开一项(其余菜单项须全部收起)154if(contractall_default==1)155{156slash_contractall();157}158//显示指定的菜单项159showmenu(sm);160}161}162163//隐藏指定的菜单元素164functionhidemenu(sm)165{166varnr=submenus[sm].getElementsByTagName(“a”).length*bypixels+speed;167submenus[sm].style.height=(parseInt(submenus[sm].style.height)-nr)+”px”;168varto=setTimeout(“hidemenu(“+sm+”)”,5);169170if(parseInt(submenus[sm].style.height)<=nr)171{172clearTimeout(to);173submenus[sm].style.display=”none”;174submenus[sm].style.height=”0px”;175arrows[sm].src=imgpath+”/top_level_ico2.gif”;176titles[sm].className=”titlehidden”;177}178}179180//显示指定的菜单元素181functionshowmenu(sm)182{183varnr=submenus[sm].getElementsByTagName(“a”).length*bypixels+speed;184submenus[sm].style.display=””;185submenus[sm].style.height=(parseInt(submenus[sm].style.height)+nr)+”px”;186varto=setTimeout(“showmenu(“+sm+”)”,30);187if(parseInt(submenus[sm].style.height)>(parseInt(heights[sm])-nr))188{189clearTimeout(to);190submenus[sm].style.height=heights[sm]+”px”;191arrows[sm].src=imgpath+”/top_level_ico1.gif”;192}193}194195//保存菜单元素196functionstore()197{198varhidden=newArray();199for(variintitles)200{201if(titles[i].className==”titlehidden”)202{203hidden.push(i);204}205}206putcookie(“menu”,hidden.join(“,”),5);207}208209//获取指定样式的元素210functiongetElementsByClassName(strClassName,strTagName,oElm){211vararrElements=(strTagName==”*”&&document.all)?document.all:oElm.getElementsByTagName(strTagName);212vararrReturnElements=newArray();213strClassName=strClassName.replace(/\-/g,”\\-“);214varoRegExp=newRegExp(“(^|\\s)”+strClassName+”(\\s|$)”);215varoElement;216for(vari=0;i<arrElements.length;i++)217{218oElement=arrElements[i];219if(oRegExp.test(oElement.className))220{221arrReturnElements.push(oElement);222}223}224return(arrReturnElements)225}226227functionputcookie(c_name,value,expiredays)228{229varexdate=newDate();230exdate.setDate(exdate.getDate()+expiredays);231document.cookie=c_name+”=”+escape(value)+((expiredays==null)?””:”;expires=”+exdate);232}233234functiongetcookie(c_name)235{236if(document.cookie.length>0)237{238varc_start=document.cookie.indexOf(c_name+”=”);239if(c_start!=-1)240{241c_start=c_start+c_name.length+1;242varc_end=document.cookie.indexOf(“;”,c_start);243if(c_end==-1)244{245c_end=document.cookie.length;246}247returnunescape(document.cookie.substring(c_start,c_end));248}249}250returnnull;251}252253window.onload=init;254255

其余的大家可以详细看一下包中的相关内容即可, 这里就不再多说了:)

好了,主要是东西就先交待到这里了。如果大家有什么问题或建议,欢迎与我交流,我的邮件是daizhj@discuz.com, daizhj617595@126.com

下载地址:/Files/daizhj/navmenu.rar 关键字: .net, 控件, navmenu, 导航, control, discuz, discuz!nt, discuznt, 代震军, daizhj

有山就有路,有河就能渡。

Discuz!NT控件剖析 之 左侧导航控件 [原创: 附源码]

相关文章:

你感兴趣的文章:

标签云: