Ajax Control Toolkits 之Calendar限制日期自定义扩展

    几个月前因项目需要,用业余时间对Ajax control Toolkits里的日历控件(Calendar)进行了扩展。今天在使用时发现了点Bug,修改了一下,把代码都Copy上来:

先看效果吧:
 
  (灰色删除线的日期,点击了是没有反应的)

扩展工程只需三个文件一个cs文件,一个js文件,一个css文件。其中,js和css的 Build Action都为Embedded Resource,另外别忘了把AjaxControlToolkit引入到工程中。

1.CalendarExtender.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Text;
  5. using System.Web.UI;
  6. using AjaxControlToolkit;
  7. [assembly: System.Web.UI.WebResource("Custom.CalendarExtender.js""text/javascript")]
  8. [assembly: System.Web.UI.WebResource("Custom.Calendar.css""text/css", PerformSubstitution = true)]
  9. namespace Custom
  10. {
  11.     [ClientCssResource("Custom.Calendar.css")]
  12.     [ClientScriptResource("Custom.CalendarExtender""Custom.CalendarExtender.js")]
  13.     [ToolboxData("<{0}:CalendarExtender runat=server></{0}:CalendarExtender>")]
  14.     public class CalendarExtender : AjaxControlToolkit.CalendarExtender
  15.     {
  16.         [DefaultValue(null)]
  17.         [ExtenderControlProperty]
  18.         [ClientPropertyName("lowerBoundDate")]
  19.         public virtual DateTime? LowerBoundDate
  20.         {
  21.             get { return GetPropertyValue("LowerBoundDate", (DateTime?)null); }
  22.             set { SetPropertyValue("LowerBoundDate", value); }
  23.         }
  24.         [DefaultValue(null)]
  25.         [ExtenderControlProperty]
  26.         [ClientPropertyName("upperBoundDate")]
  27.         public virtual DateTime? UpperBoundDate
  28.         {
  29.             get { return GetPropertyValue("UpperBoundDate", (DateTime?)null ); }
  30.             set { SetPropertyValue("UpperBoundDate", value); }
  31.         }
  32.         public IEnumerable<ScriptReference> GetScriptReferences()
  33.         {
  34.             return new ScriptReference[] { new ScriptReference("Custom.CalendarExtender.js""Custom") };
  35.         }
  36.     }
  37. }
