zoukankan      html  css  js  c++  java
  • 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
     
      

     


     

  • 相关阅读:
    python的元类
    中国的互联网:草根与精英
    PEP8中文翻译
    一些重要的算法
    tornado模板语法
    C#l类与对象
    sql_ 存储过程
    SQL_触发器
    SQL_事务处理
    C#_方法
  • 原文地址:https://www.cnblogs.com/daizhj/p/980867.html
Copyright © 2011-2022 走看看