SharePoint 客户端对象模型 (一) ECMA Script


Posted in Javascript onMay 22, 2011

所谓的客户端对象模型就是调用了背后的WCF服务来提供数据,为了减轻数据的访问量数据包使用JSON,我们还可以看到对象模型的设计也加入了诸多对于减轻数据访问量的考量。技术上没有什么新意,你要愿意,在SharePoint2007里面也可以实现类似的功能,当然在使用上方便了我们不少

SharePoint 客户端对象模型 (一) ECMA Script 
三种使用客户端模型的.NET托管、ECMA脚本,SilverLightClient.

SharePoint 客户端对象模型 (一) ECMA Script

本文讲阐述如何使用.NET托管代码来访问SharePoint对象模型。

ECMAScript Client OM需要注意的几个点

  • ECMAScript仅能够在SharePoint站点里面使用,不能够在其他的Asp.NET站点里使用ECMAScript来访问SharePoint站点资源,也不能够跨SharePoint站点访问资源;
  • JQuery和ECMAScript使用起来不会有冲突;
  • 为了安全的更新内容,在使用ECMAScript的画面里添加<SharePoint:FormDigest runat="server" />
  • 在随后你将会看到的代码里为了减轻加载的数据量,可以指定需要加载的内容,例如client.Context.load(this.web,'Title','Id','Created'), 这里的属性值名称使用和CAML一样的体系,对大小写敏感;
  • 为确保你的代码执行在SP.JS加载完之后再被调用,可以使用ExecuteOrDelayUntilScriptLoaded(myjsFunction, “sp.js”)。

我们看看SharePoint OM和客户端OM的一个简单的匹配关系:

服务器端OM 客户端OM
SPContext ClientContext
SPSite Site
SPWeb Web
SPList List
SPListItem ListItem
SPField Field

看看最后会呈现的效果,下图是初步计划的功能,主要设计列表的创建、查询以及管理,另外也涉及上传文件的Case,后续里如果有重要的也会逐步加进来。

SharePoint 客户端对象模型 (一) ECMA Script

里面的链接会调用UI方面的Javascript接口创建SharePoint2010风格的弹出窗口,弹出窗口的后台页面位于SitePage文档库内,请注意这个仅仅适用于打开的页面是WebPart page,如果不是打开的时候会报错误:“The Ribbon Tab with id: "Ribbon.Read" has not been made available for this page or does not exist”。

(注意,此Page在之后都不会被用到,留在这里仅为了解释Ribbon用)

创建列表:

首先,通过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(随后会讲到)异曲同工,但也有几点需要注意的:

  1. 在ClientContext里面不能使用服务器端URLs;
  2. 不支持LINQ;
  3. 本质上ECMAScript OM是异步的

代码非常的简单易懂,里面有个好玩的东西SP.UI.Notify.addNotification,通过这个类可以在调用的画面里显示提示消息,非常的SharePoint。

SharePoint 客户端对象模型 (一) ECMA Script

演示结果如下:

在文本框里输入列表名字后,点击"Create List”按钮,生成列表后会在右上角提示“List test1 created”,本例中使用annoucement做为列表类型。

SharePoint 客户端对象模型 (一) ECMA Script

源代码如下:

<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”按钮,会将当前站点下的所有列表都读取出来并设置了响应的超链接属性,点击“Hide List”按钮则将之隐藏(实际上就是个Div)

SharePoint 客户端对象模型 (一) ECMA Script

代码非常的直接,只说明一个点,getEnumerator()以及moveNexst(), get_current()等JavaScript函数的使用为遍历集合提供了很好的方法。

源代码:

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,当然功能可以设计的更加有利于用户使用些,Demo里就不做过多渲染。点击Search就可以进行数据的查询,有一点小发现,如果使用<asp:calendar/>控件的时候选择好日期会导致页面postback,SharePoint里面至少有两种解决方案:

  1. 单独在某个页面里面放入calendar控件,然后添加以下代码:

    <input type="text" id="txtDate" name="txtDate" />
    <button value="lookup" onclick="document.all['txtDate'].value =
    window.showModalDialog( 'Calendar.aspx' );" >

  2. 使用SharePoint Calendar控件<SharePoint:DateTimeControl runat=server id="DateTimeControl1" DateOnly="True"></SharePoint:DateTimeControl>

SharePoint 客户端对象模型 (一) ECMA Script

SharePoint 客户端对象模型 (一) ECMA Script