2.CalendarExtender.js
  1. // Register the namespace for the control.
  2. Type.registerNamespace('Custom');
  3. Custom.CalendarExtender = function(element) {
  4.     /// <summary>
  5.     /// A behavior that attaches a calendar date selector to a textbox
  6.     /// </summmary>
  7.     /// <param name="element" type="Sys.UI.DomElement">The element to attach to</param>
  8.     Custom.CalendarExtender.initializeBase(this, [element]);
  9.     this._lowerBoundDate = null;
  10.     this._upperBoundDate = null;
  11. }
  12. Custom.CalendarExtender.prototype = {
  13.     initialize: function() {
  14.         /// <summary>
  15.         /// Initializes the components and parameters for this behavior
  16.         /// </summary>
  17.         Custom.CalendarExtender.callBaseMethod(this"initialize");
  18.     },
  19.     dispose: function() {
  20.         /// <summary>
  21.         /// Disposes this behavior's resources
  22.         /// </summary>
  23.         Custom.CalendarExtender.callBaseMethod(this"dispose");
  24.     },
  25.     get_lowerBoundDate: function() {
  26.         /// <summary>
  27.         /// The date currently visible in the calendar
  28.         /// </summary>
  29.         /// <value type="Date" />
  30.         if (this._lowerBoundDate != null) {
  31.             return this._lowerBoundDate;
  32.         }
  33.     },
  34.     set_lowerBoundDate: function(value) {
  35.         if (value && (String.isInstanceOfType(value)) && (value.length != 0)) {
  36.             value = new Date(value);
  37.         }
  38.         if (value) value = value.getDateOnly();
  39.         if (this._lowerBoundDate != value) {
  40.             this._lowerBoundDate = value;
  41.             this.raisePropertyChanged("lowerBoundDate");
  42.         }
  43.     },
  44.     get_upperBoundDate: function() {
  45.         /// <value type="Date">
  46.         /// The date to use for "Today"
  47.         /// </value>
  48.         if (this._upperBoundDate != null) {
  49.             return this._upperBoundDate;
  50.         }
  51.     },
  52.     set_upperBoundDate: function(value) {
  53.         if (value && (String.isInstanceOfType(value)) && (value.length != 0)) {
  54.             value = new Date(value);
  55.         }
  56.         if (value) value = value.getDateOnly();
  57.         if (this._upperBoundDate != value) {
  58.             this._upperBoundDate = value;
  59.             this.raisePropertyChanged("upperBoundDate");
  60.         }
  61.     },
  62.     _performLayout: function() {
  63.         /// <summmary>
  64.         /// Updates the various views of the calendar to match the current selected and visible dates
  65.         /// </summary>
  66.         var elt = this.get_element();
  67.         if (!elt) return;
  68.         if (!this.get_isInitialized()) return;
  69.         if (!this._isOpen) return;
  70.         var dtf = Sys.CultureInfo.CurrentCulture.dateTimeFormat;
  71.         var selectedDate = this.get_selectedDate();
  72.         var visibleDate = this._getEffectiveVisibleDate();
  73.         var todaysDate = this.get_todaysDate();
  74.         switch (this._mode) {
  75.             case "days":
  76.                 var firstDayOfWeek = this._getFirstDayOfWeek();
  77.                 var daysToBacktrack = visibleDate.getDay() - firstDayOfWeek;
  78.                 if (daysToBacktrack <= 0)
  79.                     daysToBacktrack += 7;
  80.                 var startDate = new Date(visibleDate.getFullYear(), visibleDate.getMonth(), visibleDate.getDate() - daysToBacktrack, this._hourOffsetForDst);
  81.                 var currentDate = startDate;
  82.                 for (var i = 0; i < 7; i++) {
  83.                     var dayCell = this._daysTableHeaderRow.cells[i].firstChild;
  84.                     if (dayCell.firstChild) {
  85.                         dayCell.removeChild(dayCell.firstChild);
  86.                     }
  87.                     dayCell.appendChild(document.createTextNode(dtf.ShortestDayNames[(i + firstDayOfWeek) % 7]));
  88.                 }
  89.                 for (var week = 0; week < 6; week++) {
  90.                     var weekRow = this._daysBody.rows[week];
  91.                     for (var dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
  92.                         var dayCell = weekRow.cells[dayOfWeek].firstChild;
  93.                         if (dayCell.firstChild) {
  94.                             dayCell.removeChild(dayCell.firstChild);
  95.                         }
  96.                         dayCell.appendChild(document.createTextNode(currentDate.getDate()));
  97.                         dayCell.title = currentDate.localeFormat("D");
  98.                         dayCell.date = currentDate;
  99.                         //modify by arden 2008.8.21
  100.                         $common.removeCssClasses(dayCell.parentNode, ["ajax__calendar_other""ajax__calendar_disabled""ajax__calendar_active""custom__calendar_lower"]);
  101.                         if (this._lowerBoundDate == null && this._upperBoundDate == null) {
  102.                             Sys.UI.DomElement.addCssClass(dayCell.parentNode, this._getCssClass(dayCell.date, 'd'));
  103.                         }
  104.                         else if ((this._upperBoundDate != null && currentDate > this._upperBoundDate) ||
  105.                         (this._lowerBoundDate != null && currentDate < this._lowerBoundDate)) {
  106.                             Sys.UI.DomElement.addCssClass(dayCell.parentNode, "custom__calendar_lower");
  107.                         }
  108.                         //modify end
  109.                         currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() + 1, this._hourOffsetForDst);
  110.                     }
  111.                 }
  112.                 this._prevArrow.date = new Date(visibleDate.getFullYear(), visibleDate.getMonth() - 1, 1, this._hourOffsetForDst);
  113.                 this._nextArrow.date = new Date(visibleDate.getFullYear(), visibleDate.getMonth() + 1, 1, this._hourOffsetForDst);
  114.                 if (this._title.firstChild) {
  115.                     this._title.removeChild(this._title.firstChild);
  116.                 }
  117.                 this._title.appendChild(document.createTextNode(visibleDate.localeFormat("MMMM, yyyy")));
  118.                 this._title.date = visibleDate;
  119.                 break;
  120.             case "months":
  121.                 for (var i = 0; i < this._monthsBody.rows.length; i++) {
  122.                     var row = this._monthsBody.rows[i];
  123.                     for (var j = 0; j < row.cells.length; j++) {
  124.                         var cell = row.cells[j].firstChild;
  125.                         cell.date = new Date(visibleDate.getFullYear(), cell.month, 1, this._hourOffsetForDst);
  126.                         cell.title = cell.date.localeFormat("Y");
  127.                         $common.removeCssClasses(cell.parentNode, ["ajax__calendar_other""ajax__calendar_disabled""ajax__calendar_active"]);
  128.                         Sys.UI.DomElement.addCssClass(cell.parentNode, this._getCssClass(cell.date, 'M'));
  129.                     }
  130.                 }
  131.                 if (this._title.firstChild) {
  132.                     this._title.removeChild(this._title.firstChild);
  133.                 }
  134.                 this._title.appendChild(document.createTextNode(visibleDate.localeFormat("yyyy")));
  135.                 this._title.date = visibleDate;
  136.                 this._prevArrow.date = new Date(visibleDate.getFullYear() - 1, 0, 1, this._hourOffsetForDst);
  137.                 this._nextArrow.date = new Date(visibleDate.getFullYear() + 1, 0, 1, this._hourOffsetForDst);
  138.                 break;
  139.             case "years":
  140.                 var minYear = (Math.floor(visibleDate.getFullYear() / 10) * 10);
  141.                 for (var i = 0; i < this._yearsBody.rows.length; i++) {
  142.                     var row = this._yearsBody.rows[i];
  143.                     for (var j = 0; j < row.cells.length; j++) {
  144.                         var cell = row.cells[j].firstChild;
  145.                         cell.date = new Date(minYear + cell.year, 0, 1, this._hourOffsetForDst);
  146.                         if (cell.firstChild) {
  147.                             cell.removeChild(cell.lastChild);
  148.                         } else {
  149.                             cell.appendChild(document.createElement("br"));
  150.                         }
  151.                         cell.appendChild(document.createTextNode(minYear + cell.year));
  152.                         $common.removeCssClasses(cell.parentNode, ["ajax__calendar_other""ajax__calendar_disabled""ajax__calendar_active"]);
  153.                         Sys.UI.DomElement.addCssClass(cell.parentNode, this._getCssClass(cell.date, 'y'));
  154.                     }
  155.                 }
  156.                 if (this._title.firstChild) {
  157.                     this._title.removeChild(this._title.firstChild);
  158.                 }
  159.                 this._title.appendChild(document.createTextNode(minYear.toString() + "-" + (minYear + 9).toString()));
  160.                 this._title.date = visibleDate;
  161.                 this._prevArrow.date = new Date(minYear - 10, 0, 1, this._hourOffsetForDst);
  162.                 this._nextArrow.date = new Date(minYear + 10, 0, 1, this._hourOffsetForDst);
  163.                 break;
  164.         }
  165.         if (this._today.firstChild) {
  166.             this._today.removeChild(this._today.firstChild);
  167.         }
  168.         this._today.appendChild(document.createTextNode(String.format(AjaxControlToolkit.Resources.Calendar_Today, todaysDate.localeFormat("MMMM d, yyyy"))));
  169.         this._today.date = todaysDate;
  170.     },
  171.     _isOutOfBounds: function(date, part) {
  172.         /// <summary>
  173.         /// Gets whether the supplied date is out of the lower / upper bound date limits
  174.         /// </summary>
  175.         /// <param name="date" type="Date">The date to match</param>
  176.         /// <param name="part" type="String">The most significant part of the date to test</param>
  177.         /// <returns type="Boolean" />
  178.         switch (part) {
  179.             case 'd':
  180.                 //modify by arden 2008.11.8
  181.                 if (this._lowerBoundDate && date < this._lowerBoundDate) {
  182.                     return true;
  183.                 }
  184.                 else if (this._upperBoundDate && date > this._upperBoundDate) {
  185.                     return true;
  186.                 }
  187.                 break;
  188.             case 'M':
  189.                 //modify by arden 2008.11.8
  190.                 if (this._lowerBoundDate && ((date.getMonth() < this._lowerBoundDate.getMonth() &
  191.                       date.getFullYear() == this._lowerBoundDate.getFullYear()) || date.getFullYear() < this._lowerBoundDate.getFullYear() )) {
  192.                     return true;
  193.                 }
  194.                 else if (this._upperBoundDate && 
  195.                ( (date.getFullYear() == this._upperBoundDate.getFullYear() && date.getMonth() > this._upperBoundDate.getMonth()) ||
  196.                       date.getFullYear() > this._upperBoundDate.getFullYear())) {
  197.                     return true;
  198.                 }
  199.                 break;
  200.             case 'y':
  201.                 if (this._lowerBoundDate && date.getFullYear() < this._lowerBoundDate.getFullYear())
  202.                     return true;
  203.                 else if (this._upperBoundDate && date.getFullYear() > this._upperBoundDate.getFullYear())
  204.                     return true;
  205.                 break;
  206.         }
  207.         return false;
  208.     },
  209.     _getCssClass: function(date, part) {
  210.         /// <summary>
  211.         /// Gets the cssClass to apply to a cell based on a supplied date
  212.         /// </summary>
  213.         /// <param name="date" type="Date">The date to match</param>
  214.         /// <param name="part" type="String">The most significant part of the date to test</param>
  215.         /// <returns type="String" />
  216.         if (this._isSelected(date, part)) {
  217.             return "ajax__calendar_active";
  218.         } else if (this._isOutOfBounds(date, part)) {
  219.             return "ajax__calendar_disabled";
  220.         } else if (this._isOther(date, part)) {
  221.             return "ajax__calendar_other";
  222.         } else {
  223.             return "";
  224.         }
  225.     },
  226.     _cell_onclick: function(e) {
  227.         /// <summary> 
  228.         /// Handles the click event of a cell
  229.         /// </summary>
  230.         /// <param name="e" type="Sys.UI.DomEvent">The arguments for the event</param>
  231.         e.stopPropagation();
  232.         e.preventDefault();
  233.         if (!this._enabled) return;
  234.         var target = e.target;
  235.         var visibleDate = this._getEffectiveVisibleDate();
  236.         Sys.UI.DomElement.removeCssClass(target.parentNode, "ajax__calendar_hover");
  237.         switch (target.mode) {
  238.             case "prev":
  239.             case "next":
  240.                 this._switchMonth(target.date);
  241.                 break;
  242.             case "title":
  243.                 switch (this._mode) {
  244.                     case "days"this._switchMode("months"); break;
  245.                     case "months"this._switchMode("years"); break;
  246.                 }
  247.                 break;
  248.             case "month":
  249.      
  250.                 if (!this._isOutOfBounds(target.date, 'M')) {
  251.                     if (target.month == visibleDate.getMonth()) {
  252.                         this._switchMode("days");
  253.                     } else {
  254.                         this._visibleDate = target.date;
  255.                         this._switchMode("days");
  256.                     }
  257.                 }
  258.                 break;
  259.             case "year":
  260.                 if (!this._isOutOfBounds(target.date, 'y')) {
  261.                     if (target.date.getFullYear() == visibleDate.getFullYear()) {
  262.                         this._switchMode("months");
  263.                     } else {
  264.                         this._visibleDate = target.date;
  265.                         this._switchMode("months");
  266.                     }
  267.                 }
  268.                 break;
  269.             case "day":
  270.                 if (!this._isOutOfBounds(target.date, 'd')) {
  271.                     this.set_selectedDate(target.date);
  272.                     this._switchMonth(target.date);
  273.                     this._blur.post(true);
  274.                     this.raiseDateSelectionChanged();
  275.                 }
  276.                 break;
  277.             case "today":
  278.                 this.set_selectedDate(target.date);
  279.                 this._switchMonth(target.date);
  280.                 this._blur.post(true);
  281.                 this.raiseDateSelectionChanged();
  282.                 break;
  283.         }
  284.     }
  285. }
  286. Custom.CalendarExtender.registerClass("Custom.CalendarExtender", AjaxControlToolkit.CalendarBehavior);
  287.   
3.Calendar.css
  1. .custom__calendar_lower{color#C0C0C0;text-decorationline-through;}

使用方法:
  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2. <%@ Register assembly="AjaxCustomCalendar" namespace="Custom" tagprefix="cc1" %>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head runat="server">
  6.     <title></title>
  7. </head>
  8. <body>
  9.     <form id="form1" runat="server">
  10.     <div>
  11.     
  12.         <asp:ScriptManager ID="ScriptManager1" runat="server">
  13.         </asp:ScriptManager>
  14.         <br />
  15.         <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
  16.         <cc1:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" 
  17.             TargetControlID="TextBox1">
  18.         </cc1:CalendarExtender>
  19.         <br />
  20.         <br />
  21.     
  22.     </div>
  23.     </form>
  24. </body>
  25. </html>
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. public partial class _Default : System.Web.UI.Page 
  8. {
  9.     protected void Page_Load(object sender, EventArgs e)
  10.     {
  11.         if (!IsPostBack)
  12.         {
  13.             this.TextBox1_CalendarExtender.LowerBoundDate = DateTime.Today;
  14.             this.TextBox1_CalendarExtender.UpperBoundDate = DateTime.Today.AddMonths(3);
  15.         }
  16.     }
  17. }


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值