用色彩區分 SharePoint 2010 Calendar 的日歷項


 

今天有美女問我:可不可以在 SharePoint 的 Calendar 中給不同的日歷項以不同的顏色?我說用 Overlay,結果馬上就被否定了,她不想搞出來很多個日歷。好吧,那就只有在放置日歷的頁面上,先通過腳本找到日歷項,然后分析其內容,最后按照預先訂好的規則給這些日歷項着色了。這應該又是一個 JS(jQuery)+ CSS 的應用。

其實,我本來計划今天寫寫 Adventure 系列第 4 篇的的,不過這個應用需求也挺有趣,所以,我打算先處理這件事。

jonyzhu 的原創

最常見的面試題

“如果遇到你不會的事情,你怎么處理?”“我會先去網上或者書上找,如果沒有,就去問周圍的人,如果還是沒有,就只好自己研究了。” 多么經典的面試問答啊 :)

我就是這么實踐的。先 Google 了一下,搜索第一屏里面只有一個中文鏈接,Erucy 的 按條件決定SharePoint 2010日歷顏色。看了看,應用場景和這次的要求很匹配,基本思路就是通過 jQuery 找到 SharePoint 日歷項所特有的樣式標識(div.ms-acal-item),然后讀取放在 div 的 title 屬性中的用半角括號所包含的日歷項地點(Location)信息,再到一個預先定義的“地點:顏色”對象中取出顏色作為 div 的背景色。

 

移植

不過,在 copy & paste 前,我需要自己檢查一下,這是習慣。搞電子電路也是,上電前都需要檢查的么(我現在連焊接前都要檢查)。於是,我建了幾個測試用的日歷項,隨機選了幾天,其中有一天加了2個日歷項。通過分析HTML的內容,發現了有趣的事情。

如果一天只有一個日歷項,那么,div.ms-acal-item 里面會包含 div.ms-acal-sdiv,接着下面是 div.ms-acal-time 和 div.ms-acal-title。div.ms-acal-title 里面是一個鏈接,鏈接的里面是現實日歷項的標題。

image

 

但是,如果一天有多個日歷項,那么 SharePoint 組織當天的日歷項的時候,結構會有不同。最外面還是 div.ms-acal-item,里面會包含 div.ms-acal-sdiv,不過,接下去,就沒有 div.ms-acal-time 和 div.ms-acal-title 了,而是直接以文本顯示日歷項的時間,以鏈接顯示日歷項的標題。

image

當然,無論哪種情況,Erucy 的代碼都可以運行的,因為其查找的是 div.ms-acal-item。

不過,如果直接給 div.ms-acal-item 設置背景顏色,會有一個問題。事情是這樣的,SharePoint 的日歷項,當你把鼠標移到上面的時候,有一個高亮效果,如果覆蓋了div.ms-acal-item 的背景顏色,那么,這個高亮效果就看不到了。可是,如果只是給 div.ms-acal-item 下面的 div.ms-acal-sdiv 設置背景顏色,那么,上層的 div.ms-acal-item 會露出一點兒邊,從而使得高亮效果仍然可以保持,就像下面這樣(后面一張是鼠標移到上面的效果):

image --> image

(Jonyzhu 的 博客鏈接

好了,略微整理以后,JS 代碼如下:

 1: <script type="text/javascript">
 2:     var _color_calendar_mapping = {
 3:         "Office":"#00ff00",
 4:         "Home":"#6CA6CD",
 5:         "Gim":"#FFB6C1"
 6:     };
 7:     function _color_calendar_process(){
 8:         var reg = new RegExp("\\(([^()]+)\\)$","gi");
 9:         $('div.ms-acal-item').each(function(){
 10:             var title = $(this).attr("title");
 11:             if(typeof(title) != 'undefined' && title != null){
 12:                 var calendar_location;
 13:                 var res = reg.exec(title); if(res==null){return;}else{ calendar_location = res[1]; }
 14:                 $(this).children("div.ms-acal-sdiv").css('background-color', _color_calendar_mapping[calendar_location]);
 15:             }
 16:         });
 17:         setTimeout(_color_calendar_process,500);
 18:     }
 19:     ExecuteOrDelayUntilScriptLoaded(_color_calendar_process, "SP.UI.ApplicationPages.Calendar.js");
 20: </script>

上面的代碼先找出日歷項的地點信息(在日歷項的“地點”屬性里面寫好),然后和預定義的顏色對象組(_color_calendar_mapping)進行匹配。修改 _color_calendar_mapping 以適應你自己的定義的地點和顏色的匹配。關於網頁配色,可以去 Google 一下,找一些自己覺得比較舒服的顏色。

找個 Content Editor Web Part 把上面代碼放進去看看效果,如下所示:

image

還行 :)

 

增強

下面這些要求不是美女提的,是我自己想的。做到上面那樣,美女已經可以接受了 :)

