https://github.com/esausilva/ASP.Net-EventCalendar
http://trentrichardson.com/examples/timepicker/
https://github.com/posabsolute/jQuery-Validation-Engine
https://github.com/xdan/datetimepicker
https://fullcalendar.io/docs1/event_rendering/Colors/
https://www.codeproject.com/articles/638674/full-calendar-a-complete-web-diary-system-for-jque
https://github.com/claviska/jquery-minicolors
http://www.whatibroke.com/2013/01/01/change-current-day-color-jquery-fullcalendar/ (自定背景色)
https://www.codeproject.com/articles/638674/full-calendar-a-complete-web-diary-system-for-jque
https://github.com/venkatbaggu/jqueryfullcalendaerasp.netmvc
http://www.venkatbaggu.com/calendar-in-asp-net-mvc/
https://github.com/fullcalendar/fullcalendar
https://github.com/fullcalendar/fullcalendar-scheduler
Libraries
sql:
CREATE TABLE [event] ( event_id INT IDENTITY(1,1) PRIMARY KEY, [description] NVARCHAR(100), title NVARCHAR(100), event_start DATETIME, event_end DATETIME, all_day BIT DEFAULT(0) ) GO
edit sql:
CREATE TABLE [event] ( event_id INT IDENTITY(1,1) PRIMARY KEY, [description] NVARCHAR(100), title NVARCHAR(100), event_start DATETIME, event_end DATETIME, all_day BIT DEFAULT(0), --overlap INT DEFAULT(0), --rendering VARCHAR(50), --color VARCHAR(10), typeid INT, adddate DATETIME DEFAULT(GETDATE()) ) GO ---日程事件類型(并自定義顯示的背景色,文本色) CREATE TABLE eventType ( id INT IDENTITY(1,1) PRIMARY KEY, typename NVARCHAR(100), typedecs NVARCHAR(200), backgroundColor VARCHAR(20), textColor VARCHAR(20), borderColor VARCHAR(20) ) GO INSERT INTO eventType(typename,typedecs,backgroundColor,textColor,borderColor)VALUES(N'公司日程',N'公務','#ff9f89','#ff0000','#ffcccc') INSERT INTO eventType(typename,typedecs,backgroundColor,textColor,borderColor)VALUES(N'私人日程',N'私務','green','black','red') SELECT * FROM eventType CREATE VIEW V_Event AS SELECT a.event_id, a.description, a.title, a.event_start, a.event_end, a.all_day,a.typeid,b.backgroundColor,b.textColor,b.borderColor FROM [event] AS a,eventType AS b WHERE a.typeid=b.id GO
Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="fullcalendardemo._Default" %> <!DOCTYPE html> <html> <head id="Head1" runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>ASP.NET FullCalendar</title> <link href="ajax/libs/jqueryui/1.12.1/themes/cupertino/jquery-ui.min.css" rel="stylesheet" /> <link href="ajax/libs/fullcalendar/3.1.1/fullcalendar.min.css" rel="stylesheet" /> <link href="ajax/libs/qtip2/3.0.3/jquery.qtip.min.css" rel="stylesheet" /> <style type='text/css'> body { margin-top: 40px; text-align: center; font-size: 14px; font-family: "Lucida Grande" ,Helvetica,Arial,Verdana,sans-serif; } #calendar { width: 900px; margin: 0 auto; } /* css for timepicker */ .ui-timepicker-div dl { text-align: left; } .ui-timepicker-div dl dt { height: 25px; } .ui-timepicker-div dl dd { margin: -25px 0 10px 65px; } .style1 { width: 100%; } /* table fields alignment*/ .alignRight { text-align:right; padding-right:10px; padding-bottom:10px; } .alignLeft { text-align:left; padding-bottom:10px; } </style> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"> </asp:ScriptManager> <div id="calendar"> </div> <div id="updatedialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;display: none;" title="Update or Delete Event"> <table class="style1"> <tr> <td class="alignRight"> Name:</td> <td class="alignLeft"> <input id="eventName" type="text" size="33" /><br /></td> </tr> <tr> <td class="alignRight"> Description:</td> <td class="alignLeft"> <textarea id="eventDesc" cols="30" rows="3" ></textarea></td> </tr> <tr> <td class="alignRight"> Start:</td> <td class="alignLeft"> <span id="eventStart"></span></td> </tr> <tr> <td class="alignRight"> End: </td> <td class="alignLeft"> <span id="eventEnd"></span><input type="hidden" id="eventId" /></td> </tr> </table> </div> <div id="addDialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;" title="Add Event"> <table class="style1"> <tr> <td class="alignRight"> Name:</td> <td class="alignLeft"> <input id="addEventName" type="text" size="33" /><br /></td> </tr> <tr> <td class="alignRight"> Description:</td> <td class="alignLeft"> <textarea id="addEventDesc" cols="30" rows="3" ></textarea></td> </tr> <tr> <td class="alignRight"> Start:</td> <td class="alignLeft"> <span id="addEventStartDate" ></span></td> </tr> <tr> <td class="alignRight"> End:</td> <td class="alignLeft"> <span id="addEventEndDate" ></span></td> </tr> </table> </div> <div runat="server" id="jsonDiv" /> <input type="hidden" id="hdClient" runat="server" /> </form> <script src="ajax/libs/moment.js/2.18.1/moment.min.js" type="text/javascript"></script> <script src="ajax/libs/jquery/3.1.1/jquery.min.js" type="text/javascript"></script> <script src="ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" type="text/javascript"></script> <script src="ajax/libs/qtip2/3.0.3/jquery.qtip.min.js" type="text/javascript"></script> <script src="ajax/libs/fullcalendar/3.1.1/fullcalendar.min.js" type="text/javascript"></script> <script src='ajax/libs/fullcalendar/3.1.1/locale-all.js' type="text/javascript"></script> <script src="scripts/calendarscript.js" type="text/javascript"></script> </body> </html>
Default.aspx.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text.RegularExpressions; namespace DuFullCalendar { public partial class _Default : System.Web.UI.Page { //this method only updates title and description //this is called when a event is clicked on the calendar [System.Web.Services.WebMethod(true)] public static string UpdateEvent(CalendarEvent cevent) { List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"]; if (idList != null && idList.Contains(cevent.id)) { if (CheckAlphaNumeric(cevent.title) && CheckAlphaNumeric(cevent.description)) { EventDAO.updateEvent(cevent.id, cevent.title, cevent.description); return "updated event with id:" + cevent.id + " update title to: " + cevent.title + " update description to: " + cevent.description; } } return "unable to update event with id:" + cevent.id + " title : " + cevent.title + " description : " + cevent.description; } //this method only updates start and end time //this is called when a event is dragged or resized in the calendar [System.Web.Services.WebMethod(true)] public static string UpdateEventTime(ImproperCalendarEvent improperEvent) { List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"]; if (idList != null && idList.Contains(improperEvent.id)) { EventDAO.updateEventTime(improperEvent.id, Convert.ToDateTime(improperEvent.start), Convert.ToDateTime(improperEvent.end), improperEvent.allDay); //allDay parameter added for FullCalendar 2.x return "updated event with id:" + improperEvent.id + " update start to: " + improperEvent.start + " update end to: " + improperEvent.end; } return "unable to update event with id: " + improperEvent.id; } //called when delete button is pressed [System.Web.Services.WebMethod(true)] public static String deleteEvent(int id) { //idList is stored in Session by JsonResponse.ashx for security reasons //whenever any event is update or deleted, the event id is checked //whether it is present in the idList, if it is not present in the idList //then it may be a malicious user trying to delete someone elses events //thus this checking prevents misuse List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"]; if (idList != null && idList.Contains(id)) { EventDAO.deleteEvent(id); return "deleted event with id:" + id; } return "unable to delete event with id: " + id; } //called when Add button is clicked //this is called when a mouse is clicked on open space of any day or dragged //over mutliple days [System.Web.Services.WebMethod] public static int addEvent(ImproperCalendarEvent improperEvent) { CalendarEvent cevent = new CalendarEvent() { title = improperEvent.title, description = improperEvent.description, start = Convert.ToDateTime(improperEvent.start), end = Convert.ToDateTime(improperEvent.end), allDay = improperEvent.allDay }; if (CheckAlphaNumeric(cevent.title) && CheckAlphaNumeric(cevent.description)) { int key = EventDAO.addEvent(cevent); List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"]; if (idList != null) { idList.Add(key); } return key; //return the primary key of the added cevent object } return -1; //return a negative number just to signify nothing has been added } /// <summary> ///隻可輸入 數字,字母,中文,中文標點符號 /// </summary> /// <param name="str"></param> /// <returns></returns> private static bool CheckAlphaNumeric(string str) { return Regex.IsMatch(str, @"^[a-zA-Z0-9 |\u4e00-\u9fa5|\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]*$"); } /// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Page_Load(object sender, EventArgs e) { } } }
calendarscript.js
var currentUpdateEvent; var addStartDate; var addEndDate; var globalAllDay; function updateEvent(event, element) { //alert(event.description); if ($(this).data("qtip")) $(this).qtip("destroy"); currentUpdateEvent = event; $('#updatedialog').dialog('open'); $("#eventName").val(event.title); $("#eventDesc").val(event.description); $("#eventId").val(event.id); $("#eventStart").text("" + event.start.toLocaleString()); if (event.end === null) { $("#eventEnd").text(""); } else { $("#eventEnd").text("" + event.end.toLocaleString()); } return false; } function updateSuccess(updateResult) { //alert(updateResult); } function deleteSuccess(deleteResult) { //alert(deleteResult); } function addSuccess(addResult) { // if addresult is -1, means event was not added // alert("added key: " + addResult); if (addResult != -1) { $('#calendar').fullCalendar('renderEvent', { title: $("#addEventName").val(), start: addStartDate, end: addEndDate, id: addResult, description: $("#addEventDesc").val(), allDay: globalAllDay }, true // make the event "stick" ); $('#calendar').fullCalendar('unselect'); } } function UpdateTimeSuccess(updateResult) { //alert(updateResult); } function selectDate(start, end, allDay) { $('#addDialog').dialog('open'); $("#addEventStartDate").text("" + start.toLocaleString()); $("#addEventEndDate").text("" + end.toLocaleString()); addStartDate = start; addEndDate = end; globalAllDay = allDay; //alert(allDay); } function updateEventOnDropResize(event, allDay) { //alert("allday: " + allDay); var eventToUpdate = { id: event.id, start: event.start }; if (event.end === null) { eventToUpdate.end = eventToUpdate.start; } else { eventToUpdate.end = event.end; } var endDate; if (!event.allDay) { endDate = new Date(eventToUpdate.end + 60 * 60000); endDate = endDate.toJSON(); } else { endDate = eventToUpdate.end.toJSON(); } eventToUpdate.start = eventToUpdate.start.toJSON(); eventToUpdate.end = eventToUpdate.end.toJSON(); //endDate; eventToUpdate.allDay = event.allDay; PageMethods.UpdateEventTime(eventToUpdate, UpdateTimeSuccess); } function eventDropped(event, dayDelta, minuteDelta, allDay, revertFunc) { if ($(this).data("qtip")) $(this).qtip("destroy"); updateEventOnDropResize(event); } function eventResized(event, dayDelta, minuteDelta, revertFunc) { if ($(this).data("qtip")) $(this).qtip("destroy"); updateEventOnDropResize(event); } //隻可輸入數字,字母,中文,中文標點符號 20170417 塗聚文 EDIT function checkForSpecialChars(stringToCheck) { var pattern = /[^A-Za-z0-9 |\u4e00-\u9fa5|\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]/; //A-Za-z0-9 return pattern.test(stringToCheck); } //是否整天時間 function isAllDay(startDate, endDate) { var allDay; if (startDate.format("HH:mm:ss") == "00:00:00" && endDate.format("HH:mm:ss") == "00:00:00") { allDay = true; globalAllDay = true; } else { allDay = false; globalAllDay = false; } return allDay; } //提示內容 function qTipText(start, end, description) { var text; if (end !== null) text = "<strong>Start:</strong> " + start.format("MM/DD/YYYY hh:mm T") + "<br/><strong>End:</strong> " + end.format("MM/DD/YYYY hh:mm T") + "<br/><br/>" + description; else text = "<strong>Start:</strong> " + start.format("MM/DD/YYYY hh:mm T") + "<br/><strong>End:</strong><br/><br/>" + description; return text; } $(document).ready(function() { // update Dialog $('#updatedialog').dialog({ autoOpen: false, width: 470, buttons: { "update": function() { //alert(currentUpdateEvent.title); var eventToUpdate = { id: currentUpdateEvent.id, title: $("#eventName").val(), description: $("#eventDesc").val() }; if (checkForSpecialChars(eventToUpdate.title) || checkForSpecialChars(eventToUpdate.description)) { alert("please enter characters: 可輸入數字,字母,中文,中文標點符號, 空格"); } else { PageMethods.UpdateEvent(eventToUpdate, updateSuccess); $(this).dialog("close"); currentUpdateEvent.title = $("#eventName").val(); currentUpdateEvent.description = $("#eventDesc").val(); $('#calendar').fullCalendar('updateEvent', currentUpdateEvent); } }, "delete": function() { if (confirm("do you really want to delete this event?")) { PageMethods.deleteEvent($("#eventId").val(), deleteSuccess); $(this).dialog("close"); $('#calendar').fullCalendar('removeEvents', $("#eventId").val()); } } } }); //add dialog $('#addDialog').dialog({ autoOpen: false, width: 470, buttons: { "Add": function() { //alert("sent:" + addStartDate.format("dd-MM-yyyy hh:mm:ss tt") + "==" + addStartDate.toLocaleString()); var eventToAdd = { title: $("#addEventName").val(), description: $("#addEventDesc").val(), start: addStartDate.toJSON(), end: addEndDate.toJSON(), allDay: isAllDay(addStartDate, addEndDate) }; if (checkForSpecialChars(eventToAdd.title) || checkForSpecialChars(eventToAdd.description)) { alert("please enter characters: 可輸入數字,字母,中文,中文標點符號, 空格"); } else { //alert("sending " + eventToAdd.title); PageMethods.addEvent(eventToAdd, addSuccess); $(this).dialog("close"); } } } }); var date = new Date(); var d = date.getDate(); var m = date.getMonth(); var y = date.getFullYear(); var options = { weekday: "long", year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }; $('#calendar').fullCalendar({ theme: true, header: { left: 'prev,next today customBtn', center: 'title', right: 'month,agendaWeek,agendaDay,listWeek' //顯示日程列表 }, customButtons: { customBtn: { text: 'Custom Button', click: function() { alert('This custom button is hot! 🔥\nNow go have fun!'); } } }, defaultView: 'agendaWeek', eventClick: updateEvent, selectable: true, selectHelper: true, select: selectDate, editable: true, navLinks: true, // can click day/week names to navigate views weekNumbers: true, //顯示第几周 weekNumbersWithinDays: true, weekNumberCalculation: 'zh-cn', locale: 'zh-cn', events: "JsonResponse.ashx", eventDrop: eventDropped, eventResize: eventResized, eventRender: function(event, element) { //alert(event.title); element.qtip({ content: { text: qTipText(event.start, event.end, event.description), title: '<strong>' + event.title + '</strong>' }, position: { my: 'bottom left', at: 'top right' }, style: { classes: 'qtip-shadow qtip-rounded' } }); } }); });
JsonResponse.ashx
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.SessionState; using System.Web.Services; namespace DuFullCalendar { /// <summary> /// JsonResponse 的摘要说明 /// </summary> public class JsonResponse : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; DateTime start = Convert.ToDateTime(context.Request.QueryString["start"]); DateTime end = Convert.ToDateTime(context.Request.QueryString["end"]); List<int> idList = new List<int>(); List<ImproperCalendarEvent> tasksList = new List<ImproperCalendarEvent>(); //Generate JSON serializable events foreach (CalendarEvent cevent in EventDAO.getEvents(start, end)) { tasksList.Add(new ImproperCalendarEvent { id = cevent.id, title = cevent.title, start = String.Format("{0:s}", cevent.start), end = String.Format("{0:s}", cevent.end), description = cevent.description, allDay = cevent.allDay, }); idList.Add(cevent.id); } context.Session["idList"] = idList; //Serialize events to string System.Web.Script.Serialization.JavaScriptSerializer oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); string sJSON = oSerializer.Serialize(tasksList); //Write JSON to response object context.Response.Write(sJSON); } /// <summary> /// /// </summary> /// <param name="cevent"></param> /// <returns></returns> private String convertCalendarEventIntoString(CalendarEvent cevent) { String allDay = "true"; if (ConvertToTimestamp(cevent.start).ToString().Equals(ConvertToTimestamp(cevent.end).ToString())) { if (cevent.start.Hour == 0 && cevent.start.Minute == 0 && cevent.start.Second == 0) { allDay = "true"; } else { allDay = "false"; } } else { if (cevent.start.Hour == 0 && cevent.start.Minute == 0 && cevent.start.Second == 0 && cevent.end.Hour == 0 && cevent.end.Minute == 0 && cevent.end.Second == 0) { allDay = "true"; } else { allDay = "false"; } } return "{" + "id: '" + cevent.id + "'," + "title: '" + HttpContext.Current.Server.HtmlEncode(cevent.title) + "'," + "start: " + ConvertToTimestamp(cevent.start).ToString() + "," + "end: " + ConvertToTimestamp(cevent.end).ToString() + "," + "allDay:" + allDay + "," + "description: '" + HttpContext.Current.Server.HtmlEncode(cevent.description) + "'" + "},"; } /// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> private long ConvertToTimestamp(DateTime value) { long epoch = (value.ToUniversalTime().Ticks - 621355968000000000) / 10000000; return epoch; } /// <summary> /// /// </summary> public bool IsReusable { get { return false; } } } }
自定義樣式:
fullCalendarTimepicker.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="fullCalendarTimepicker.aspx.cs" Inherits="fullcalendardemo.fullCalendarTimepicker" %> <!DOCTYPE html> <html> <head id="Head1" runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>ASP.NET FullCalendar</title> <link href="ajax/libs/jqueryui/1.12.1/themes/cupertino/jquery-ui.min.css" rel="stylesheet" /> <link href="ajax/libs/fullcalendar/3.1.1/fullcalendar.min.css" rel="stylesheet" /> <link href="ajax/libs/qtip2/3.0.3/jquery.qtip.min.css" rel="stylesheet" /> <link rel="stylesheet" media="all" type="text/css" href="ajax/libs/timepicker/jquery-ui-timepicker-addon.css" /> <link rel="stylesheet" href="ajax/libs/formValidator/css/validationEngine.jquery.css" type="text/css" media="screen" charset="utf-8" /> <style type='text/css'> body { margin-top: 40px; text-align: center; font-size: 14px; font-family: "Lucida Grande" ,Helvetica,Arial,Verdana,sans-serif; } #calendar { width: 900px; margin: 0 auto; } /* css for timepicker */ .ui-timepicker-div dl { text-align: left; } .ui-timepicker-div dl dt { height: 25px; } .ui-timepicker-div dl dd { margin: -25px 0 10px 65px; } .style1 { width: 100%; } /* table fields alignment*/ .alignRight { text-align:right; padding-right:10px; padding-bottom:10px; } .alignLeft { text-align:left; padding-bottom:10px; } </style> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"> </asp:ScriptManager> <div id="calendar"> </div> <div id="updatedialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;display: none;" title="Update or Delete Event"> <table class="style1"> <tr> <td class="alignRight"> Name:</td> <td class="alignLeft"> <input id="eventName" type="text" size="33" /><br /></td> </tr> <tr> <td class="alignRight"> Description:</td> <td class="alignLeft"> <textarea id="eventDesc" cols="30" rows="3" ></textarea></td> </tr> <tr> <td class="alignRight"> Start:</td> <td class="alignLeft"> <input id="eventStart" name="eventStart" value="" /></td> </tr> <tr> <td class="alignRight"> End: </td> <td class="alignLeft"> <input id="eventEnd" name="eventEnd" value=""/><input type="hidden" id="eventId" /></td> </tr> </table> </div> <div id="addDialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;" title="Add Event"> <table class="style1"> <tr> <td class="alignRight"> Name:</td> <td class="alignLeft"> <input id="addEventName" type="text" size="33" /><br /></td> </tr> <tr> <td class="alignRight"> Description:</td> <td class="alignLeft"> <textarea id="addEventDesc" cols="30" rows="3" ></textarea></td> </tr> <tr> <td class="alignRight"> Start:</td> <td class="alignLeft"> <input id="addEventStartDate" class="validate[required,funcCall[validate2time]]" name="addEventStartDate" value=""/></td> </tr> <tr> <td class="alignRight"> End:</td> <td class="alignLeft"> <input id="addEventEndDate" class="validate[required,funcCall[validate2time]]" name="addEventEndDate" value=""/></td> </tr> </table> </div> <div runat="server" id="jsonDiv" /> <input type="hidden" id="hdClient" runat="server" /> </form> <script src="ajax/libs/moment.js/2.18.1/moment.min.js" type="text/javascript"></script> <script src="ajax/libs/jquery/3.1.1/jquery.min.js" type="text/javascript"></script> <script src="ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" type="text/javascript"></script> <script src="ajax/libs/qtip2/3.0.3/jquery.qtip.min.js" type="text/javascript"></script> <script type="text/javascript" src="ajax/libs/timepicker/jquery-ui-timepicker-addon.js"></script> <script type="text/javascript" src="ajax/libs/timepicker/i18n/jquery-ui-timepicker-addon-i18n.min.js"></script> <script type="text/javascript" src="ajax/libs/timepicker/i18n/jquery-ui-timepicker-zh-CN.js"></script> <script type="text/javascript" src="ajax/libs/timepicker/jquery-ui-sliderAccess.js"></script> <script src="ajax/libs/fullcalendar/3.1.1/fullcalendar.min.js" type="text/javascript"></script> <script src='ajax/libs/fullcalendar/3.1.1/locale-all.js' type="text/javascript"></script> <script src="ajax/libs/formValidator/js/jquery.validationEngine.js" type="text/javascript"></script> <script src="ajax/libs/formValidator/js/languages/jquery.validationEngine-zh_CN.js" type="text/javascript"></script> <script src="ajax/libs/jqueryui/1.12.1/ui/i18n/datepicker-zh-CN.js" type="text/javascript"></script> <script src="scripts/calendarscriptTime.js" type="text/javascript"></script> </body> </html>
calendarscriptTime.js:
var currentUpdateEvent; var addStartDate; var addEndDate; var globalAllDay; //修改時,穫取值 // 涂聚文 Geovin Du edit 20170417 function updateEvent(event, element) { //alert(event.description); if ($(this).data("qtip")) $(this).qtip("destroy"); currentUpdateEvent = event; $('#updatedialog').dialog('open'); $("#eventName").val(event.title); $("#eventDesc").val(event.description); $("#eventId").val(event.id); $("#eventStart").val("" + $.fullCalendar.formatDate(event.start, "YYYY-MM-DD HH:mm")); //text $.fullCalendar.formatDate(event.start, "YYYY-MM-DD HH:mm") $("#eventStart").datetimepicker({ timeInput: true, changeMonth: true, changeYear: true, dateFormat: 'yy-mm-dd', timeFormat: 'HH:mm', hourMin: 5, hourMax: 24, hourGrid: 3, minuteGrid: 15 }); //timeInput: true, //$("#eventStart").datetimepicker('setDate', (new Date())); if (event.end === null) { $("#eventEnd").val(""); //text } else { $("#eventEnd").val("" + $.fullCalendar.formatDate(event.end, "YYYY-MM-DD HH:mm")); //text event.end.toLocaleString() $("#eventEnd").datetimepicker({ timeInput: true, changeMonth: true, changeYear: true, dateFormat: 'yy-mm-dd', timeFormat: 'HH:mm', hourMin: 5, hourMax: 24, hourGrid: 3, minuteGrid: 15 }); // } return false; } function updateSuccess(updateResult) { //alert(updateResult); } function deleteSuccess(deleteResult) { //alert(deleteResult); } function addSuccess(addResult) { // if addresult is -1, means event was not added // alert("added key: " + addResult); if (addResult != -1) { $('#calendar').fullCalendar('renderEvent', { title: $("#addEventName").val(), start: addStartDate, end: addEndDate, id: addResult, description: $("#addEventDesc").val(), allDay: globalAllDay }, true // make the event "stick" ); $('#calendar').fullCalendar('unselect'); } } function UpdateTimeSuccess(updateResult) { //alert(updateResult); } // $("#addEventStartDate").datetimepicker({ timeInput: true, changeMonth: true, changeYear: true, dateFormat: 'yy-mm-dd', timeFormat: 'HH:mm', hourMin: 5, hourMax: 24, hourGrid: 3, minuteGrid: 15 }); // $("#addEventEndDate").datetimepicker({ timeInput: true, changeMonth: true, changeYear: true, dateFormat: 'yy-mm-dd', timeFormat: 'HH:mm', hourMin: 5, hourMax: 24, hourGrid: 3, minuteGrid: 15 }); //選擇時,穫取值 function selectDate(start, end, allDay) { //$('#addEventStartDate').datetimepicker(); $('#addDialog').dialog('open'); $("#addEventStartDate").val("" + $.fullCalendar.formatDate(start, "YYYY-MM-DD HH:mm")); //text //標簽span $.fullCalendar.formatDate(start, "yyyy/MM/dd HH:mm"); $("#addEventEndDate").val("" + $.fullCalendar.formatDate(end, "YYYY-MM-DD HH:mm")); //text $.fullCalendar.formatDate(end, "yyyy/MM/dd HH:mm"); //$("#addEventStartDate").datetimepicker('setDate', $.fullCalendar.formatDate(start, "YYYY-MM-DD HH:mm")); //設置值,日期格式還存在不相符問題 addStartDate = start; addEndDate = end; globalAllDay = allDay; //alert(allDay); } function updateEventOnDropResize(event, allDay) { //alert("allday: " + allDay); var eventToUpdate = { id: event.id, start: event.start }; if (event.end === null) { eventToUpdate.end = eventToUpdate.start; } else { eventToUpdate.end = event.end; } var endDate; if (!event.allDay) { endDate = new Date(eventToUpdate.end + 60 * 60000); endDate = endDate.toJSON(); } else { endDate = eventToUpdate.end.toJSON(); } eventToUpdate.start = eventToUpdate.start.toJSON(); eventToUpdate.end = eventToUpdate.end.toJSON(); //endDate; eventToUpdate.allDay = event.allDay; PageMethods.UpdateEventTime(eventToUpdate, UpdateTimeSuccess); } function eventDropped(event, dayDelta, minuteDelta, allDay, revertFunc) { if ($(this).data("qtip")) $(this).qtip("destroy"); updateEventOnDropResize(event); } function eventResized(event, dayDelta, minuteDelta, revertFunc) { if ($(this).data("qtip")) $(this).qtip("destroy"); updateEventOnDropResize(event); } //隻可輸入數字,字母,中文,中文標點符號 20170417 塗聚文 EDIT function checkForSpecialChars(stringToCheck) { var pattern = /[^A-Za-z0-9 |\u4e00-\u9fa5|\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]/; //A-Za-z0-9 return pattern.test(stringToCheck); } //是否整天時間 function isAllDay(startDate, endDate) { var allDay; if (startDate.format("HH:mm:ss") == "00:00:00" && endDate.format("HH:mm:ss") == "00:00:00") { allDay = true; globalAllDay = true; } else { allDay = false; globalAllDay = false; } return allDay; } //提示內容 function qTipText(start, end, description) { var text; if (end !== null) text = "<strong>Start:</strong> " + start.format("YYYY-MM-DD hh:mm T") + "<br/><strong>End:</strong> " + end.format("YYYY-MM-DD hh:mm T") + "<br/><br/>" + description; else text = "<strong>Start:</strong> " + start.format("YYYY-MM-DD hh:mm T") + "<br/><strong>End:</strong><br/><br/>" + description; return text; } $(document).ready(function () { // update Dialog 修改,刪除 $('#updatedialog').dialog({ autoOpen: false, width: 470, buttons: { "update": function () { //alert(currentUpdateEvent.title); var eventToUpdate = { id: currentUpdateEvent.id, title: $("#eventName").val(), description: $("#eventDesc").val() }; if (checkForSpecialChars(eventToUpdate.title) || checkForSpecialChars(eventToUpdate.description)) { alert("please enter characters: 可輸入數字,字母,中文,中文標點符號, 空格"); } else { PageMethods.UpdateEvent(eventToUpdate, updateSuccess); $(this).dialog("close"); currentUpdateEvent.title = $("#eventName").val(); currentUpdateEvent.description = $("#eventDesc").val(); $('#calendar').fullCalendar('updateEvent', currentUpdateEvent); } }, "delete": function () { if (confirm("do you really want to delete this event?")) { PageMethods.deleteEvent($("#eventId").val(), deleteSuccess); $(this).dialog("close"); $('#calendar').fullCalendar('removeEvents', $("#eventId").val()); } } } }); //add dialog 添加 $('#addDialog').dialog({ autoOpen: false, width: 470, buttons: { "Add": function () { //alert("sent:" + addStartDate.format("dd-MM-yyyy hh:mm:ss tt") + "==" + addStartDate.toLocaleString()); var eventToAdd = { title: $("#addEventName").val(), description: $("#addEventDesc").val(), start: addStartDate.toJSON(), //addStartDate.toJSON() end:addEndDate.toJSON(), allDay: isAllDay(addStartDate, addEndDate) }; if (checkForSpecialChars(eventToAdd.title) || checkForSpecialChars(eventToAdd.description)) { alert("please enter characters: 可輸入數字,字母,中文,中文標點符號, 空格"); } else { //alert("sending " + eventToAdd.title); PageMethods.addEvent(eventToAdd, addSuccess); $(this).dialog("close"); } } } }); var date = new Date(); var d = date.getDate(); var m = date.getMonth(); var y = date.getFullYear(); var options = { weekday: "long", year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }; $('#calendar').fullCalendar({ theme: true, header: { left: 'prev,next today customBtn', center: 'title', right: 'month,agendaWeek,agendaDay,listWeek' //顯示日程列表 }, customButtons: { customBtn: { text: 'Custom Button', click: function () { alert('This custom button is hot! 🔥\nNow go have fun!'); } } }, defaultView: 'agendaWeek', eventClick: updateEvent, selectable: true, selectHelper: true, select: selectDate, editable: true, navLinks: true, // can click day/week names to navigate views weekNumbers: true, //顯示第几周 //weekNumbersWithinDays: true, weekNumberCalculation: 'zh-cn', locale: 'zh-cn', events: "JsonResponse.ashx", eventDrop: eventDropped, //可以拖動 eventResize: eventResized, //可以改變大小 eventRender: function (event, element) { //alert(event.title); element.qtip({ content: { text: qTipText(event.start, event.end, event.description), //提示顯示的內容 title: '<strong>' + event.title + '</strong>' }, position: { my: 'bottom left', at: 'top right' }, style: { classes: 'qtip-shadow qtip-rounded' } }); } }); }); function validate2time() { //alert("debug"); var start = $("#addEventStartDate").val(); var end = $("#addEventEndDate").val(); var cresult = 0; if (new Date(start) < new Date(end)) { cresult = 0; } else { cresult = 1; } // alert(cresult); if (cresult == 0) { return false; } else if (cresult == 1) { $.validationEngine.closePrompt("#addEventStartDate"); return true; } }
jquery-ui-timepicker-addon.js (時間刻度格式修改)
// Prevent displaying twice 顯示時間標題 if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) { var noDisplay = ' ui_tpicker_unit_hide', html = '<div class="ui-timepicker-div' + (o.isRTL ? ' ui-timepicker-rtl' : '') + (o.oneLine && o.controlType === 'select' ? ' ui-timepicker-oneLine' : '') + '"><dl>' + '<dt class="ui_tpicker_time_label' + ((o.showTime) ? '' : noDisplay) + '">' + o.timeText + '</dt>' + '<dd class="ui_tpicker_time '+ ((o.showTime) ? '' : noDisplay) + '"><input class="ui_tpicker_time_input" ' + (o.timeInput ? '' : 'disabled') + '/></dd>'; // Create the markup for (i = 0, l = this.units.length; i < l; i++) { litem = this.units[i]; uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1); show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem]; // Added by Peter Medeiros: // - Figure out what the hour/minute/second max should be based on the step values. // - Example: if stepMinute is 15, then minMax is 45. 分鐘顯示刻度 max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10); gridSize[litem] = 0; html += '<dt class="ui_tpicker_' + litem + '_label' + (show ? '' : noDisplay) + '">' + o[litem + 'Text'] + '</dt>' + '<dd style="margin-top:2px;" class="ui_tpicker_' + litem + (show ? '' : noDisplay) + '"><div class="ui_tpicker_' + litem + '_slider' + (show ? '' : noDisplay) + '"></div>';//更改小時,分鐘刻度之間行距 if (show && o[litem + 'Grid'] > 0) { html += '<div style="padding-left: 1px;"><table class="ui-tpicker-grid-label"><tr>'; //顯示小時,分鐘的刻度值的文本 if (litem === 'hour') { for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) { gridSize[litem]++; var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o); html += '<td style="padding-left: 1px;margin-top:20px;" data-for="' + litem + '">' + tmph + '</td>'; } } else { for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) { gridSize[litem]++; html += '<td style="padding-left: 1px;margin-top:20px;" data-for="' + litem + '">' + ((m < 10) ? '0' : '') + m + '</td>'; } } html += '</tr></table></div>'; } html += '</dd>'; }
jquery-ui-timepicker-addon.css:
.ui-timepicker-div .ui-widget-header { margin-bottom: 10px; margin-top:5px; } .ui-timepicker-div dl { text-align: left; } .ui-timepicker-div dl dt { float: left; clear:left; padding: 0 0 0 5px; } .ui-timepicker-div dl dd { margin: 10px 10px 10px 40%; } .ui-timepicker-div td { font-size: 90%; } .ui-tpicker-grid-label { background: none; border: none; margin: 5px 15px 0px 0px; padding: 0; } .ui-timepicker-div .ui_tpicker_unit_hide{ display: none; } .ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { background: none; color: inherit; border: none; outline: none; border-bottom: solid 1px #555; width: 95%; margin-top:15px;} /*把選擇的顯示時間文本和刻度條拉開開了*/ .ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { border-bottom-color: #aaa; } .ui-timepicker-rtl{ direction: rtl; margin-top:20px; } .ui-timepicker-rtl dl { text-align: right; padding: 0 5px 0 0; } .ui-timepicker-rtl dl dt{ float: right; clear: right; color:#cccccc; } .ui-timepicker-rtl dl dd { margin: 0 40% 10px 10px; } /* Shortened version style ui_tpicker_timezone_label*/ .ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px;color:#cccccc;} .ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time, .ui-timepicker-div.ui-timepicker-oneLine dt { display: none; } .ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; padding-bottom:0px; } .ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; } .ui-timepicker-div.ui-timepicker-oneLine dl dd, .ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; } .ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before, .ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; } .ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before, .ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { content:'.'; display:inline-block; } .ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide, .ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{ display: none; } .ui-timepicker-div{} .ui_tpicker_timezone_label { margin-top:10px; color:#000000;} .ui_tpicker_time_label{ margin-top:20px; color:#000000;} /*"小時"文本格式*/ .ui-tpicker-grid-label{ color:#000000;} /*顯示小時,分鐘的刻度值的文本*/ .ui-datepicker-title{ margin-top:20px; }