javascript
用JavaScript实现一个Timeline
這兩天在忙著修飾自己部門的Team Site,老板提出了一個期望,想在Team Site首頁上放一個Timeline,這樣部門有什么新的事件、日程,都能在Timeline上展現出來。這件事本身并非特別麻煩,但是我們的Team Site是放在公司Hosting的SharePoint系統之中(公司提供SharePoint Hosting服務,每個人/部門可以根據自由要求,以自助的方式申請Site來使用),而公司Hosting的系統,是不允許各個網站的所有者使用任何Server Code(服務器端代碼)的。從IT管理的角度來說,這也是非常合理的,但這的確大大限制了各個網站的使用者對各自的網站進行定制的能力。換句話說,我能使用的工具,只有SharePoint內置的各個Web Part,以及SharePoint Designer。(在SharePoint 2010中,提供了一個新的特性:Sandboxed Solution,來解決這個問題,各個網站集的管理員可以通過upload的方式,部署功能與權限受限的Solution Package到網站集之中,但又不會影響其他網站集和整個服務器場的安全與穩定。)
在經過一番考慮之后,我確認在不允許服務器端代碼的前提下,是可以通過JavaScript和HTML的能力,實現一個Timeline的。下面這張圖是最終實現后的效果:?
?
這個Timeline分成了3欄,從上至下分別是日、周、月視圖,用戶可以使用鼠標對每個欄進行滑動操作,以查看之前和之后日期的各個事件。Timeline中的事件,來自于網站中一個日歷類別列表中的數據,這樣網站使用者只用在列表中添加新的事件,Timeline中就會自動顯示出來:?
?
實現的關鍵是兩點:
1、使用JS從網站列表中,獲取到所需的列表項數據;
2、使用JS和HTML,在SharePoint頁面上渲染出Timeline。
首先,我在網站中使用“日歷”列表模板,創建了一個新列表。由于在Timeline控件上,我只希望能夠顯示當天前后30天之內發生的事件,為了更容易的取到當天前后30天的事件列表項,我在列表中創建了一個新的視圖,在這個視圖中只顯示事件開始時間是位于當天前后30天的事件。為什么創建這樣的一個視圖就能方便我們在頁面上用JS獲取想要的數據,看到后面大家就明白了。
為了讓這個新視圖能進行查詢過濾,我為列表創建了兩個新的計算類型字段,"30DaysBeforeStartTime"和"30DaysAfterStartTime",下圖顯示了"30DaysBeforeStartTime"的定義方法:?
?
"30DaysAfterStartTime"的定義方法也類似,只是公式變成了"=[Start Time]+30"。
很多人都不知道在計算字段中,應該如何使用公式。在這個頁面上,有能夠使用的所有公式和函數的說明,這里還有一些最常用的公式的示范。
有了這兩個字段,我們就可以為新的視圖來設置過濾條件了,通過下圖中的條件,就能過濾出當天的前后30天之類的事件:?
?
有了這個新的視圖之后,我們就能保證,我們需要在Timeline中顯示的數據,肯定都會被這個視圖所包含。接下來我們進入到JS階段...
如果要用JS獲取SharePoint網站中的數據,比較靠譜的方法是用JS調用SharePoint的Web Services接口。SharePoint提供了不少Web Services接口,讓我們可以在各種平臺和語言中調用,其中就包括運行在頁面上的JS。我們需要的是能夠從列表中獲取數據的Web Services接口,這個接口位于Lists Web Service里面,它提供了一個GetListItems()方法,讓我們拿到列表項數據。其中,GetListItems()方法的第二個參數:"viewName",就可以讓我們指定列表的一個視圖,作為取數據的篩選條件。當然,我們也可以使用GetListItems()方法后面的參數來重新指定篩選條件,但是通過列表視圖來制定篩選條件,要簡單很多,而且修改起來也容易得多。
如何在JS中調用Web Services的方法在網絡上能找到很多很多的文章,我就不再重復了。但我要推薦一個不錯的JS庫,使用這個JS庫,可以免去手工構建SOAP包的麻煩,而且使用也相當的簡捷。它包含許多的.js文件,將這些.js文件上載到網站的某個文檔庫中即可(實際上,并不一定需要復制所有的.js文件,比如,對于我的要求,我只用復制"SPAPI_Core.js"、"SPAPI_Types.js"和"SPAPI_Lists.js"即可)。我將所有這些亂七八糟的文件都放在一個名叫"SupportingFiles"的文檔庫中:?
?
然后,用SharePoint Designer打開網站的母版頁文件(默認是"default.master"),添加上對這幾個.js文件的引用(圖片上顯示出還添加了對"http://simile.mit.edu/timeline/api/timeline-api.js"的引用,這個東東下面會講到):?
?
使用上面所介紹的那個JS庫,下面所示的代碼就可以讓我從一個列表中,將列表項取出來:
function getCalendarListItems()
{
??? var lists = new SPAPI_Lists("網站URL");
??? var items = lists.getListItems(
??????? "Timeline", // 要獲取數據的列表的顯示名稱
??????? "{14CB7B04-46AA-421C-B6B2-C5FBEEBA9F5B}", // 視圖的GUID,注意兩邊要加上大括號
??????? "", // 查詢條件
??????? "", // 要返回的字段
??????? 100, // 要返回的數據的最大行數
??????? "", // 查詢選項
??????? null // 網站的GUID,null表示使用上面的SPAPI_Lists構造函數里面的網站URL所對應的網站
??????? );
??? if (items.status == 200)
??? {
??????? var rows = items.responseXML.getElementsByTagName("z:row");???????
??????? return rows; // 如果獲取數據成功,將所有數據放在一個數組中,然后返回
??? }
??? else
??? {
??????? return null;
??? }
}
通過JS拿到所需的日歷事件數據之后,接下來,就是如何在頁面上用HTML+JS渲染出一個Timeline。作為一個典型的ELC(Exist Library Caller),我首先想到的是到網上找找是否已經有人做過類似的東東,果然,在Google Code上就被我找到了一個,嘿嘿嘿...
在這個名為SIMILE Widgets的工具集中,包含了一個用JS實現的Timeline。經過在文檔中一陣亂翻,下面的JS代碼就能夠幫我實現想要的效果(第一行不是JS代碼,而是JS代碼里面會使用的一個div元素,Timeline就是通過它顯示出來):
<div id="my-timeline" style="height: 120px; border: 1px solid #aaa; font-size: 9pt"></div>
var resizeTimerID = null;
function onResize() {
??? if (resizeTimerID == null) {
??????? resizeTimerID = window.setTimeout(function() {
??????????? resizeTimerID = null;
??????????? tl.layout();
??????? }, 500);
??? }
}
window.onresize = onResize;
function formatDateString(originDateStr)
{
??? var yearStr = originDateStr.substr(0, 4);
??? var monthStr = originDateStr.substr(5, 2);
??? var dayStr = originDateStr.substr(8, 2);???????
??? return monthStr + "/" + dayStr + "/" + yearStr + " " + originDateStr.substr(11);
}
function createTimeLineAndEvents()
{
??? var items = getCalendarListItems();
??? if (items == null)
??? {
??????? alert("cannot got items from list.");
??????? return;
??? }
??? var eventSource = new Timeline.DefaultEventSource();
??? for (var i = 0; i < items.length; ++i)
??? {
??????? var ows_EventDate = formatDateString(items[i].getAttribute("ows_EventDate"));
??????? var ows_EndDate = formatDateString(items[i].getAttribute("ows_EndDate"));
??????? var ows_Title = items[i].getAttribute("ows_Title");
??????? var ows_Location = items[i].getAttribute("ows_Location");???????
??????? var eventDate = new Date(ows_EventDate);
??????? var endDate = new Date(ows_EndDate);
??????? var event = new Timeline.DefaultEventSource.Event(
??????????? eventDate, //start
??????????? endDate , //end
??????????? eventDate, //latestStart
??????????? endDate , //earliestEnd
??????????? false, //instant
??????????? ows_Title, //text
??????????? ows_Location //description
??????? );
??????? eventSource.add(event);
??? }
??? var bandInfos = [
??????? Timeline.createBandInfo({
??????????? trackGap:?????? 0.2,
??????????? width:????????? "60%",
??????????? intervalUnit:?? Timeline.DateTime.DAY,
??????????? intervalPixels: 100,
??????????? timeZone : 8,
??????????? eventSource: eventSource
??????? }),
??????? Timeline.createBandInfo({
??????????? showEventText:? false,
??????????? trackHeight:??? 0.5,
?????????????? trackGap:?????? 0.2,
??????????? width:????????? "25%",
??????????? intervalUnit:?? Timeline.DateTime.WEEK,
??????????? intervalPixels: 150,
??????????? timeZone : 8,
??????????? eventSource: eventSource
??????? }),
??????? Timeline.createBandInfo({
??????????? showEventText:? false,
??????????? trackHeight:??? 0.5,
?????????????? trackGap:?????? 0.2,
??????????? width:????????? "15%",
??????????? intervalUnit:?? Timeline.DateTime.MONTH,
??????????? intervalPixels: 400,
??????????? timeZone : 8,
??????????? eventSource: eventSource
??????? })
????? ];
????? bandInfos[1].syncWith = 0;
??? bandInfos[2].highlight = true;
??? bandInfos[2].syncWith = 1;
??? var timeLine = Timeline.create(document.getElementById("my-timeline"), bandInfos);
}
_spBodyOnLoadFunctionNames.push("createTimeLineAndEvents");
唉,實在是有點長,本來不想全部貼出來,可想到也許有人要用的話,所以就...另外,別忘了在母版頁里面,添加對"http://simile.mit.edu/timeline/api/timeline-api.js"的引用(如上面的截圖所示)。
把上面的這些JS代碼(以及一個"div"標簽)都放到一個單獨的.htm文件中,然后在想要顯示Timeline的頁面上放一個內容編輯Web部件。通過設置內容編輯Web部件的屬性,告訴Web部件從那個.htm文件中去拿要顯示出來的HTML源碼(這種方式能讓我們直接使用SharePoint Designer編輯那個.htm文件中的HTML和JS源碼,而不必使用內容編輯Web部件內置的那個笨拙編輯器):?
?
?
OK,完成。另外提一下,在SharePoint 2010中提供了專門的Client OM,它直接支持使用ECMAScript(標準名詞解釋:ECMAScript是一種由Ecma國際(前身為歐洲計算機制造商協會)通過ECMA-262標準化的腳本程序設計語言。這種語言在萬維網上應用廣泛,它往往被稱為JavaScript或JScript,但實際上后兩者是ECMA-262標準的實現和擴展。)來訪問SharePoint。
總結
以上是生活随笔為你收集整理的用JavaScript实现一个Timeline的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无盘系统
- 下一篇: C#开发WPF/Silverlight动