這個增強的要求主要應該怪微軟。SharePoint 2010 Calendar 日歷里面,除了地點以外,還有一個分類“Category”,里面可以選會議、休假、生日什么的,偏偏微軟自家的 Outlook 里面,日歷項是可以按照這個類型來用不同顏色呈現的。所以問題在於:為什么不是按照日歷項類型來顯示不同的顏色,而是地點啊!而且,地點信息在 SharePoint 2010 的日歷項里面是手動輸入的,這個很容易出錯以及產生在顏色映射組之外的地方的。

 

於是,SharePoint 2010 的客戶端對象模型就用上了。通過日歷項的ID,去日歷列表里面,把對應的類型“Category”字段值查出來,然后,就可以按照這個類型來設置日歷項的顏色了。

代碼如下:

   1: <script type="text/javascript">
 2:     /* Script for the Color Calendar 
 3:  I don't think you'll need any comment for the code :) 
 4:  Created by Jony Zhu. v1.3. 4/27/2013. http://www.cnblogs.com/jonyzhu */
 5:  
 6:     /* Begin
 7:  * You can change settings in this section */
 8:     var _color_calendar_mapping = {
 9:         "Holiday":"#00ff00",
 10:         "Business":"#6CA6CD",
 11:         "Meeting":"#FFB6C1"
 12:     };
 13:     var _color_calendar_timeout = 2000;
 14:     /* End */
 15:  
 16:     /* Do no change anything in this section, unless you know what you are doing. */
 17:     var _color_calendar_initialized = 0;
 18:     var _color_calendar_context;
 19:     var _color_calendar_list_item;
 20:     function _color_calendar_process(){
 21:         $('div.ms-acal-sdiv a').each(function(){
 22:             var href = $(this).attr('href');
 23:  
 24:             var list_title,item_id;
 25:             var reg = new RegExp("/Lists/(.*)/DispForm\.aspx","gi");
 26:             var res = reg.exec(href); if(res==null){return;}else{ list_title = res[1]; }
 27:             reg = new RegExp("ID\=(\\d+)","gi");  
 28:             res = reg.exec(href); if(res==null){return;}else{ item_id = res[1]; }
 29:  
 30:             _color_calendar_context = new SP.ClientContext.get_current();
 31:             var web = _color_calendar_context.get_web();
 32:             var list = web.get_lists().getByTitle(list_title);
 33:             this._color_calendar_list_item = list.getItemById(item_id);
 34:             _color_calendar_context.load(this._color_calendar_list_item,'ID','Category');
 35:             _color_calendar_context.executeQueryAsync(Function.createDelegate(this, _color_calendar_succeeded), Function.createDelegate(this, _color_calendar_failed));
 36:         });
 37:         if(_color_calendar_initialized==0){
 38:             setTimeout(_color_calendar_process,_color_calendar_timeout);
 39:         }
 40:     }
 41:     function _color_calendar_succeeded(sender, args){
 42:         var id = this._color_calendar_list_item.get_item('ID');
 43:         if(id!=null){
 44:             var category = this._color_calendar_list_item.get_item('Category');
 45:             $("div.ms-acal-sdiv a[href$='ID="+id+"']").each(function(){    
 46:                 $(this).parent().parent().css('background-color', _color_calendar_mapping[category]);
 47:             });
 48:             _color_calendar_initialized = 1;
 49:         }
 50:     }
 51:     function _color_calendar_failed(sender, args){
 52:         // TODO: I don't know what to do here, just do it yourself.
 53:         // alert(args);
 54:     }
 55:     ExecuteOrDelayUntilScriptLoaded(_color_calendar_process, "SP.UI.ApplicationPages.Calendar.js");
 56: </script>

效果如下(其實沒有變化啦,但是,此時已經是根據日歷項的類型來改變現實顏色了)。修改上面代碼的 _color_calendar_mapping 數組,就可以改變日歷項類型對應的背景顏色。

image

嗯,好多了,至少自己心里這么覺得 :)  IE、火狐都測了一遍以后,放心了。

 

這里還有一個小問題要說一下。Erucy 的方案里面用了 setTimeout 以便定期檢查日歷項的加載情況,在純 jQuery + CSS 的時候,這個沒有什么性能問題的。但是,如果像后面那樣用了 SCOM 去查詢日歷項的類型字段,那么,就有問題了。所以,我增加了一個 _color_calendar_initialized 變量來記錄是否已經完成了一次色彩設置了(等於1),如果完成,就不要再去讀列表了。

下面是 _color_calendar_initialized 添加前后的CPU占用記錄。前面不停振動的就是沒有加 _color_calendar_initialized  前的,最后一段很低的 CPU 占用的,就是加了 _color_calendar_initialized  以后的,差距明顯啊!(CPU 占用降低前有一個高峰,那是我重刷整個頁面引起的)

image

 

還有一個可以改進的地方。

上面的方案都是直接給 div.ms-acal-sdiv 設置 background-color 屬性,效果比較單調,如果改成 addClass 來給個樣式類的話,就能實現更豐富的效果了。這個大家結合自己的工作需要去調整把。

 

最后看個好玩的:FireFox 的 3D 頁面顯示。

image

調休的這一天也就過去了,Adventure 系列只能后面再找時間寫了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM