JSCal2 簡介
這一套 JSCal 已經出道很久了,我第一次在 ASP 程式的 Calendar 就是使用 JSCal 版,還不是 JSCal2,不過後來轉為付費版本且免費資源越來越多的情況下,就換其他選擇了。但今天我們還是選擇介紹它,因為我想透過 JSCal2 介紹一個 ASP.NET MVC 裡的功能,這個功能常讓人家誤解。先把 Model、Controller \ Action、View 建立起來。
Model:BlogPostJSCal2.vb
Imports System.ComponentModel.DataAnnotations ''' <summary> ''' Blog 發佈文章類別 ''' </summary> Public Class BlogPostJSCal2 ' 標題 Public Property Title() As String ' 發佈日期 <DataType(DataType.Date)> Public Property PostedOn() As DateTime ' 標籤 Public Property Tags() As String ' 內容 Public Property Content() As String End Class
Controller \ Action:BlogPostJSCal2Controller.vb
Namespace Mvc3HTMLEditorAndDatePicker Public Class BlogPostJSCal2Controller Inherits System.Web.Mvc.Controller ' ' GET: /BlogPostJSCal2/Create Function Create() As ActionResult Return View() End Function <HttpPost(), ActionName("Create")> Function Create_Post(model As BlogPostMy97) As ActionResult ViewBag.HtmlContent = model.Content Return View(model) End Function End Class End Namespace
View:Create.aspx
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of Mvc3HTMLEditorAndDatePicker.BlogPostJSCal2)" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> KKBruce : DatePicker (使用 JSCal2) 日期選擇器測試 </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>DatePicker (使用 JSCal2) 日期選擇器測試</h2> <%-- The following line works around an ASP.NET compiler warning --%> <%: "" %> <script src="<%: Url.Content("~/Scripts/jquery.validate.min.js") %>" type="text/javascript"></script> <script src="<%: Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script> <% Using Html.BeginForm() %> <%: Html.ValidationSummary(True) %> <fieldset> <legend>JSCal2 DatePicker</legend> <div class="editor-label"> <%: Html.LabelFor(Function(model) model.Title) %> </div> <div class="editor-field"> <%: Html.EditorFor(Function(model) model.Title) %> <%: Html.ValidationMessageFor(Function(model) model.Title) %> </div> <div class="editor-label"> <%: Html.LabelFor(Function(model) model.PostedOn) %> </div> <div class="editor-field"> <%: Html.EditorFor(Function(model) model.PostedOn) %> <%: Html.ValidationMessageFor(Function(model) model.PostedOn) %> </div> <div class="editor-label"> <%: Html.LabelFor(Function(model) model.Tags) %> </div> <div class="editor-field"> <%: Html.EditorFor(Function(model) model.Tags) %> <%: Html.ValidationMessageFor(Function(model) model.Tags) %> </div> <div class="editor-label"> <%: Html.LabelFor(Function(model) model.Content) %> </div> <div class="editor-field"> <%: Html.EditorFor(Function(model) model.Content) %> <%: Html.ValidationMessageFor(Function(model) model.Content) %> </div> <p> <input type="submit" value="Create" /> </p> </fieldset> <% End Using %> <div> <%: Html.ActionLink("Back to List", "Index") %> </div> </asp:Content>
讓我們來使用 JSCal2 吧。
下載及複製 JSCal2
我們先下載 JSCal2-1.9 (目前最新) ,以下為授權內文:
The version you can download from here is fully functional, but the source code is minified and mangled (using the YUI compressor). If you want the full source code, please purchase a license.我們測試使用上沒有授權問題。
Feel free to use the version distributed here for non-commercial purposes, i.e. on your personal blog, on a charity or educational website, in your free software, etc.
解壓縮後,
- 把 「JSCal2-1.9\src\js」下所有檔案複製到專案 「Scripts\JSCal2-1.9」 目錄之下,
- 「JSCal2-1.9\src\css」下有檔案複製到專案「Content\JSCal2-1.9」目錄之下。
在解壓縮的 JSCal2-1.9 目錄下,有完整的說明與範例文章,我們先看「JSCal2-1.9/demo/simple.html」這個文件 Source Code,以了解如何使用。
需要引用二個 JavaScript 與 三個 CSS 檔案:
<!-- JSCal2 --> <script src="<%: Url.Content("~/Scripts/JSCal2-1.9/jscal2.js") %>" type="text/javascript"></script> <script src="<%: Url.Content("~/Scripts/JSCal2-1.9/lang/cn.js") %>" type="text/javascript"></script> <link href="<%: Url.Content("~/Content/JSCal2-1.9/jscal2.css") %>" rel="stylesheet" type="text/css" /> <link href="<%: Url.Content("~/Content/JSCal2-1.9/border-radius.css") %>" rel="stylesheet" type="text/css" /> <link href="<%: Url.Content("~/Content/JSCal2-1.9/steel/steel.css") %>" rel="stylesheet" type="text/css" />
然後看一下它所撰寫的 JavaScript,還好,很簡單易懂。
<input size="30" id="f_date1" /><button id="f_btn1">...</button><br /> <script type="text/javascript"> //<![CDATA[ Calendar.setup({ inputField: "f_date1", // 重要:選擇後的值要放到那個 input 欄位 trigger: "f_btn1", // 重要:JSCal2 必須由"button"觸發 onSelect: function () { this.hide() }, showTime: 12, dateFormat: "%Y-%m-%d %I:%M %p" // 日期格式:年-月-日 時:分 PM|AM // 例如,2011-10-06 04:30 PM }); //]]> </script>
依上面的注解,我們改寫一下此 JavaScript 與 Create.aspx:
<div class="editor-field"> <%: Html.EditorFor(Function(model) model.PostedOn) %> <%: Html.ValidationMessageFor(Function(model) model.PostedOn) %> </div> <!-- 觸發 JSCal2 使用 --> <button id="jscal_bnt">選擇日期</button> <!-- 設定 JSCal2 --> <script type="text/javascript"> //<![CDATA[ Calendar.setup({ inputField: "PostedOn", trigger: "jscal_bnt", onSelect: function () { this.hide() }, showTime: 12, dateFormat: "%Y-%m-%d %I:%M %p" }); //]]> </script>
圖一:ASP.NET MVC - JSCal2 執行畫面 |
JSCal 行程曆範例
「你又想往下寫,是呀?」訪客說。在解壓縮的目錄「JSCal2-1.9\demo」之下,有許多用好的範例,其中一個 dateInfo.html 引起我的興趣。它是一個類似程事曆範例,
「多學一些,又不會怎樣。」KKBruce說:「寫的人又不你,累的人是我。」
「也對!」訪客說。
圖二:JSCal2 dateInfo.html 範例 |
<script type="text/javascript"> //<![CDATA[ var DATE_INFO = { 20090507: { klass: "highlight", tooltip: "%Y/%m/%d (%A)<br />That was yesterday" }, 20090508: { klass: "highlight", tooltip: "And this is TODAY" } }; function getDateInfo(date, wantsClassName) { var as_number = Calendar.dateToInt(date); if (as_number >= 20090518 && as_number <= 20090524) return { klass : "highlight2", tooltip : "<div style='text-align: center'>This is the green week</div>" }; return DATE_INFO[as_number]; }; var cal = Calendar.setup({ cont : "cont", fdow : 1, date : 20090501, dateInfo : getDateInfo }); //]]> </script>
你能發現,以上參數都是寫死的,一般而言,會像我在「ASP.NET+jqPlot實作線上即時統計圖表(Chart) 」所介紹的,這種程式碼,應該由後端去組合出來,然後回傳給前端,以保持前端動態且即時的資訊。
ASP.NET MVC - JavaScript ActionResult 使用介紹
這時候,就讓我們 ASP.NET MVC 中的 JavaScript ActionResult 上場吧!常看到有人問,這個 JavaScript ActionResult 是做什麼用?直接呼叫它,還會給我一個下載提示或顯示為純文字!常有人誤解它的用處,在這樣讓我們把 JavaScript ActionResult 的用處展示一下。我們改寫上面 dateInfo.html 裡的 JavaScript,然後放到 BlogPostJSCal2Controller.vb 之中:
''' <summary> ''' 回傳行事曆所需要的JavaScript,可動態調整參數內容。 ''' </summary> ''' <returns>JavaScript</returns> Function Create_DateInfoJS() As JavaScriptResult ' 一般這裡是會去取得 Database 資訊 ' 為簡化範例,我們只簡單使用變數 Dim thisMonth As Date = Date.Now Dim starDay As Date = Date.Now Dim endDay As Date = Date.Now.AddDays(7) Dim DateInfoJS As New System.Text.StringBuilder DateInfoJS.Append("var DATE_INFO = {") ' 單日動態 DateInfoJS.Append("" & thisMonth.ToString("yyyyMM") & "01" & ": { klass: ""highlight"", tooltip: ""%Y/%m/%d (%A)<br />KKBruce說:初一要記得拜拜!"" },") DateInfoJS.Append("" & thisMonth.ToString("yyyyMM") & "15" & ": { klass: ""highlight"", tooltip: ""%Y/%m/%d (%A)<br />KKBruce說: 十五要記的觀賞月亮!"" }") DateInfoJS.Append("};") DateInfoJS.Append("") DateInfoJS.Append("function getDateInfo(date, wantsClassName) {") DateInfoJS.Append("var as_number = Calendar.dateToInt(date);") ' 一週動態 DateInfoJS.Append("if (as_number >= " & starDay.ToString("yyyyMMdd") & " && as_number <= " & endDay.ToString("yyyyMMdd") & ")") DateInfoJS.Append("return {") DateInfoJS.Append("klass : ""highlight2"",") DateInfoJS.Append("tooltip : ""<div style='text-align: center'>KKBruce說:希望接下來的一週每天都是green不要red!</div>""") DateInfoJS.Append("};") DateInfoJS.Append("return DATE_INFO[as_number];") DateInfoJS.Append("};") DateInfoJS.Append("") DateInfoJS.Append("var cal = Calendar.setup({") ' 這一個名稱需對應 div 的 id 名稱 DateInfoJS.Append("cont : ""cont"",") DateInfoJS.Append("fdow : 1,") ' 讓它保持在本月第一天 DateInfoJS.Append("date : "& thisMonth.ToString("yyyyMM") & "01" &",") DateInfoJS.Append("dateInfo : getDateInfo") DateInfoJS.Append("});") Return JavaScript(DateInfoJS.ToString()) End Function
增加一個 Action,以強型別新增一個 View。
Action:Create_DateInfo
' GET: /BlogPostJSCal2DatePicker/Create_DateInfo Function Create_DateInfo() As ActionResult Return View() End Function
View:Create_DateInfo.aspx 引用相關 JavaScript
<!-- ASP.NET MVC Ajax 需引用 --> <script src="<%: Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js") %>" type="text/javascript"></script> <!-- 使用 JSCal2 所必須 Javascript 與 CSS --> <script src="<%: Url.Content("~/Scripts/JSCal2-1.9/jscal2.js") %>" type="text/javascript"></script> <script src="<%: Url.Content("~/Scripts/JSCal2-1.9/lang/cn.js") %>" type="text/javascript"></script> <link href="<%: Url.Content("~/Content/JSCal2-1.9/jscal2.css") %>" rel="stylesheet" type="text/css" /> <link href="<%: Url.Content("~/Content/JSCal2-1.9/border-radius.css") %>" rel="stylesheet" type="text/css" /> <link href="<%: Url.Content("~/Content/JSCal2-1.9/matrix/matrix.css") %>" rel="stylesheet" type="text/css" /> <style type="text/css"> .highlight { color: #f00 !important; } .highlight2 { color: #0f0 !important; font-weight: bold; } </style>
然後,透過 Ajax 技術的幫忙,讓我們動態的去載入此日曆。
<div class="editor-field"> <%-- <%: Html.EditorFor(Function(model) model.PostedOn) %> <%: Html.ValidationMessageFor(Function(model) model.PostedOn) %> --%> <div id="datapicker"> <div id="cont"></div> </div> <%: Ajax.ActionLink("載入日曆", "Create_DateInfoJS", new AjaxOptions With {.UpdateTargetId= "datapicker" }) %> </div>
建置,執行網頁「http://localhost:6944/BlogPostJSCal2/Create_DateInfo」(記得換成你的 port)。
圖三:Ajax 動態載入 JavaScript |
圖四:Ajax 動態載入 - 前一次的效果不會消失 |
<div class="editor-field"> <%-- <%: Html.EditorFor(Function(model) model.PostedOn) %> <%: Html.ValidationMessageFor(Function(model) model.PostedOn) %> --%> <div id="datapicker"> <div id="cont"></div> </div> <%: Ajax.ActionLink("載入日曆", "Create_DateInfoJS", new AjaxOptions With {.UpdateTargetId= "datapicker", .OnBegin = "RemovePreDataPicker" }) %> <script type="text/javascript"> // 每次按載入日曆畫面會重覆出現日曆 // 必須在每次更新前,先刪除前一個日曆 function RemovePreDataPicker() { var datepickerId = $('#cont'); datepickerId.find('table').each(function() { this.remove(); }); } </script> </div>
建置,重新執行網頁。
如何移除JSCal2按下enter觸發下拉選單的動作呢?謝謝
回覆刪除