SharePoint 客戶端對象模型 (一) ECMA Script
三種使用客戶端模型的.NET托管、ECMA腳本,SilverLightClient.
本文講闡述如何使用.NET托管代碼來訪問SharePoint對象模型。
ECMAScript Client OM需要注意的幾個點
- ECMAScript僅能夠在SharePoint站點里面使用,不能夠在其他的Asp.NET站點里使用ECMAScript來訪問SharePoint站點資源,也不能夠跨SharePoint站點訪問資源;
- JQuery和ECMAScript使用起來不會有沖突;
- 為了安全的更新內(nèi)容,在使用ECMAScript的畫面里添加<SharePoint:FormDigest runat="server" />
- 在隨后你將會看到的代碼里為了減輕加載的數(shù)據(jù)量,可以指定需要加載的內(nèi)容,例如client.Context.load(this.web,'Title','Id','Created'), 這里的屬性值名稱使用和CAML一樣的體系,對大小寫敏感;
- 為確保你的代碼執(zhí)行在SP.JS加載完之后再被調(diào)用,可以使用ExecuteOrDelayUntilScriptLoaded(myjsFunction, “sp.js”)。
我們看看SharePoint OM和客戶端OM的一個簡單的匹配關(guān)系:
服務(wù)器端OM | 客戶端OM |
SPContext | ClientContext |
SPSite | Site |
SPWeb | Web |
SPList | List |
SPListItem | ListItem |
SPField | Field |
看看最后會呈現(xiàn)的效果,下圖是初步計劃的功能,主要設(shè)計列表的創(chuàng)建、查詢以及管理,另外也涉及上傳文件的Case,后續(xù)里如果有重要的也會逐步加進(jìn)來。
里面的鏈接會調(diào)用UI方面的Javascript接口創(chuàng)建SharePoint2010風(fēng)格的彈出窗口,彈出窗口的后臺頁面位于SitePage文檔庫內(nèi),請注意這個僅僅適用于打開的頁面是WebPart page,如果不是打開的時候會報錯誤:“The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist”。
(注意,此Page在之后都不會被用到,留在這里僅為了解釋Ribbon用)
創(chuàng)建列表:
首先,通過Designer,加入以下兩個Script鏈接:
<SharePoint:ScriptLink Name="SP.js" runat="server" OnDemand="true" Localizable="false" />
<SharePoint:ScriptLink Name="SP.debug.js" runat="server" OnDemand="true" Localizable="false" />
ECMAScriptOM和.NET Managed ClientOM(隨后會講到)異曲同工,但也有幾點需要注意的:
- 在ClientContext里面不能使用服務(wù)器端URLs;
- 不支持LINQ;
- 本質(zhì)上ECMAScript OM是異步的
代碼非常的簡單易懂,里面有個好玩的東西SP.UI.Notify.addNotification,通過這個類可以在調(diào)用的畫面里顯示提示消息,非常的SharePoint。
演示結(jié)果如下:
在文本框里輸入列表名字后,點擊"Create List”按鈕,生成列表后會在右上角提示“List test1 created”,本例中使用annoucement做為列表類型。
源代碼如下:
<script type="text/javascript">
var messageId;
function createList(listName){
var clientContext = new SP.ClientContext();
var oWebSite = clientContext.get_web();
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listName);
listCreationInfo.set_templateType(SP.ListTemplateType.announcements);
listCreationInfo.set_quickLaunchOption(SP.QuickLaunchOptions.on);
var oList = oWebSite.get_lists().add(listCreationInfo);
clientContext.load(oList);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
//Remove the 'creating' event notification
if(messageId != null)
{
SP.UI.Notify.removeNotification(messageId);
}
//Add 'created' notification as non sticky
messageId = SP.UI.Notify.addNotification("List <b>" + oList.get_title() + "</b> created...", false, "", null);
}
function onQueryFailed(sender, args) {
//Remove the 'creating' event notification
if(messageId != null)
{
SP.UI.Notify.removeNotification(messageId);
}
//Shown in case of error on the JS OM call
messageId = SP.UI.Notify.addNotification("Operation was cancelled...", false, "", null);
}
</script>
獲取所有列表:
同樣,先看一下效果,點擊“Get All List”按鈕,會將當(dāng)前站點下的所有列表都讀取出來并設(shè)置了響應(yīng)的超鏈接屬性,點擊“Hide List”按鈕則將之隱藏(實際上就是個Div)
代碼非常的直接,只說明一個點,getEnumerator()以及moveNexst(), get_current()等JavaScript函數(shù)的使用為遍歷集合提供了很好的方法。
源代碼:
function getLists(){
var clientContext = new SP.ClientContext();
var oWebSite = clientContext.get_web();
listCollection = oWebSite.get_lists();
clientContext.load(listCollection);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onGetListsSucceeded), Function.createDelegate(this, this.onGetListsFailed));
}
function onGetListsSucceeded(){
var str = "";
var listsEnumerator = listCollection.getEnumerator();
while(listsEnumerator.moveNext()){
var objList = listsEnumerator.get_current();
str += "<a href='" + "http://localhost" + objList.get_parentWebUrl() + objList.get_defaultViewUrl() + "'>" + objList.get_title() + "</a>" + "<br/>";
}
document.getElementById("lists").innerHTML = str;
}
function onGetListsFailed(sender, args){
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
CAML查詢:
這里面提供了兩種方式查詢,一個按DueDate,一種按Title,當(dāng)然功能可以設(shè)計的更加有利于用戶使用些,Demo里就不做過多渲染。點擊Search就可以進(jìn)行數(shù)據(jù)的查詢,有一點小發(fā)現(xiàn),如果使用<asp:calendar/>控件的時候選擇好日期會導(dǎo)致頁面postback,SharePoint里面至少有兩種解決方案:
- 單獨在某個頁面里面放入calendar控件,然后添加以下代碼:
<input type="text" id="txtDate" name="txtDate" />
<button value="lookup" onclick="document.all['txtDate'].value =
window.showModalDialog( 'Calendar.aspx' );" > -
使用SharePoint Calendar控件<SharePoint:DateTimeControl runat=server id="DateTimeControl1" DateOnly="True"></SharePoint:DateTimeControl>
做了一段對控件顯示的控制,選擇Date則出現(xiàn)輸入Date的控件,選擇Title則出現(xiàn)輸入Title的控件,本來想用JQuery的方法,后來一下沒想起來JQuery的Selector寫法,半土不洋的用了下面的方法結(jié)合控制:
<script type="text/javascript">
function changeQueryMethod(){
var method = $("select[id='selectQueryMethod']").val();
if(method == 'Title'){
document.getElementById('querybytitle').style.display = "inline";
document.getElementById('querybyDate').style.display = "none";
}
else{
document.getElementById('querybytitle').style.display = "none";
document.getElementById('querybyDate').style.display = "inline";
}
}
</script>
關(guān)于CAML查詢的細(xì)節(jié)本身也不做過多說明,如果有興趣可以參見拙文(http://www.cnblogs.com/johnsonwong/archive/2011/02/27/1966008.html),這是一篇針對2007版本的CAML,在2010里有了很多增強,譬如跨列表Joint查詢等,隨后會發(fā)布相應(yīng)2010的版本。
需要注意的知識是:
里面使用了對field的查詢,注意相關(guān)API的調(diào)用;
ClientContext里面對若干個結(jié)果集進(jìn)行操作,但需要調(diào)用Load對不同結(jié)果集進(jìn)行加載:clientContext.load(fieldCollection);clientContext.load(listItemCollection);
如果有需要讀取的字段值需要在CAML查詢XML里面顯示說明,否則不會返回到結(jié)果集里,這也是出于對性能的考慮
function search(){
var clientContext = new SP.ClientContext();
var oWebSite = clientContext.get_web();
var list = oWebSite.get_lists().getByTitle("Tasks");
fieldCollection = list.get_fields();
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml( "<View><Query><Where><Gt>" +
"<FieldRef Name='DueDate' />" +
"<Value Type='DateTime'>2008-01-1T00:00:00Z</Value>" +
"</Gt></Where></Query><ViewFields>" +
"<FieldRef Name=\"Title\" /><FieldRef Name=\"Body\" />" +
"<FieldRef Name=\"DueDate\" />" +
"</ViewFields></View>");
listItemCollection = list.getItems(camlQuery);
clientContext.load(fieldCollection);
clientContext.load(listItemCollection);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onSearchListSucceeded), Function.createDelegate(this, this.onSearchListFailed));
}
function onSearchListSucceeded(){
var str = "";
var listItemEnumerator = listItemCollection.getEnumerator();
var fieldsEnumerator = fieldCollection.getEnumerator();
while(listItemEnumerator.moveNext()){
var oListItem = listItemEnumerator.get_current();
str += "Item " + oListItem.get_id() + ":"
while(fieldsEnumerator.moveNext()){
var oField = fieldsEnumerator.get_current();
str += oField.get_staticName() + "<br/>";
}
str += "<br/>";
}
document.getElementById("lists").innerHTML = str;
}
function onSearchListFailed(sender, args){
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
操作文件:
遺憾的是在ECMAScript里面無法上傳文件,雖然有SP.File對象,但更多的是對獲取回來的SP.File對象進(jìn)行操作。
相關(guān)文章
JavaScript如何實現(xiàn)在文本框(密碼框)輸入提示語
為了更好的達(dá)到用戶體驗度,我們在登錄表單時會有一些提示語言,比如說:“請輸入用戶名”和“請輸入密碼”等語言,下面小編通過本篇文章給大家分享JavaScript如何實現(xiàn)在密碼框中出現(xiàn)提示語,對js密碼框提示語相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧2015-12-12js實現(xiàn)界面向原生界面發(fā)消息并跳轉(zhuǎn)功能
這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)界面向原生界面發(fā)消息并跳轉(zhuǎn)功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11js 關(guān)于=+與+=日期函數(shù)使用說明(賦值運算符)
js 關(guān)于=+與+=日期函數(shù)使用說明(賦值運算符),可以看下,就是一些運算符的使用,看哪個更適合你。2011-11-11getElementsByTagName vs selectNodes效率 及兼容的selectNodes實現(xiàn)
天在csdn上看到有人問 getElementsByTagName 和 selectNodes誰更快 ,這個還真沒研究過。2010-02-02JavaScript實現(xiàn)搜索的數(shù)據(jù)顯示
這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)搜索的數(shù)據(jù)顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10JavaScript Dom實現(xiàn)輪播圖原理和實例
這篇文章主要為大家詳細(xì)介紹了JavaScript Dom實現(xiàn)輪播圖原理和實例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-02-02