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

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

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

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

    效果图1:
 
         

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

    

  1Property ScriptPath
 21
 22

 23    Property ImageUrl

 45
 46

 47    Property CssPath

 67
 68

 69    Property XmlFileFullPathName

 89
 90    protected override void OnPreRender(EventArgs e)

119
120 
/// <summary> 
121 ///
 将此控件呈现给指定的输出参数。
122 /// </summary>

123 /// <param name="output"> 要写出到的 HTML 编写器 </param>

124 protected override void Render(HtmlTextWriter output)
125 
{
126
         
127  output.Write("<div class=\"sdmenu\">\r\n"
);
128
  
129  System.Data.DataSet dsSrc = new
 System.Data.DataSet();
130  dsSrc.ReadXml(Page.Server.MapPath(this
.XmlFileFullPathName));
131

132  int count=0
;
133  foreach(System.Data.DataRow dr in dsSrc.Tables[0
].Rows)
134  
{
135   输出主菜单

153
154   输出子菜单

193
194   //打印分割符

195   output.Write("<div class=\"splitter\">&nbsp;</div>\r\n");
196   count++
;
197   }

198
199   output.Write("</div>\r\n"
);   
200  }

201 }
202

203
    
204

205

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


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

  1   
  2var remember = false//记录当前菜单状态,当下次访问时使用

  3var contractall_default= 1//系统菜单项状态  1:只显示第一项  2:展开所有项   3:收缩所有的菜单项
  4
  5var menu, titles, submenus, arrows, bypixels; //定义指定的菜单数组变量
  6var heights = new Array();
  7var speed=10;  //加载菜单项的速度 

  8
  9var n = navigator.userAgent;
 10

 11if(/Opera/
.test(n)) 
 12
{
 13    bypixels = 2
;
 14}

 15else if(/Firefox/.test(n)) 
 16
{
 17    bypixels = 3
;
 18}

 19else if(/MSIE/.test(n)) 
 20
{
 21   bypixels = 2
;
 22}

 23
 24

 25//展开所有菜单项

 26function slash_expandall()
 27
{
 28    if (typeof menu!="undefined"
)
 29    
{
 30     for(i=0; i<Math.max(titles.length, submenus.length); i++
)
 31     
{
 32      titles[i].className="title"
;
 33      arrows[i].src = imgpath+"/top_level_ico1.gif"
;
 34      submenus[i].style.display=""
;
 35      submenus[i].style.height = heights[i]+"px"
;
 36     }

 37    }

 38}

 39
 40

 41//收缩所有菜单项

 42function slash_contractall()
 43
{
 44    if (typeof menu!="undefined"
)
 45    
{
 46     for(i=0; i<Math.max(titles.length, submenus.length); i++
)
 47     
{
 48      titles[i].className="titlehidden"
;
 49      arrows[i].src = imgpath+"/top_level_ico2.gif"
;
 50      submenus[i].style.display="none"
;
 51      submenus[i].style.height = 0
;
 52     }

 53    }

 54}

 55
 56
 
 57

 58//初始化函数

 59function init(){
 60    menu = getElementsByClassName("sdmenu""div", document)[0
];
 61    titles = getElementsByClassName("title""span"
, menu);
 62    submenus = getElementsByClassName("submenu""div"
, menu);
 63    arrows = getElementsByClassName("arrow""img"
, menu);
 64    for(i=0; i<Math.max(titles.length, submenus.length); i++

 65    
{
 66        titles[i].onclick =
 gomenu;
 67        arrows[i].onclick =
 gomenu;
 68        heights[i] =
 submenus[i].offsetHeight;
 69        submenus[i].style.height = submenus[i].offsetHeight+"px"
;
 70        /*alert(i); */

 71 
 72        if(i>0
)
 73        
{
 74           titles[i].className="titlehidden"
;
 75        arrows[i].src = imgpath+"/top_level_ico2.gif"
;
 76        submenus[i].style.display="none"
;
 77        submenus[i].style.height = 0
;
 78        //alert('123');

 79     }

 80 }

 81 
 82    if
(remember)
 83 
{
 84
     restore();
 85 }

 86 
 87 //根据菜单项状态设置,显示菜单

 88 switch(contractall_default)
 89 
{
 90     case 1

 91     
{
 92         break
;
 93     }

 94     case 2:
 95     
{
 96         slash_expandall();break
;
 97     }

 98     case 3:
 99     
{
100
         slash_contractall();
101     }

102     default:
103     
{
104         break
;
105     }

106 }

107}

108
109//存储菜单项状态

110function restore() {
111    if(getcookie("menu"!= null
{
112        var hidden = getcookie("menu").split(","
);
113        for(var i in hidden) 
{
114
           
115            titles[hidden[i]].className = "titlehidden"
;
116            submenus[hidden[i]].style.height = "0px"
;
117            submenus[hidden[i]].style.display = "none"
;
118            arrows[hidden[i]].src =imgpath+"/top_level_ico2.gif"
;
119         }

120    }

121}

122
123//定向到指定的菜单项进行相应操作

124function gomenu(e)
125
{
126    if (!
e)
127    
{
128       e = window.event
;
129    }
   
130
    
131    var ce = (e.target) ?
 e.target : e.srcElement;
132
    
133
    var sm;
134
    
135    //找到当前菜单项在数组中的位置,用于下面显示或隐藏判断

136    for(var i in titles) 
137    
{
138        if(titles[i] == ce || arrows[i] ==
 ce)
139        
{
140            sm =
 i;
141        }

142    }

143
144    //当前菜单项是展示状态时

145    if(parseInt(submenus[sm].style.height) > parseInt(heights[sm])-2
146    
{
147
        hidemenu(sm);
148    }

149    else if(parseInt(submenus[sm].style.height) < 2)  //当是收缩状态
150    {
151        titles[sm].className = "title"
;
152
        
153        //当菜单只能展开一项(其余菜单项须全部收起)

154        if(contractall_default ==1)
155        
{
156
            slash_contractall();
157        }

158        //显示指定的菜单项
159        showmenu(sm);
160    }

161}

162
163//隐藏指定的菜单元素

164function hidemenu(sm) 
165
{
166    var nr = submenus[sm].getElementsByTagName("a").length*bypixels+
speed;
167    submenus[sm].style.height = (parseInt(submenus[sm].style.height)-nr)+"px"
;
168    var to = setTimeout("hidemenu("+sm+")"5
);
169

170    if(parseInt(submenus[sm].style.height) <=
 nr) 
171    
{
172
        clearTimeout(to);
173        submenus[sm].style.display = "none"
;
174        submenus[sm].style.height = "0px"
;
175        arrows[sm].src = imgpath+"/top_level_ico2.gif"
;
176        titles[sm].className = "titlehidden"
;
177    }

178}

179
180//显示指定的菜单元素

181function showmenu(sm) 
182
{
183    var nr = submenus[sm].getElementsByTagName("a").length*bypixels+
speed;
184    submenus[sm].style.display = ""
;
185    submenus[sm].style.height = (parseInt(submenus[sm].style.height)+nr)+"px"
;
186    var to = setTimeout("showmenu("+sm+")"30
);
187    if(parseInt(submenus[sm].style.height) > (parseInt(heights[sm])-
nr)) 
188    
{
189
        clearTimeout(to);
190        submenus[sm].style.height = heights[sm]+"px"
;
191        arrows[sm].src = imgpath+"/top_level_ico1.gif"
;
192    }

193}

194
195//保存菜单元素

196function store() 
197
{
198    var hidden = new
 Array();
199    for(var i in
 titles) 
200    
{
201        if(titles[i].className == "titlehidden"
)
202        
{
203
            hidden.push(i);
204        }

205    }

206    putcookie("menu", hidden.join(","), 5);
207}

208
209//获取指定样式的元素

210function getElementsByClassName(strClassName, strTagName, oElm){
211    var arrElements = (strTagName == "*" && document.all)?
 document.all : oElm.getElementsByTagName(strTagName);
212    var arrReturnElements = new
 Array();
213    strClassName = strClassName.replace(/\-/g, "\\-"
);
214    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)"
);
215
    var oElement;
216    for(var i=0; i<arrElements.length; i++
)
217    
{
218        oElement =
 arrElements[i];      
219        if
(oRegExp.test(oElement.className))
220        
{
221
            arrReturnElements.push(oElement);
222        }
   
223    }

224    return (arrReturnElements)
225}

226
227
function putcookie(c_name,value,expiredays) 
228
{
229    var exdate=new
 Date();
230    exdate.setDate(exdate.getDate()+
expiredays);
231    document.cookie = c_name + "=" + escape(value) + ((expiredays==null? "" : ";expires="+
exdate);
232}

233
234
function getcookie(c_name) 
235
{
236    if(document.cookie.length > 0

237    
{
238        var c_start = document.cookie.indexOf(c_name + "="
);
239        if(c_start != -1
)
240        
{
241            c_start = c_start + c_name.length + 1
;
242            var c_end = document.cookie.indexOf(";"
,c_start);
243            if(c_end == -1
)
244            
{
245                c_end =
 document.cookie.length;
246            }

247            return unescape(document.cookie.substring(c_start, c_end));
248        }

249    }

250    return null;
251}

252
253window.onload =
 init;
254

255

 

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

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

    下载地址:/Files/daizhj/navmenu.rar

    关键字: .net, 控件, navmenu, 导航, control, discuz, discuz!nt, discuznt, 代震军, daizhj
 
  

 


 

posted @ 2007-12-04 12:29  代震军  阅读(6542)  评论(21编辑  收藏  举报