[Asp.netAjaxToolkit扩展]Calendar支持时间段
来源:互联网 发布:网关mac地址怎么查 编辑:程序博客网 时间:2024/06/06 12:27
Asp.Net Ajax Control Toolkit中的Calendar是一个相当不错的日历控件。但是有些时候它却不能满足我们的要求,比如:这次客户要求不能选择当前日期以前的日期,只能点未来的日期。这个大家应该在酒店、航班等时效性要求比较强的网站上经常见到。之前的日期都加了个删除线,并且不能选择。
为了实现这个功能,又不想浪费这么好的Calendar控件功能。 怎么办呢?
原来,Asp.Net Ajax 为我们提供了扩展接口,方便我们对Asp.Net Ajax Control Toolkit的二次开发。
经过Google,在网上找到了一段原始代码,已经实现了,不能对之前的日期进行选择等功能。但是,在显示上,它却不能进行显示灰色,加上删除线。所以我进行的进一步的修改。代码如下(注:以下代码在VS2008 sp1 环境下编译通过):
---------------代码开始(Code Begin)----------------
CalendarCustom.cs代码如下:
--------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using AjaxControlToolkit;
[assembly: System.Web.UI.WebResource("Custom.CalendarExtender.js", "text/javascript")]
[assembly: System.Web.UI.WebResource("Custom.Calendar.css", "text/css", PerformSubstitution = true)]
namespace Custom
{
[ClientCssResource("Custom.Calendar.css")]
[ClientScriptResource("Custom.CalendarExtender", "Custom.CalendarExtender.js")]
[ToolboxData("<{0}:CalendarExtender runat=server></{0}:CalendarExtender>")]
public class CalendarExtender : AjaxControlToolkit.CalendarExtender
{
[DefaultValue(null)]
[ExtenderControlProperty]
[ClientPropertyName("lowerBoundDate")]
public virtual DateTime? LowerBoundDate
{
get { return GetPropertyValue("LowerBoundDate", (DateTime?)null); }
set { SetPropertyValue("LowerBoundDate", value); }
}
[DefaultValue(null)]
[ExtenderControlProperty]
[ClientPropertyName("upperBoundDate")]
public virtual DateTime? UpperBoundDate
{
get { return GetPropertyValue("UpperBoundDate", (DateTime?)null ); }
set { SetPropertyValue("UpperBoundDate", value); }
}
public IEnumerable<ScriptReference> GetScriptReferences()
{
return new ScriptReference[] { new ScriptReference("Custom.CalendarExtender.js", "Custom") };
}
}
}
----------------------------
CalendarExtender.js代码如下:
----------------------------
// Register the namespace for the control.
Type.registerNamespace('Custom');
Custom.CalendarExtender = function(element) {
/// <summary>
/// A behavior that attaches a calendar date selector to a textbox
/// </summmary>
/// <param name="element" type="Sys.UI.DomElement">The element to attach to</param>
Custom.CalendarExtender.initializeBase(this, [element]);
this._lowerBoundDate = null;
this._upperBoundDate = null;
}
Custom.CalendarExtender.prototype = {
initialize: function() {
/// <summary>
/// Initializes the components and parameters for this behavior
/// </summary>
Custom.CalendarExtender.callBaseMethod(this, "initialize");
},
dispose: function() {
/// <summary>
/// Disposes this behavior's resources
/// </summary>
Custom.CalendarExtender.callBaseMethod(this, "dispose");
},
get_lowerBoundDate: function() {
/// <summary>
/// The date currently visible in the calendar
/// </summary>
/// <value type="Date" />
if (this._lowerBoundDate != null) {
return this._lowerBoundDate;
}
},
set_lowerBoundDate: function(value) {
if (value && (String.isInstanceOfType(value)) && (value.length != 0)) {
value = new Date(value);
}
if (value) value = value.getDateOnly();
if (this._lowerBoundDate != value) {
this._lowerBoundDate = value;
this.raisePropertyChanged("lowerBoundDate");
}
},
get_upperBoundDate: function() {
/// <value type="Date">
/// The date to use for "Today"
/// </value>
if (this._upperBoundDate != null) {
return this._upperBoundDate;
}
},
set_upperBoundDate: function(value) {
if (value && (String.isInstanceOfType(value)) && (value.length != 0)) {
value = new Date(value);
}
if (value) value = value.getDateOnly();
if (this._upperBoundDate != value) {
this._upperBoundDate = value;
this.raisePropertyChanged("upperBoundDate");
}
},
_performLayout: function() {
/// <summmary>
/// Updates the various views of the calendar to match the current selected and visible dates
/// </summary>
var elt = this.get_element();
if (!elt) return;
if (!this.get_isInitialized()) return;
if (!this._isOpen) return;
var dtf = Sys.CultureInfo.CurrentCulture.dateTimeFormat;
var selectedDate = this.get_selectedDate();
var visibleDate = this._getEffectiveVisibleDate();
var todaysDate = this.get_todaysDate();
switch (this._mode) {
case "days":
var firstDayOfWeek = this._getFirstDayOfWeek();
var daysToBacktrack = visibleDate.getDay() - firstDayOfWeek;
if (daysToBacktrack <= 0)
daysToBacktrack += 7;
var startDate = new Date(visibleDate.getFullYear(), visibleDate.getMonth(), visibleDate.getDate() - daysToBacktrack, this._hourOffsetForDst);
var currentDate = startDate;
for (var i = 0; i < 7; i++) {
var dayCell = this._daysTableHeaderRow.cells[i].firstChild;
if (dayCell.firstChild) {
dayCell.removeChild(dayCell.firstChild);
}
dayCell.appendChild(document.createTextNode(dtf.ShortestDayNames[(i + firstDayOfWeek) % 7]));
}
for (var week = 0; week < 6; week++) {
var weekRow = this._daysBody.rows[week];
for (var dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
var dayCell = weekRow.cells[dayOfWeek].firstChild;
if (dayCell.firstChild) {
dayCell.removeChild(dayCell.firstChild);
}
dayCell.appendChild(document.createTextNode(currentDate.getDate()));
dayCell.title = currentDate.localeFormat("D");
dayCell.date = currentDate;
//modify by arden 2008.8.21
$common.removeCssClasses(dayCell.parentNode, ["ajax__calendar_other", "ajax__calendar_disabled", "ajax__calendar_active", "custom__calendar_lower"]);
if (this._lowerBoundDate == null && this._upperBoundDate == null ) {
Sys.UI.DomElement.addCssClass(dayCell.parentNode, this._getCssClass(dayCell.date, 'd'));
}
else if ((this._upperBoundDate != null && currentDate > this._upperBoundDate) ||
(this._lowerBoundDate != null && currentDate < this._lowerBoundDate))
{
Sys.UI.DomElement.addCssClass(dayCell.parentNode, "custom__calendar_lower");
}
//modify end
currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() + 1, this._hourOffsetForDst);
}
}
this._prevArrow.date = new Date(visibleDate.getFullYear(), visibleDate.getMonth() - 1, 1, this._hourOffsetForDst);
this._nextArrow.date = new Date(visibleDate.getFullYear(), visibleDate.getMonth() + 1, 1, this._hourOffsetForDst);
if (this._title.firstChild) {
this._title.removeChild(this._title.firstChild);
}
this._title.appendChild(document.createTextNode(visibleDate.localeFormat("MMMM, yyyy")));
this._title.date = visibleDate;
break;
case "months":
for (var i = 0; i < this._monthsBody.rows.length; i++) {
var row = this._monthsBody.rows[i];
for (var j = 0; j < row.cells.length; j++) {
var cell = row.cells[j].firstChild;
cell.date = new Date(visibleDate.getFullYear(), cell.month, 1, this._hourOffsetForDst);
cell.title = cell.date.localeFormat("Y");
$common.removeCssClasses(cell.parentNode, ["ajax__calendar_other", "ajax__calendar_disabled", "ajax__calendar_active"]);
Sys.UI.DomElement.addCssClass(cell.parentNode, this._getCssClass(cell.date, 'M'));
}
}
if (this._title.firstChild) {
this._title.removeChild(this._title.firstChild);
}
this._title.appendChild(document.createTextNode(visibleDate.localeFormat("yyyy")));
this._title.date = visibleDate;
this._prevArrow.date = new Date(visibleDate.getFullYear() - 1, 0, 1, this._hourOffsetForDst);
this._nextArrow.date = new Date(visibleDate.getFullYear() + 1, 0, 1, this._hourOffsetForDst);
break;
case "years":
var minYear = (Math.floor(visibleDate.getFullYear() / 10) * 10);
for (var i = 0; i < this._yearsBody.rows.length; i++) {
var row = this._yearsBody.rows[i];
for (var j = 0; j < row.cells.length; j++) {
var cell = row.cells[j].firstChild;
cell.date = new Date(minYear + cell.year, 0, 1, this._hourOffsetForDst);
if (cell.firstChild) {
cell.removeChild(cell.lastChild);
} else {
cell.appendChild(document.createElement("br"));
}
cell.appendChild(document.createTextNode(minYear + cell.year));
$common.removeCssClasses(cell.parentNode, ["ajax__calendar_other", "ajax__calendar_disabled", "ajax__calendar_active"]);
Sys.UI.DomElement.addCssClass(cell.parentNode, this._getCssClass(cell.date, 'y'));
}
}
if (this._title.firstChild) {
this._title.removeChild(this._title.firstChild);
}
this._title.appendChild(document.createTextNode(minYear.toString() + "-" + (minYear + 9).toString()));
this._title.date = visibleDate;
this._prevArrow.date = new Date(minYear - 10, 0, 1, this._hourOffsetForDst);
this._nextArrow.date = new Date(minYear + 10, 0, 1, this._hourOffsetForDst);
break;
}
if (this._today.firstChild) {
this._today.removeChild(this._today.firstChild);
}
this._today.appendChild(document.createTextNode(String.format(AjaxControlToolkit.Resources.Calendar_Today, todaysDate.localeFormat("MMMM d, yyyy"))));
this._today.date = todaysDate;
},
_isOutOfBounds: function(date, part) {
/// <summary>
/// Gets whether the supplied date is out of the lower / upper bound date limits
/// </summary>
/// <param name="date" type="Date">The date to match</param>
/// <param name="part" type="String">The most significant part of the date to test</param>
/// <returns type="Boolean" />
switch (part) {
case 'd':
if (this._lowerBoundDate && date < this._lowerBoundDate)
return true;
else if (this._upperBoundDate && date > this._upperBoundDate)
return true;
case 'M':
if (this._lowerBoundDate && (date.getMonth() < this._lowerBoundDate.getMonth() ||
date.getFullYear() < this._lowerBoundDate.getFullYear()))
return true;
else if (this._upperBoundDate && (date.getMonth() > this._upperBoundDate.getMonth() ||
date.getFullYear() > this._upperBoundDate.getFullYear()))
return true;
case 'y':
if (this._lowerBoundDate && date.getFullYear() < this._lowerBoundDate.getFullYear())
return true;
else if (this._upperBoundDate && date.getFullYear() > this._upperBoundDate.getFullYear())
return true;
}
return false;
},
_getCssClass: function(date, part) {
/// <summary>
/// Gets the cssClass to apply to a cell based on a supplied date
/// </summary>
/// <param name="date" type="Date">The date to match</param>
/// <param name="part" type="String">The most significant part of the date to test</param>
/// <returns type="String" />
if (this._isSelected(date, part)) {
return "ajax__calendar_active";
} else if (this._isOutOfBounds(date, part)) {
return "ajax__calendar_disabled";
} else if (this._isOther(date, part)) {
return "ajax__calendar_other";
} else {
return "";
}
},
_cell_onclick: function(e) {
/// <summary>
/// Handles the click event of a cell
/// </summary>
/// <param name="e" type="Sys.UI.DomEvent">The arguments for the event</param>
e.stopPropagation();
e.preventDefault();
if (!this._enabled) return;
var target = e.target;
var visibleDate = this._getEffectiveVisibleDate();
Sys.UI.DomElement.removeCssClass(target.parentNode, "ajax__calendar_hover");
switch (target.mode) {
case "prev":
case "next":
this._switchMonth(target.date);
break;
case "title":
switch (this._mode) {
case "days": this._switchMode("months"); break;
case "months": this._switchMode("years"); break;
}
break;
case "month":
if (!this._isOutOfBounds(target.date, 'M')) {
if (target.month == visibleDate.getMonth()) {
this._switchMode("days");
} else {
this._visibleDate = target.date;
this._switchMode("days");
}
}
break;
case "year":
if (!this._isOutOfBounds(target.date, 'y')) {
if (target.date.getFullYear() == visibleDate.getFullYear()) {
this._switchMode("months");
} else {
this._visibleDate = target.date;
this._switchMode("months");
}
}
break;
case "day":
if (!this._isOutOfBounds(target.date, 'd')) {
this.set_selectedDate(target.date);
this._switchMonth(target.date);
this._blur.post(true);
this.raiseDateSelectionChanged();
}
break;
case "today":
this.set_selectedDate(target.date);
this._switchMonth(target.date);
this._blur.post(true);
this.raiseDateSelectionChanged();
break;
}
}
}
Custom.CalendarExtender.registerClass("Custom.CalendarExtender", AjaxControlToolkit.CalendarBehavior);
PS: 如果AjaxControlToolkit升级到了40412verstion, 默认的客户端命名空间要改为Sys.Extended.UI,不然就会报"AjaxControlTookit is undefined"错误。
---------------------
Calendar.css代码如下:
---------------------
.custom__calendar_lower{color: #C0C0C0;text-decoration: line-through;}
---------------代码结束(Code End)----------------
注:在CalendarCustom.cs文件中加红显示的,是我这次解决这个问题花费时间最长的地方。一不小心就会报错了,出现问题时可查看以下内容
http://blogs.msdn.com/irenak/archive/2007/04/17/sysk-330-how-to-use-an-embedded-resource-from-a-sub-folder.aspx
-------------------摘录开始(Begin)----------------
SYSK 330: How To Use An Embedded Resource From A Sub-Folder
If you’re creating a custom client-side control by deriving from System.Web.UI.IScriptControl, you may want to embed the .js files into your assembly instead of having to deploy them to every web site that uses those controls (this is especially valuable if you’re developing a control library). All you need to do is to:
- Click on the .js file in the Solution Explore to select it, and then set Build Action (in the properties window) to Embedded Resource.
- Add the following attribute to your control code-behind file (e.g. MyControl.cs):
[assembly: System.Web.UI.WebResource("ControlLibrary.MyControl.js", "text/javascript")]
- In GetScriptReferences, instead of setting the Path property, use the parameterized constructor as follows:
public IEnumerable<ScriptReference> GetScriptReferences()
{
return new ScriptReference[] { new ScriptReference("ControlLibrary.MyControl.js", "ControlLibrary") };
}
However, if you place your JavaScript files in a subfolder (e.g. /ControlLibrary/Scripts/MyControl.js), then you will have to add the folder name to the dotted resource name above, e.g. ControlLibrary.Scripts.MyControl.js.
If you don’t add the folder name, you’ll probably see a run-time error message like this:
System.InvalidOperationException: Assembly ControlLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' contains a Web resource with name 'ControlLibrary.MyControl.js', but does not contain an embedded resource with name 'ControlLibrary.MyControl.js'.
-------------------摘录结束(End)----------------
页面代码:
<%@ Register Assembly="Custom" Namespace="Custom" TagPrefix="cc1" %>
<cc1:CalendarExtender LowerBoundDate="2010-7-18" UpperBoundDate="2010-12-30" ID="CalendarExtender1" runat="server" TargetControlID="Date1" />
运行效果:
- [Asp.netAjaxToolkit扩展]Calendar支持时间段
- ASP.NET MVC HtmlHelper扩展之Calendar日期时间选择
- Android 日期 Calendar 关于时间段的操作
- Calendar的使用经历,验证时间段
- asp access 时间段
- Asp.net完美日历控件,支持FireFox,IE7(AjaxControlToolKit.Calendar)中文版
- Asp.net完美日历控件,支持FireFox,IE7(AjaxControlToolKit.Calendar)中文版
- 通过扩展让ASP.NET Web API支持JSONP
- asp.net Calendar 控件
- 时间段
- Asp.net MVC Fckeditor的扩展(支持PV3及自动绑定)
- Asp.net MVC Fckeditor的扩展(支持PV3及自动绑定)
- [CORS:跨域资源共享] 通过扩展让ASP.NET Web API支持JSONP
- [CORS:跨域资源共享] 通过扩展让ASP.NET Web API支持W3C的CORS规范
- 扩展dtree支持checkbox
- GCC编译器扩展支持
- gd支持freetype扩展
- php支持oci扩展
- 视频播放魔法师与兔子时,出现死机
- 初识vb利用ADO访问数据库
- zlib压缩库备忘
- /proc/meminfo and procrank (procrank | busybox grep launcher)
- initialization of * is skipped by 'default' label
- [Asp.netAjaxToolkit扩展]Calendar支持时间段
- FCK 异常小结(使用JAVA-core-2.5.jar)
- DICOM命令集和数据集解析
- DICOM中的入门概念
- Vimperator —— 用键盘畅游网络
- 从这个帖子说开“稀疏向量的计算方法”
- MDA工具
- java的内存控制效率优化
- 解释EJB相关术语