SharePoint 客戶端對(duì)象模型 (一) ECMA Script
三種使用客戶端模型的.NET托管、ECMA腳本,SilverLightClient.
本文講闡述如何使用.NET托管代碼來(lái)訪問(wèn)SharePoint對(duì)象模型。
ECMAScript Client OM需要注意的幾個(gè)點(diǎn)
- ECMAScript僅能夠在SharePoint站點(diǎn)里面使用,不能夠在其他的Asp.NET站點(diǎn)里使用ECMAScript來(lái)訪問(wèn)SharePoint站點(diǎn)資源,也不能夠跨SharePoint站點(diǎn)訪問(wèn)資源;
- JQuery和ECMAScript使用起來(lái)不會(huì)有沖突;
- 為了安全的更新內(nèi)容,在使用ECMAScript的畫(huà)面里添加<SharePoint:FormDigest runat="server" />
- 在隨后你將會(huì)看到的代碼里為了減輕加載的數(shù)據(jù)量,可以指定需要加載的內(nèi)容,例如client.Context.load(this.web,'Title','Id','Created'), 這里的屬性值名稱使用和CAML一樣的體系,對(duì)大小寫(xiě)敏感;
- 為確保你的代碼執(zhí)行在SP.JS加載完之后再被調(diào)用,可以使用ExecuteOrDelayUntilScriptLoaded(myjsFunction, “sp.js”)。
我們看看SharePoint OM和客戶端OM的一個(gè)簡(jiǎn)單的匹配關(guān)系:
服務(wù)器端OM | 客戶端OM |
SPContext | ClientContext |
SPSite | Site |
SPWeb | Web |
SPList | List |
SPListItem | ListItem |
SPField | Field |
看看最后會(huì)呈現(xiàn)的效果,下圖是初步計(jì)劃的功能,主要設(shè)計(jì)列表的創(chuàng)建、查詢以及管理,另外也涉及上傳文件的Case,后續(xù)里如果有重要的也會(huì)逐步加進(jìn)來(lái)。
里面的鏈接會(huì)調(diào)用UI方面的Javascript接口創(chuàng)建SharePoint2010風(fēng)格的彈出窗口,彈出窗口的后臺(tái)頁(yè)面位于SitePage文檔庫(kù)內(nèi),請(qǐng)注意這個(gè)僅僅適用于打開(kāi)的頁(yè)面是WebPart page,如果不是打開(kāi)的時(shí)候會(huì)報(bào)錯(cuò)誤:“The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist”。
(注意,此Page在之后都不會(huì)被用到,留在這里僅為了解釋Ribbon用)
創(chuàng)建列表:
首先,通過(guò)Designer,加入以下兩個(gè)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(隨后會(huì)講到)異曲同工,但也有幾點(diǎn)需要注意的:
- 在ClientContext里面不能使用服務(wù)器端URLs;
- 不支持LINQ;
- 本質(zhì)上ECMAScript OM是異步的
代碼非常的簡(jiǎn)單易懂,里面有個(gè)好玩的東西SP.UI.Notify.addNotification,通過(guò)這個(gè)類可以在調(diào)用的畫(huà)面里顯示提示消息,非常的SharePoint。
演示結(jié)果如下:
在文本框里輸入列表名字后,點(diǎn)擊"Create List”按鈕,生成列表后會(huì)在右上角提示“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>
獲取所有列表:
同樣,先看一下效果,點(diǎn)擊“Get All List”按鈕,會(huì)將當(dāng)前站點(diǎn)下的所有列表都讀取出來(lái)并設(shè)置了響應(yīng)的超鏈接屬性,點(diǎn)擊“Hide List”按鈕則將之隱藏(實(shí)際上就是個(gè)Div)
代碼非常的直接,只說(shuō)明一個(gè)點(diǎn),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查詢:
這里面提供了兩種方式查詢,一個(gè)按DueDate,一種按Title,當(dāng)然功能可以設(shè)計(jì)的更加有利于用戶使用些,Demo里就不做過(guò)多渲染。點(diǎn)擊Search就可以進(jìn)行數(shù)據(jù)的查詢,有一點(diǎn)小發(fā)現(xiàn),如果使用<asp:calendar/>控件的時(shí)候選擇好日期會(huì)導(dǎo)致頁(yè)面postback,SharePoint里面至少有兩種解決方案:
- 單獨(dú)在某個(gè)頁(yè)面里面放入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>
做了一段對(duì)控件顯示的控制,選擇Date則出現(xiàn)輸入Date的控件,選擇Title則出現(xiàn)輸入Title的控件,本來(lái)想用JQuery的方法,后來(lái)一下沒(méi)想起來(lái)JQuery的Selector寫(xiě)法,半土不洋的用了下面的方法結(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é)本身也不做過(guò)多說(shuō)明,如果有興趣可以參見(jiàn)拙文(http://www.cnblogs.com/johnsonwong/archive/2011/02/27/1966008.html),這是一篇針對(duì)2007版本的CAML,在2010里有了很多增強(qiáng),譬如跨列表Joint查詢等,隨后會(huì)發(fā)布相應(yīng)2010的版本。
需要注意的知識(shí)是:
里面使用了對(duì)field的查詢,注意相關(guān)API的調(diào)用;
ClientContext里面對(duì)若干個(gè)結(jié)果集進(jìn)行操作,但需要調(diào)用Load對(duì)不同結(jié)果集進(jìn)行加載:clientContext.load(fieldCollection);clientContext.load(listItemCollection);
如果有需要讀取的字段值需要在CAML查詢XML里面顯示說(shuō)明,否則不會(huì)返回到結(jié)果集里,這也是出于對(duì)性能的考慮
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里面無(wú)法上傳文件,雖然有SP.File對(duì)象,但更多的是對(duì)獲取回來(lái)的SP.File對(duì)象進(jìn)行操作。
相關(guān)文章
JavaScript如何實(shí)現(xiàn)在文本框(密碼框)輸入提示語(yǔ)
為了更好的達(dá)到用戶體驗(yàn)度,我們?cè)诘卿洷韱螘r(shí)會(huì)有一些提示語(yǔ)言,比如說(shuō):“請(qǐng)輸入用戶名”和“請(qǐng)輸入密碼”等語(yǔ)言,下面小編通過(guò)本篇文章給大家分享JavaScript如何實(shí)現(xiàn)在密碼框中出現(xiàn)提示語(yǔ),對(duì)js密碼框提示語(yǔ)相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2015-12-12(function(){})()的用法與優(yōu)點(diǎn)
(function(){})()的用法與優(yōu)點(diǎn)...2007-03-03js強(qiáng)制把網(wǎng)址設(shè)為默認(rèn)首頁(yè)
有時(shí)候你會(huì)發(fā)現(xiàn)設(shè)首頁(yè)為失效,那么來(lái)一個(gè)js強(qiáng)制設(shè)置首頁(yè)的代碼,不過(guò)為了綠色上網(wǎng),盡量不要強(qiáng)迫你的用戶意志,弄不好網(wǎng)站用戶體驗(yàn)會(huì)降低。感興趣的小伙伴可以參考一下2015-09-09js實(shí)現(xiàn)界面向原生界面發(fā)消息并跳轉(zhuǎn)功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)界面向原生界面發(fā)消息并跳轉(zhuǎn)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11js 關(guān)于=+與+=日期函數(shù)使用說(shuō)明(賦值運(yùn)算符)
js 關(guān)于=+與+=日期函數(shù)使用說(shuō)明(賦值運(yùn)算符),可以看下,就是一些運(yùn)算符的使用,看哪個(gè)更適合你。2011-11-11JavaScript中的簡(jiǎn)寫(xiě)語(yǔ)法分享
這篇文章主要為大家整理了12個(gè)JavaScript中常用的簡(jiǎn)寫(xiě)語(yǔ)法技巧,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,需要的小伙伴可以收藏一下2023-04-04getElementsByTagName vs selectNodes效率 及兼容的selectNodes實(shí)現(xiàn)
天在csdn上看到有人問(wèn) getElementsByTagName 和 selectNodes誰(shuí)更快 ,這個(gè)還真沒(méi)研究過(guò)。2010-02-02JavaScript實(shí)現(xiàn)搜索的數(shù)據(jù)顯示
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)搜索的數(shù)據(jù)顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10禁用頁(yè)面部分JavaScript方法的具體實(shí)現(xiàn)
方法重寫(xiě),重寫(xiě)要禁用的方法,并讓它什么也不做,結(jié)果證明真的可行,但并不知道是不是一個(gè)科學(xué)的方法,我拿出來(lái)與大家共同討論一下2013-07-07JavaScript Dom實(shí)現(xiàn)輪播圖原理和實(shí)例
這篇文章主要為大家詳細(xì)介紹了JavaScript Dom實(shí)現(xiàn)輪播圖原理和實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02