利用jquery ui的datepicker開發一個課程日曆

    這兩天在開發某商學院的網站,裏面有涉及到課程的模塊,客戶希望在網站的首頁顯示一個日曆,在有課程的日期加上顯眼的標識,使網站用戶一眼看到日曆後就能知道哪天商學院有課程以便他們安排時間報名修讀。

    這個功能挺有意思的,符合本人及非常小器公司一直所堅持的“爲客戶創造價值”的理念,它真正從用戶的角度思考問題了,客戶真正需要的、實用的東西是我最喜歡開發的產品因爲我覺得不能爲客戶創造價值的產品最終必定不能爲自己創造價值,這個世界是講因果的。

    剛開始的時候感覺用第三方的東西挺麻煩的,一來要研究別人的接口,規範等一大堆的東西,有什麼地方滿足不了要求的時候就更加麻煩了,要去讀懂別人的源碼再修改,還不如自己全新開發來得直接簡單,但日曆這東西,說複雜不復雜,但要做得好也有一定工作量,利用google快速瞭解了目前幾個比較知名的輕量級日曆插件的接口、提供的配置項及功能情況後,決定不重複製造輪子,在jquery ui的datepicker控件上進行開發,因爲它雖然功能簡單,但提供的配置項比較靈活,不需要經過大調整就能實現想要的效果,而且自備多種UI風格,相信總有一款能很好地與網站風格相融合,呵呵。廢話不多說了,下面來看看實現的過程吧,希望能被有需要的朋友借鑑,同時歡迎各位大神提出寶貴建議。首先看看效果:圖中2013年4月30號被一個紅色的圈圈住了,這是一個設計時的一個約定,日期被圈住說明當天是有課程的,點擊這個日期的時候再列出這天有哪些課程。

    井田商學院課程日曆,UI的風格其實就是jquery ui中的藍色主題版本的,由於本身網站是以藍色作爲基調的,所以用藍色主題的UI能與網站整體融合得非常好,可能很多人印象中都覺得datepicker是用來選日期的,以前應用它的時候都是有一個輸入框,點擊輸入框後才彈出這個日曆面板,選擇一個日期後觸發回調,把選中的日期更新回到一個特定的元素當中,日期選擇控件的使命就完成了,但這裏,它做的卻是完全不同的事情。它就像檯曆一樣,只負責顯示日期列表及標記一些特定日子的作用,當然,它比檯曆更加複雜和先進一點,因爲它是根據後臺的課程開課日期設置來自動在日曆中做標記的。

    實現的細節:

    1)怎樣讓datepicker默認就顯示在指定的地方而不是通過輸入框焦點觸發? 這點其實很簡單,通過查datepicker的api就可以知道datepicker初始化的時候會自動判斷調用它的元素類型是什麼,如果是input,它就會等待點擊觸發,如果是div,它默認就會顯示出來了,所以,這裏,只需要在要顯示的位置放一個div,然後用jquery的選擇器找到這個元素,並且在上面調用datepicker()方法就可以了,示例:$('.datePickerWraper').datepicker();

    2)怎樣讓datepicker符合設計的要求?這個其實也簡單,用CSS配合一下了,我的建議是不要直接在jquery ui的樣式上面改,一來影響它自身的完整及獨立性,到時或許會用到它的控件,如果直接改會導致一些意想不到的情況發生,我認爲比較好的辦法是在特定的頁面下用自己的樣式把默認的樣式覆蓋掉以使控件的尺寸符合我們的預期,即方便又靈活。

    3)怎樣在特定的日期加上特殊的標記?這個是課程日曆的關鍵所在。首先,當然是需要課程開課日期的數據了,由服務端提供的課程信息數組而來,這裏就不再贅述了,研究了datepicker的api,發現它提供了一個beforeShowDay的鉤子,所有的日期在渲染之前都會通過這裏的,有這個機制就好辦了,在這個鉤子裏添加代碼,遍歷課程列表,如果當前單元格的日期與課程的開課日期是同一天,就返回一個帶有三個元素的數組變量,分別代表日期是否可選,要在日期容器裏額外添加的class屬性及單元格的hover事件觸發時顯示的內容,相當於a的title。由於每次渲染日期時都會經過這個方法處理,所以,只要把課程列表初始化好,在用戶切換月份和年份的時候都會自動處理,不需要再在切換年月份的時候做干預,非常簡便就能達到想要的效果了。

    4)怎樣實現沒有課程的日期不可點擊(選擇),有課程的日期點擊(選擇)後顯示這天的課程列表?第三點中提到,beforeShowDay接收的返回參數中,第一個參數就是是否可以選擇的標記,所以,只有在比較到有開課的日期才返回true,否則返回false就能達到控制日期是否可選的效果了,但是需要注意的一點是,默認的樣式中,不可選的日期的opacity(不透明度)是1來的,也就是,基本上處於矇住的狀態了,看起來很不和諧,所以我通過CSS把它的默認樣式修改了,而在返回false的日期中,jquery ui自動是把它的日期文本由a標籤改成 span標籤括住的,所以不用擔心點擊錨點會引起錯誤的問題。選中有課程的日期時,會觸發控件的onSelect事件,彈出課程列表的操作寫在onSelect事件的響應方法裏面就可以了。下面是初始化控件的完整代碼,僅供參考。

   

		var curYear = new Date().getFullYear();
		$('.calendar').datepicker({
				yearRange: curYear+':'+curYear,
				prevText: '前一月',
				nextText: '後一月',
				yearSuffix: '年',
				dateFormat: "yy-mm-dd",
				showMonthAfterYear: true,
				dayNamesMin: ['日','一','二','三','四','五','六'],
				monthNames: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
				onSelect: function(text, instance){
					var arr = text.split('-');
					var year = arr[0], month = arr[1], day = arr[2];
					var curDateTime = new Date(year, month-1, day, 8, 0, 0);
					var dialogTitle = '商學院於'+text+'的課程安排';
					var curDateCourseList = [];
					var dialogHeight = 40;
					for(var i in courseList){
						var time = courseList[i].begin_date * 1000;
						if(time == curDateTime.getTime()){
							curDateCourseList.push("<a title='點擊查看詳情' href='/course/index.php?id="+courseList[i].id+"' target='_blank'>"+courseList[i].name+"</a>  <span style='color:#888;'>地點:"+ courseList[i].address +"</span><br>");
							dialogHeight += 35;
						}
					}
					$(".dateCourseList").html(curDateCourseList.join(',')).dialog({title:dialogTitle, height:dialogHeight});
					$(".dateCourseList").dialog("open");
					return false;
				},
				beforeShowDay: function(date){
					for(var i in courseList){
						var courseTime = (courseList[i].begin_date - 60 * 60 * 8)*1000;
						if(courseTime == date.getTime()){
							return [true, 'hasCourse', '課程日'];
							break;
						}
					}
					return [false, 'noCourse', '沒有課程'];
				}
		});


demo就不設獨立的網址了,有興趣看看效果的朋友可以直接訪問http://center.royalfield.org看課程日曆就清楚了。

另外,爲大家推薦一個史上最優惠的在線話費和遊戲點卡充值網站:http://cn008.taobao.com,你值得收藏

發佈了70 篇原創文章 · 獲贊 64 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章