说明:
因为项目(OA)的需要,我负责开发日程的模块,相信大家用过谷歌的日历了吧,是不是觉得挺好用,但又苦于无法实现?
这里告诉你一个很好的插件,Wijmo,而里面有一个类似谷歌的日历事件插件,真的很好很强大,注意,我不是托。
当时找到这个插件的时候,真心佩服那些牛逼的外国开发员,能做到这么厉害,并且还开源了。
因为菜鸟,苦苦做了一个多星期才完成,个中原因能归结为:
1、没有中文的介绍和帮助,百度谷歌就是找不到很好的例子。
2、英文不行,看官网API很吃力,没有认真看官网的Demo。
3、不是很熟悉js。
技术要点:
1、基本的js、jQuery使用
2、正则表达式的使用(确实很好很强大)
3、wijmo 日历事件插件的基本使用
4、JSON的基本使用
废话不说,先上几张效果图,还在完善中,希望能帮到有需要的人。
我的Demo 图:
开始上代码,首先这个日历中的数据是要存到本地的,所以要创建数据库。
贴上数据库代码:代码是用SQL 2008的,里面的注释很清楚了,仅供参考。
/********************************************************* 说明:日历事件表:保存日历事件的信息 作者:Frank 2013-6-17 17:34:05 *********************************************************/ USE HFOA IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[tsk_calendar_events]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP TABLE [dbo].[tsk_calendar_events] GO CREATE TABLE [dbo].[tsk_calendar_events] ( --除了id不是插件的关键字,所有的都是插件的关键字,都要注意转换,有些不用转,带c开头的都要转,不然插件会显示错误 id int identity (1,1) NOT NULL, --日历事件编号 allday VARCHAR(10) NULL, --是否为全天事件 calendar VARCHAR(20) NULL, --该事件属于哪个日程的,有 My 和 Work csubject VARCHAR(100) NULL, --事件主题,显示时必须转为 subject color VARCHAR(20) NULL, --该事件的重要程度,以颜色来区分 cdescription varchar(250) NULL, --日程事件的描述,显示时必须转为 description cstart VARCHAR(50) NOT NULL, --开始时间,页面显示时必须转为 start 格式为 new Date(2013,5,17,6,0) cend VARCHAR(50) NOT NULL, --结束时间,注意,页面显示到页面的时候必须把字段名改为 end ,否则该日历插件会报错 格式为 new Date(2013,5,17,6,0) cid VARCHAR(50) NOT NULL, --日历插件的 id,页面显示时必须转为 id isNewEvent VARCHAR(10) NULL, --是否为新事件 location VARCHAR(100) NULL, --事件地点 recurrenceState VARCHAR(20) NULL, --当有重复事件的时候,该事件为主事件还是派生的 重复事件 parentRecurrenceId VARCHAR(50) NULL, --重复事件的主事件 Id ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日历事件编号' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否为全天事件' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'allday' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'该事件属于哪个日程的,有 My 和 Work' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'calendar' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'事件主题,显示时必须转为 subject' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'csubject' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'该事件的重要程度,以颜色来区分' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'color' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日程事件的描述,显示时必须转为 description' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'cdescription' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'开始时间,页面显示时必须转为 start 格式为 new Date(2013,5,17,6,0)' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'cstart' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'结束时间,注意,页面显示到页面的时候必须把字段名改为 end ,否则该日历插件会报错 格式为 new Date(2013,5,17,6,0)' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'cend' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日历插件的 id,页面显示时必须转为 id ' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'cid' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'是否为新事件' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'isNewEvent' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'事件地点' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'location' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'当有重复事件的时候,该事件为主事件还是派生的 重复事件' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'recurrenceState' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重复事件的主事件 Id' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_events', @level2type=N'COLUMN', @level2name=N'parentRecurrenceId' GO /********************************************************* 说明:日历事件重复表:保存日历事件重复的信息 作者:Frank 2013-6-17 17:34:05 *********************************************************/ USE HFOA IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[tsk_calendar_recu]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP TABLE [dbo].[tsk_calendar_recu] GO CREATE TABLE [dbo].[tsk_calendar_recu] ( id int identity (1,1) NOT NULL, --重复事件的id startTime VARCHAR(50) NULL, --开始时间 格式为 Date(2013,5,17,6,0) endTime VARCHAR(50) NULL, --结束时间 格式为 Date(2013,5,17,6,0) parentRecurrenceId VARCHAR(50) NULL, --重复事件的主事件 Id recurrenceType VARCHAR(20) NULL, --事件重复的类型,有每天、每周等 patternStartDate VARCHAR(50) NULL, --主事件的开始时间 格式为 new Date(2013,5,17,6,0) event_id int NOT NULL, --日历主表主键 Id ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重复事件的id' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'id' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'开始时间 格式为 Wed Jun 19 2013 20:30:00' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'startTime' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'结束时间 格式为 Wed Jun 19 2013 20:30:00' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'endTime' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'重复事件的主事件 Id' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'parentRecurrenceId' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'事件重复的类型,有每天、每周等' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'recurrenceType' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主事件的开始时间 格式为 Wed Jun 19 2013 20:30:00' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'patternStartDate' GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'日历主表主键 Id' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tsk_calendar_recu', @level2type=N'COLUMN', @level2name=N'event_id' GO
好了,最重要的数据库咱们已经设计好了,现在就来执行代码实施吧!
注意,涉及到2个表,一个是日历主事件表,一个是用来记录重复事件的表。
代码实施:
页面有2个:
1. tsk_EventsCalendar.aspx
2. tsk_EventsCalendar.aspx.cs
没错,就是用C#来写的,哈哈,被你发现了!不过原理都差不多的,我之前搞SSH,无奈公司不用Java开发,只好学学 ASP.NET 了。
1. tsk_EventsCalendar.aspx
1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="tsk_EventsCalendar.aspx.cs" 2 Inherits="Web.General.tsk.tsk_EventsCalendar" %> 3 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head runat="server"> 7 <title>日历控件</title> 8 <!-- Theme --> 9 <link href="../../js/Wijmo/Theme/cobalt/jquery-wijmo.css" rel="stylesheet" type="text/css" /> 10 <style type="text/css"> 11 #eventscalendar 12 { 13 width: 750px; 14 } 15 </style> 16 </head> 17 <body> 18 <form id="form1" runat="server"> 19 <span id="strjson"> 20 <%=GetStringJSON()%> 21 <!-- style="display: none;" --> 22 </span> 23 <div id="eventscalendar"> 24 </div> 25 </form> 26 </body> 27 </html> 28 <!-- External dependencies --> 29 <script src="../../js/Wijmo/External/jquery-1.9.1.min.js" type="text/javascript"></script> 30 <script src="../../js/Wijmo/External/jquery-ui-1.10.1.custom.min.js" type="text/javascript"></script> 31 <script src="../../js/Wijmo/External/globalize.min.js" type="text/javascript"></script> 32 <!--这个加载太大了,看看不要行不行 33 <script src="Wijmo/External/globalize.cultures.js" type="text/javascript"></script>--> 34 <script src="../../js/Wijmo/External/jquery.mousewheel.min.js" type="text/javascript"></script> 35 <!-- Enable built-in datastorage --> 36 <script src="../../js/Wijmo/datastorage/amplify.core.min.js" type="text/javascript"></script> 37 <script src="../../js/Wijmo/datastorage/amplify.request.min.js" type="text/javascript"></script> 38 <script src="../../js/Wijmo/datastorage/amplify.store.min.js" type="text/javascript"></script> 39 <!-- Wijmo-Open dependencies --> 40 <script src="../../js/Wijmo/Open/jquery.wijmo.wijutil.min.js" type="text/javascript"></script> 41 <link href="../../js/Wijmo/Open/jquery.wijmo.wijutil.css" rel="stylesheet" type="text/css" /> 42 <script src="../../js/Wijmo/Open/jquery.wijmo.widget.min.js" type="text/javascript"></script> 43 <script src="../../js/Wijmo/Open/jquery.wijmo.wijtouchutil.min.js" type="text/javascript"></script> 44 <script src="../../js/Wijmo/Open/jquery.wijmo.wijcalendar.min.js" type="text/javascript"></script> 45 <link href="../../js/Wijmo/Open/jquery.wijmo.wijcalendar.css" rel="stylesheet" type="text/css" /> 46 <script src="../../js/Wijmo/Open/jquery.wijmo.wijdropdown.min.js" type="text/javascript"></script> 47 <link href="../../js/Wijmo/Open/jquery.wijmo.wijdropdown.css" rel="stylesheet" type="text/css" /> 48 <script src="../../js/Wijmo/Open/jquery.wijmo.wijdialog.min.js" type="text/javascript"></script> 49 <link href="../../js/Wijmo/Open/jquery.wijmo.wijdialog.css" rel="stylesheet" type="text/css" /> 50 <script src="../../js/Wijmo/Open/jquery.wijmo.wijtextbox.min.js" type="text/javascript"></script> 51 <link href="../../js/Wijmo/Open/jquery.wijmo.wijtextbox.css" rel="stylesheet" type="text/css" /> 52 <script src="../../js/Wijmo/Open/jquery.wijmo.wijcheckbox.min.js" type="text/javascript"></script> 53 <link href="../../js/Wijmo/Open/jquery.wijmo.wijcheckbox.css" rel="stylesheet" type="text/css" /> 54 <script src="../../js/Wijmo/Open/jquery.wijmo.wijpopup.min.js" type="text/javascript"></script> 55 <script src="../../js/Wijmo/Open/jquery.wijmo.wijsuperpanel.min.js" type="text/javascript"></script> 56 <link href="../../js/Wijmo/Open/jquery.wijmo.wijsuperpanel.css" rel="stylesheet" 57 type="text/css" /> 58 <!-- Wijmo-Pro dependencies --> 59 <script src="../../js/Wijmo/Pro/jquery.plugin.wijtextselection.min.js" type="text/javascript"></script> 60 <script src="../../js/Wijmo/Pro/jquery.wijmo.wijinputcore.min.js" type="text/javascript"></script> 61 <link href="../../js/Wijmo/Pro/jquery.wijmo.wijinput.css" rel="stylesheet" type="text/css" /> 62 <script src="../../js/Wijmo/Pro/jquery.wijmo.wijinputdate.min.js" type="text/javascript"></script> 63 <script src="../../js/Wijmo/Pro/jquery.wijmo.wijdatepager.min.js" type="text/javascript"></script> 64 <link href="../../js/Wijmo/Pro/jquery.wijmo.wijdatepager.css" rel="stylesheet" type="text/css" /> 65 <script src="../../js/Wijmo/Pro/jquery.wijmo.wijevcal.min.js" type="text/javascript"></script> 66 <link href="../../js/Wijmo/Pro/jquery.wijmo.wijevcal.css" rel="stylesheet" type="text/css" /> 67 <script src="../../js/Wijmo/json.js" type="text/javascript"></script> 68 <script type="text/javascript"> 69 $(document).ready(function () { 70 71 var b = eval($("#strjson").text()); 72 73 //获取日历插件里的属性 74 function getData2(obj) { 75 //取得日历的开始和结束的时间变量传到后台,添加操作 76 var stime = "new Date(" + obj.start.getFullYear() + "," + obj.start.getMonth() + "," + obj.start.getDate() + "," + obj.start.getHours() + "," + obj.start.getMinutes() + ")"; 77 var etime = "new Date(" + obj.end.getFullYear() + "," + obj.end.getMonth() + "," + obj.end.getDate() + "," + obj.end.getHours() + "," + obj.end.getMinutes() + ")"; 78 //没有重复事件时的属性值 79 var strGet1 = "&strId=" + obj.id + "&strDes=" + obj.description + "&strEnd=" + etime + "&strLocation=" + obj.location + "&strStart=" + stime + "&strSubject=" + obj.subject + "&strColor=" + obj.color + "&strAllday=" + obj.allday + "&strCalendar=" + obj.calendar + "&strisNewEvent=" + obj.isNewEvent; 80 81 if (obj.recurrencePattern != null) { 82 alert(obj.recurrencePattern.endTime + "结束"); 83 var strGet2 = "&strrecurrenceState=" + obj.recurrenceState + "&strendTime=" + obj.recurrencePattern.endTime + "&strpatternStartDate=" + obj.recurrencePattern.patternStartDate + "&strRecurrenceId=" + obj.recurrencePattern.parentRecurrenceId + "&strrecurrenceType=" + obj.recurrencePattern.recurrenceType + "&strstartTime=" + obj.recurrencePattern.startTime; 84 return strGet2 + strGet1; 85 } else { 86 return strGet1; 87 } 88 }; 89 $("#eventscalendar").wijevcal({ 90 91 visibleCalendars: ["My", "Work"], 92 dataStorage: { 93 addEvent: function (obj, successCallback, errorCallback) {//添加事件 94 var strData = getData2(obj); 95 //如果是重复事件则把重复事件加进来 96 if (obj.recurrencePattern != null) { 97 $.post("tsk_EventsCalendar.aspx?dol=addmore" + strData); 98 } 99 else { 100 $.post("tsk_EventsCalendar.aspx?dol=add" + strData); 101 } 102 successCallback(); 103 }, 104 updateEvent: function (obj, successCallback, errorCallback) { 105 var strData = getData2(obj); 106 $.post("tsk_EventsCalendar.aspx?dol=update" + strData); 107 successCallback(); 108 }, 109 deleteEvent: function (obj, successCallback, errorCallback) { 110 //删除操作 111 $.post("tsk_EventsCalendar.aspx?dol=del" + "&strId=" + obj.id); 112 successCallback(); 113 }, 114 loadEvents: function (visibleCalendars, successCallback, errorCallback) { 115 116 117 successCallback(b); 118 119 } 120 } 121 }); 122 123 124 }); 125 126 127 </script>