做了一段对控件显示的控制,选择Date则出现输入Date的控件,选择Title则出现输入Title的控件,本来想用JQuery的方法,后来一下没想起来JQuery的Selector写法,半土不洋的用了下面的方法结合控制:

<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>

关于CAML查询的细节本身也不做过多说明,如果有兴趣可以参见拙文(http://www.cnblogs.com/johnsonwong/archive/2011/02/27/1966008.html),这是一篇针对2007版本的CAML,在2010里有了很多增强,譬如跨列表Joint查询等,随后会发布相应2010的版本。

需要注意的知识是:

里面使用了对field的查询,注意相关API的调用;
ClientContext里面对若干个结果集进行操作,但需要调用Load对不同结果集进行加载:clientContext.load(fieldCollection);clientContext.load(listItemCollection);
如果有需要读取的字段值需要在CAML查询XML里面显示说明,否则不会返回到结果集里,这也是出于对性能的考虑

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对象进行操作。

Javascript 相关文章推荐
javascript form 验证函数 弹出对话框形式
Jun 23 Javascript
一个简单的JS鼠标悬停特效具体方法
Jun 17 Javascript
js获取当前页面的url网址信息
Jun 12 Javascript
JavaScript数值转换的三种方式总结
Jul 31 Javascript
JavaScript进阶练习及简单实例分析
Jun 03 Javascript
谈谈Vue.js——vue-resource全攻略
Jan 16 Javascript
Web 开发中Ajax的Session 超时处理方法
Jan 19 Javascript
Swiper自定义分页器使用详解
Dec 28 Javascript
浅析vue插槽和作用域插槽的理解
Apr 22 Javascript
ES6 Object方法扩展的应用实例分析
Jun 25 Javascript
Vue快速实现通用表单验证的方法
Feb 24 Javascript
浅谈Vue的computed计算属性
Mar 21 Vue.js
JQuery里选择超链接的实现代码
May 22 #Javascript
改善用户体验的五款jQuery插件分享
May 22 #Javascript
JS 进度条效果实现代码整理
May 21 #Javascript
jquery 使用点滴函数代码
May 20 #Javascript
JQuery对checkbox操作 (循环获取)
May 20 #Javascript
检测jQuery.js是否已加载的判断代码
May 20 #Javascript
JQuery datepicker 使用方法
May 20 #Javascript
You might like
AM/FM收音机的安装与调试
2021/03/02 无线电
1 Tube Radio
2021/03/02 无线电
PHP去除数组中重复的元素并按键名排序函数
2008/08/18 PHP
使用Codeigniter重写insert的方法(推荐)
2017/03/23 PHP
使用swoole 定时器变更超时未支付订单状态的解决方案
2019/07/24 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
js日历功能对象
2012/01/12 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
即将发布的jQuery 3 有哪些新特性
2016/04/14 Javascript
对Angular.js Controller如何进行单元测试
2016/10/25 Javascript
js继承实现方法详解
2016/12/16 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
vue 中filter的多种用法
2018/04/26 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
layui 表格的属性的显示转换方法
2018/08/14 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
浅入深出Vue之组件使用
2019/07/11 Javascript
小程序开发之模态框组件封装
2020/04/23 Javascript
基于js实现数组相邻元素上移下移
2020/05/19 Javascript
[54:27]TNC vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
利用Python中的输入和输出功能进行读取和写入的教程
2015/04/14 Python
Python实现多线程HTTP下载器示例
2017/02/11 Python
python按行读取文件,去掉每行的换行符\n的实例
2018/04/19 Python
python对html过滤处理的方法
2018/10/21 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
2020/02/21 Python
Python基于类路径字符串获取静态属性
2020/03/12 Python
解决flask接口返回的内容中文乱码的问题
2020/04/03 Python
CSS3 仿微信聊天小气泡实例代码
2017/04/05 HTML / CSS
欧舒丹加拿大官网:L’Occitane加拿大
2017/10/29 全球购物
德国在线订购鲜花:Fleurop
2018/08/25 全球购物
澳大利亚领先的时尚内衣零售商:Bras N Things
2020/07/28 全球购物
应届生人事助理求职信
2013/11/09 职场文书
小学生组织委员竞选稿
2015/11/21 职场文书
《妈妈别哭,有我在》读后感3篇
2020/01/13 职场文书
MySQL系列之二 多实例配置
2021/07/02 MySQL