Discuz!NT控件剖析 之 ColorPicker(颜色拾取) 和Calendar(日历) [原创: 附源码]

时间:2022-06-03 17:10:42

          继上篇文章之后(链接),大家给了一些反馈和意见,有些BUG和不当之处我已修正,将会在2.0正式版本中提供给大家。希望大家能继续
支持我们这个开源项目。

          好了,开始今天的话题,首先需要说明的是因为这两个控件都比较简单所以放在一起给大家说一下。
   
          先说一下 ColorPicker 控件 ,贴一张运行效果图让大家看一下:

    Discuz!NT控件剖析 之 ColorPicker(颜色拾取) 和Calendar(日历) [原创: 附源码]

   

           在Discuz.Controls项目中的admin/目录下有ColorPicker.cs这个文件, 大家也可以从下载压缩包中得到这个文件的源码
   
    
           那么现在就对这个文件中的关键代码给代码作一下概述:
   
           CreateChildControls() 创建相关子控件,代码如下:
    
     

 1  protected  Discuz.Controls.TextBox tb  =   new  Discuz.Controls.TextBox();
 2        protected  System.Web.UI.HtmlControls.HtmlImage img  =   new  System.Web.UI.HtmlControls.HtmlImage();
 3 
 4        protected   override   void  CreateChildControls()
 5       {
 6            
 7              tb.Size  =   8 // 设置选取的文件框宽度为8
 8              tb.ID  =   this .ID;
 9               this .Controls.Add(tb);
10 
11               // 设置图版按钮的相关图片路径和点击后运行的JS脚本
12              img.ID  =   " ColorPreview "
13              img.Src  =  ImageUrl;
14              img.Attributes.Add( " onclick " " IsShowColorPanel(' "   +   this .tb.ClientID  +   " ',' "   +   this .img.ClientID  +   " ', "   +   this .LeftOffSet  +   " , "   +   this .TopOffSet  +   " ) " );
15              img.Attributes.Add( " class " " img " );
16              img.Attributes.Add( " title " " 选择颜色 " );
17               this .Controls.Add(img);
18 
19               base .CreateChildControls();
20       }
21 
22 

              而客户端呈现HTML输出的代码交给了ColorPickHtmlContent()函数,这个函数会调用JS中的WriteColorPanel, 它的JS代码如下:
        

 1  function WriteColorPanel(tb_ClientID,img_ClientID,leftvalue,topvalue)
 2  {
 3      
 4      document.write( ' <td > ' );
 5      document.write( ' <table border=/"0/" cellPadding=/"0/" cellSpacing=/"0/" id=/"ColorTable_ ' + tb_ClientID + ' /" style=/"cursor:crosshair;/" > ' );
 6      var cnum  =   new  Array( 1 0 0 1 1 0 0 1 0 0 1 1 0 0 1 1 0 1 1 0 0 );
 7       for (i  =   0 ; i  <   16 ; i  ++ )
 8      {
 9          document.write( ' <TR> ' );
10           for (j  =   0 ; j  <   30 ; j  ++ )
11          {
12              n1  =  j  %   5 ;
13              n2  =  Math.floor(j  /   5 *   3 ;
14             n3  =  n2  +   3 ;
15              wc((cnum[n3]  *  n1  +  cnum[n2]  *  ( 5   -  n1)),
16              (cnum[n3  +   1 *  n1  +  cnum[n2  +   1 *  ( 5   -  n1)),
17              (cnum[n3  +   2 *  n1  +  cnum[n2  +   2 *  ( 5   -  n1)), i,tb_ClientID);
18          }
19          document.write( ' </tr> ' );
20      }
21      document.write( ' </table></td> ' );
22      
23      
24      document.write( ' <td> ' );
25      document.write( ' <table border=/"0/" cellPadding=/"0/" cellSpacing=/"0/" id=/"GrayTable ' + tb_ClientID + ' /" style=/"CURSOR: hand;cursor:crosshair;/" > ' );
26       for (i  =   255 ; i  >=   0 ; i  -=   8.5 )
27         document.write( ' <tr bgcolor=# '   +  ToHex(i)  +  ToHex(i)  +  ToHex(i)  +   ' ><td title= '   +  Math.floor(i  *   16   /   17 +   '  height=4 width=20 onmouseover=/"GrayTableMouseOver(this)/" onmousedown=/"GrayTableMouseDown(this)/"  onmouseout=/"GrayTableMouseOut(this)/" ></td></tr> ' );
28             
29       //  alert(tb_ClientID);      
30      document.write( " <tbody></tbody></table></td> " );
31  }


              基本上客户端JS脚本中用的是网上搜的一个代码段,因为里面对FIREFOX不支持,所以做了一些改造和代码重构。大家只要看一下js/colorpicker.js
     应该就全明白了。
    
    
             下面接着说一下Calender 控件, 贴一张运行效果图让大家看一下:
Discuz!NT控件剖析 之 ColorPicker(颜色拾取) 和Calendar(日历) [原创: 附源码]
     
              在Discuz.Controls项目中的admin/目录下有Calendar.cs这个文件, 大家也可以从下载压缩包中得到这个文件的源码
   
              该控件的CreateChildControls函数代码内容如下:
     

 1  protected   override   void  CreateChildControls()
 2       {
 3              tb.Size  =   10 ;
 4              tb.ID  =   this .ID;
 5               this .Controls.Add(tb);
 6 
 7              img.Src  =  ImageUrl + " /btn_calendar.gif " ;
 8              img.Align  =   " bottom " ;
 9              img.Attributes.Add( " onclick " " showcalendar(event, $(' "   +   this .ID  +   " _ "   +   this .ID  +   " ')) " );
10              img.Attributes.Add( " class " " calenderimg " );
11               this .Controls.Add(img);
12 
13               // 添加日期校验控件功能设置
14              System.Web.UI.WebControls.RegularExpressionValidator RegularExpressionValidator1  =   new  RegularExpressionValidator();
15              RegularExpressionValidator1.ID  =  RegularExpressionValidator1.ClientID;
16              RegularExpressionValidator1.Display  =  System.Web.UI.WebControls.ValidatorDisplay.Dynamic;
17              RegularExpressionValidator1.ControlToValidate  =  tb.ID;
18              RegularExpressionValidator1.ValidationExpression  =   @" ^((((1[6-9]|[2-9]/d)/d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]/d|3[01]))|(((1[6-9]|[2-9]/d)/d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]/d|30))|(((1[6-9]|[2-9]/d)/d{2})-0?2-(0?[1-9]|1/d|2[0-8]))|(((1[6-9]|[2-9]/d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$ " ;
19              RegularExpressionValidator1.ErrorMessage  =   " 请输入正确的日期,如:2006-1-1 " ;
20               this .Controls.Add(RegularExpressionValidator1);
21 
22               base .CreateChildControls();
23       }
24 
25 

     
              相关的日期设置和选取值的属性是 SelectedDate,在下面的代码中进行了相关日期格式的转换
       

 1    public  DateTime SelectedDate
 2          {
 3               get
 4              {
 5                   try
 6                  {
 7                       return  DateTime.Parse(tb.Text);
 8                  }
 9                   catch
10                  {
11                       return  Convert.ToDateTime( " 1900-1-1 " );
12                  }
13              }
14               set
15              {
16                   try
17                  {
18                      tb.Text  =  value.ToString( " yyyy-MM-dd " );
19                  }
20                   catch
21                  {
22                      tb.Text  =   "" ;
23                  }
24              }
25          }
26 

      
    相关的JS使用的是DISCUZ PHP版JS代码,并进行了相应的修改以支持控件设计.
   
    这里将主要的代码段贴在此处,以便大家进行阅读
    

 1    // 显示日历面板
 2  function showcalendar( event , controlid1, addtime1, startdate1, enddate1) {
 3   controlid  =  controlid1;
 4   addtime  =  addtime1;
 5   startdate  =  startdate1  ?  parsedate(startdate1) :  false ;
 6   enddate  =  enddate1  ?  parsedate(enddate1) :  false ;
 7   currday  =  controlid.value  ?  parsedate(controlid.value) : today;
 8   hh  =  currday.getHours();
 9   ii  =  currday.getMinutes();
10   var p  =  getposition(controlid);
11   $( ' calendar ' ).style.display  =   ' block ' ;
12   $( ' calendar ' ).style.left  =  p[ ' x ' ] + ' px ' ;
13   $( ' calendar ' ).style.top  =  (p[ ' y ' +  controlid1.offsetHeight  +   1  ) + ' px ' ;
14   
15   _cancelBubble( event );
16   refreshcalendar(currday.getFullYear(), currday.getMonth());
17    if (lastcheckedyear  !=   false ) {
18    $( ' calendar_year_ '   +  lastcheckedyear).className  =   ' default ' ;
19    $( ' calendar_year_ '   +  today.getFullYear()).className  =   ' today ' ;
20   }
21    if (lastcheckedmonth  !=   false ) {
22    $( ' calendar_month_ '   +  lastcheckedmonth).className  =   ' default ' ;
23    $( ' calendar_month_ '   +  (today.getMonth()  +   1 )).className  =   ' today ' ;
24   }
25   $( ' calendar_year_ '   +  currday.getFullYear()).className  =   ' checked ' ;
26   $( ' calendar_month_ '   +  (currday.getMonth()  +   1 )).className  =   ' checked ' ;
27   $( ' hourminute ' ).style.display  =  addtime  ?   ''  :  ' none ' ;
28   lastcheckedyear  =  currday.getFullYear();
29   lastcheckedmonth  =  currday.getMonth()  +   1 ;
30  }
31      
32       // 加载初始化代码
33      function loadcalendar() {
34   s  =   '' ;
35   s  +=   ' <div id="calendar" style="display:none; position:absolute; z-index:9;" onclick="_cancelBubble(event)"> ' ;
36   s  +=   ' <div style="width: 200px;"><table class="calendartable" cellspacing="0" cellpadding="0" width="100%" style="text-align: center;"> ' ;
37   s  +=   ' <tr align="center" class="header"><td class="header"><a href="###" onclick="refreshcalendar(yy, mm-1)" title="上一月"><img src= '   +  imgpath  +   ' /prev.gif border=0></a></td><td colspan="5" style="text-align: center" class="header"><a href="###" onclick="showdiv(/ ' year/ ' );_cancelBubble(event)" title="点击选择年份" id="year"></a>&nbsp; - &nbsp;<a id="month" title="点击选择月份" href="###" onclick="showdiv(/ ' month/ ' );_cancelBubble(event)"></a></td><td class="header"><A href="###" onclick="refreshcalendar(yy, mm+1)" title="下一月"><img src= '   +  imgpath  +   ' /next.gif border=0></A></td></tr> ' ;
38   s  +=   ' <tr class="category"><td>日</td><td>一</td><td>二</td><td>三</td><td>四</td><td>五</td><td>六</td></tr> ' ;
39    for (var i  =   0 ; i  <   6 ; i ++ ) {
40    s  +=   ' <tr class="altbg2"> ' ;
41     for (var j  =   1 ; j  <=   7 ; j ++ )
42     s  +=   " <td id=d "   +  (i  *   7   +  j)  +   "  height=/ " 19 / " >0</td> " ;
43    s  +=   " </tr> " ;
44   }
45   s  +=   ' <tr id="hourminute"><td colspan="7" align="center"><input type="text" size="1" value="" id="hour" onKeyUp=/ ' this .value = this .value  >   23   ?   23  : zerofill( this .value);controlid.value = controlid.value.replace( / //d + (/://d + ) / ig,  this .value + " $1 " )/ ' > 点 <input type="text" size="1" value="" id="minute" onKeyUp=/ ' this .value = this .value  >   59   ?   59  : zerofill( this .value);controlid.value = controlid.value.replace( / (//d + /:)//d +/ ig,  " $1 " + this .value)/ ' > 分</td></tr> ' ;
46   s  +=   ' </table></div></div> ' ;
47   s  +=   ' <div id="calendar_year" onclick="_cancelBubble(event)"><div class="col"> ' ;
48    for (var k  =   1930 ; k  <=   2019 ; k ++ ) {
49    s  +=  k  !=   1930   &&  k  %   10   ==   0   ?   ' </div><div class="col"> '  :  '' ;
50    s  +=   ' <a href="###" onclick="refreshcalendar( '   +  k  +   ' , mm);$(/ ' calendar_year/ ' ).style.display=/ ' none/ ' "><span '   +  (today.getFullYear()  ==  k  ?   '  class="today" '  :  '' +   '  id="calendar_year_ '   +  k  +   ' "> '   +  k  +   ' </span></a><br /> ' ;
51   }
52   s  +=   ' </div></div> ' ;
53   s  +=   ' <div id="calendar_month" onclick="_cancelBubble(event)"> ' ;
54    for (var k  =   1 ; k  <=   12 ; k ++ ) {
55    s  +=   ' <a href="###" onclick="refreshcalendar(yy,  '   +  (k  -   1 +   ' );$(/ ' calendar_month/ ' ).style.display=/ ' none/ ' "><span '   +  (today.getMonth() + 1   ==  k  ?   '  class="today" '  :  '' +   '  id="calendar_month_ '   +  k  +   ' "> '   +  k  +  ( k  <   10   ?   ' &nbsp; '  :  '' +   '  月</span></a><br /> ' ;
56   }
57   s  +=   ' </div> ' ;
58 
59   document.write(s);
60   document.onclick  =  function( event ) {
61    $( ' calendar ' ).style.display  =   ' none ' ;
62    $( ' calendar_year ' ).style.display  =   ' none ' ;
63    $( ' calendar_month ' ).style.display  =   ' none ' ;
64   }
65   $( ' calendar ' ).onclick  =  function( event ) {
66    _cancelBubble( event );
67    $( ' calendar_year ' ).style.display  =   ' none ' ;
68    $( ' calendar_month ' ).style.display  =   ' none ' ;
69   }
70  }
71 

          这两个控件的外观都有相应的CSS控制,分制是colorpicker.css ,calendar.css

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

          下载包地址:/Files/daizhj/ControlsTest_color_calendar.rar