使用-HTML-和-JavaScript-为-SharePoint-2013-定制解决方案-全-
使用 HTML 和 JavaScript 为 SharePoint 2013 定制解决方案(全)
原文:Custom SharePoint solutions with HTML and JavaScript for SharePoint 2013
一、设置您的环境
正确设置您的环境将为您提供构建定制解决方案所需的所有工具。您需要的许多东西已经内置到 SharePoint 中,并且随时可以使用。然而,你也会想下载和安装一些额外的工具,让你的生活更轻松。这些工具包括:
- SharePoint Online 开发人员网站
- SharePoint 设计器
- 免费版
- 各种浏览器和开发工具
- 框架
- 在您的 SharePoint 环境中实现 jQuery
如果这个列表看起来令人生畏,不要担心。在本章中,我们将详细探究每一个项目,让您熟悉它们以及它们的用途。此外,我们还将了解如何创建您自己的 SharePoint Online 环境来用作开发区域,并向您展示如何在该环境中实现 jQuery。
如果您已经在开发 SharePoint 解决方案,甚至只是在进行 web 开发,那么您很可能已经安装了这些解决方案。本章将更多地面向商业用户或那些刚接触前端开发的人。因此,如果你是一个经验丰富的开发人员,你可以浏览这一章,以确保你有你需要的一切。无论您是谁,在本章结束时,您都将做好充分准备,开始在 SharePoint 中构建自定义解决方案的旅程!
SharePoint Online 开发人员网站
不言而喻,如果没有地方可以构建自定义 SharePoint 解决方案,那么构建自定义 SharePoint 解决方案是一项浪费的技能!你们中的一些人已经有了一个用于开发的环境。这可能是您的企业用于内部网的 SharePoint Online 环境,也可能是 SharePoint 2013 内部环境。可能是你第一次想学习 SharePoint 开发,却没有地方工作。在任何情况下,您都有很多选择,我们将在这里探讨这些选择。
Note
本节探讨的选项将集中在 SharePoint Online 和 Office 365 上。如果您在内部安装了 SharePoint,您可以轻松地创建一个新的工作网站。即使您在工作中随手可得 SharePoint,您可能仍然希望在自己的环境中工作,以便此处的选项仍然适用。
微软使得在最新版本的 SharePoint 上开始前端开发变得非常容易。您可以通过以下网址注册 Office 365 开发人员网站: http://msdn.microsoft.com/en-us/library/office/fp179924(v=office.15).aspx
。图 1-1 显示了注册的页面和各种选项。
图 1-1。
Office 365 Developer Site sign-up options on the Microsoft site
如您所见,创建开发人员站点有三个选项:
- MSDN 订阅者-如果你或你的公司订阅了 MSDN,你可以免费创建一个开发者网站。很多有专职开发人员的公司都有 MSDN 订阅,或者你自己也有一个。无论哪种情况,只需点击标题为“立即兑现您的权益”的链接即可开始。如果您是商业用户,也值得考虑这个选项。如果您的公司订阅了 MSDN,您可以申请许可,或者让 IT 部门的人为您创建网站并提供访问权限。
- Office 365 订阅者-已经订阅了 e 3 或 E4 Office 365 计划的企业可以直接从 Office 365 管理中心提供开发人员站点。这些订阅级别允许开发人员使用特殊的网站模板创建新的私有网站集。要了解创建开发者网站的全部细节和步骤,请访问以下 URL:
http://msdn.microsoft.com/en-us/library/office/jj692554(v=office.15).aspx
。 - 30 天试用或开发者订阅-如果你想或需要拥有自己的环境,微软还允许你对 Office 365 进行 30 天的试用。这是一个很好的选择,因为它为您提供了大量的时间来探索 Office 365 和 SharePoint Online,以及在完全属于您的环境中测试您的开发技能。您也可以随时以 99 美元的价格将试用升级为年度订阅。这是一个很好的选择,即使你的公司有 SharePoint。它为您提供了一个远离任何生产场所的完美区域,您可以在这里构建自己的定制解决方案。每年 99 美元,它提供了一个构建解决方案的低成本选项,可以轻松地迁移到生产环境中。
无论您的情况如何,您都可以轻松获得一个可以开发自定义 SharePoint 解决方案的环境。既然我们已经介绍了在哪里以及如何获得您的 SharePoint 环境,那么让我们来探索一下我们将在本书中使用的一些工具。
Note
本书中的所有示例和屏幕截图都来自 SharePoint Online 环境,这是 SharePoint 的最新版本。
SharePoint 设计器
如果您过去使用过 SharePoint,那么您可能也使用过 SharePoint Designer。这是微软提供的免费工具,也是 SharePoint 的主要工具。它允许您执行广泛的任务—从品牌、连接到外部数据库、构建列表等等。老实说,对于这本书来说,Designer 并没有发挥很大的作用,但它将是帮助我们在 SharePoint 中实现 jQuery 的关键。这是本章的结尾。现在,让我们只下载设计师。
您可以从以下网址下载 SharePoint Designer:http://www.microsoft.com/en-us/download/details.aspx?id=35491
。图 1-2 显示了微软下载中心网站的页面,您可以在这里下载 Designer。
图 1-2。
SharePoint Designer download page on the Microsoft site
现在,您可以简单地下载并安装 Designer 我们以后会用到它。尽管我们在本书中没有深入探讨 Designer,但您会发现它是使用 SharePoint 时的一个有用工具。正如我之前所说的,它具有广泛的功能,可以帮助你完成许多任务。Designer 适用于 SharePoint Online 和内部环境。
免费版
如果您不是开发人员,那么您可能没有听说过 Visual Studio Express 如果你有,它可能看起来像一个代码骑师压倒性的计划。在某种程度上,它是,但它是一个强大的工具,我们将使用它来编写我们的 HTML 和 JavaScript。它也是免费的,由微软提供。
Visual Studio 是一个集成开发环境,简称 IDE。这是“允许你写代码的程序”的一种奇特说法对于这本书,我们所有的例子都是 HTML 和 JavaScript。HTML 和 JavaScript 的一个优点是它们只是带有特殊扩展名的文本文件:.html
和.js
。为此,创建和编辑这些文件真正需要的是记事本。然而,尽管 Notepad 看起来友好且不起眼,但在编写代码时,它绝不是你的朋友。Visual Studio Express 提供了您需要的所有工具,甚至会在检测到问题时通知您。记事本做不到!
Visual Studio 有许多不同的版本,这取决于您的技术需求。速成版是一个功能齐全的版本,将超过这本书的需要。您可以从以下网址下载 Visual Studio Express:http://www.visualstudio.com/en-us/products/visual-studio-express-vs.aspx
。图 1-3 显示了 Visual Studio 站点的下载页面。
图 1-3。
Visual Studio Express download page on the Microsoft site
Visual Studio 速成版有多个版本,包括 Web 版、Windows 版等等。Express for Web 是使用 HTML 和 JavaScript 构建解决方案的完美版本。
浏览器和开发工具
当作为最终用户使用 SharePoint 时,最明显的浏览器选择是 Internet Explorer。虽然 SharePoint 与其他浏览器(如 Firefox 和 Chrome)配合得很好,但 Internet Explorer 显然是微软推荐的浏览器,也是 SharePoint 最有可能与之友好相处的浏览器。也就是说,这本书是关于使用 HTML 和 JavaScript 构建定制解决方案的,你会发现大多数现代浏览器的行为和表现都是一样的。在讨论浏览器之前,我们先来讨论一下开发者工具。
开发者工具是一个通用术语,意思是用来帮助开发、调试和了解浏览器中的 HTML、JavaScript 和 CSS 的工具。这些工具也可以被称为开发者工具栏、浏览器工具,或者可以用一个完全不同的名字,比如 Firebug。不管是什么工具,它们都执行相同的功能,即帮助您开发解决方案。在几乎所有的浏览器中,你需要做的就是按下键盘上的 F12 键来启动开发者工具,如 Internet Explorer 中的图 1-4 所示。
图 1-4。
Developer tools launched in Internet Explorer after hitting F12
正如您在图 1-4 中看到的,这些工具提供了对浏览器中正在发生的事情的深入了解。您可以立即看到生成页面的 HTML,以及已经应用的任何 CSS 样式。使用工具左侧的菜单,您还可以查看页面上加载了哪些 JavaScripts,甚至可以查看其中的代码。您可以更进一步,在 JavaScript 中设置“断点”来暂停它的执行,这样您就可以看到这些脚本运行时发生了什么。在您的前端开发工作中,这是一个非常有价值的工具,并且会经常使用。
图 1-5 显示了 Google Chrome 中打开的开发者工具。同样,只需按 F12 即可打开工具。与 Internet Explorer 一样,您可以立即看到应用于页面的 HTML 和样式。
图 1-5。
Developer tools launched in Google Chrome after hitting F12
在 Chrome 中,菜单选项在工具屏幕的顶部运行,并提供类似的功能。您可以像打开开发人员工具一样,通过按 F12 来关闭它们。你应该下载几个浏览器,感受一下它们的工具。每个开发人员都有自己对浏览器和工具的偏好;我的是 Firefox 和 Firebug,我们将在本书中使用它们。
我要公开声明,我认为 Internet Explorer 是一个非常棒的浏览器,至少最新版本是这样。这些年来,它已经走过了一段漫长的路,终于可以和这个街区的一些新人比肩了。Internet Explorer 中的开发工具非常好,但我更喜欢在 Firefox 中使用 Firebug。Firebug 是 Firefox 中的一个插件,它的表现就像其他浏览器中的工具一样,但在我看来,它以一种更友好的方式组织内容,并且更容易使用。你一定要找到你的偏好,并使用最适合你的浏览器/工具。本书中的所有示例都将使用 Firebug,但您并不局限于这些工具。
要安装 Firebug,请从以下网址下载 Firefox 浏览器: https://www.mozilla.org/firefox/
。安装完成后,单击右上角的菜单图标。图 1-6 显示菜单打开,附加选项高亮显示。
图 1-6。
The Add-ons menu option in the Firefox menu
单击附加组件选项将在新选项卡中打开附加组件管理器页面。此页面允许您管理所有加载项并搜索新的加载项。在屏幕右上角的搜索框中键入 firebug,然后单击放大镜图标。图 1-7 显示输入后的搜索框。
图 1-7。
Search box on the Add-ons Manager page before searching
搜索结果会返回与您的请求相匹配的任何附加组件,Firebug 应该位于列表的顶部。点击图 1-8 所示的安装按钮,将 Firebug 添加到 Firefox 中。
图 1-8。
Clicking the Install button will install Firebug in Firefox
一旦下载和安装完成,Firefox 就会在右上角的菜单旁边显示一个“bug”图标。图 1-9 突出显示了 Firebug 图标。
图 1-9。
Firebug icon is present once the installation is complete
现在已经安装了 Firebug,您可以像在其他浏览器中打开开发人员工具一样打开它——通过按键盘上的 F12 键。你也可以点击 Firebug 图标打开它,如图 1-10 所示。
图 1-10。
Firebug toggled open by clicking F12
正如你在图 1-10 中看到的,Firebug 的外观和行为与其他浏览器中的开发工具非常相似。同样,您最终决定使用哪些工具是您的个人偏好。本书中的所有例子都将使用 Firefox 和 Firebug。
框架
如果你过去做过 JavaScript 工作,你可能会不时地感到有点沮丧。JavaScript 是前端开发的一个很好的框架。它很快,你可以用它立刻构建有用的代码。但是它可能很难使用,有时很难调试,而且对新手来说似乎很吓人。jQuery 的出现改变了这一切。
jQuery 是一个框架,它与 JavaScript 一起工作,使编写前端代码更加容易和快速。jQuery 标榜自己是“写得更少,做得更多”的框架——你会发现事实就是如此。它很快成为了 JavaScript 开发的标准,本书中的很多例子都会以某种方式利用 jQuery。如果您以前从未使用过它,不要担心:我们会慢慢开始,让您快速上手。
Note
如果您是 jQuery 新手,jQuery 网站上有一个很棒的“入门”指南,网址是 http://learn.jquery.com/about-jquery/how-jquery-works/
。还有 Jack Franklin 的 Beginning jQuery(a press,2013),对于那些刚刚入门的人来说是一个很好的资源(参见 www.apress.com/9781430249320
)。
现在,让我们做一个快速的 jQuery 练习,让您熟悉它是如何工作的。jQuery 的一个主要优点是能够轻松地选择页面上的 HTML 元素。实现这一点的两种主要方法是使用元素的 ID 或它的 CSS 类。图 1-11 显示了 Firefox 中打开 Firebug 的 jQuery 主页( jquery.com
)。我们将在这个练习中使用 jQuery 的站点,因为他们肯定已经加载了它!
图 1-11。
The jQuery home page in Firefox with Firebug open. Hovering over an HTML section with the mouse will highlight it on the page
我们已经在 Firebug 中展开了 HTML,并在页面的左上方找到了徽标。当你将鼠标悬停在 HTML 上时,Firebug 会高亮显示浏览器中的部分,这样你就可以很容易地看到它。在这个页面上,徽标位于 ID 为"logo-events"
的 DIV 元素中。因为这个元素有一个 ID,所以可以很容易地用 jQuery 定位它。在 Firebug 中,点击标题为脚本的选项卡将其激活,如图 1-12 所示。
图 1-12。
Scripts tab activated in Firebug
在“脚本”选项卡中,您将在两个主要区域使用前端代码。左侧面板显示您正在检查的当前脚本。在它的上方有一个下拉菜单,在这里您可以看到并选择当前加载到这个页面上的所有 JavaScript 文件。稍后我们将更详细地探讨这一点。右边的面板有更多的标签,但主要的是手表标签。在该选项卡中,我们可以使用“新观察表达式”文本框在浏览器中运行按需 JavaScript 命令。这个区域在编写前端代码的时候会非常有用。
在“新观察表达式”文本框内单击,键入以下行,然后按 Enter 键:
$("#logo-events")
图 1-13 显示了运行这行代码的输出。
图 1-13。
Output of running the jQuery command in the Watch tab
如您所见,结果是一个对象,在括号内您可以看到"div#logo-events"
,这意味着 jQuery 成功地找到了您正在寻找的元素。让我们花点时间来看看这里发生了什么以及 jQuery 是如何工作的。我们可以像这样分解 jQuery 命令的结构:
- 这是一个调用 jQuery 的简写符号。所有 jQuery 命令都将以这个符号开始。您可以把它想象成让 jQuery 为您做一些事情。在这种情况下,我们说,“jQuery 查找具有这个 ID 的元素。”
$
后面总是跟着()
,它包含了您正在寻找的元素。 - 这是一个简写符号,告诉 jQuery 你正在通过它的 ID 寻找某样东西。任何跟在
#
后面的文本都应该是 HTML 元素上的有效 id,并且只返回一个条目,因为 HTML 元素不能共享 ID。 - 句点是告诉 jQuery 你正在通过它的 CSS 类寻找某样东西的简写。因此,如果你的 HTML 中有 10 个 div 共享同一个 CSS 类
"red-box"
,你可以使用下面的命令找到它们:$(".red-box")
。它的结构与 ID 命令完全相同,只是用.
代替了$
。.
后面总是跟着()
,它包含了您正在寻找的元素。
现在我们已经找到了包含徽标的 DIV,我们可以开始在它上面使用 jQuery 并操作页面上的 HTML。在“新观察表达式”文本框内单击,键入以下行,然后按 Enter 键:
$("#logo-events").hide("slow")
您将看到徽标区域慢慢从浏览器窗口中消失。您可以使用以下命令将其恢复:
$("#logo-events").show("slow")
这些都是非常简单的例子,但是应该显示出 jQuery 可以轻松地为您的代码带来的强大功能。我们将在整本书中使用 jQuery,所以随着您的进步,您将会看到更多的例子,并且更加熟悉使用它。现在,让我们在 SharePoint 环境中实现 jQuery,这样它就可以使用了。
使用 SharePoint Designer 在 SharePoint 环境中实现 jQuery
对于你们中的一些人来说,jQuery 已经在 SharePoint 中实现了。这样做可能是为了支持之前的开发。但是,如果您刚开始使用 SharePoint Online 或者刚刚注册试用,您需要为本书中的示例实现 jQuery。实现 jQuery 实际上非常简单明了,在本节中,我们将了解如何使用 SharePoint Designer 来实现这一点。
Note
在您的环境中有许多不同的方法来实现 jQuery。这些包括自定义代码部署以将其注入所有页面,将内容编辑器 web 部件放置在特定页面上,等等。我们将使用 SharePoint Designer,因为它提供了一种将 jQuery 导入 SharePoint 的快捷方式。
获取 jQuery
在我们可以实现 jQuery 之前,我们首先需要引用 jQuery 代码或者下载一个副本并将其物理上传到 SharePoint。在本节中,我们将使用内容交付网络(CDN)来引用 jQuery。CDN 基本上是一个公共可用的服务器,你可以在你的站点上使用内容。jQuery 运行一个 CDN,你可以在 https://code.jquery.com
引用。许多其他公司也运营托管 jQuery 的 cdn,包括微软和谷歌。
使用 CDN 的好处有很多。最大的好处是速度,因为网上有许多网站使用相同的 CDN。如果您的用户已经访问过这些网站,那么 jQuery 可能已经加载到他们的浏览器中了,所以您的页面会加载得更快。另一大好处是你不必担心直接下载和存储代码。无论哪种情况,在生产站点使用 CDN 的决定都应该与您的 IT 部门讨论。在我们的例子中,它会工作得很好,您应该对在开发环境中使用它感到舒适。
为了从 CDN 引用 jQuery,我们将使用下面一行代码:
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
这是一个基本的 HTML 脚本标记,它将从 jQuery CDN 加载 jQuery 1.11 版。您会注意到在 URL 中没有 HTTP 或 HTTPS。这一点已被删除,以便脚本在不安全或安全的 URL 中都可以正常运行。现在让我们看看如何将它放入 SharePoint。
工作组网站模板
既然我们已经知道了如何实现 jQuery,我们就需要这样做了!我们将看到两个选项:一个团队站点和一个发布站点。它们略有不同,所以让我们先来看一个团队站点。启动 SharePoint Designer,点击打开网站图标,如图 1-14 所示。
图 1-14。
The home screen in SharePoint Designer with an Open Site icon
单击此按钮将启动“打开网站”对话框,您需要在其中指定 SharePoint 网站集的 URL。您可以打开特定的网站集,也可以通过键入 SharePoint 环境的基本 URL 来打开根网站。如果你正在使用 SharePoint online,你的根站点的 URL 看起来会像 https://YOURSITENAME.sharepoint.com
。
图 1-15 显示了打开场地对话框。您将在标有“网站名称”的文本框中键入 URL,然后单击“打开”。在 Designer 打开网站之前,您将看到另一个对话框来输入您的凭据。
图 1-15。
Open Site dialog where you supply the URL to your SharePoint site
一旦您提供了凭据并通过了身份验证,SharePoint Designer 将会打开并为您提供网站视图。如果你以前从未使用过 Designer,花点时间四处看看;你可能会对你所能获得的信息量印象深刻。Designer 让您深入了解所有列表和库、工作流、外部内容类型等。这是一个非常有用的工具,尤其是在 SharePoint Online 中,您无法访问服务器。
Note
SharePoint Designer 是一个非常强大的工具,可以非常轻松地更改您的 SharePoint 环境。如果您不熟悉这个工具,那么在浏览时要小心,并且只做那些您知道不会对您的环境有害的更改。
熟悉 Designer 后,点击左侧导航栏中的母版页链接,如图 1-16 所示。此区域不仅显示 SharePoint 中的所有母版页,还显示其他布局,包括搜索结果、显示模板等。我们将在本书的后面回到这个领域,但是现在,突出显示seattle.master
文件。此文件高亮显示后,单击功能区中的编辑文件。
图 1-16。
The Master Pages tab in SharePoint Designer. Once you highlight the seattle.master file, click Edit File in the Ribbon
如果您是开发新手,下一个屏幕可能看起来很吓人,但事实并非如此。一旦你编辑了seattle.master
文件,你将会看到所有呈现你的 SharePoint 页面的 ASP.NET 代码。嗯,差不多了。该文件负责 SharePoint 页面的公共部分,如徽标、功能区、导航等。尽管这里有很多,我们只需要添加我们的 jQuery 引用——然后退出!
我们将把我们的代码行放在页面顶部附近,就在结束标签</head>
之前,如图 1-17 所示。
图 1-17。
jQuery reference added the Seattle master page
正如你在图 1-17 中看到的,我们将 jQuery 引用放在右</head>
标签之前,右<body>
标签之上。它基本上是母版页中 Head 区域引用的最后一个脚本。完成后,单击屏幕左上方的保存图标保存更改。这将自动将更改发布到您的 SharePoint 环境中。
保存更改后,启动浏览器并导航到您的站点。图 1-18 显示了 Firebug 打开时的 SharePoint 环境。检查 HTML,我们可以看到 jQuery 引用现在位于母版页中,并且可用于 SharePoint 中的所有页面。
图 1-18。
Inspecting your SharePoint environment with Firebug to ensure the jQuery reference is in place Note
一般来说,在 SharePoint 中修改现成的母版页不是一个好主意。最大的原因是因为它们是现成的,如果更新或新版本出现,并且您的 SharePoint Online 升级,您的更改丢失的风险很高。最佳做法是制作一份要修改的母版页的副本,并更改该母版页。这样,更新将不会覆盖您的更改。
发布网站模板
当涉及到修改母版页时,发布站点的行为非常不同。SharePoint 2013 提供了设计管理器,允许您上传 HTML 文件,该文件将被转换为母版页。这对于想要上传自定义设计并完全改变其网站外观的用户来说非常好。然而,我们只需要注入 jQuery,所以我们需要完成一些额外的步骤。
打开 SharePoint Designer 并单击左侧导航栏中的母版页链接。您将注意到的第一件事是比团队网站中多得多的文件。所有额外的文件都有一个发布网站,所以你现在可以完全忽略它们。找到seattle.master
文件,你会注意到它有一个附带的 HTML 文件,如图 1-19 所示。
图 1-19。
Master Pages in SharePoint Designer on a Publishing Site template
在这个模型中,您只能编辑 HTML 文件。对 HTML 文件进行编辑并保存后,更改将被转换并保存到母版页文件中。我们需要做的第一件事是复制一份seattle.html
文件,因为这是我们实际可以编辑的文件。突出显示seattle.html
文件,并从功能区中单击复制按钮。粘贴按钮将被激活。单击粘贴。将会创建一个seattle.html
的副本,如图 1-20 所示。
图 1-20。
Copy and Paste buttons in the Ribbon
一旦您制作了文件的副本,它将以默认名称seattle_copy(1).html
粘贴进来。对于大多数人来说,这只是一个不能接受的名字!你可以右键点击新文件,从上下文菜单中选择重命名,如图 1-21 所示。
图 1-21。
The Rename option from the context menu
我们将文件重命名为 seattle_jquery.html,然后单击 Enter。由于 HTML 文件以相同的名称链接到母版页,因此在重命名新文件之前,Designer 会提示您。图 1-22 显示了重命名过程中您将看到的提示。
图 1-22。
The Rename prompt when renaming the copied HTML file
重命名后,您现在将拥有一个seattle_jquery.html
和一个seattle_jquery.master
文件。突出显示新的seattle_jquery.html
文件,并单击功能区中的编辑文件。与团队站点母版页一样,我们将插入下面一行来引用 jQuery:
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
这次我们将把它放在不同的位置,如图 1-23 所示。它将被添加到 META 标签的正下方,一些现成的 SharePoint 标签之后。
图 1-23。
Adding the jQuery line to the new master page file
添加 jQuery 引用后,单击 Save,这将保存并发布文件。它还会生成一个包含更改的新的seattle_jquery.master
文件。现在我们已经添加了引用,并且所有文件都已更新,我们需要将这个新的母版页设置为默认母版页,以便我们的站点使用它。高亮显示seattle_jquery.master
,点击功能区中的【设为默认】,如图 1-24 所示。
图 1-24。
Setting the new master page as the default
既然已经创建了新的母版页并将其设置为默认母版页,我们将检查以确保 jQuery 引用设置正确。导航到使用发布网站模板的网站。图 1-25 显示了 Firebug 打开时的 SharePoint 环境。检查 HTML,我们可以看到 jQuery 引用现在位于母版页中,并且可用于 SharePoint 中的所有页面。
图 1-25。
jQuery reference in the new master page
使用发布模板从父网站创建的任何子网站都将自动继承这个新母版页。这是在母版页中添加 jQuery 引用的首选方式。制作文件副本可确保在更新应用到 SharePoint 时,您的更改将保持不变。
摘要
在这一章中,我们看了你在这本书里做前端开发需要的各种组件。如果您已经在开发解决方案,那么在阅读本书之前,您可能已经安装了大部分(如果不是全部)这些组件。如果你是前端开发的新手,你可能安装了一些新程序!现在,您应该已经具备了开始创建自己的定制解决方案所需的一切。这些组件的优点在于,在 SharePoint Online 和 Designer 之外,所有这些组件都可以用于许多其他项目。如果你发现你喜欢前端开发,你可以将这些工具用于广泛的项目!
在下一章,我们将探索服务器端和前端开发的区别。我们还将看看 SharePoint 提供的允许这种类型开发的一些组件。您将看到一些代码,并为后面的章节做准备!
二、SharePoint 前端解决方案简介
SharePoint 自问世以来已经走过了漫长的道路,其发展历程也不例外。如果您必须在 SharePoint 2007 或更早版本上进行任何开发,可以相当肯定地说,您讨厌这种体验。SharePoint 2010 使事情变得更加简单,并引入了一些允许前端开发的新组件,如 ECMAScript 对象模型,后来更名为 JavaScript 对象模型。对于最新版本的 SharePoint,真正的重点是将代码从 SharePoint 服务器转移到浏览器或其他服务器。
这种关注在一定程度上是因为微软看到了许多由服务器代码引起的支持问题,这些代码要么写得很差,要么只是将服务器推到了极限。再加上 SharePoint Online 的引入,最终用户无法访问服务器本身,因此需要更强大的前端开发解决方案。由此而来的是一个扩展的 JavaScript 对象模型、一个新的 REST API 和 SharePoint 应用。
我们将在本书中更详细地探讨 JavaScript 对象模型和 REST API。我们还将关注新的前端组件,比如 JSLink 和显示模板。本章将探讨服务器端和前端开发之间的差异,以及这种开发风格的一些功能。我们还将探讨在这个过程中可能会遇到的一些限制。
Note
本书不涉及 SharePoint 应用。虽然在某些情况下应用可以被认为是前端开发,但这是一个非常大的主题,涉及开发、网络和域管理。在很多情况下,SharePoint 的应用在服务器端运行,只是不在运行 SharePoint 的服务器上。有关构建 SharePoint 应用的更多信息,请访问以下 URL: http://msdn.microsoft.com/en-us/library/office/jj163230(v=office.15).aspx
。
服务器端开发与前端开发
SharePoint 开发和定制解决方案的构建在很长一段时间内都是核心开发人员的领域。它需要广泛的组件知识,包括 Visual Studio、PowerShell、ASP.NET、微软服务器等等。这有时是一次令人生畏的经历——即使对那些一直在做的人来说。NET 开发,但不熟悉 SharePoint。图 2-1 展示了一个典型的服务器端开发体验,其中包括 Visual Studio、部署包和一个 PowerShell 窗口,用于将代码实际部署到服务器。
图 2-1。
A typical SharePoint server-side development experience
服务器端代码是专门为在 SharePoint 服务器上运行而编写的。一旦为部署编写并打包了代码,它就被复制到服务器上,并使用 PowerShell 或管理中心进行安装。在大多数情况下,它需要开发人员、业务用户和服务器管理员一起工作。由于代码直接在服务器上运行,因此它具有巨大的威力,很容易对 SharePoint 环境产生负面影响。
甚至为 SharePoint 编写服务器端代码也很困难,因为这需要一台安装了 SharePoint 的功能强大的 PC。过去,大多数开发人员会在他们的电脑上构建虚拟机,他们可以在隔离的环境中为 SharePoint 编写代码。学习服务器端开发有时很困难,因为您需要学习新的代码框架,需要在您的 PC 上安装 SharePoint,并且需要编码最佳实践来确保您不会用糟糕的代码损害服务器。
一旦 SharePoint Online 和 Office 365 出现,服务器端开发就受到了打击,因为使用这些产品,你无法访问运行 SharePoint 的服务器。从使用同一台服务器的所有其他客户的角度来看,这很好。如果一个客户安装了写得很差或恶意的代码,他们就有可能让所有人的整个服务器瘫痪。但是,如果您是一个需要定制解决方案的客户,您将不再拥有健壮的服务器端代码。
Note
沙盒解决方案提供了在 SharePoint 中编写和部署服务器端代码的另一种方式。这些解决方案不需要访问服务器,因为网站集管理员可以使用浏览器安装它们。它们被称为“沙盒”,因为它们在服务器上独立运行,并由 SharePoint 监控,以确保它们不会影响性能。对于 SharePoint 2013,沙盒解决方案仍然可以安装在内部,但在 SharePoint Online 中已被否决,并且只能包含 HTML 和 JavaScript。有关沙盒解决方案的更多信息,请访问以下网址: http://technet.microsoft.com/en-us/library/ee721992(v=office.14).aspx
。
乍一看,微软似乎已经放弃了为你的业务创建定制 SharePoint 解决方案的能力,尤其是当你使用 Office 365 的时候。使用 SharePoint 内部部署的客户也收到了来自微软的相同消息,该公司已停止在服务器上放置自定义代码。幸运的是,微软没有让任何人“孤立无援”。最新版本的 SharePoint 附带了广泛的前端组件来开发解决方案。
前端开发或客户端代码是专门为在 web 浏览器中运行而编写的。它使用 HTML、JavaScript 和 CSS,可以在任何浏览器上运行。您仍将向 SharePoint 添加您的代码,但由于它只有 HTML 和 JavaScript,您可以利用现成的组件(如文档库)来上传和存储您的解决方案。在下一节中,我们将探索使用 SharePoint 进行前端开发的各种组件,并看看它们能为您提供什么。
SharePoint 中前端开发的组件
既然我们已经了解了服务器端和前端开发之间的一些差异,那么让我们来看看本书将要涉及的前端开发的一些组件。在本书中,我们将展示几种不同的创建定制解决方案的方法,在这一节中,我们将向您介绍它们。这些将是相当快速、高水平的介绍,因为我们将在后面的章节中更深入地探讨每一个。我们会探索
- JavaScript 对象模型(JSOM)
- 应用接口
- JS 链接
- 显示模板
这些项目中的每一项都与其他组件配合使用,构成一个完整的前端解决方案。如果需要的话,你甚至可以一起使用其中的几个。现在,我们将快速地看一下每一项,让你准备好在接下来的章节中开始构建一些解决方案。
JavaScript 对象模型(JSOM)
JavaScript 对象模型,简称 JSOM,是 SharePoint 客户端 API 家族的一部分。这通常被称为客户端对象模型,或简称为 CSOM。所有这些都相当令人困惑,因为人们倾向于在广泛的讨论中使用“客户端对象模型”这个术语。CSOM 囊括了从 JSOM 到 Silverlight 库,再到一组服务器端库,甚至是 REST API。这里的要点是,如果有人在谈论 CSOM,你可能需要他们更具体地说明他们在做什么。
JavaScript 对象模型基本上是作为 SharePoint 一部分的 JavaScript 文件的集合。每个文件都包含允许您执行各种任务的代码——从与术语库交互、访问用户配置文件信息,或者只是阅读列表和网站等常见的核心任务。如果您可以访问服务器,您可以在C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS
查看所有这些文件。图 2-2 显示了 Windows 资源管理器中的这个文件夹。如果您在 SharePoint Online 上,请不要担心,所有这些文件仍然对您可用,只是您无法在 Windows 资源管理器中查看它们!
图 2-2。
Files that make up the JavaScript Object Model on the file system
所有文件都位于 SharePoint 的 Layouts 文件夹中。Layouts 文件夹是 SharePoint 中的一个常用文件夹,包含许多在整个环境中使用的通用文件和代码。当部署使用自定义页面、图像等的自定义服务器端代码时,通常会将其部署到 Layouts 文件夹中。如果你还不熟悉,没必要担心,你很快就会熟悉的。
图 2-2 仅显示了您可用的部分文件,但应该有助于说明 JSOM 在构建定制解决方案方面的强大功能。微软投入了大量的时间和精力来扩展 JSOM 的功能。由于他们告诉他们的客户不再使用服务器端代码,并在许多方面转移到 SharePoint Online,他们确保提供一套全面的工具,以提供丰富的开发体验。
Note
有关 JSOM 的更多信息,请访问 SharePoint 的 JavaScript API 参考,网址为: http://msdn.microsoft.com/en-us/library/office/jj193034(v=office.15).aspx
。
在您的解决方案中使用 JSOM 相当简单,因为它们都是 JavaScript。首先,您需要放置一个对特定文件的引用,如下所示:
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
这是 HTML 中的标准脚本标记,它告诉浏览器加载位于 SRC 属性中指定位置的特定文件。在这种情况下,浏览器将加载位于 Layouts 文件夹中的sp.js
文件。一旦我们有了对我们需要的 SharePoint JSOM 文件的引用,我们就可以编写一个类似这样的脚本:
$(function () {
retrieveListItems();
});
function retrieveListItems() {
var clientContext = new SP.ClientContext();
var oList = clientContext.get_web().get_lists().getByTitle('Demo List');
var camlQuery = new SP.CamlQuery();
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsyn
c(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
如果这是你第一次看到 JSOM 代码,不要不知所措!它可能看起来令人生畏,但是当你读完这本书,它将变得更容易阅读和写作。让我们把这个例子分解一下,看看每一部分。
$(function () {});
——这是代码的入口点,都是 jQuery。这被称为 document.ready 函数,之所以这样叫是因为它在浏览器完全加载 HTML 页面时被触发。在 jQuery 开发中,您会经常看到这种情况,因为这是在页面加载时启动代码的一种简单方便的方式。在这个例子中,我们所做的就是调用 JSOM 代码所在的另一个函数。SP.ClientContext()
-该行获取对客户端上下文的引用,并在对 SharePoint 服务器的每个 JSOM 调用中使用。客户端上下文包含许多关于当前 web 应用、站点、站点集合等的信息。- 使用客户端上下文,我们可以获得对站点中任何内容的引用。在这一行中,我们引用当前站点,从所有列表中请求一个标题为“演示列表”的特定列表。这一行的语法非常容易理解:获取 Web、获取列表、按标题获取。使用 REST API 时,您会看到类似的模式。
SP.CamlQuery()
-这一行允许您使用 CAML 查询来指定要返回的项目,这是一种用于查询 SharePoint 的语法。它已经存在了一段时间,在处理列表和库时经常使用。在本例中,我们简单地传递一个空查询,告诉 SharePoint 我们需要列表中的所有项目。我们通过在查询中调用oList.getItems(camlQuery)
来实现这一点。clientContext.executeQueryAsync()
-该行将实际启动对 SharePoint 服务器的查询。然后,您可以处理返回的数据,并将其显示给用户。
这是对 JSOM 尽可能高层次的解释了!主要目的是展示一些 JSOM 和简要说明部分。关于 JSOM 还有很多内容,但是在我们开始任何演示之前,您至少已经接触了一些代码。
应用接口
SharePoint 2013 和 SharePoint Online 引入了 REST API。它允许您通过特制的 URL 对 SharePoint 进行 RESTful 调用。数据可以以 XML 或 JSON 的形式返回,并且可以很容易地被浏览器中的 JavaScript 使用。RESTful 数据在 SharePoint 的早期版本中是可用的,但仅限于大多数列表交互。像 JSOM 一样,新的 REST API 已经得到了极大的扩展,包含了广泛的函数。
Note
有关 REST API 的更多信息,请访问 SharePoint 的 REST API 参考和示例,网址为: http://msdn.microsoft.com/en-us/library/office/jj860569(v=office.15).aspx
。
典型的 REST API 调用将类似于以下 URL:
http://SERVER/_api/web/lists/GetByTitle('Demo
List')/items
就像上一节中的 JSOM 示例一样,这个 URL 将查询名为 Demo List 的列表,并请求所有项目。语法也应该看起来很熟悉:Web、列表、GetByTitle、Items。在这两个例子中,调用的结构非常容易阅读,并为您提供了您需要了解的关于预期数据的所有上下文。图 2-3 显示了浏览器中 REST 调用的结果。
图 2-3。
REST API call in the browser returned as XML
在这个例子中,结果以 XML 的形式返回,因为这是浏览器默认请求的。当通过 JavaScript 调用时,我们可以请求 XML 或 JSON。我们稍后会更详细地讨论这个问题。像 JSOM 一样,我们可以提供一个 CAML 查询来限制结果,我们可以使用查询字符串操作符来选择、过滤和排序我们从 API 请求的数据。
如果我们想将数据限制为一行,REST API 调用将类似于以下 URL:
http://SERVER/_api/web/lists/GetByTitle('Demo
List')/items?$top=1
查询字符串操作符top=1
告诉 API 只返回第一行数据。图 2-4 在浏览器中显示了这次调用的结果。
图 2-4。
REST API call with a query string operator limiting results
有许多操作符可以用来编写 REST API 调用。我们将在后面的章节中看到更多,但是请放心,您将拥有获得正确结果所需的所有工具。这个例子应该说明使用 REST API 从 SharePoint 请求数据是多么容易。
路由器
JSLink 是 SharePoint 2013 中的新增功能,它提供了一种非常强大且简单的方法来设置列表视图 web 部件的样式。在 JSLink 出现之前,您必须使用 XSLT 或可扩展样式表语言转换。XSLT 是一种样式化或转换 HTML 并赋予其生命力的方法。它在允许开发人员改变 web 部件的呈现方式方面做得很好,但使用起来相当痛苦。大多数开发人员一想到必须使用 XSLT 就畏缩不前,通常会远离它。
伴随而来的是 JSLink,它允许使用 JavaScript 和 HTML 对部件进行样式化。它提供了一种更容易、更快速的方法来呈现 web 部件以满足业务需求,并提供更多的功能。JSLink 不仅提供了一种简单的方法来设计 web 部件的样式,因为它是 HTML 和 JavaScript,你还可以用它做更多的事情。现在,让我们来看看 JSLink 是如何工作的。图 2-5 显示了一个标准的 SharePoint 主页,上面插入了一个列表 Web 部件,并显示了演示列表中的项目。
图 2-5。
SharePoint page with a List Web Part inserted, listing the items from the Demo List
这是 SharePoint 附带的标准列表 Web 部件,但现在它有了新的属性。如果将 web 部件置于编辑模式,并在 web 部件工具窗格中展开“杂项”面板,您将看到一个名为“JS 链接”的新属性。这是一个文本框,您可以在其中放置将在呈现 web 部件期间使用的 JavaScript 文件的路径。图 2-6 显示了这个新属性。
图 2-6。
JSLink property in the Web Part Properties pane
现在您已经知道如何通过 JSLink 属性应用 JavaScript 文件,让我们看看 JavaScript 实际上是什么样子。下面的代码简单演示了 JS 链接代码是如何工作的。
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
function overrideTemplate(ctx) {
return "<div style='font-size:32px;border:solid 1px Silver;'>" + ctx.CurrentItem.Title + "</div>";
}
让我们把这个例子分解一下,看看每一部分。
overrideContext
、overrideContext.Templates
和overrideContext.Templates.Item
——顾名思义,这些是覆盖 web 部件默认呈现的对象。父对象overrideContext
,可以随意命名。前两行只是创建了一个对象和一个名为Templates
的属性。这是所有 JSLink 文件的标准,因为它是代码的基础。第三行定义了另一个 JavaScript 函数,它将为 web 部件中的每个单独的项目触发;这是由它的名字中的“Item
”指定的。您可以将项目作为目标,或者仅将项目中的特定属性作为目标。例如,如果我们只想设计Title
的样式,我们可以只引用那个属性。SPClientTemplates.TemplateManager.R``egisterTemplateOverrides(overrideContext)
——一旦你构建了你的对象,你必须告诉 SharePoint 你想使用它。这一行就是通过将它注册到TemplateManager
对象来实现的。一旦完成,您引用的 JavaScript 函数将在呈现 web 部件时被调用。function overrideTemplate(ctx)
-这是呈现 web 部件时将运行的实际代码。它非常简单:它所做的只是呈现一个 HTML DIV 元素,其中包含一些样式和当前项目的标题。
一旦这些代码被放到一个文件中,我们就把它上传到 SharePoint 中的一个库中。然后,我们将文件的路径放在 web 部件的 JSLink 属性中。图 2-7 显示了使用 JSLink 文件呈现 web 部件后的输出。
图 2-7。
List Web Part after applying JS Link code
我们将在后面的章节中更详细地讨论 JSLink 的使用,我将展示更多的方法来设计内容和构建定制的解决方案。当在页面上使用列表 web 部件时,您会发现 JSLink 是一个非常有用的工具,可以满足您的业务需求。
显示模板
与 JSLink 一样,显示模板是 SharePoint 2013 和 SharePoint Online 中的新增功能。它们与搜索 Web 部件协同工作,例如 SharePoint 附带的内容搜索 Web 部件。显示模板使用 HTML 和 JavaScript 来呈现内容,并允许您指定要显示的属性、放置位置以及样式。通过使用这些模板,您可以极大地控制搜索结果及其显示方式。图 2-8 显示了放置在页面上的标准内容搜索 Web 部件。
图 2-8。
Out-of-the-box Content Search Web Part placed on a page
我们可以通过将 web 部件置于编辑模式并查看 web 部件工具窗格中的属性面板来更改正在使用的显示模板。在搜索条件的正下方,您将找到显示模板区域。这一部分有两个下拉框,允许您选择内容应该如何呈现:控件和项目。图 2-9 显示了显示模板区域和下拉菜单。
图 2-9。
Control and Item options in the Content Search Web Part tool pane
这些项目中的每一个都是一个模板,它们一起工作来呈现内容。控件模板为您的内容提供了一个总体的 HTML 布局。你可以把它想象成一个保存所有搜索结果项的容器。这也是一个加载您想在搜索结果中使用的任何 JavaScript 或 CSS 的好地方。项目模板为每个搜索结果项目提供了单独的 HTML。此模板还利用搜索结果上的托管属性,并允许您控制显示哪些属性。当一起使用时,这些模板提供了一个完整的方法来呈现您的内容。
您可以通过导航到网站设置,然后导航到 Web Designer 库标题下的母版页来查看现成的显示模板。这将打开母版页图库页面,如图 2-10 所示。
图 2-10。
Master Page Gallery where you can find the out-of-the-box display templates Note
为了使用显示模板和内容搜索 Web 部件,您需要确保 SharePoint Server 发布网站功能已激活。如果您的站点正在使用发布模板,应该已经激活了。此 web 部件也仅在 Office 365 E3 和 E4 计划或 SharePoint 内部部署的企业版中可用。
单击显示模板文件夹将显示另一个页面,其中所有当前显示模板都按文件夹组织。内容搜索 Web 部件显示模板都位于内容 Web 部件文件夹中,如图 2-11 所示。
图 2-11。
Display Templates and the Content Web Parts folder
打开内容 Web 部件文件夹时,您会发现一堆显示模板。每个模板都有一个 HTML 文件和一个对应的 JavaScript 文件,如图 2-12 所示。
图 2-12。
Display template with an HTML file and corresponding JavaScript file
当您构建新的显示模板时,您将只能使用 HTML 文件。上传 HTML 文件后,SharePoint 会为您生成 JavaScript 文件,这是它在呈现内容时使用的文件。有了这个模型,您不需要担心所需的脚本;您只需要担心 HTML,SharePoint 会处理其余的事情。显示模板使用搜索结果中的托管属性来呈现内容。该模板使用令牌系统来呈现内容,如下面的代码示例所示:
<a class="cbs-pictureImgLink" href="_#= linkURL =#_" title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= pictureLinkId =#_">
令牌看起来像_#= variabl
eName =#_
。您可以创建自己的变量来存储稍后在模板中使用的内容。我们将在后面的章节中更详细地讨论这些。
摘要
在这一章中,我们研究了服务器端开发和前端开发之间的区别,并探索了一些可用于定制解决方案的组件。在最新版本的 SharePoint 中,微软强调了在开发工作中不使用服务器端代码的优势。说到 SharePoint Online,您根本无法使用它!正如你在本章中读到的,它们提供了许多选项来构建不依赖于服务器端代码的定制解决方案。所有这些解决方案都利用了 HTML 和 JavaScript,使得任何习惯于构建网页的人都可以轻松访问这些解决方案。
在下一章中,我们将继续扩展我们目前所学的内容。我们将看看内容编辑器 Web 部件,以及如何将 HTML 内容直接放在页面上。此外,我们将探索新的脚本编辑器 Web 部件,它可以与内容编辑器结合使用。我们将使用你在本章中看到的一些代码,并实际看到它的运行。
三、内容编辑器和脚本编辑器 Web 部件
此时,您应该已经安装了所有需要的工具,并拥有了一个 SharePoint 开发环境。您还了解了服务器端开发和前端开发之间的差异。我们还研究了构成前端开发的一些部分。现在是时候实际开始使用我们所学的一些东西并构建一些东西了!
在本章中,我们将了解如何使用内容编辑器和脚本编辑器 Web 部件。如果您使用 SharePoint 已经有一段时间了,那么您应该已经了解了内容编辑器 Web 部件,并且知道它如何允许您轻松地向任何页面添加 HTML。SharePoint 的最新版本带来了脚本编辑器 Web 部件,它允许您轻松地将 JavaScript 添加到任何页面。我们将了解这些 web 部件如何工作以及如何相互交互。到本章结束时,你将理解使用这些 web 部件的利弊,并且你将已经使用 HTML 和 JavaScript 构建了一些自定义解决方案。
内容编辑器 Web 部件
内容编辑器 Web 部件(CEWP)是 SharePoint 领域中的主力;它已经存在很长时间了,大多数用户都很熟悉它。顾名思义,CEWP 用于在 SharePoint 的页面上放置内容。使用此 web 部件,您可以轻松地将 HTML 放在页面上,向用户发布内容、链接列表等等。
通过 CEWP,您可以使用预定义的样式和类似于 Microsoft Word 的编辑工具从功能区添加丰富的内容。您可以直接将 HTML 编写到编辑器中,或者将它指向保存您的标记的 HTML 文件。通过功能区插入 web 部件时,可以在“媒体和内容”类别下找到 CEWP,如图 3-1 所示。
图 3-1。
The Media and Content category where you can find the Content Editor Web Part
在页面中插入一个 CEWP,并将其置于编辑模式。您将看到有三种方式可以添加和编辑内容,如下所述,如图 3-2 所示。
图 3-2。
The various ways you can add content in a Content Editor Web Part
- 丰富的内容——当你第一次添加一个 CEWP 到一个页面时,那里显然没有内容。在这种情况下,您将看到一个标题为“单击此处添加新内容”的链接。单击此链接会将光标直接放在 web 部件上,您可以使用功能区添加丰富的内容,就像在 Microsoft Word 中一样。这是向页面添加内容的一种简单而方便的方法,但不是构建使用 SharePoint 数据的自定义解决方案的好方法。
- HTML 标记-插入内容的另一种方法是单击“单击此处添加新内容”链接,然后单击功能区中的“编辑源”按钮。这将打开一个对话框,您可以在其中直接在 CEWP 中键入 HTML 内容。对于快速 HTML 插入或测试 HTML 标记,这是一个很好的选择。对于构建定制解决方案来说,这是一个更好的选择,但不是最好的。
- 链接到 HTML 文件-您也可以直接链接到 HTML 文件以显示 web 部件中的内容。在 CEWP 工具窗格中,第一个属性的标题为内容链接。在此文本框中,只需将 URL 添加到 HTML 文件中,当呈现 web 部件时,就会显示其内容。这是构建定制解决方案时的首选用法,我们将在下一章中讨论。
现在,让我们使用功能区中的 Edit Source 按钮放置一些 HTML。将 CEWP 置于编辑模式,单击“单击此处添加新内容”链接,然后单击功能区中的编辑源按钮。图 3-3 显示了点击该按钮后显示的对话框。
图 3-3。
Dialog that is presented after clicking the Edit Source button in the Ribbon
在这个对话框中,我们可以简单地输入我们的 HTML 内容。在这个例子中,我们将添加一个包含 ID 和一些文本的DIV
元素。下面的 HTML 是所有需要的:
<div id="divHelloWorld">Hello World!</div>
添加这些内容并保存页面将会产生一个漂亮的“Hello World!”页面上显示的消息,如图 3-4 所示。
图 3-4。
HTML content displayed in the Content Editor Web Part
这是一个向页面添加 HTML 内容的非常简单也不太令人兴奋的例子。然而,如果你是添加自定义 HTML 的新手,这将是本章和后续章节的一个很好的起点。现在页面上有了一些 HTML,让我们看看脚本编辑器 Web 部件,并了解如何将自定义 JavaScript 和 HTML 一起注入到页面中。
脚本编辑器 Web 部件
脚本编辑器 Web 部件(SEWP)是 SharePoint 2013 的新增功能;顾名思义,它是为在 SharePoint 中向页面添加脚本而设计的。在此 web 部件出现之前,如果您想在页面上插入脚本,可以使用 CEWP。如果您链接到一个包含脚本的文件,这非常有用,但是如果您想要编辑源代码并手动放置脚本,您经常会遇到问题。有时,脚本不会运行,或者会抛出错误,或者更糟的是,CEWP 会更改您输入的代码。这不是一次愉快的经历。
有了 SEWP,这些不再是你需要担心的问题。现在,您可以使用 SEWP 轻松地将 JavaScript 放到页面上,因为它就是为此而构建的。您还可以在此 web 部件中放置其他项目,包括对象标记、HTML 等。通过功能区插入 web 部件时,可以在“媒体和内容”类别下找到 SEWP,如图 3-5 所示。
图 3-5。
The Media and Content category where you can find the Script Editor Web Part
在页面中插入一个 SEWP,并将其置于编辑模式。您将看到有一种方法可以添加和编辑脚本——通过单击编辑片段链接,如图 3-6 所示。
图 3-6。
Click Edit Snippet to add or edit your JavaScript
点击编辑代码片段链接会打开一个名为嵌入的对话框,你可以在这里写你的 JavaScript,如图 3-7 所示。放入此 web 部件的 JavaScript 必须有效,并且包含<script></script>
标记,才能正常运行。SEWP 甚至还可以用来在页面上放置 HTML。如果您正在放置 HTML,对话框将在您正在工作的文本框下方显示内容的预览。如果您正在编写 JavaScript,则不会显示预览,因为该代码通常在页面中不可见。
图 3-7。
Embed dialog for writing scripts inside the Script Editor Web Part Note
尽管脚本编辑器 web 部件可用于注入 HTML,但您应该将此 Web 部件视为仅用于脚本。将 HTML 和脚本分离到不同的 web 部件中是更好的做法。也就是说,如果您只需要对脚本进行快速测试,它会非常有用。
在本例中,我们将使用 jQuery 添加一些 JavaScript,在页面加载时显示警告:
<script type="text/javascript">
$(function() {
alert("Hello World!");
});
</script>
如您所见,这段代码包含一个开始和结束的<script>
标记,其中包含一个 jQuery document.ready 函数。这个脚本所做的只是发出一个警告,文本为“Hello World!”当 jQuery 检测到页面已经被加载时。将这段代码放在对话框中,然后单击 Insert。保存页面。当页面刷新时,您将看到警报触发,如图 3-8 所示。
图 3-8。
JavaScript alert being shown via the Script Editor Web Part
与使用内容编辑器 Web 部件的示例非常相似,这非常简单,也不令人兴奋。然而,现在你的页面上应该有一个 CEWP 和一个 SEWP。接下来,让我们看看如何将它们连接在一起,形成一个完整的解决方案。
将它们与 REST API 放在一起
既然我们已经在页面上放置了一个 CEWP 和一个 SEWP,我们可以将它们连接起来一起工作。在这个例子中,我们将使用 REST API 从我们站点的列表中提取一些数据。我们将使用 jQuery 通过 SEWP 进行 AJAX 调用,然后在调用完成后更新 CEWP。我们将了解如何在一个页面上同时使用这两个 web 部件,以及如何使用 jQuery 进行 AJAX 调用。首先,我们需要一个列表来调用获取数据。
演示列表
在本书中,我们将使用 JSOM 和 REST API 从 SharePoint 中查询数据。为了方便起见,我们将创建一个新的自定义列表,以便在工作中使用。我们将保持它相当简单:只需创建一个新的自定义列表并向其添加一个附加列。这里没有多余的东西。首先,只需使用添加应用功能添加一个自定义列表,然后将这个新列表命名为演示列表。
Note
本节假定您知道如何在 SharePoint 中创建新列表以及如何创建新栏。如果您需要创建新栏目的帮助,请访问以下网址: http://office.microsoft.com/en-us/sharepoint-server-help/create-change-or-delete-a-column-in-a-list-or-library-HA102771913.aspx
。
一旦列表被添加,它将在默认视图中有一个单独的列,即标题。这很好,但是让我们再添加一个——这样我们就有一些额外的数据要处理。转到列表设置,并使用该页面上的“创建栏”链接添加新栏。选择多行文本的类型,并将此列命名为描述。在我的列表中,我将它设为纯文本列,只是为了保持简单。图 3-9 显示了添加一些数据后的演示列表。
图 3-9。
Demo List ready to be queried for data
现在只插入几行数据。列表中的实际数据现在并不重要;它实际上只是为了确保我们可以查询它和检索列表项。现在我们有了一个列表,让我们看看通过 REST API 查询它所需的代码。
jQuery、AJAX 和 REST API
查询列表将通过使用 jQuery 对 REST API 进行 AJAX 调用来完成。在前一章中,我们快速看了一下 REST API URL 的结构。查询列表的典型 URL 结构如下所示:
http://DOMAIN/SITE/_api/web/lists/GetByTitle('List
Name')/items
所有 REST API URLs 都在数据所在的站点后以_api
开头,或者如果查询 SharePoint 的根站点集合,则紧跟在域名之后。_api
向 SharePoint 表明您正在通过 REST 请求数据。可以用 XML 或 JSON 格式请求数据,但是对于大多数 JavaScript 调用,它将是 JSON。使用 REST API 的一个好处是,您可以在任何浏览器中创建 URL,并在代码中使用它们之前进行测试!
Note
在我的环境中,我在名为 Apress 的主网站集下创建了一个子网站。这个站点是我编写和运行本书中所有代码的地方。因此,您将看到如下所示的 URL 结构:/apress/
。如果您在网站集中的根网站工作,那么您的 URL 引用将只以/
开头。记下你的网址,并确保你的参考是正确的!稍后,我们将为您编写一些代码来完成所有这些工作,但是对于本节来说,拥有正确的 URL 结构非常重要。
为了通过浏览器进行调用,我们将使用标准的 jQuery AJAX 调用。下面的代码演示了这个调用:
<script type="text/javascript">
$(function() {
$.ajax({
url: "/apress/_api/web/lists/GetByTitle('Demo List')",
type: "GET",
headers: {
"accept": "application/json;odata=verbose"
},
}).success(function(data) {
alert(data.d.Title + " : " + data.d.Created);
});
});
</script>
在本例中,我们将调用包装在我们现在熟悉的 document.ready 函数中。AJAX 调用是使用$.ajax()
函数进行的。它非常简单,只包含几个属性:
- 这是 REST API URL,可以请求您需要的任何特定数据。在这个例子中,我们所请求的只是列表属性。
type
-类型代表标准的 HTTP 方法,即:GET、POST、PUT 和 DELETE。对于这个例子,我们只是请求数据,所以我们使用 GET。headers
——如前所述,REST API 可以返回 XML 或 JSON。如果您没有指定想要的格式,它将返回缺省值,即 XML。通过指定一个头部"accept": "application/json;odata=verbose"
,我们告诉 REST API 我们希望 JSON 返回。
在$.ajax
调用的末尾,我们附加了一个success
函数,它处理从 REST API 返回的“数据”。jQuery 使得处理 AJAX 调用变得非常容易,并根据调用执行各种功能。例如,你可以附加其他功能,比如一个failure
和一个finally
。稍后我们将更详细地讨论这些。
在我们的success
函数中,我们传递从 REST API 返回的data
对象。我们现在要做的就是弹出一个带有列表标题和创建数据的警报。我们使用以下代码行来实现这一点:
data.d.Title
data.d.Created
data
对象是查询返回的所有数据。这件物品中有很多我们不会用到的东西。d
属性保存了我们正在寻找的所有列表属性。这可能看起来很奇怪,但这就是你将如何访问所有通过 REST API 返回的数据。例如,如果您在查询中请求列表项,您可以访问data.d.results
。将该代码放入 SEWP 并保存页面将会导致如图 3-10 所示的警告。
图 3-10。
JavaScript alert showing the Demo List title and date created
现在我们已经建立了 AJAX 调用,并且正在返回数据,您应该会看到令人讨厌的警告弹出窗口。这很好,因为它让我们知道一切都正常工作。然而,在现实生活中,你可能不会仅仅为了弹出提示而调用 REST。让我们用更多的 jQuery 魔法将这些数据放入 CEWP。
把它们都连接起来
此时,您的页面上应该有一个 CEWP 和一个 SEWP。CEWP 正在显示一些基本的 HTML,SEWP 正在进行 REST API 调用并弹出一个警告。现在是时候让它们一起工作了,让 SEWP 调用以获取列表数据,然后用结果更新 CEWP 中的 HTML。看完这个示例后,您应该会看到让这两个 web 部件协同工作来创建解决方案是多么容易。
幸运的是,我们不需要对 CEWP 做任何修改!如果你使用了本章这一节中的 HTML,你就已经准备好了。如果不是,应该是这样的:
<div id="divHelloWorld">Hello World!</div>
这行代码的关键是 DIV 标签中的 ID 属性:"divHelloWorld"
。通过给 DIV 一个 ID,我们可以很容易地使用 jQuery 在 HTML 中找到元素并更新其内容。还有其他方法可以做到这一点;例如,我们可以在 DIV 上放置一个 CSS 类,并以这种方式进行搜索。无论哪种方式,只要我们能容易地找到元素,我们就能容易地更新它!
现在让我们更新 SEWP 脚本来更新 CEWP。变化很小,但应该会产生很大的影响。用以下代码更新您的脚本;唯一的变化是在success
函数中,用一些新的 jQuery 代码替换了警告:
<script type="text/javascript">
$(function() {
$.ajax({
url: "/apress/_api/web/lists/GetByTitle('Demo List')",
type: "GET",
headers: {
"accept": "application/json;odata=verbose"
},
}).success(function(data) {
$("#divHelloWorld").html(data.d.Title + " : " + data.d.Created);
});
});
</script>
这一新行只是搜索一个 ID 为"divHelloWorld"
的 HTML 元素。#
符号用于指示 jQuery 我们正在寻找一个 ID,而不是其他属性。用这些更改更新 SEWP,点击页面上的保存,将导致 CEWP 的 HTML 被更新,如图 3-11 所示。我们在结果中显示创建的日期;您的日期将不同于示例中显示的日期。
图 3-11。
Content Editor Web Part has been updated via the Script Editor Web Part
如果您的眼睛一直盯着 CEWP,您可以在屏幕上看到“Hello World”消息,然后它会更新为列表信息。这是因为我们正在使用 jQuery document.ready 函数,该函数在页面(文档)加载之前不会触发。如果你第一次没有看到,只需点击浏览器中的刷新按钮就可以再次看到。在现实世界中,您的 HTML 可能只是空的,以避免这种类型的可见变化。
不是一刀切的解决方案
CEWP 和 SEWP 是将自定义 HTML 和脚本注入页面的快捷方式。此时,你可能会想:我还需要什么?我现在就可以开始构建定制解决方案!当然,这两个 web 部件给了你一个很好的机会为你的用户构建解决方案,它们很容易使用,并且它们可以很好地协同工作。但是,对于更复杂的定制开发来说,这种解决方案不一定是一个很好的选择。
随着您的开发工作的进展,不仅在本书中,而且在您自己的工作中,您可能会发现解决方案需求变得更大、更复杂。您可能会发现需要多个 JavaScript 文件、自定义样式表,甚至可能需要多个 HTML 文件。这种情况会使 CEWP 和 SEWP 的使用变得非常难以控制和管理。此外,您可能会发现需要在多个页面上使用相同的功能。不得不将多个 web 部件放在多个页面上并将它们连接起来是一个挑战。这也为其他用户修改您的 HTML 和 JavaScript 打开了大门。请记住,任何拥有编辑 web 部件权限级别的人都可以编辑这些代码,这可能是一件非常糟糕的事情。
这种解决方案可能非常有效,但应该谨慎使用。对于执行少量工作的简单一次性脚本,或者显示有限数据量的简单 HTML,这是一个很好的解决方案。由于这是一个快速的解决方案,它非常适合测试一些 HTML 和脚本,以确保它们能够正常工作。无论您决定使用这种方法,请花点时间考虑一下,对于您的需求和您的用户来说,这是否是最佳选择。
摘要
在本章中,我们探讨了内容编辑器 Web 部件及其新的对应部件,脚本编辑器 Web 部件。我们研究了如何使用这些 web 部件在页面上放置定制的 HTML 和 JavaScript,以及这样做有多容易。您了解了如何通过 jQuery 将 AJAX 调用连接到 REST API 并检索关于列表的数据。最后,我们看了如何将两个 web 部件结合成一个解决方案。
在下一章中,我们将继续使用我们目前所学的知识来构建定制解决方案。我们将看看如何将这种开发转移到更易维护的结构中,并接触一些更高级的脚本。我们还将扩展 REST API 调用,以及 JavaScript 对象模型调用。
四、使用 HTML 和 JavaScript 构建自定义 Web 部件
与脚本编辑器 Web 部件相结合的内容编辑器 Web 部件允许您在自己的环境中快速构建解决方案。虽然这种组合无疑为您提供了开发解决方案的选择,但它不是一个容易扩展或重用的解决方案。您可能会发现它适合您对简单的单页解决方案的需求,但是一旦您的需求变得更加复杂,您会发现该解决方案在许多方面都有局限性。幸运的是,你在前一章学到的东西可以扩展成更健壮的解决方案。
在本章中,你将学习如何使用 Etherson 方法构建健壮的、可重用的 web 部件。这种方法仍然适用于 HTML 和 JavaScript,扩展了上一章的内容。您将看到如何更好地组织您的代码,以及这种方法如何允许您处理您能想到的任何定制解决方案。
埃瑟森方法
在过去的几年里,我有幸在许多激动人心的 SharePoint 项目中担任顾问。此外,我还能与一些最有才华的人一起工作,他们每天都在鞭策我。其中一个人是迈克·埃瑟里格德。Mike 和我开发了一个面向公众的 SharePoint 2010 网站,该网站需要响应移动设备。它还需要连接到未集成到 SharePoint 中的外部数据库。迈克的解决方案是构建可以通过 JavaScript 调用的定制 WCF web 服务。这些服务随后与定制的 HTML 和 JavaScript 一起被部署到服务器上。HTML 是通过放置在每个页面上的 XML 查看器 Web 部件来使用的。
这个解决方案非常有效。它易于开发和快速部署。它允许我们轻松地将服务器上的数据集中在一起,并将其返回到我们的页面,并且可以轻松地从 SharePoint 服务器提供 HTML。这在 SharePoint 2010 中工作得很好,在 SharePoint 2013 中也会很好,但在 SharePoint Online 中不行,因为那里不能部署任何服务器端代码。幸运的是,由于微软扩展了 JavaScript 对象模型和 REST API,该解决方案可以被调整以允许服务器之外的完整开发生命周期——于是 Etherson 方法诞生了。
Etherson 方法由以下组件组成:
- 文档库
- 文件夹
- 内容编辑器 Web 部件
- HTML、JavaScript 和 CSS
如您所见,该解决方案只需要几个组件就能产生巨大影响。乍一看,您可能会想,如何用这么简单的一组项目构建健壮的解决方案呢?这种方法的真正强大之处在于它的简单性以及 JavaScript 对象模型和 REST API 的强大功能。让我们详细看看每个组件。
文档库
这种方法的核心是一个文档库。该库将作为自定义 web 部件中使用的所有代码的主存储库。所有代码都将存储在该库中,每个 web 部件都有一个文件夹。如果符合您的需要,您可以使用多个库。例如,您可以在网站集的根目录下有一个库,用于您的所有子网站。您可以更细化,在每个子网站中放置一个仅用于该网站的库。您可以非常灵活地构造它,因为它只是一个放置代码的地方。
设置库需要以下步骤:
Create a new document library. Turn off search indexing. Turn on versioning. Place unique permissions on the library.
首先,我们将简单地创建一个现成的文档库,并将其命名为 Webparts,如图 4-1 所示。
图 4-1。
A new out-of-the-box document library for our code
这没什么特别的:我们只是通过设置菜单使用添加应用选项并选择文档库来添加它。接下来,我们将确保搜索引擎不会索引这个库。这样做的原因是该库将用于存储代码。普通用户没有必要看到这段代码,因为它是用来呈现自定义 web 部件的;因此,让它出现在搜索结果中会混淆用户的搜索体验。关闭搜索索引将确保代码文件不出现在搜索结果中。从功能区进入库设置,选择高级设置,如图 4-2 所示。
图 4-2。
Accessing the Advanced Settings page in the Library Settings
在“高级设置”页面上,您会发现文档库有许多选项。在页面中间寻找搜索标题。只有两个选项:允许或不允许项目出现在搜索结果中。点击否,如图 4-3 所示。
图 4-3。
Turning off the search indexing for the document library
滚动到页面底部,然后单击确定保存您的更改。您将返回到设置页面,在这里您可以继续进行版本控制。版本控制很重要,因为它允许轻松回滚代码。如果您需要实现对现有代码的更改,这可以让您安心。例如,假设您已经开发了一个满足当前业务需求的解决方案,并且一切都运行良好。你被要求做一个大的改变并开发新的代码来满足需求。你测试你的代码,一切看起来都很好。您上传了更改——用户立即开始抱怨出了问题!你忘记了在不同的浏览器中测试,你的代码对每个使用 Chrome 的人来说都是错误的。
如果打开了版本控制,只需转到文档库并恢复以前的代码文件。就这样,用户看到了之前的代码,至少一切又正常了。正如您所看到的,拥有快速、轻松地回滚代码更改的能力在开发过程中的某个时刻会非常有帮助。
要打开版本控制,点击版本控制设置链接,如图 4-4 所示。
图 4-4。
Accessing the Versioning Settings for the document library
进入版本设置页面后,点击文档版本历史标题下的创建主要版本选项,如图 4-5 所示。您还可以创建主要版本和次要版本;然而,对于这本书,我们将保持简单,只使用主要版本。
图 4-5。
Turning on Create Major Versions in the document library
滚动到页面底部,单击确定保存更改。您将返回到设置页面,在这里您可以转到权限。
Note
根据您创建的网站类型,您可能会发现版本控制已经打开。例如,打开了发布基础结构的发布门户或团队站点已经打开了版本控制。在任一情况下,打开“版本控制设置”页面以确保它已打开。
最后,您必须通过应用独有权限来保护文档库。我们希望保护这个库,以控制谁可以添加或修改其中的代码。用户需要具有读取权限,以便可以将代码加载到 web 部件中;但是您只希望开发人员拥有 contribute 访问权限。这一点至关重要,因为您只希望一小部分人能够上传代码并有可能删除代码。要修改权限,点击“该文档库的权限”链接,如图 4-6 所示。
图 4-6。
Accessing the permissions settings for the document library
单击此链接会将您带到文档库的权限页面。要应用独有权限,点击功能区中的停止继承权限按钮,如图 4-7 所示。
图 4-7。
The Permissions tab in the Ribbon for the document library
通常,SharePoint 中的所有项目都继承其父项目的权限。当您创建此新文档库时,默认情况下,它拥有所在网站的权限。如果您选择停止继承权限,SharePoint 确实希望确保这是您的意图,并通过确认对话框提示您,如图 4-8 所示。
图 4-8。
Confirmation dialog when breaking permissions
单击“确定”确认更改,您将返回到“权限”页面。你会注意到功能区现在有了一些额外的选项,最明显的是 Grant Permissions 按钮,如图 4-9 所示。您将使用“授予权限”选项在中添加权限。
图 4-9。
Grant permissions using the Grant Permissions button in the Ribbon Note
一旦停止继承权限,您应该删除列表中当前的所有用户和组。即使您破坏了权限,以前的用户和组仍将保留,除非手动删除。
点击“授予权限”按钮会打开“共享”对话框,在这里您可以选择要授予谁权限,如图 4-10 所示。对话框中的第一个文本框允许您指定哪些用户或组可以访问该库。在这一步中,您希望授予每个人读权限。当您在文本框中键入内容时,SharePoint 会提供一个自动完成的人员和组列表供您选择。键入 Everyone,然后从建议列表中选择它。
图 4-10。
Granting Read access to all users
您可以单击“显示选项”链接来展开对话框,并查看可用的其他选项。您可能希望取消选中发送电子邮件邀请选项,尤其是在添加大型群组时。在这种情况下,它会向有权访问 SharePoint 的每个人发送一封电子邮件,这可能不是一个好主意。另一个选项是“选择权限级别”下拉列表;选择“读取”,因为我们希望每个人都拥有特定级别的访问权限。
单击共享按钮保存自定义权限。此时,所有用户都拥有对库的读取权限。对所有开发人员重复这些步骤,并授予他们 Contribute 权限级别。通过这种方式,这些用户可以上传新代码并修改库中现有的代码。
Note
如果您使用的是只有少数人访问的开发环境或站点,则可以跳过应用独有权限。这在 QA 或生产环境中是至关重要的,但是在这里开发环境可以不那么严格。
既然已经创建并配置了文档库,我们可以继续处理其他组件,如文件夹。除了为您的解决方案编写代码之外,使用 Etherson 方法建立文档库是最大的任务。相比之下,其余的组件似乎很简单。
文件夹
使用这种方法,每个自定义 web 部件都有一个文件夹,其中包含该 web 部件所需的所有文件。您也可以有一个集中的文件夹,其中包含所有 web 部件共享的脚本。例如,如果您想在一个文件夹中存储一份 jQuery,您可以避免通过母版页添加它,而只让每个 web 部件从中心文件夹引用它。您可能还有一些工具脚本,用于执行多个 web 部件的通用功能。无论需要什么,一个中心文件夹可能会派上用场。
导航到您在上一节中创建的 web 部件文档库。使用菜单中的新建命令,从上下文菜单中选择新建文件夹,如图 4-11 所示。
图 4-11。
Creating a new folder
创建一个新文件夹并将其命名为 Simple Example。我们将使用这个文件夹来存放第一个示例的 HTML 和 JavaScript。此时,Webparts 文档库中应该只有一个文件夹。随着阅读本书的深入,您将添加更多文件夹;但目前来看,这是一个好的开始。
HTML、JavaScript 和 CSS
现在我们有了一个文档库和一个存放代码的文件夹,让我们把 HTML 文件和 JavaScript 文件放在一起。在本节中,我们将使用 Visual Studio 编写代码并构建 HTML 和 JavaScript 文件。如果你在第一章安装了 Visual Studio 速成版,你就一切就绪了。你可以使用任何你喜欢的代码编辑器——甚至记事本!启动 Visual Studio,点击【文件】➤新建➤文件,新建一个文件,如图 4-12 所示。
图 4-12。
Creating a new file in Visual Studio
这将打开一个新的对话框,您可以在其中选择想要创建的文件类型。这里有很多选择,但我们要找的那个就在前面。从列表中点击 HTML 页面,然后点击打开,如图 4-13 所示。
图 4-13。
Creating a new HTML page from the New File dialog
单击“打开”后,将会创建并显示一个新的 HTML 文件。如果您是 Visual Studio 的新手,您将很难体会到代码编辑器带给您的效率。新创建的 HTML 文件已经为你生成了一些代码,如图 4-14 所示。
图 4-14。
Newly created HTML file with code
如果您要保存此文件并将其加载到 SharePoint 中,它不会显示任何内容,因为在浏览器中没有内容呈现给用户。然而,它是一个完全有效的 HTML 文件!虽然这并没有给人留下太深刻的印象,但是您会发现 Visual Studio 在您编写代码时会提供很多类似的帮助。
对于这个例子,我们将从使用第三章中的代码开始,除了我们将代码分成一个 HTML 文件和一个 JavaScript 文件。首先将下面一行添加到新的 HTML 页面中:
<div id="divHelloWorld">Hello World!</div>
将这条线放在两个<body>
标签之间,如图 4-15 所示。
图 4-15。
New HTML file with code from the previous chapter
现在让我们创建一个 JavaScript 文件来托管我们的脚本。像以前一样,从菜单中选择文件➤新➤文件。当“新建文件”对话框打开时,您会注意到没有列出用于创建新 JavaScript 文件的选项。为此,我们需要从左侧导航栏中选择“Web ”,以查看网站的所有文件模板。滚动到所列模板的底部,你会找到 JavaScript 文件模板,如图 4-16 所示。
图 4-16。
JavaScript file option in the New File dialog
一旦创建了新的 JavaScript 文件,您会注意到它看起来与您之前创建的 HTML 文件非常不同。实际上是完全空白的,如图 4-17 所示。
图 4-17。
New JavaScript file created in Visual Studio
与 HTML 文件一样,您将使用第三章示例中的相同代码。将以下代码放入刚刚创建的新 JavaScript 文件中:
$(function() {
$.ajax({
url: "/apress/_api/web/lists/GetByTitle('Demo List')",
type: "GET",
headers: {
"accept": "application/json;odata=verbose"
},
}).success(function(data) {
$("#divHelloWorld").html(data.d.Title + " : " + data.d.Created);
});
});
Note
在本书的所有代码示例中,URL 都是针对我的环境的,其中包括一个根网站集和一个名为 Apress 的子网站,我的所有代码都驻留在那里。因此,我的所有 URL 将显示为“/apress/…..”。您应该相应地更新您的代码部署的 URL,以及您的站点的结构。
你会注意到不像在第三章的例子中,你没有开始和结束<script></script>
标签来包装你的代码。由于代码是由扩展名为.js
的 JavaScript 文件提供的,浏览器不需要被告知这是一个带有这些标签的脚本,如图 4-18 所示。
图 4-18。
JavaScript code in Visual Studio
现在这两个文件都已创建,您将保存它们。将这些文件保存在计算机上您喜欢的任何位置。将 HTML 文件命名为 SimpleExample.js,将 JavaScript 文件命名为 SimpleExample.js。保存文件后,我们现在需要将 JavaScript 文件连接到 HTML 文件,以便代码能够正确运行。为此,我们需要向 HTML 文件添加一个 JavaScript 引用,类似于下面的代码行:
<script type="text/javascript" src="/apress/webparts/Simple Example/SimpleExample.js"></script>
在我的环境中,我有一个名为 Apress 的子网站,这是我的 web 部件文档库所在的位置。这个脚本引用以一个/
开头,意思是使用站点的根 URL。接下来,我们放置子网站名称、文档库名称、文件夹名称,最后是脚本文件名。根据您设置环境的方式,您可能不需要子网站引用,或者它的名称可能有所不同。
将脚本引用放在 HTML 文件的<head>
中,如图 4-19 所示。
图 4-19。
The HTML file with the script reference added in
用新的脚本引用保存SimpleExample.html
文件。接下来,您将把这两个文件上传到您在文档库中创建的简单示例文件夹中,如图 4-20 所示。
图 4-20。
HTML and JavaScript files uploaded to the Simple Example folder
此时,使用 Etherson 方法,您已经创建并上传了重新创建第三章中的示例所需的两个文件。如果您有一个更复杂的解决方案,您可以想象这个文件夹包含几个 JavaScript 文件、CSS 文件,可能还有多个 HTML 文件。这完全取决于你的需求是复杂还是简单。接下来,让我们看看如何使用内容编辑器 Web 部件来使用这些文件。
内容编辑器 Web 部件
现在我们已经有了呈现某些内容所需的文件,让我们在页面上放置一个 CEWP 并使用它们。我们将使用第三章示例中的相同站点和页面。如果您的页面上还有 CEWP 和 SEWPs,请继续删除它们,使页面为空。将页面置于编辑模式,然后在页面上插入一个新的 CEWP。保存页面—我们稍后将回到此 web 部件。
导航回 web 部件文档库并打开简单示例文件夹。右键单击SimpleExample.html
文件,从菜单中选择复制链接位置,如图 4-21 所示。
图 4-21。
Copying the location of the HTML file
根据您使用的浏览器,此选项的标题可能会有所不同。例如,如果使用 Internet Explorer,您可以选择复制快捷方式。无论您使用哪种浏览器,右键单击都会显示将 URL 复制到文件的选项。一旦您复制了它,您就可以导航回带有 CEWP 的页面。
将页面置于编辑模式,然后将 CEWP 置于编辑模式。就像在第三章中一样,在 CEWP 工具窗格中,第一个属性是标题内容链接。将您复制的网址粘贴到该文本框中,如图 4-22 所示。
图 4-22。
The URL to the SimpleExample.html file in the CEWP Content Link property
与第三章中的例子不同,由于这个 HTML 包含了对 JavaScript 文件的引用,我们需要做的就是将文件的 URL 放入内容链接属性中。当 HTML 文件加载时,JavaScript 文件也会加载。本例中不需要脚本编辑器 Web 部件。单击确定,然后保存页面。当它重新加载时,HTML 文件将呈现如图 4-23 所示。
图 4-23。
SimpleExample.html file rendered in the Content Editor Web Part
此时,您可能想知道为什么要执行如此多的设置和配置,因为使用 CEWP 和 SEWP 可以更快地产生结果。随着实际解决方案越来越多,使用 Etherson 方法的好处变得越来越明显。例如,假设您需要开发一个定制的解决方案,该解决方案聚合用户正在跟踪的任务和文档,并将它们放入一个链接列表中,供用户单击以查看项目。它将部署在网站集中每个部门子网站的主页上。使用 CEWP/SEWP 解决方案,您不仅需要将代码粘贴到每个页面上,如果以后需要对解决方案进行更改,您还需要更新该代码的所有实例。这可能是一个相当大的挑战。使用 Etherson 方法,您仍然在每个站点中添加一个 CEWP,但是只引用一组代码文件。如果需要更改,您只需要在一个地方更新代码。这更容易管理。
这种方法的另一个好处是 CEWP 可以为您执行一些错误处理。如果由于某种原因 HTML 文件不再可用(可能被移动或删除),CEWP 可以向用户显示一条友好的消息。为了演示这一点,让我们从 CEWP 中删除内容链接,然后单击 Apply 按钮。web 部件中的内容将被删除,留给您一个空白的 CEWP,如图 4-24 所示。
图 4-24。
Content Editor Web Part after the Content Link has been removed
此时,您已经基本上将 CEWP 恢复到了添加时的初始状态。单击 web 部件中间的“单击此处添加新内容”链接。您会注意到 web 部件中出现了一个光标,您可以在其中直接键入文本。在这里,您将添加文本抱歉,我们遇到了一个错误。接下来,你将把SimpleExample.html
的链接添加回内容链接属性,如图 4-25 所示。
图 4-25。
Plain text and Content Link URL placed in the Content Editor Web Part
单击确定,然后保存页面。您会注意到 web 部件看起来与您仅使用内容链接属性时完全一样。不显示纯文本消息,而是呈现 HTML 页面中的内容。CEWP 将总是尝试使用添加到内容链接属性的任何 URL,而不是显示它可能有的任何纯文本。现在,让我们从简单示例文件夹中删除 HTML 和 JavaScript 文件,如图 4-26 所示。
图 4-26。
HTML and JavaScript files deleted from the Simple Example folder
一旦 HTML 文件被删除,CEWP 将不再能够加载它;它不见了。通过在 web 部件中提供纯文本,它现在将显示您加载的错误消息,如图 4-27 所示。
图 4-27。
The plain-text message displayed when the web part could not load the HTML file
您可能希望对开发工作中的错误进行编码,但是这种内置于 CEWP 中的回退是一个很好的选择,以防出现其他错误。你应该总是以这种方式提供一些内容。在许多情况下,CEWP 无法访问您的 HTML 文件,例如:
- 文件从文件夹中删除(就像我们刚才做的那样)
- 出现网络错误
- 您在内容链接属性中手动键入 URL,并且拼错了文件名
为了以防万一,最好还是利用这个功能。现在让我们更新前一个例子中的代码,不仅仅是显示一个列表名称。
使用列表数据
前面的例子向您介绍了 Etherson 方法。此时,您已经有了一个 HTML 文件和一个 JavaScript 文件,它们提取并显示关于列表的数据。不算太坏,但显然这不是你在现实世界的解决方案中会做的事情。因此,让我们扩展这段代码,从列表中提取一些数据并显示给用户。如果你还没有,将一些数据放入你的演示列表,如图 4-28 所示。
图 4-28。
The Demo List with a few items populated in it
此时,列表中的项目并不重要;我们只是需要一些数据来提取和显示。您可以随意摆放物品;我们要把他们都抓起来。现在我们在列表中有了更多的数据,我们将更新前面的SimpleExample.js
文件,以便我们请求列表项,而不是关于列表的数据。用以下内容更新您的代码:
$(function () {
$.ajax({
url: "/apress/_api/web/lists/GetByTitle('Demo List')/items",
type: "GET",
headers: {
"accept": "application/json;odata=verbose"
},
}).success(function (data) {
var listItemInfo = ";
$.each(data.d.results, function (key, value) {
listItemInfo += "<strong>Title: </strong>" + value.Title + " <strong>Description: </strong>" + value.Description + "<br />";
});
$("#divHelloWorld").html(listItemInfo);
});
});
它看起来与前面的代码相似,但是添加了一些关键的东西。首先,AJAX 调用中的 URL 已经更新,在末尾包含了/items
:
url: "/apress/_api/web/lists/GetByTitle('Demo List')/items"
我们仍然调用同一个列表,但是我们需要让 REST API 知道我们这次想要列表中的项目。通过提供/items
而不提供其他信息,我们告诉 API 返回列表中的所有项目。
Note
除非你确信你的列表中不会有太多的数据,否则你不应该在任何数据调用中请求所有的条目。您可以通过提供限制器或 CAML 查询来提供限制返回数据的方法,该查询将只返回您正在寻找的项目。我们将在本书后面更深入地探讨这些选项。
在 JavaScript 的 success 函数中,我们将遍历返回的所有数据:
var listItemInfo = ";
$.each(data.d.results, function (key, value) {
listItemInfo += "<strong>Title: </strong>" + value.Title + " <strong>Description: </strong>" + value.Description + "<br />";
});
我们从一个名为listItemInfo
的新空变量开始。这个变量用于保存我们在循环 API 调用结果时构建的所有 HTML。接下来,我们使用一个内置的 jQuery 函数each
来遍历结果。通过使用$.each
,我们说对于data.d.results
对象中的每一项,执行下面的函数。在您的定制解决方案中,您会经常用到这个函数,因为遍历列表项是非常常见的。
就像我们简单显示列表的属性和数据的例子一样,我们看到了熟悉的data.d
对象。但是,这次我们有了一个新的属性,叫做results
。当我们查询该列表的数据时,我们需要的所有信息都在d
属性下找到;比如说,d.Title
。当你请求列表项时,所有的数据都会在results
属性中找到。
在each
函数中,我们将listItemInfo
变量设置为获取当前列表项标题和描述的 HTML。使用+=
语法,我们将变量设置为当前值加上新值。这是一个简单的添加到 HTML 的方法,如果有来自前面的循环的话。循环完成后,我们将 HTML 设置为 Hello World DIV:
$("#divHelloWorld").html(listItemInfo);
图 4-29 显示了 Visual Studio 中的完整文件。
图 4-29。
The updated SimpleExample.js file in Visual Studio
用更新的代码保存文件。在将它上传到文档库之前,让我们快速更改一下 CEWP 的标题,这样这个例子就更加真实了。导航回放置 web 部件的页面,并将其置于编辑模式。展开外观手风琴并更新标题属性,如图 4-30 所示。
图 4-30。
Updating the title of the Content Editor Web Part
单击“确定”,然后保存该页面。将更新后的SimpleExample.js
文件上传到 Webparts 文档库中的简单示例文件夹。将出现一个对话框,询问您是否要替换当前文档;单击确定。埃瑟森方法的优点仍然有效;因为您在文档库中打开了版本控制,所以您可以轻松地替换文件。如果弄错了,可以恢复之前的版本!导航回你的页面,你会看到更新后的代码抓取列表项并显示出来,如图 4-31 所示。
图 4-31。
Updated JavaScript fetching list items
结合更新的标题,这个 CEWP 现在更像一个现实世界的解决方案!当然,我们在这里真正做的只是重新创建一个现成的列表视图 Web 部件,但是它应该已经展示了使用 HTML 和 JavaScript 开始处理 SharePoint 数据是多么容易。接下来,让我们继续看看 Etherson 方法的一些好处。
使用版本控制回滚更改
在本章的前面,当您创建文档库来保存自定义代码时,您启用了版本控制。在开发过程中的某个时刻,你会在编写代码时犯错误,而它会通过测试。这发生在我们所有人身上,是不可避免的。幸运的是,打开版本控制后,如果发生这种情况,您可以快速回滚更改。您可能会发现,仅仅因为用户对您代码的最新版本不满意,您就需要回滚。不管什么原因,都是又快又容易。
当您上传新版本的SimpleExample.js
文件时,系统会询问您是否要替换现有版本。通过单击“确定”,您在库中创建了该文件的新版本。由于版本控制是打开的,您只需点击几下就可以恢复以前的版本。导航到简单示例文件夹,点击SimpleExample.js
文件的菜单,如图 4-32 所示。
图 4-32。
Accessing the Version History on a file
菜单打开后,您需要访问二级菜单,在那里您可以找到版本历史选项。点击这个选项,你会看到一个对话框,显示文件的所有版本。此处显示的版本数量取决于您设置库的方式。例如,如果您将版本数量限制为五个,您将只能在这里看到五个以前的版本。选择您想要的版本;在这种情况下,它将是列表中的第二个版本。版本从上传日期开始按升序排列。使用菜单选项,从菜单中选择恢复,如图 4-33 所示。
图 4-33。
Restoring a previous version on the file
当您单击“还原”选项时,会出现一个确认对话框,提示您“您将要用所选版本替换当前版本”单击确定确认恢复,屏幕将刷新。新版本被添加到列表中。使用 CEWP 导航回您的页面并刷新页面。您可能需要通过按键盘上的 Ctrl+F5 来执行硬刷新;这将指示浏览器从服务器加载 JavaScript 文件的新副本。结果应该是加载列表数据的前一个脚本,如图 4-34 所示。
图 4-34。
Restored file being displayed in the Content Editor Web Part
这里需要注意的一点是,虽然脚本内容已经更新,但是 web 部件的标题保持不变。由于这是拼图的两个独立部分,恢复脚本文件对 web 部件本身没有任何影响!
使用 Firebug(开发人员工具)调试
当你为任何东西写代码时,不管是工具、语言还是环境,你都需要能够调试它。简单地说,停止代码运行,一行一行地查看有什么数据进来,以及代码是如何处理的。由于 Etherson 方法利用 HTML 和 JavaScript,您可以使用 Firebug 或开发工具在浏览器中轻松调试代码。正如在第一章中提到的,我们将使用 Firebug——Firefox 的一个插件。您可以在任何浏览器中使用内置的开发工具。要启动这些工具,只需按键盘上的 F12 键,工具就会在屏幕下方启动,如图 4-35 所示。
图 4-35。
Firebug console window in Firefox
如果尚未打开,请在 Firebug 中选择脚本选项卡。如果这是您第一次启动 Firebug,您可能需要通过下拉选项卡上的箭头并在选项中选择 Enabled 来启用脚本调试。此选项卡允许您检查正在为页面加载的所有脚本。左侧窗格显示您正在查看的当前脚本,右侧窗格显示任何已加载的 JavaScript 对象。这些对象位于右窗格的“监视”选项卡下。让我们使用左窗格正上方的下拉列表打开我们的SimpleExample.js
脚本,如图 4-36 所示。
图 4-36。
Locating the SimpleExample.js file in Firebug
该列表包含为页面加载的所有 JavaScript 文件。向下滚动直到找到SimpleExample.js
,然后点击它。您会注意到 Firebug 提供了加载脚本的路径,如果您需要在您的环境中找到它,这非常方便。点击文件将其载入左窗格,如图 4-37 所示。
图 4-37。
SimpleExample.js file loaded in Firebug
您会注意到脚本文件的左边提供了行号。如果出现错误,这些非常方便,因为浏览器会让您知道错误发生在哪一行。您可以通过单击其中一个行号来设置断点。断点只是代码将停止运行的位置,以便您可以检查正在发生的事情。您可以设置多个断点;事实上,您可以在每行上设置一个。设置断点时,行号旁边会出现一个红点,如图 4-38 所示。
图 4-38。
Placing a breakpoint in the JavaScript file
一旦设置了断点,就可以重新加载页面,加载脚本时,一旦命中断点就会停止运行。如图 4-39 所示,当红点内有一个黄色箭头并且该线被高亮显示时,您可以看到这一点。
图 4-39。
Breakpoint hit while debugging SimpleExample.js in Firebug
既然脚本已经停止,您可以在 Watch 选项卡的右窗格中查看脚本正在使用的对象。例如,在这个success
函数中,我们声明了一个名为data
的变量,它是结果所在的位置。“观察”选项卡现在有了一个我们可以检查的data
对象。点击data
旁边的+图标,可以展开查看其属性。继续点击+图标直到看到结果,如图 4-40 所示。
图 4-40。
Data object that is sent back from the REST API
我们知道从我们的列表中返回的项目的数量,我们可以在results
对象中看到这些。它们由它们在列表中的索引或位置来标记,并且索引总是从 0 开始。您可以进一步展开项目并查看它们的属性。单击 0 索引处项目旁边的+图标。您可以看到 SharePoint 返回了大量关于列表项的数据。这不仅仅适用于列表项——几乎任何你在 SharePoint 中请求的数据都会附带大量信息。向下滚动浏览项目中的所有属性,您会发现我们通过脚本显示的标题和描述属性,如图 4-41 所示。
图 4-41。
Expanding the first list item to inspect its properties
当您开发定制解决方案时,调试将证明对您非常有用,因为您可以检查所有返回的数据,以确保它正是您所需要的。它也非常方便,因为有时数据不在你想的地方。由于脚本在此处停止,您有几种方法可以再次启动它。按下键盘上的 F10 键会让脚本一次向前移动一行。这非常有帮助,因为您可以看到每一行执行时发生了什么。一些代码块将一起执行;例如,如果您使用 F10 来单步执行代码,$.each
循环中的所有代码将作为一行。您可以很容易地在循环中放置另一个断点来停止它。
另一种选择是使用箭头图标,如图 4-42 所示。
图 4-42。
Continue to run the script by clicking the Play icon
这个图标只是告诉调试器继续并恢复处理脚本。如果没有其他断点,它将完全处理完脚本。按钮和文件位置在不同的开发工具之间会有很大的不同。你可以在图 4-43 和 4-44 中看到 Chrome 和 Internet Explorer 开发者工具。
图 4-44。
Developer tools in Internet Explorer 11
图 4-43。
Developer tools in Chrome
无论您使用哪种浏览器,或者开发人员工具看起来有多奇怪,请放心,它们都执行相同的功能。您可以检查 HTML,检查和更改 CSS,最重要的是,调试您的 JavaScript。随着您沿着使用 HTML 和 JavaScript 定制解决方案的道路前进,您会发现这些工具一如既往地重要。
摘要
在本章中,您了解了使用 HTML 和 JavaScript 构建定制解决方案的 Etherson 方法。我们讲述了各种组件,您看到了如何配置每个组件,并了解了它们如何作为一个单元一起工作。您构建了几个示例解决方案,并看到了在上传新文件后如何轻松地恢复代码。在您阅读本书的过程中,我们将继续在许多例子中使用这种方法,您将学习如何使用 CSS 扩展它。
在下一章,我们将探索使用 JSLink 来设计和增强列表视图 Web 部件。JSLink 是一种令人兴奋的新方法,可以为现成的 SharePoint 带来更多功能。它还可以与 JavaScript 结合,创建非常独特的解决方案来满足您的业务需求。
五、使用 JSLink 设置列表 Web 部件的样式
在 SharePoint 中,您可以将许多不同的现成 web 部件放在页面上。这些提供了列表、搜索、日历、外部数据等视图。其中最流行和使用最广泛的是列表视图 Web 部件。创建自定义列表,然后通过这些 web 部件向用户显示其内容是很常见的。这些 web 部件允许您快速、轻松地向用户公开数据,并且大多数用户都非常熟悉它们。
列表视图 Web 部件提供了多种不同的方式来自定义所显示的数据。这些选项包括:
- 选择要显示的列
- 整理
- 过滤
- 分组
这是为您提供的现成的大量功能。在很多情况下,这些选项提供了您定制数据所需的一切;然而,如果您需要真正定制的东西,这些选项是不够的。设想一个场景,业务需求是根据列表中某个项目的状态显示图像。也许有一个状态为“准时”和“迟到”的列。对于每种状态,您需要根据该状态显示笑脸或皱眉。对于现成的列表视图 Web 部件,您必须使用一种称为 XSLT 的呈现技术。现在,您可以利用 JSLink 在列表视图 Web 部件中执行这种数据操作。在这一章中,我们将探索 JSLink 是如何工作的,以及你可以用它完成什么。
JSLink 和一个简单的例子
在 SharePoint 2013 之前,如果您想要在列表视图 Web 部件上执行任何类型的样式,您必须使用 XSLT。XSLT 代表可扩展样式表语言转换,它用于样式化和呈现 XML 内容。不仅很难说,而且更难共事。您很难找到一个不仅知道如何有效地编写 XSLT,而且愿意接触它的开发人员。这很难写,也很难理解。典型的 XSLT 文件如下所示:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="``http://www.w3.org/1999/XSL/Transform
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Description</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="description"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
微软知道使用 XSLT 的挑战,需要为开发人员提供开发这类解决方案的更好方法。JSLink 就是从这种需求中诞生的,它是一个完美的替代品。JSLink 的妙处在于它基本上是 JavaScript!任何熟练编写 JavaScript 的人都可以快速编写 JSLink 代码。此外,JSLink 可以与其他 JavaScript 文件结合,创建非常健壮的解决方案。
JSLink 基本上是 web 部件上的一个属性,为 JavaScript 文件提供一个或多个位置。如果使用文件的有效 URL 设置此属性,则在呈现 web 部件时,它会选取该文件并使用该文件将内容呈现给浏览器。由于都是 JavaScript,所有的渲染都由浏览器处理,因此减轻了 SharePoint 服务器的负担,因为它只负责返回数据。这提供了不影响服务器性能的简单定制。
让我们看一个使用 JSLink 来设置 web 部件样式的简单例子。我们将利用 Webparts 文档库和演示列表来扩展我们在前面章节中构建的内容。导航到放置内容编辑器 Web 部件的页面,然后将其删除,这样您就有了一个干净的页面。使用功能区为演示列表插入一个列表视图 Web 部件,如图 5-1 所示。
图 5-1。
Adding the List View Web Part for the Demo List
如果尚未高亮显示,请点按“应用”类别。演示列表应该在列表的顶部,这取决于你的站点中有多少列表。将 web 部件插入页面并保存。结果视图将简单地显示列表项,如图 5-2 所示。
图 5-2。
The out-of-the-box List View Web Part for the Demo List
我们需要创建一个文件夹来保存这个例子的脚本。导航回 Webparts 文档库,创建一个名为 JSLink 的新文件夹,如图 5-3 所示。对于这一章,我们将把所有的脚本放在这个文件夹中;但是,在生产环境中,您可能希望遵循 Etherson 方法,并为使用 JSLink 设计样式的每个 web 部件创建一个文件夹。
图 5-3。
Adding a new folder for JSLink in the Webparts document library
打开 Visual Studio,通过转到文件➤新➤文件创建一个新文件。选择 Web 类别,然后从选项中选择“JavaScript 文件”。我们将从一个非常基本的脚本开始,该脚本将获取 web 部件中的每个项目并对其进行样式化。将以下代码放入文件中:
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
function overrideTemplate(ctx) {
return "<div style='font-size:18px;border:solid 1px Silver;margin-bottom:6px;padding:4px;width:200px;'>"
+ ctx.CurrentItem.Title
+ "</div>";
}
这个脚本是我们能够制作的最精简的 JSLink JavaScript 文件;然而,它将对这些脚本如何工作提供一个很好的介绍。首先,你会注意到我们声明了一个没有名字的函数。这个函数作为脚本的入口点,并且是所有设置发生的地方。接下来,我们用下面一行声明一个新变量:
var overrideContext = {};
这是一个简单的 JavaScript 变量,我们将其命名为overrideContext
,并使用{}
语法将其设置为一个空对象。这里需要注意的是,这个名字并没有什么魔力。我们可以称它为“myObject
”或“SomeCoolNewThing
”,或任何类似的名字。我们称之为overrideContext
,因为我们提供了默认样式的覆盖。接下来,我们用下面的代码行声明另一个名为Templates
的对象:
overrideContext.Templates = {};
这个对象用于保存对我们想要覆盖样式的所有不同模板的引用。例如,您可以添加Item
来覆盖整个列表项的样式,或者添加Field
来覆盖列表中单个列的样式。我们使用下面的代码行来实现这一点:
overrideContext.Templates.Item = overrideTemplate;
这一行表明我们想用另一个函数覆盖Item
模板,这个函数叫做overrideTemplate
。还是那句话,这个函数的名字没什么神奇的;它可以是任何东西。最后,我们用下面的代码行注册覆盖:
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
SPClientTemplates.TemplateManager.RegisterTemplateOverrides
是一个内置的 SharePoint 函数,将注册您的代码进行渲染。您传入您在开始时创建的基本对象。一旦注册了覆盖,最后一部分就是实际执行渲染的函数:
function overrideTemplate(ctx) {
return "<div style='font-size:18px;border:solid 1px Silver;margin-bottom:6px;padding:4px;width:200px;'>"
+ ctx.CurrentItem.Title
+ "</div>";
}
这个函数接受一个名为ctx
的参数。和这个脚本中的其他项目一样,这个名称没有任何意义。ctx
是列表上下文,将用于根据该函数中的内容呈现列表项。我们将保持简单,对于列表中的每一项,我们将返回一个 DIV 元素,其中包含列表项标题。我们可以使用ctx.CurrentItem.Title
访问标题。因为这个函数将为列表中的每一项触发,CurrentItem
就是循环中的当前列表项。DIV 有一些内联 CSS,因此自定义呈现非常突出。
保存该文件并将其命名为 JSLinkDivExample.js,然后将其上载到 Webparts 文档库中的 JSLink 文件夹。Visual Studio 中的完整文件如图 5-4 所示。
图 5-4。
JSLinkDivExample.js file in Visual Studio
文件上传后,我们需要获取文件的 URL。在前一章中,我们看到了如何右击文件并从上下文菜单中选择复制链接位置。也可以通过打开文件的菜单,从弹出的文本菜单中复制来获取 URL,如图 5-5 所示。
图 5-5。
Copying the URL of the JavaScript file from the menu
导航回放置列表视图 Web 部件的页面。将页面置于编辑模式,然后将列表视图 Web 部件也置于编辑模式。在 web 部件的工具窗格中,滚动到底部并展开“杂项”折叠面板。在这个面板的底部,你会发现 JSLink 属性,如图 5-6 所示。
图 5-6。
JSLink property in the web part tool pane
在内容编辑器 Web 部件中使用 URL 时,您只需粘贴 URL,SharePoint 会自动将其转换为相对路径 URL。也就是说,SharePoint 将从 URL 中剥离域,只留下定位文件所需的部分。例如,我的环境中的JSLinkDivExample.js
文件路径如下所示:
https://brandonatkinson.sharepoint.com/apress/Webparts/JSLink/JSLinkDivExample.js
如果将此内容粘贴到 JSLink 属性中并保存 web 部件,SharePoint 会将 URL 转换为以下内容:
/apress/Webparts/JSLink/JSLinkDivExample.js
通常,SharePoint 更喜欢它的 URL,因为 SharePoint 可以配置为提供来自多个域的内容。通过利用相对路径 URL(没有域的 URL),SharePoint 可以很容易地计算出内容的位置,无论它是从哪个域提供的。这对于内容编辑器 Web 部件非常有用,但是在与 JSLink 一起使用时会失败。
幸运的是,SharePoint 通过使用 URL 令牌提供了一种简单的补救方法。令牌提供了一种为 SharePoint 想要删除的 URL 部分传入占位符的方法。以下列表显示了一些较常见的令牌:
∼site
-当前站点的 URL∼sitecollection
-当前网站的网站集的 URL∼layouts
-_layouts/15
文件夹的 URL
使用这些令牌,可以将 URL 更新为以下内容:
∼sitecollection
/apress/Webparts/JSLink/JSLinkDivExample.js
或者
∼site/Webparts/JSLink/JSLinkDivExample.js
这两个新 URL 都可以使用,因为它们都指向同一个位置。因为我们的 web 部件文档库与放置 web 部件的页面位于同一站点,所以我们可以使用两者中较短的一个。在 JSLink 属性中输入这个 URL,如图 5-7 所示。
图 5-7。
URL to the JavaScript file using the URL token
单击确定并保存页面。当页面重新加载时,JSLinkDivExample.js
文件将被加载,列表项将基于其中的overrideTemplate
函数呈现。结果如图 5-8 所示。
图 5-8。
JSLink rendering of the Demo List items
如您所见,每个列表项都呈现在一个具有边框和更大文本的 DIV 中,就像 JavaScript 文件中的内联 CSS 一样。在我们的函数中,我们呈现的唯一一段数据是Title
属性,它显示在 DIV 中。这个简单的例子应该开始说明 JSLink 为设计列表视图 Web 部件样式提供的强大功能,以及开始构建健壮的自定义解决方案的一种方法。
使用项模板
前面的例子是用 JSLink 可以做什么的一个快速示例。然而,这远远不是一个现实的解决方案,它有一些问题。例如,标题和描述列的排序链接仍然存在,并显示在列表项下。显然,这不是您希望最终用户看到的样子。在这一节中,我们将更深入地探讨条目模板以及如何使用它。
使用项目模板时,您通常会设置列表视图 Web 部件的所有方面的样式。我的意思是,它通常看起来不再像列表视图。JSLink 提供了很多方法来帮助你实现这个目标。让我们首先使用下面的代码为列表视图的页眉和页脚提供一个模板:
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
overrideContext.Templates.Header = "<h2>Custom Header</h2>";
overrideContext.Templates.Footer = "<h3>Custom Footer</h3>";
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
这个示例与之前的完全相同,只是我们增加了两行:
overrideContext.Templates.Header = "<h2>Custom Header</h2>";
overrideContext.Templates.Footer = "<h3>Custom Footer</h3>";
通过使用这些行,我们告诉 SharePoint 我们希望使用提供的 HTML 覆盖默认的页眉和页脚。HTML 非常简单——它只返回一些包装在 H2 和 H3 标签中的文本。然而,结果很快显示了这些覆盖的力量,如图 5-9 所示。
图 5-9。
Custom header and footer being rendered on the List View Web Part
您可以通过提供返回页眉和页脚的函数来进一步扩展这一点,而不是在同一行中声明 HTML,如下所示:
overrideContext.Templates.Header = overrideHeader;
overrideContext.Templates.Footer = overrideFooter;
生成的函数如下所示:
function overrideHeader() {
return "<h2>Custom Header</h2>";
}
function overrideFooter() {
return "<h3>Custom Footer</h3>";
}
将这段代码放在它自己的函数中为增加功能打开了大门。您可以想象这样一个场景,您需要进行一个 web 服务调用来检索您想要在标题中显示的数据。这允许非常健壮的代码启动并执行任何可用的任务。您可以开始以这种方式创建非常丰富的用户体验。Visual Studio 中的完整代码如图 5-10 所示。
图 5-10。
Providing header and footer overrides via JavaScript functions
使用文件➤另存为以新名称保存此文件。将其命名为 JSLinkItemTemplate.js,上传到 Webparts 文档库中的 JSLink 文件夹。导航回列表视图 Web 部件,将其置于编辑模式,并将 JSLink 属性更新为以下内容:
∼site/Webparts/JSLink/JSLinkItemTemplate.js
web 部件应该使用新的 JSLink 文件。这个例子离真实世界的体验还很远。让我们用一些数据来更新演示列表,这些数据可以表示一个任务列表或者其他类型的具有状态的列表。导航到演示列表并从功能区访问列表设置。在“列表设置”页面上,创建一个名为“状态”的新选项栏。提供以下选择(见图 5-11 ):
- 准时
- 延时的
- 晚
图 5-11。
Adding a Choice field to the Demo List called Status
我们将使用这个新的状态栏来显示基于所选状态的图像。然而,在我们这样做之前,让我们用一些对业务更有意义的数据填充演示列表。图 5-12 显示了一些更合适的数据列表。
图 5-12。
Demo List with more real-world data populated
为了使这个例子更加真实,我们将更新我们的脚本,以便满足以下要求:
- 呈现 web 部件时,每个项目将只显示标题。
- 将显示自定义页眉和页脚,并为用户提供说明。
- 当用户单击项目标题时,状态和描述将显示在下面。
- 状态将显示为图像。
让我们从页眉和页脚开始,因为这些函数已经存在,我们只需要更新返回的内容。可以使用以下内容更新自定义代码:
function overrideHeader() {
return "<h3>These items are tasks from the Demo List:</h3>";
}
function overrideFooter() {
return "<h4>Click an item to view it's details.</h4>";
}
我们实际上根本没有对代码做太多修改。我们已经分别将 H2/H3 更改为 H3/H4,并更新了返回的文本。我们将使用客户页眉作为 web 部件中的标题,自定义页脚现在为用户提供说明。接下来,我们将更新overrideTemplate
函数;这是实施重大变革的地方。以下面的代码为例:
function overrideTemplate(ctx) {
var status = ctx.CurrentItem.Status;
var image = "";
if (status == "Delayed")
image = "/apress/Webparts/JSLink/Status-Delayed.png";
if (status == "On-time")
image = "/apress/Webparts/JSLink/Status-Ontime.png";
if (status == "Late")
image = "/apress/Webparts/JSLink/Status-Late.png";
return "<div style='font-size:18px;margin-bottom:6px;padding:4px;cursor:pointer;' class='list-item-div'>"
+ ctx.CurrentItem.Title
+ "<div style='font-size:14px;display:none;'>"
+ "<span style='display:inline-block;'>" + ctx.CurrentItem.Status + "<br /><img src='" + image + "' /></span>"
+ "<span style='display:inline-block;vertical-align:top;'>" + ctx.CurrentItem.Description + "</span>"
+ "</div>"
+ "</div>";
}
overrideTemplate
功能更新了不少。虽然乍一看它似乎有更多的功能,但实际上并没有更多的功能。有额外的逻辑以及更多的 HTML。让我们分别分解每一部分,以便更好地理解发生了什么。
var status = ctx.CurrentItem.Status;
var image = "";
这两行简单地声明了将在代码的其余部分使用的几个变量。首先,我们声明一个名为status
的变量,并将当前列表项的Status
属性的值赋给它。这只是简化了代码,使其可读性更好。接下来,我们声明一个名为image
的空字符串。这将保存我们希望根据项目状态显示的图像的 URL。
if (status == "Delayed")
image = "/apress/Webparts/JSLink/Status-Delayed.png";
if (status == "On-time")
image = "/apress/Webparts/JSLink/Status-Ontime.png";
if (status == "Late")
image = "/apress/Webparts/JSLink/Status-Late.png";
这个部分是对if
语句的简单分组。我们检查变量status
的值,对照列表列的已知值进行检查。一旦发现状态匹配,我们就将image
变量设置为我们想要显示的图像的适当 URL。
Note
本例中使用的图像可以从 Apress 网站下载。访问 Apress 站点,搜索这本书的标题,找到图像文件和源代码。在这个例子中,为了简单起见,我将图像和 JavaScript 文件上传到同一个文件夹中。
return "<div style='font-size:18px;margin-bottom:6px;padding:4px;cursor:pointer;' class='list-item-div'>"
+ ctx.CurrentItem.Title
+ "<div style='font-size:14px;border-top:solid 1px Silver;display:none;'>"
+ "<span style='display:inline-block;'>" + ctx.CurrentItem.Status + "<br /><img src='" + image + "' /></span>"
+ "<span style='display:inline-block;vertical-align:top;padding-left:16px;'>"
+ "<strong>Description</strong><br />"
+ ctx.CurrentItem.Description + "</span>"
+ "</div>"
+ "</div>"
最后,我们更新了返回的 HTML,这样我们就可以显著地改变结果。首先,我们用一些额外的内联 CSS 创建一个 DIV 元素,以及一个 CSS 类list-item-div
。当我们使用 jQuery 定位元素时,将会用到这个 CSS 类。接下来,我们显示当前的列表项标题,然后创建一个子 DIV 元素来保存状态和描述。这个 DIV 也有一些包含display:none;
的内联 CSS。这将使 DIV 保持隐藏,直到我们想要查看它。我们继续创建 HTML 来保存项目状态、状态图像和描述,最后关闭所有的 DIV 元素。
此时,页面将呈现出来,您将看到页面上每个列表项的标题,但是状态和描述信息将被隐藏。我们需要提供一种方便查看这些信息的方法。下面的函数将处理这个问题:
function listItemClick() {
$(".list-item-div").on("click", function () {
var childDiv = $(this).children()[0];
$(childDiv).toggle("slow");
});
}
当我们在前一个函数中创建每个子 DIV 时,我们隐藏了那些使用 CSS 的子 DIV,并应用了一个 CSS 类。这个类只是提供一种通过 jQuery 定位它的方法。我们使用 jQuery 内置的on
函数为每个 DIV 附加一个点击事件。所以通过使用$(".list-item-div").on("click", function ()...
,我们告诉 jQuery 找到所有带有list-item-div
CSS 类的元素,并为每个元素附加一个on click
事件。当单击元素时,将触发提供的函数。在这个函数中,我们要求 jQuery 给出 DIV 中的第一个子元素。$(this).children()[0]
告诉 jQuery,对于刚刚被点击的条目(“this”),给我们它的“children”集合中的第一个子对象。因为我们精心制作的 HTML 有一个父 DIV 和一个子 DIV,所以我们知道这将返回保存状态和描述信息的 DIV 元素。
接下来,我们使用一个名为toggle
的 jQuery 函数来显示元素。toggle
实际上会切换元素的可见性。因此,如果元素当前是隐藏的,toggle
将显示它,反之亦然。通过使用这个函数,我们可以用一行代码轻松地提供打开和关闭功能。
一旦我们有了用于将点击事件附加到 div 的函数,我们就需要一种方法来触发它。简单地编写这个函数并把它放在脚本中,在它被调用之前什么都不会做。通常,我们会包含一个 jQuery Document
.ready
调用,以确保使用$(function()...
调用正确连接事件。然而,在 JSLink 中,这不起作用,它将产生一个错误。原因是 JSLink onload 函数将在 jQuery 加载之前触发。这意味着来自 jQuery 的可靠的Document.ready
函数在 JSLink 中是无用的。但是,SharePoint 提供了自己的内置函数来做同样的事情:
_spBodyOnLoadFunctions.push(listItemClick);
_spBodyOnLoadFunctions
允许您注册自己的 JavaScript 函数,以便在页面加载时触发。它与 jQuery 的Document.ready
非常相似,但是它与 JSLink 配合得很好,所以这是我们在连接 jQuery 事件时需要使用的方法。Visual Studio 中的完整脚本如图 5-13 所示。
图 5-13。
The updated JSLinkItemTemplate.js script in Visual Studio. The custom header and footer functions have been collapsed for readability
保存更新后的文件,并将其上载到 web 部件库中的 JSLink 文件夹。在此脚本正常工作之前,您需要更新列表视图 Web 部件的一些属性。当您第一次将列表视图 Web 部件放在页面上时,返回的数据是列表类型的最低数据。例如,演示列表是一个自定义列表,所以默认情况下只返回标题和描述。这对于任务列表也是一样的;例如,当列表视图 Web 部件添加到页面时,只返回创建时存在的列。当然,你可以很容易地更新这个。导航到放置列表视图 web 部件的页面,并将该页面和 Web 部件置于编辑模式。在 web 部件的工具窗格中,第一个属性称为Selected
视图。使用下拉菜单选择所有物品视图,如图 5-14 所示。
图 5-14。
Changing the Selected View on the List View Web Part
更改这个视图可以确保新的Status
属性将被返回,并可用于我们的 JSLink 代码。接下来,因为我们在代码中使用自定义标题来呈现标题,所以我们将从 web 部件中移除 Chrome。在工具窗格中展开“外观”折叠面板。在这一部分的最底部,你会找到 Chrome 类型属性。从下拉菜单中选择无,如图 5-15 所示。
图 5-15。
Changing the Chrome Type on the List View Web Part
单击确定,然后保存页面。列表视图 Web 部件现在应该可以使用 JSLink 文件正确显示。结果如图 5-16 所示。将显示自定义页眉和页脚,它们为用户提供 web 部件标题以及如何使用 web 部件的说明。Chrome 不再显示,每个项目仅显示项目标题。将鼠标悬停在项目上,鼠标光标将变为指针,表示可以单击它。单击该项会触发 jQuery toggle
函数,打开和关闭该项。
图 5-16。
The Demo List items displayed using the JSLink file
正如您所看到的,这与您之前看到的现成的列表视图 Web 部件相比有了很大的变化。事实上,它的外观和行为就像您所期望的那样——一个根据业务需求构建的自定义 web 部件!过去,这种类型的解决方案需要服务器端编码和已部署到 SharePoint 服务器的自定义 web 部件。现在这一切都可以在浏览器中用 JavaScript 实现了!接下来,让我们看看如何操作单个列,而不是一次操作所有数据。
使用字段模板
JSLink 中的字段模板允许您针对列表中的特定字段或列进行自定义呈现。当您的自定义渲染需求不复杂时,您可以使用字段模板。使用这个模板,您肯定会得到非常复杂的自定义渲染。但是,与项目模板不同的是,项目模板更有针对性,在项目模板中,您最终得到的东西看起来一点也不像列表视图 Web 部件。最终结果是类似于类固醇的列表视图 Web 部件。
代码看起来非常类似于项目模板代码。我们将继续使用状态栏。对于此解决方案,我们将检查状态栏并返回相应的图像,但这次它将作为列数据出现在列表视图 Web 部件中。在 Visual Studio 中创建一个新文件,并从以下代码开始:
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields =
{
'Status': { 'View': overrideTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
这段代码看起来非常类似于条目模板代码,但有几处主要的变化。首先,我们不再使用自定义页眉和页脚。原因是该模板不会覆盖 web 部件的标准功能。所以我们仍然需要常规的列标题、排序等等。接下来,我们用以下代码行指定这是一个字段模板:
overrideContext.Templates.Fields =
{
'Status': { 'View': overrideTemplate }
};
'Status'
告诉 JSLink 我们的目标是列表中的状态字段。'View'
指定在呈现状态栏时触发哪个函数。所以我们需要使用下面的代码声明名为overrideTemplate
的函数来呈现列:
function overrideTemplate(ctx) {
var status = ctx.CurrentItem.Status;
var image = "";
if (status == "Delayed")
image = "/apress/Webparts/JSLink/Status-Delayed.png";
if (status == "On-time")
image = "/apress/Webparts/JSLink/Status-Ontime.png";
if (status == "Late")
image = "/apress/Webparts/JSLink/Status-Late.png";
return "<img class='status-image' src='" + image + "' data-val='" + status + "' />";
}
这个函数与前面的例子几乎相同。我们仍然声明了几个变量来保存当前项目的状态和图像 URL。通过使用if
语句,我们根据状态设置图像 URL,就像以前一样。不同的是返回,这是一个图像 HTML 元素。我们将SRC
属性设置为从if
语句中确定的图像 URL。我们还设置了一个 CSS 类status-image
和一个名为data-val
的属性,用于保存状态的文本值。最后两个属性将用于 jQuery click 事件。这个函数只是返回状态的图像,而不是状态的文本。
接下来,我们将使用下面的代码来设置将点击事件附加到每个图像的函数:
function listItemClick() {
$(".status-image").on("click", function () {
var status = $(this).attr("data-val");
alert(status);
});
}
这个函数看起来和前面的例子非常相似。我们使用 CSS 类“status-image
”设置了一个 jQuery click 事件。接下来,我们使用$(this).attr("data-val")
获取状态文本。jQuery 的“attr
”函数返回 HTML 元素上任何属性的值,所以我们可以很容易地访问这个值。然后,我们发出一个带有状态文本的标准警报。最后,我们使用_spBodyOnLoadFunctions.push
函数连接函数:
_spBodyOnLoadFunctions.push(listItemClick);
这个例子比条目模板例子小得多。这是因为覆盖只针对单个字段,而不是所有列以及页眉和页脚。Visual Studio 中完整的代码示例如图 5-17 所示。
图 5-17。
JSLinkFieldTemplate.js file in Visual Studio
保存这个文件,并将其命名为JSLinkFieldTemplate.js
。将其上载到 Webparts 文档库中其他 JSLink 文件所在的 JSLink 文件夹中。导航回列表视图 Web 部件,将其置于编辑模式,并将 JSLink 属性更新为以下内容:
∼site/Webparts/JSLink/JSLinkFieldTemplate.js
与项模板一样,您可能需要使用 Selected View 属性设置适当的视图。您也可以将 Chrome 类型设置回默认值,以便再次显示 web 部件标题。列表视图 Web 部件中呈现的新 JSLink 文件如图 5-18 所示。
图 5-18。
Field template rendering using JSLink
您也可以点击图像,在 JavaScript 警告中查看状态文本,如图 5-19 所示。
图 5-19。
Click event on the status image
您可以通过提供多个覆盖函数来覆盖多个字段。例如,如果我们想对描述字段应用自定义呈现,我们可以将代码更新为:
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields =
{
'Status': { 'View': overrideTemplate },
'Description': { 'View': overrideDescTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
function overrideDescTemplate(ctx) {
return "<span style='font-weight:bold;'>" + ctx.CurrentItem.Description + "</span>";
}
Fields 属性将接受多个覆盖,只需在每个覆盖之间放置一个逗号。在本例中,我们创建了另一个名为overrideDescTemplat
e
的函数,它只是返回当前项目的描述字段,该字段包含在一个 SPAN 元素中,该元素提供了一种粗体字体。Visual Studio 中完整的脚本如图 5-20 所示。
图 5-20。
The updated JSLinkFieldTemplate.js file in Visual Studio Note
有些字段不能使用 JSLink 覆盖。例如,分类字段不允许不同的呈现。如果您可以覆盖像托管元数据列这样复杂的字段的呈现,您可以想象这会导致多么令人头痛的问题。如果您试图覆盖任何不允许这样做的字段,只会导致 SharePoint 忽略您的自定义呈现功能。这很好,因为这意味着你的脚本不会分页;然而,这可能会令人沮丧,因为似乎什么也没发生!如果您注意到了这一点,请后退一步,记住有些字段是不能被覆盖的。
正如您在这个更新的代码示例中看到的,JSLink 提供了覆盖一个或多个字段所需的所有工具。只需提供一个函数来处理呈现并定义覆盖。保存此文件并将其上载到文档库。图 5-21 显示了使用新的 JSLink 文件呈现的列表视图 Web 部件。
图 5-21。
Updated JSLink file rendering multiple fields on the web part
现在,您已经看到了使用 JSLink 呈现列表视图 Web 部件的多个示例。无论您需要覆盖特定的字段还是完全改变 web 部件的外观,您都拥有了获得自定义解决方案所需的所有工具。通过加载多个脚本来帮助您创建健壮的解决方案,您可以进一步使用 JSLink。
加载多个脚本
在使用 JSLink 进行开发的过程中,您可能会发现您的文件变得越来越大,或者您可能还有其他一些想要加载的脚本。幸运的是,使用 JSLink 很容易做到这一点。JSLink 允许添加多个文件,只需使用管道|
,将其放在 JSLink 属性中的每个文件路径之间。例如,如果我们的文件夹中有多个文件,我们可以使用以下路径:
∼site/Webparts/JSLink/File1.js|∼site/Webparts/JSLink/File2.js
带有|
分隔符的组合路径将放在列表视图 Web 部件的 JSLink 属性中。我们可以更新前面的代码示例来说明这一点。首先,我们将使用以下代码返回到该示例的简化版本:
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields =
{
'Status': { 'View': overrideTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
})();
function overrideTemplate(ctx) {
var status = ctx.CurrentItem.Status;
var image = "";
if (status == "Delayed")
image = "/apress/Webparts/JSLink/Status-Delayed.png";
if (status == "On-time")
image = "/apress/Webparts/JSLink/Status-Ontime.png";
if (status == "Late")
image = "/apress/Webparts/JSLink/Status-Late.png";
return "<img class='status-image' src='" + image + "' data-val='" + status + "' />";
}
这个示例基本上回到了第一个字段代码示例,其中我们只使用图像覆盖了 Status 字段。呈现警报的自定义 jQuery 代码已经被删除,所以我们将把它移到另一个文件中。Visual Studio 中的脚本如图 5-22 所示。
图 5-22。
JSLink file that only renders the Status field on the list
保存该文件并将其命名为 JSLinkFieldTemplateBase.js。接下来,我们将创建配套文件来处理 jQuery click 事件功能。使用文件➤新➤文件创建一个新文件。选取“Web”类别,然后从选项中选取“JavaScript 文件”。我们将使用上一节中的代码,该代码使用 jQuery 将 click 事件添加到 DIV 中,如下所示:
function listItemClick() {
$(".status-image").on("click", function () {
var status = $(this).attr("data-val");
alert("STATUS: " + status);
});
}
_spBodyOnLoadFunctions.push(listItemClick);
这与之前的代码相同,只是在警报中添加了文本“STATUS:”而已。这主要是为了表明我们正在使用一个新文件,并且 JSLink 正在加载这两个文件。保存该文件,命名为 JSLinkFieldTemplateExt.js,Visual Studio 中的脚本如图 5-23 所示。
图 5-23。
JSLinkFieldTemplateExt.js file in Visual Studio
既然已经创建了这两个文件,请将它们上载到 Webparts 文档库中的 JSLink 文件夹。文件上传后,您可以创建组合路径,它应该如下所示:
∼site/Webparts/JSLink/JSLinkFieldTemplateBase.js|∼site/Webparts/JSLink/ JSLinkFieldTemplateExt.js
将列表视图 Web 部件置于编辑模式,并使用组合路径更新 JSLink 属性。单击应用,然后保存页面。乍一看,自定义渲染变化不大。点击一个状态图像触发点击事件,如图 5-24 所示。
图 5-24。
Updated click event from the second JavaScript file
在警报中,您可以看到显示了附加“状态:”文本的状态。这是对两个 JavaScript 文件已经通过 JSLink 加载的确认。虽然这是一个非常简单的例子,但它应该说明了加载多个文件的强大功能。随着脚本变得越来越大,您现在可以灵活地将代码分成多个文件,并通过 JSLink 引用它们。
摘要
在本章中,我们探讨了 JSLink 作为在 SharePoint 中构建自定义解决方案的一种方式的强大功能。我们看到了如何使用此方法来覆盖列表视图 Web 部件的默认呈现。您可以使用“项目”模板来完全自定义整体呈现,或者使用“字段”模板来覆盖列表中的单个或多个字段。我们还看到了如何将代码分解成多个文件。希望这一章展示了 JSLink 的可能性。在下一章中,我们将继续关注 SharePoint 中使用显示模板和结果源创建自定义搜索解决方案的新功能。
六、搜索 Web 部件的内容和显示模板
自从 SharePoint 出现以来,搜索一直在它的使用中扮演着重要的角色。无论是网站搜索、企业搜索还是自定义解决方案,SharePoint 的主要优势之一就是能够轻松找到所需内容。在 SharePoint 中简化搜索的方法之一是通过内容搜索 Web 部件。这可以很容易地放在页面上,并配置为向用户返回特定的结果。这是一个久经考验的 web 部件,已经存在很长时间了。在最新版本的 SharePoint 中,内容搜索 Web 部件利用了结果源和显示模板形式的新功能。
结果源允许您创建特定的搜索标准,以快速定位您正在寻找的内容。显示模板允许您根据您的业务需求设计和呈现这些搜索结果。这项新功能为开发人员在 SharePoint 中创建丰富的自定义解决方案提供了另一种途径。在这一章中,我们将看看这些领域,并创建一些自定义搜索解决方案。
添加文档
在开始使用 SharePoint 中的搜索功能构建解决方案之前,您需要实际搜索一些文档。如果您正在使用现有的 SharePoint 环境,您可能已经有了一些要搜索的文档。如果您已经为这本书设置了环境,您需要上传一些文档来执行一些搜索。在本例中,您可以搜索各种文档类型,包括 Word、Excel 和 PDF。图 6-1 显示了文档库中的一些样本文件。
图 6-1。
Excel, PDF, and Word documents in the Documents library Note
本例中使用的文档可以从一个网站下载。访问 Apress ( www.apress.com
)并搜索这本书的书名来定位文档和源代码。
我使用了开箱即用的“文档”文档库,它是在我创建名为 Apress 的团队站点时创建的。无论您将文档存储在哪里,这里的主要要点是将一些文件上传到 SharePoint,以便您可以搜索它们。现在,一些文件已经上传并将最终被编入索引,您可以创建一个定制的结果源来方便搜索。
结果来源
在 SharePoint 2010 中,您有了自定义搜索范围的概念。它们允许您将搜索结果限制为特定内容,从而为您的最终用户提供更有针对性的搜索,而无需他们知道如何设计复杂的搜索查询。在 SharePoint 2013 中,您可以使用自定义结果源完成完全相同的事情。
在 SharePoint 2013 中执行搜索时,系统会将查询与结果源进行匹配以提供结果。结果源是指定以下内容的定义:
- 协议——这可以是本地搜索服务索引、远程 SharePoint 安装、Exchange,甚至是另一个使用 OpenSearch 协议的搜索引擎。
- 源 URL -如果您使用的是本地 SharePoint 以外的协议,您需要为返回搜索结果的服务提供一个 URL。
- 类型-使用本地或远程 SharePoint 时,您可以指定 SharePoint 搜索或人员搜索。
- 查询转换——使用查询转换,您可以使用 KQL 属性限制来缩小给定搜索的结果范围。
- 凭据-您可以指定用于搜索的凭据。
SharePoint 附带了许多预配置的结果源供您使用,包括对话、文档和图片等。还可以在整个 SharePoint 中的不同级别创建自定义结果源,创建结果源的位置决定了您需要的权限级别。下面列出了可以创建结果源的级别以及创建结果源时所需的权限:
- 网站集-您必须是网站集管理员,并且网站集中的任何网站都可以使用结果源。
- 站点-您必须是该站点所有者组的成员,并且结果源只能由该站点使用。
您还可以在搜索服务应用级别或 SharePoint 管理中心为 Office 365 指定结果源,结果源可用于任何使用搜索服务应用的网站集。本书不会涉及这一层,但是,在这一层创建结果源的步骤也是完全相同的。
创建自定义结果源时,您需要决定的第一件事是创建它的级别。这取决于您打算如何使用源代码;例如,如果要突出显示特定站点中的项目,那么站点级别就有意义。但是,如果您想要一个更全面的结果源,您可能希望在网站集级别创建它。两者的步骤完全相同。如果您计划在网站集或网站级别创建新的结果源,只需导航到“网站设置”页面,选择“网站级别”的“搜索”标题下的“结果源”,或“网站集级别”的“网站集管理”标题下的“搜索结果源”。图 6-2 显示了网站集的网站设置页面。
图 6-2。
Accessing Result Sources from the Site Collection site settings page
正如您在网站集级别看到的,您可以为整个网站集创建结果源,也可以只为根级别的网站创建结果源。对于这个例子,我们将导航到其他代码样本所在的 Apress 子站点,并仅为这个站点创建一个新的结果源,如图 6-3 所示。
图 6-3。
Accessing Result Sources from the Site’s site settings page
单击“结果源”链接会将您带到“管理结果源”页面。此页面显示所有已设置的当前结果来源。它还包括 SharePoint 附带的所有现成的结果源。您不能更改任何现成的结果源;但是,您可以查看它们的设置。要开始创建自定义结果源,请单击页面顶部的新结果源链接,如图 6-4 所示。
图 6-4。
Manage Result Sources page in site settings
一旦进入 Add Result Source 页面,首先需要提供名称和描述。描述是可选的,但是您应该为其他用户提供一个描述。图 6-5 显示了新结果源所需的初始属性。
图 6-5。
Providing a name and description for the new result source
在本例中,您将创建一个结果源,该结果源将只返回网站文档库中的 PDF 文档。为此,我们将提供标题 Custom PDF Source 和适当的描述,以便用户确切地知道使用这个结果源时会发生什么。接下来,您需要提供一个协议和类型;在这种情况下,协议将是本地 SharePoint,类型将是 SharePoint 搜索结果,如图 6-6 所示。根据您的需要,您可能需要选择不同的协议和类型,并提供附加信息。在这种情况下,页面将更新以显示所选选项所需的附加字段。
图 6-6。
Protocol and Type options for the new result source
接下来,您需要提供一个查询转换,它将实际限制搜索结果。这是使用关键字查询语言完成的,关键字查询语言是一组搜索选项、属性限制和操作符。查询转换将始终以标记{searchTerms}开始;这将被替换为用户输入的任何搜索词。之后,您可以提供任何有效的属性限制和/或操作符。我们稍后将对此进行更深入的探讨。现在,您可以在文本框中看到{searchTerms}标记,以及启动查询生成器按钮,如图 6-7 所示。
图 6-7。
Query Transform options and the Launch Query Builder option
最后,您可以指定用于该结果源的凭据。您可以指定默认身份验证,以便在执行搜索时使用用户身份验证。这通常是期望的结果。认证类型如图 6-8 所示。
图 6-8。
Credentials Information for the result source
单击保存创建新的结果源。您将返回到管理结果源页面,其中将列出自定义结果源,如图 6-9 所示。新的结果源列在页面顶部的标题“为此网站定义”下。
图 6-9。
The new result source in the Manage Result Sources page
由于我们没有在查询转换部分提供任何细节,这个新的结果源将简单地接受用户的输入并执行搜索。我们绝对不需要创造一个新的结果来达到那个结果。让我们更新它,使它只从 Documents 文件夹返回 pdf。打开结果源快捷菜单,点击编辑,如图 6-10 所示。
图 6-10。
Editing the result source we just created
编辑结果源会将您带到“编辑结果源”页面,您将看到刚才输入的所有先前设置。向下滚动到查询转换部分,并单击启动查询构建器按钮,如图 6-11 所示。
图 6-11。
Query Transform section with the Launch Query Builder button
将打开“构建查询模式”窗口,这将帮助您构建查询转换。通过访问提供的下拉列表,您可以在此窗口中使用许多现成的过滤器。您也可以在这里应用排序和测试您的查询。您也可以选择只输入您的查询,如图 6-12 所示。
图 6-12。
The Build Your Query modal window
查询是使用关键字查询语言(简称 KQL)在 SharePoint 中构建的。使用 KQL,您可以指定传递给 SharePoint 搜索服务的搜索词或属性限制。KQL 查询并不复杂,由以下一个或多个元素组成:
- 自由文本关键字——可以是单词或短语,比如白皮书、事件、Bob Smith 等等。
- 属性限制——这些可以是文件类型、作者、文件名等等。
属性限制顾名思义就是限制搜索结果。例如,您可以添加一个文件类型限制器,并通过使用FileType:docx
只返回 Word 文件来只返回特定的文档类型。有许多可用的属性限制,使得 KQL 在你的搜索需求中非常健壮。
Note
关键字查询语言虽然易于实现,但具有非常丰富和深刻的语法。这对于精心设计完全满足您需求的查询来说是很棒的,但是对于本书来说这是一个太大的主题。我们将简单地描述一下你能完成的事情。有关 KQL、财产限制等详细信息,请访问 http://msdn.microsoft.com/en-us/library/office/ee558911(v=office.15).aspx
。
KQL 查询必须包含一个自由文本关键字,或者一个属性限制,或者两者的组合才有效。首先,我们将删除查询的{searchTerms}部分。我们不会使用它,因为我们的内容搜索 Web 部件将简单地返回结果,而不需要用户的任何交互。接下来,我们将使用path
属性添加一个属性限制:
path:"``https://brandonatkinson.sharepoint.com/apress/Shared Documents
path
属性指示查询,我们只需要来自指定路径及其下的任何内容的结果,包括文件夹、子网站等等。路径必须是完全限定的 URL,如果它包含任何空格,URL 必须用引号括起来。在我的环境中,我使用现成的文档文件夹,它实际上是共享文档文件夹。您始终可以通过在导航面板中单击文件夹的实际名称并在浏览器的地址栏中检查 URL 来仔细检查该文件夹的实际名称。将该属性限制放置在查询文本文本框中并点击测试查询按钮将产生如图 6-13 所示的结果。
图 6-13。
Path property restriction returning only files from the specific document library
属性限制将搜索结果限制在文档库中,只有七个文档被返回。我们现在可以使用FileType
属性再次限制它:
FileType:pdf
该属性指示查询只返回扩展名为.pdf
的文件。将此添加到查询中并单击测试查询按钮将进一步限制结果,如图 6-14 所示。
图 6-14。
FileType property restriction limiting results to only PDF files
现在只有两个文件被返回,因为我们在文档库中只有两个 PDF 文件。虽然这是一个非常简单的例子,但是它应该说明了 KQL 在构造查询时所提供的强大功能。由于只有两个属性限制,我们已经能够很好地限制搜索结果。您可以想象,如果您要求只显示位于特定站点的 Office 文件,不管它们在哪个文件夹中,您的 KQL 查询将类似于以下内容:
path:"``http://SERVER/SITE
正如您所看到的,您可以组合相同类型的属性限制器来制作您所需要的东西。KQL 非常灵活;找到符合您需求的搜索词和属性限制的正确组合应该没有问题。
既然我们已经按照我们想要的方式设置了查询,那么在 Build Your Query 窗口中单击 OK。然后在“编辑结果源”页面上单击保存。自定义结果源现在已经设置好,可以使用了。接下来,让我们在页面上放置一个内容搜索 Web 部件,并使用结果源。
内容搜索 Web 部件
内容搜索 Web 部件是 SharePoint 2013 的另一个新功能。当内容搜索 Web 部件放置在页面上时,它会在用户加载页面时自动发出搜索查询。根据 web 部件的配置方式,用户很可能甚至不知道正在进行搜索。这使得内容搜索 Web 部件成为创建基于搜索的自定义解决方案的强大方法。这是一个易于使用和配置的 web 部件,正如您在上一节中看到的,根据您的需要设置特定的搜索查询非常容易。
Note
内容搜索 Web 部件是搜索 Web 部件功能的一部分。这仅适用于 SharePoint Online E3 和 E4 计划,以及企业内部许可。如果没有这些功能,您会发现内容搜索 web 部件不可用于向页面添加新的 Web 部件。您可以在 http://technet.microsoft.com/en-us/library/sharepoint-online-service-description.aspx
找到有关 SharePoint Online 计划可用功能的更多信息。
首先,导航到放置本书的其他 web 部件的页面,然后从前面的章节中删除任何现有的 web 部件。在页面仍处于编辑模式的情况下,通过从功能区中选择“插入”选项卡来放置新的内容搜索 Web 部件。从类别部分选择内容汇总,然后选择内容搜索,如图 6-15 所示。
图 6-15。
Inserting the Content Search Web Part onto the page
单击“添加”将 web 部件放置在页面上。web 部件将立即显示搜索结果。内容搜索 Web 部件的默认搜索名为“最近更改的项目”,它只显示最近更改的项目列表。在这种情况下,列表由最近添加到文档库中的文档组成,如图 6-16 所示。
图 6-16。
The Content Search Web Part using the Recently Changed Items search
乍一看,这个 web 部件几乎正在做我们从一开始就想做的事情,即只显示 PDF 文档。事实上,这两个 PDF 文档显示在这个 web 部件只是运气。例如,根据您上传文档的顺序,您可能会在顶部看到两个 Word 文档。我们将更新 web 部件以使用我们在上一节中创建的自定义结果源,从而确保我们在结果中仅获得 PDF 文档。将内容搜索 Web 部件置于编辑模式,在属性折叠窗格中,单击更改查询按钮,如图 6-17 所示。
图 6-17。
Accessing the query settings of the Content Search Web Part
单击此按钮将打开“构建您的查询模式”窗口。在“基本”选项卡下,您会看到“选择查询”标题和“最近更改的项目(系统)”选项,如图 6-18 所示。
图 6-18。
The Build Your Query modal window with the “Recently changed items” result source selected
正如您在此窗口中所看到的,内容搜索 Web 部件有许多设置,而且这些设置只与搜索查询有关!可以对该 web 部件进行配置,以提供非常准确的结果,并且它能够满足各种各样的业务需求。现在,让我们将结果源更改为自定义 PDF 源。点击切换到高级模式窗口右上角的链接,如图 6-19 所示。
图 6-19。
Switch to Advanced Mode link in the Build Your Query modal window
单击此链接会弹出一个窗口,该窗口看起来很像您在构建自定义结果源时看到的构建查询窗口。您可以键入查询,使用关键字过滤器和属性过滤器,甚至可以在右窗格中看到搜索查询的预览。当我们创建自定义结果源时,所有这些设置都可用;但是,这里有一个新的下拉菜单,名为“选择查询”。打开它将显示一个结果源列表,您可以选择用于查询。打开下拉列表,选择自定义 PDF 源,如图 6-20 所示。
图 6-20。
Choosing the custom result source Custom PDF Source from the drop-down menu
从下拉列表中选择结果源后,单击模式窗口底部的“测试查询”按钮预览自定义结果源查询。如图 6-21 所示,它正在执行仅从 documents 文件夹返回 PDF 文档的适当搜索。
图 6-21。
The Custom PDF Source result source search shown in the preview window
在“构建查询模式”窗口中,单击“确定”。接下来,在内容搜索 Web 部件工具窗格中单击“确定”保存更改。保存页面。自定义结果源将被激活,仅显示 PDF 文档,如图 6-22 所示。
图 6-22。
Custom result source displaying only PDF documents
现在,我们已经创建了一个自定义结果源,并成功地将其应用于内容搜索 Web 部件。只有结果源指定的文档被返回并显示给用户。然而,显示效果并不令人满意。虽然内容是正确的,但看起来不太好。接下来,让我们探索显示模板,看看如何应用定制样式来匹配定制结果。
Note
内容搜索 Web 部件相当复杂。它有许多设置可以配置,以帮助您实现非常精确的结果为您的解决方案。有关这些设置的更多详细信息,请访问 https://support.office.com/en-us/article/Configure-a-Content-Search-Web-Part-in-SharePoint-0dc16de1-dbe4-462b-babb-bf8338c36c9a
。
显示模板
SharePoint 允许您完全控制搜索结果,包括它们在页面上的显示方式。这是通过显示模板实现的。您可以使用显示模板来设计您的搜索结果,无论您喜欢使用 HTML。您可以创建两种类型的显示模板:
- 控件-这些模板处理搜索结果显示的整体结构,可以包括页眉和页脚之类的内容。此模板在每个 web 部件上只会呈现一次。
- Item -这些模板处理每个搜索结果项的显示方式。该模板将为返回的每个搜索结果呈现一次。
您可以通过将内容搜索 Web 部件置于编辑模式来查看这些显示模板,并且在工具窗格中,您可以在属性折叠中找到显示模板标题,如图 6-23 所示。
图 6-23。
Control and Item display templates in the Content Search Web Part tool pane
有许多现成的显示模板可用,您可以通过单击每种类型的下拉列表来查看它们。例如,控制模板包括列表、分页列表和幻灯片。项目模板甚至有更多的选项可供选择。要开始创建新的显示模板,最简单的方法是从现有模板开始。若要查看所有当前的搜索显示模板,请导航到母版页样式库,该样式库位于“网站设置”和“网站设计者样式库”下。点击“母版页和页面布局”链接,如图 6-24 所示。
图 6-24。
The “Master pages and page layouts” link in Site Settings
进入母版页样式库后,您会发现它比以前版本的 SharePoint 多了很多。靠近顶部有一个名为显示模板的文件夹。通过打开此文件夹,您将看到对应于 SharePoint 中不同区域的多个文件夹;其中之一是内容 Web 部件,如图 6-25 所示。
图 6-25。
Content Web Parts folder inside the Display Templates folder
打开“内容 Web 部件”文件夹,查看 SharePoint 自带的所有可用显示模板。如图 6-26 所示,这里有不少。在页面顶部,您可以看到在内容搜索 Web 部件工具窗格中看到的控件模板。
图 6-26。
Out-of-the-box display templates in the Content Web Parts folder
每个显示模板都有一个与之相关联的 JavaScript 文件。在幕后,SharePoint 使用这个 JavaScript 文件来呈现显示模板。您不需要创建或修改该文件;当你上传一个新的显示模板到这个文件夹时,一个相应的 JavaScript 文件被创建,我们将在本章的后面看到。
Note
显示模板可以非常简单,也可以非常复杂。您可以很好地控制哪些属性可用以及内容如何布局,甚至可以向模板添加额外的 JavaScript。显示模板的总体主题非常庞大和复杂,无法在本章中完全涵盖。更多信息请访问 http://msdn.microsoft.com/en-us/library/office/jj945138%28v=office.15%29.aspx
。
为了开始构建新的显示模板,我们将下载另一个模板的副本,并将其用作基础。显示模板可能相当复杂,从头构建一个模板可能是一项艰苦的任务。使用一个现有的模板开始将大大减少创建一个新模板的时间。对于这个例子,我们将关注一个项目模板,并使用默认的“图片在左边,3 行在右边”模板。在内容 Web 部件文件夹中,该模板的标题为Item_Picture3Lines.html
。在文件夹中勾选此模板,在功能区中点击下载副本,如图 6-27 所示。
图 6-27。
Downloading a copy of an existing display template
一旦下载了副本,就可以在 Visual Studio 中打开它。检查一下这份文件,你会发现它有点复杂。它有一个 HEAD 部分、一个 TITLE 和一个 BODY——正如您所期望的 HTML 文档一样——以及许多呈现代码。实际的渲染发生在身体里。您会注意到在主体内部有几个包含所有逻辑的 div。Visual Studio 中的文件如图 6-28 所示。
图 6-28。
Item_Picture3Lines.html file open in Visual Studio
让我们将这个文件按每个部分进行分解,以便了解正在发生的事情。首先,保存文件并将其命名为 Item_CustomPdf.html。这些标签没有什么特别的。TITLE 标记非常重要,因为在内容搜索 Web 部件中选择项目模板时,它将显示在下拉列表中。将标题更改为自定义 PDF 模板。
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<title>Custom PDF Template</title>
下一节是名为 CustomDocumentProperties 的一节中的属性集合。这些属性向 SharePoint 提供有关显示模板的附加信息。其中一些是自动为您填充的,而其他的您将需要更新。以下是一些比较重要的例子:
ManagedPropertyMapping
-该属性获取搜索使用的托管属性,并将它们映射到显示模板可以使用的值。MasterPageDescription
-该属性为显示模板提供友好的描述,并显示给用户。TargetControlType
-该属性指定显示模板使用的上下文;例如,内容 Web 部件。
ManagedPropertyMapping
属性允许您在搜索中使用托管属性,并将它们映射到显示模板可以使用的值。它是一个逗号分隔的值列表,使用以下格式:
'property display name'{property name}:'managed property'
例如,在这个显示模板中的ManagedPropertyMapping
中,您可以找到以下内容:'Link URL'{Link URL}:'Path'
。这将托管属性Path
映射到一个名为Link URL
的变量。ManagedPropertyMapping
映射了几个托管属性:
<mso:ManagedPropertyMapping msdt:dt="string">'Picture URL'{Picture URL}:'PublishingImage;PictureURL;PictureThumbnailURL','Link URL'{Link URL}:'Path','Line 1'{Line 1}:'Title','Line 2'{Line 2}:'Description','Line 3'{Line 3}:'','SecondaryFileExtension','ContentTypeId'</mso:ManagedPropertyMapping>
映射属性后,您可以使用以下 JavaScript 获取其值:
var linkURL = $getItemValue(ctx, "Link URL");
getItemValue()
函数有两个参数。第一个称为ctx
,代表当前上下文。你会注意到它没有被定义。正好可以用。你需要记住的是,你必须把它传入,它会一直在那里使用。第二个参数是用单引号括起来的属性显示名,用在ManagedPropertyMapping
元素中。在本例中,Link URL
是属性名。
我们要更新的另一个属性是MasterPageDescription
属性,只是为了更新描述,以免混淆。
<mso:MasterPageDescription msdt:dt="string">This Item Display Template will display custom PDF results.</mso:MasterPageDescription>
紧跟在<body>
标记之后,您会发现一个<script>
部分:
<script>
$includeLanguageScript(this.url, "∼sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
</script>
在这一部分,您可以添加自己的脚本或 CSS 引用。默认情况下,它包含一个对名为CustomStrings.js
的文件的引用,该文件存在于所有显示模板中。您可以使用以下几行来添加额外的引用:
- 位于同一站点的脚本:
$includeScript(this.url, "∼site/Webparts/CustomScript.js");
- 位于外部站点的脚本:
$includeScript(this.url, "
http://www.contoso.com/CustomScript.js
");
- 位于同一站点的 CSS 文件:
$includeCSS(this.url, "∼site/Webparts/CustomCSS.css");
紧接在<script>
标签之后,您会发现一个<div>
元素,它包含了将包含在显示模板中的所有 HTML 和代码。这个 DIV 的 ID 必须与显示模板文件的名称相匹配。例如,本例中的 DIV 如下所示:
<div id="Item_CustomPdf">
在 DIV 元素之后,您会看到注释块中的代码以<!--#_
开始,以_#-->
结束。在这个块中,您可以使用任何您喜欢的 JavaScript 代码,在这里您还可以获得任何托管属性的所有值。我们将保持这个显示模板的简单,只使用两个托管属性,代码如下:
<!--#_
var linkURL = $getItemValue(ctx, "Link URL");
var line1 = $getItemValue(ctx, "Line 1");
_#-->
如您所见,我们简单地声明了两个变量来保存在ManagedPropertyMapping
中定义的托管属性的值。我们将在 HTML 代码中使用这两个变量。我们将用下面的代码保持 HTML 的简单:
<div style="border:solid 1px Silver;padding:10px;margin-bottom:20px;">
<strong>_#= line1 =#_</strong>
<br />
<a href="_#= linkURL =#_">
_#= linkURL =#_
</a>
</div>
在这段代码中,我们简单地用一个 DIV 包装所有内容。我们通过内联 CSS 应用了一个简单的边框和填充。接下来,我们将使用下面的语法: _#= line1 =#_
显示line1
变量。通过使用以下语法,可以在显示模板中使用 JavaScript 变量。接下来,我们将使用一个<a>
元素显示 PDF 文件的链接。完整的文件如图 6-29 所示。
图 6-29。
Display template in Visual Studio
导航回母版页样式库中的内容 Web 部件文件夹,并从功能区将Item_CustomPdf.html
文件上载到库中。文件上传后,会出现一个模态窗口提示您,您可以在其中设置文件的属性,如图 6-30 所示。
图 6-30。
Properties dialog for the display template
该对话框具有您在显示模板的 HTML 文件中看到的许多属性。文件中的所有属性都将被提取并填充到此窗口中。因此,您几乎可以保持所有属性不变,然后单击 Save。你会看到显示模板已经上传到库中,如图 6-31 所示。
图 6-31。
The newly uploaded display template and generated JavaScript file
您还会看到已经创建了一个同名的配套 JavaScript 文件。SharePoint 根据您上载的 HTML 文件生成此文件。这是它在呈现内容时使用的内容。你不需要担心这个文件,也不应该试图修改它。如果您需要进行更改,只需更改 HTML 文件并再次上传即可。每次您上传 HTML 的新副本时,都会生成一个新的 JavaScript 文件。
导航回包含内容搜索 web 部件的页面,并将该 Web 部件置于编辑模式。如果您单击显示模板部分中的项目下拉菜单,您将看到自定义 PDF 模板作为一个选项,如图 6-32 所示。选择此选项,单击确定,然后保存页面。
图 6-32。
The new display template is available for use
页面重新加载,呈现新的显示模板,如图 6-33 所示。
图 6-33。
The new display template being used to render the Content Search Web Part
这个例子是你能得到的最基本的例子,但是希望它展示了显示模板和搜索 web 部件的简单和强大。使用这些模板,您可以构建利用托管属性、JavaScript 和 CSS 的自定义搜索解决方案。创建丰富体验所需的所有工具都已准备就绪。
Note
花些时间下载并探索 SharePoint 附带的现成显示模板。只需浏览这些文件并查看每个文件中使用的代码,就可以找到许多有用的信息。
摘要
在本章中,我们探讨了如何使用内容搜索 Web 部件、自定义结果源和自定义显示模板来构建自定义搜索解决方案。您了解了结果源,并了解了如何构建新的源并将其用于内容搜索 Web 部件。我们很快研究了显示模板,并创建了一个简单的例子来说明如何应用自定义渲染。搜索将永远在 SharePoint 中发挥重要作用,现在您有了一些工具来为您的业务需求构建自定义搜索解决方案。
在下一章中,我们将继续探索 SharePoint 在设计定制解决方案时所提供的功能。我们将研究一些内置的 JavaScript 功能,这些功能在编写代码时唾手可得。我们已经看到了一些这种功能,我们将更深入地探究什么是可能的。
七、使用 SharePoint 的内置 JavaScript 函数和属性
当使用 JavaScript 构建定制解决方案时,经常需要其他库的帮助来完成您的工作。我们已经看到了 jQuery 库的强大功能,以及它如何帮助我们在页面上定位 HTML 元素、更新它们的值,甚至使用 AJAX 调用数据。使用 SharePoint 时,您经常需要构建 URL、向用户显示通知等。幸运的是,微软提供了大量的 JavaScript 来帮助你完成这些任务。我不是简单地谈论 JavaScript 对象模型或 REST API。在这一章中,我们将探索一些内置的 JavaScript 函数和属性,它们可以很容易地帮助你构建你的定制解决方案。
探索 JavaScript
SharePoint 附带了一长串内置的 JavaScript 方法和属性,您可以在代码中使用它们。事实上,这份清单太长了,一旦你开始钻研,它似乎会让人不知所措。然而,在您的日常编码工作中,您将很快习惯其中的一些,并且当需要时,您可以放心地知道有更多的帮助。让我们首先使用 Internet Explorer 11 的开发工具来探索一些文件。正如本书前面提到的,每种浏览器都有自己的一套开发工具,每种工具都略有不同。你完全可以在每一个中执行相同的任务,但是一旦你开始在 JavaScript 控制台中键入,IE11(和 Chrome)会显示一个可用功能的便捷列表,如图 7-1 所示。
图 7-1。
Developer tools in IE11. Typing an underscore in the console window will display a list of available JavaScript functions
通过按键盘上的 F12 打开 IE11 中的开发工具。您也可以通过浏览器中的设置按钮来访问它们。单击控制台选项卡,并在底部的文本框中键入下划线。将打开一个列表,显示所有以下划线开头的 JavaScript 函数。您可以使用箭头键在列表中上下移动。
花几分钟时间浏览你在这里看到的一切。它应该给你一个很好的指示,说明在 SharePoint 中使用 JavaScript 的可能性。您已经看到了其中一些功能的运行;例如,当使用 JSLink 时,我们利用了SPClientTemplates
功能来覆盖 web 部件呈现。
Note
可供您使用的 JavaScript 方法和属性非常广泛。以至于没有办法在一个单独的章节中恰当地涵盖它;这需要一整本书。我们将查看一些功能,并在示例代码中使用它们。你应该花些时间充分探索开发者工具中的功能,并使用 Google 或 Bing 追踪更多信息。
_spBodyOnLoadFunctions
_spBodyOnLoadFunctions
是一个数组,它保存了一组 JavaScript 函数,这些函数应该在页面加载时被触发。我们在第五章中看到过,当我们需要连接一个函数来触发页面加载时。该数组包含一个名为push
的方法,您可以在其中传入应该被触发的函数的名称:
_spBodyOnLoadFunctions.push(<FUNCTION_NAME>);
当您无法访问 jQuery Document.ready()
函数时,这是一个非常有用的函数。还有一个等价的函数叫做ExecuteOrDelayUntilBodyLoaded
,它执行相同的任务,甚至有相同的签名:
ExecuteOrDelayUntilBodyLoaded(<FUNCTION_NAME>);
_spPageContextInfo
在编写任何类型的代码时,无论是 JavaScript 还是 C#之类的,总会有需要了解页面、位置或其他环境变量的时候。_spPageContextInfo
对象可以轻松地提供大量有用的信息。在本书的大多数例子中,它被用来提供位置信息,以便构建请求数据的 URL。起初,这似乎不是非常重要的信息,但是当进行 REST API 调用或者通过 JavaScript 对象模型定位另一个站点时,它变得极其重要。
Note
在 Firebug 或开发工具中,可以很容易地访问_spPageContextInfo
对象的所有属性。只需打开 JavaScript 控制台窗口,在每个窗口中键入内容,就可以看到您的环境的结果。
_ sppagecontext info . site absolute URL
此属性提供用户所在的当前网站集的绝对 URL。绝对 URL 是完全限定的 URL,它包含协议(http://
或https://
)和域名( www.
yoursite
.com
)。由于 SharePoint 可以利用备用访问映射,从而允许您对相同的内容使用不同的域,因此该功能提供了一种非常有用的方法来构建 URL,而不必担心用户从哪里访问页面。
由于这是网站集的路径,因此生成的 URL 可能类似于以下内容:
http://www.<DOMAIN>.com
http://www.<DOMAIN>.com/sites/<SITE_NAME
>
_ sppagecontext info . site server relative URL
此属性为用户所在的当前网站集提供相对于服务器的 URL。相对 URL 只是从 URL 中省略了协议和域。这是一个方便的工具,因为很多时候你需要网站集的相对 URL。如前所述,由于 SharePoint 内容能够在许多不同的域上被访问,因此以相对 URL 为目标允许您跨多个域发布相同的代码,而不用担心代码将在哪里运行。
例如,如果您要在根站点集合中调用该属性,那么产生的 URL 将只是/
。
_ sppagecontextinfo . webabsoluteurl
此属性提供用户所在的当前网站的绝对 URL。这是包括协议和域的完全限定的 URL。URL 生成的代码如下所示:
http://www.<DOMAIN>.com
http://www.<DOMAIN>.com/<SUBSITE
>
http://www.<DOMAIN>.com/sites/<SITE_COLLECTION>/<SUBSITE
>
_ sppagecontextinfo 服务器相对关系
此属性为用户所在的当前网站提供相对于服务器的 URL。与相对于站点的 URL 一样,它从 URL 中省略了协议和域。URL 生成的代码如下所示:
/
/<SUBSITE>
/sites/<SITE_COLLECTION>/<SUBSITE>
ExecuteOrDelayUntilScriptLoaded
这个函数允许您指定一个 JavaScript 函数延迟,直到另一个脚本被完全加载。本质上,我们是在告诉 SharePoint:“我想运行这个特定的函数,但是我需要等到这个脚本被加载。”它有以下签名:
ExecuteOrDelayUntilScriptLoaded(<FUNCTION_NAME>, <SCRIPT_FILE>);
SharePoint 首先检查是否加载了指定的 JavaScript 文件;如果是,它会立即执行指定的函数。如果文件没有被加载,它将函数调用放入一个队列中,稍后再执行。我们将在下一章使用 JavaScript 对象模型查询用户数据时用到它:
$(function () {
ExecuteOrDelayUntilScriptLoaded(getUserProfileProperties, "sp.userprofiles.js");
});
function getUserProfileProperties() {
var clientContext = new SP.ClientContext();
...
正如您在这个代码片段中看到的,我们有一个 jQuery Document.ready()
函数,我们在其中放置了ExecuteOrDelayUntilScriptLoaded
函数。我们传入函数getUserProfileProperties
和 JavaScript 文件sp.userprofiles.js
。我们需要在这里实现这个函数,因为函数中包含的代码只有在加载了sp.userprofiles.js
文件的情况下才能运行。SharePoint 提供了一种确保代码功能的简单方法!
Note
ExecuteOrDelayUntilScriptLoaded
功能是 SharePoint 2010 的延续,它位于SP.SOD
对象下。SharePoint 2013 中存在较新版本无法正常工作的情况,通常是在发布门户页面上。如果您发现此功能不起作用,您可以恢复到 2010 年的实现。更多信息请访问 http://msdn.microsoft.com/en-us/library/office/ff408081%28v=office.14%29.aspx
。
物种 UI .通知
SP.UI.Notify
对象提供了多种方式来通知用户有事情发生。此功能提供了一种利用现成 SharePoint 通知的方式,并允许您的自定义解决方案无缝融入环境。虽然本书中的示例没有利用这种通知框架,但是可以很容易地对它们进行重构,以便在发生创建或删除操作时包含通知。如果可能的话,通知用户事件的发生总是一个好的做法。
SP(存储处理器)。ui . notify . showloadingnotification
SP.UI.Notify.showLoadingNotification
功能是显示熟悉的“正在处理中...”的一种快速简单的方式通知。如果你使用 SharePoint 有一段时间了,你肯定会看到这些信息中的一条,它会从屏幕的右侧弹出。它包括一个“旋转器”图标,如图 7-2 所示。
图 7-2。
Loading notification launched via Firebug
您可以随时在代码中使用以下代码行启动此通知:
SP.UI.Notify.showLoadingNotification();
事实上,您也可以启动 Firebug 或开发人员工具,并在浏览器中直接调用它。图 7-2 显示了从控制台通过 Firebug 触发的通知。
这是一种快速便捷的方式,通过您的代码通知用户有事情发生。虽然这种一般的通知在某些情况下肯定是足够的,但是您可能需要提供更多关于正在发生的事情的解释。为此,您可以使用SP.UI.Notify.addNotification
方法。
物种 UI.Notify.addNotification
与前面的函数非常相似,SP.UI.Notify.addNotification
用于在同一位置向用户显示通知,但带有自定义消息。当您需要通知用户一个动作正在发生,但需要比简单的“正在进行中...”更具描述性时,这是非常完美的消息。图 7-3 显示了正在显示的自定义信息。
图 7-3。
A custom message being displayed to notify the user
您可以使用以下命令行启动此通知:
SP.UI.Notify.addNotification("Your Custom Message");
如您所见,通过 JavaScript 添加自定义通知再简单不过了。您显示的消息没有最大长度限制。然而,随着消息变长,它最终会到达屏幕的另一侧,文本开始换行。这可能并不总是正确的布局,所以最好保持你的信息简短。图 7-4 显示了一条更长的信息。
图 7-4。
A longer message can be displayed via a notification
通知只会在页面上停留大约 6 秒钟。如果您只需要通知用户发生了一个动作,但不需要等待响应,这就很好。然而,有时候你需要开始一个行动,然后等待一个结果。在这种情况下,你可能需要你的通知多留一会儿。您可以使用以下行包含一个布尔值来指示通知应该保留:
SP.UI.Notify.addNotification("Your Custom Message", true);
通过使用前面的代码行,通知将一直存在,直到被手动关闭。您可以通过调用SP.UI.Notify.removeNotification
函数,从addNotification
函数调用传入通知 ID 来实现这一点。当您调用addNotification
函数时,您会得到刚刚创建的通知的 ID,如图 7-5 所示。
图 7-5。
The Notification ID that is returned when you create a new notification
如果我们在代码中使用它,该行将如下所示:
var notifyId = SP.UI.Notify.addNotification("Hello World", true);
当我们执行这一行时,notifyId
变量现在有了新创建的通知的 ID。稍后,我们可以使用以下代码行来关闭通知:
SP.UI.Notify.removeNotification(notifyId);
SP.UI.Notify.removeNotification
只是获取通知的 ID 并将其从屏幕上删除。当调用showLoadingNotification
函数时,也可以使用布尔标志:
SP.UI.Notify.showLoadingNotification(true);
传入布尔值触发通知 ID 的相同返回,如图 7-6 所示。
图 7-6。
A Notification ID is returned when using the Boolean flag
这些函数提供了一种简单的方式,通过 JavaScript 通知用户正在发生什么。例如,如果您需要执行一个长时间运行的 AJAX 调用,您可以让用户知道这正在发生,这样他们就不会对您的 web 部件失去耐心。
摘要
微软已经走了很长一段路,不仅为开发人员提供了通过 JavaScript 访问数据的方法,还开发了核心的 SharePoint 功能。在这一章中,我们探索了一些内置的 JavaScript 函数和属性。我们看到了如何访问位置数据来更容易地为 REST API 调用和超链接构建 URL。我们看到了如何将函数调用加载到 SharePoint 内的 body onload 事件中,以及如何确保在执行代码之前功能对代码可用。最后,我们看了一些不同的方法来通知你的用户你的代码正在做什么来提供更好的用户体验。
八、使用 JavaScript 对象模型
到目前为止,已经向您介绍了使用 HTML 和 JavaScript 在 SharePoint 中创建自定义解决方案的几种不同方法。在这一章中,我们将继续探索使用 Etherson 方法来创建定制的 web 部件以及 JavaScript 对象模型。在第二章中,我们简要地看了一下 JavaScript 对象模型,或 JSOM。在这一章中,我们将了解如何使用 JSOM 处理列表、库、文件、网站和社交数据。将向您介绍使用 SharePoint 数据的各种方法,并开始全面了解这项技术的威力。
JSOM 有能力为您的发展需求提供广泛的选择。您可以创建新列表和网站;你可以读取文件,与社交数据互动。到本章结束时,你将对如何编写 JSOM 代码有一个坚实的掌握,并知道它能做什么。
Note
利用 JavaScript 对象模型的代码在登录用户的上下文中运行。这意味着代码只能执行用户权限级别允许的操作。例如,如果您有在网站集中创建新的子网站的代码,但登录的用户没有该权限,它将运行但会产生错误。在构建解决方案时请记住这一点,并确保不向用户展示他们无法利用的选项。
正在设置
在开始之前,我们需要在本书中一直使用的演示列表中添加一些额外的数据。添加一些额外的数据将允许我们查询更多的数据和应用过滤器。导航到演示列表,并添加更多具有不同状态的列表项。更新后的列表如图 8-1 所示。
图 8-1。
Demo List with more items added to it
现在我们在列表中有了一些额外的数据,让我们开始看看如何使用 JSOM 查询数据。本章中的例子将利用第四章中介绍的 Etherson 方法。导航到站点中的 Webparts 文件夹,新建一个名为 Chapter 8 的文件夹,如图 8-2 所示。
图 8-2。
Chapter 8 folder in the Webparts document library
本章中的每个例子都将遵循相同的模式。我们将查看在内容编辑器 Web 部件中呈现的 HTML 文件,用于检索和呈现数据的 JavaScript 文件,最后是结果。在这个过程中,我们将深入每个文件并解释发生了什么。
使用列表
SharePoint 中到处都是列表!作为用户,您将在 SharePoint 中与列表进行交互。下面的例子将演示通过代码与列表交互的各种方式。
获取列表数据
在这个例子中,我们将简单地检索一些列表数据来显示给用户。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMGetListData.html。本例的 HTML 非常简单,仅包含以下几行:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/webparts/chapter 8/JSOMGetListData.js"></script>
<div id="divGetListData"></div>
首先,您会注意到我们必须加载两个 SharePoint JavaScript 文件:sp.runtime.js
和sp.js
。这两个文件非常重要,因为它们提供了正确运行 JSOM 代码所需的必要代码。在 SharePoint 2010 中,所有需要的 JavaScript 总是加载在每个页面上。这使得 JavaScript 开发变得更加容易,因为您不必担心核心 SharePoint 脚本是否被加载。在 SharePoint 2013 中,只加载页面所需的基本代码。这有助于 SharePoint 更快地加载页面;但这也意味着,如果你需要一个特定的库,你需要确保它是加载的。在我们的例子中,我们需要这两个文件。
接下来,我们加载名为JSOMGetListData
的自定义 JavaScript 文件。该文件包含将数据加载到页面上的 DIV 的所有代码,该页面的 ID 为divGetListData
。总而言之,这一页没有多少内容。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 JSOMGetListData.js。相比之下,该 JavaScript 文件更复杂,由以下几行组成:
$(function () {
getListData();
});
function getListData() {
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
this.collList = oWebsite.get_lists();
clientContext.load(collList);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
var listInfo = '';
var listEnumerator = collList.getEnumerator();
while (listEnumerator.moveNext()) {
var oList = listEnumerator.get_current();
listInfo += 'Title: ' + oList.get_title() + ' - Created: ' +
oList.get_created().toString() + '<br />';
}
$("#divGetListData").html(listInfo);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
本书中的大多数 JSOM 例子都遵循与这个例子相同的模式。让我们深入到每一行的细节,以充分了解发生了什么。该脚本以一个 jQuery Document.ready
方法开始,该方法简单地调用一个名为getListData
的自定义函数,该函数进行 JSOM 调用,并且是主要代码所在的位置。
首先,我们创建一个名为clientContext
的新变量,并使用以下代码行设置它:
var clientContext = new SP.ClientContext();
客户端上下文是一个 SharePoint 对象,它实际上是所有 JSOM 调用的入口点。它保存了大量关于当前站点、用户、web 等的上下文信息。在这个例子中,我们只是要求返回上下文,而不传递任何参数。这将自动返回当前站点的上下文。您也可以通过传入一个 URL 来询问其他站点的上下文;比如,SP.ClientContext('
http://www.site.com
')
。
接下来,我们创建另一个名为oWebsite
的变量,并使用以下代码行设置它:
var oWebsite = clientContext.get_web();
这将为我们提供用户执行代码的站点集合中的当前站点或网站。我们需要这个网站来获取所有的列表。接下来,我们使用下面的代码行创建另一个名为collList
的变量:
this.collList = oWebsite.get_lists();
该变量由来自oWebsite
变量的所有列表填充。collList
变量的声明与其他变量略有不同,因为这里没有var
关键字,而是this
。这样做的原因是,this
关键字将使这个变量成为全局变量,以便以后处理数据所需的函数可以访问它。
当您第一次开始使用 JSOM 时,下一行通常会让您感到头疼:
clientContext.load(collList);
这一行将查询“加载”到客户端上下文中,以发送到 SharePoint。这意味着此时您实际上还没有向 SharePoint 发送任何数据请求。在大多数 JavaScript 开发中,您可能会认为像this.collList = oWebsite.get_lists();
这样的行会立即返回所有列表,您可以开始使用它们了。在 JSOM,情况并非如此。您必须加载您想要发出的任何请求,然后使用下面的行提交它们:
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
直到调用executeQueryAsync
函数,对 SharePoint 的请求才真正发生。在使用 JSOM 时,理解这一点非常重要,这也是很多开发人员第一次起步时会犯的错误。在提交请求之前必须加载所有请求的原因是一个称为批处理的特性。基本上,SharePoint 允许您加载多个数据请求,然后只进行一次执行调用来获取您需要的所有数据。这使得实际处理 JSOM 调用的服务器性能更好。本书中没有一个例子真正利用了批处理,但这是一个需要了解的重要概念。
executeQueryAsync
方法允许您指定一个success
函数和一个failure
函数,它们在 SharePoint 返回查询结果后被调用。这些是使用Function.createDelegate
方法声明的,如前所示。一旦指定了这些,就需要创建函数来实际处理结果。
function onQuerySucceeded() {
var listInfo = '';
var listEnumerator = collList.getEnumerator();
while (listEnumerator.moveNext()) {
var oList = listEnumerator.get_current();
listInfo += 'Title: ' + oList.get_title() + ' - Created: ' +
oList.get_created().toString() + '<br />';
}
$("#divGetListData").html(listInfo);
}
这个函数以一个名为listInfo
的新变量开始,这个变量将用于保存查询的所有结果,然后将它们显示在页面上。接下来,我们使用collList.getEnumerator()
方法从collList
变量中获取一个枚举器,并将其放入一个名为listEnumerator
的变量中。我们需要遍历返回的所有结果,枚举器允许我们这样做。使用while
循环,我们遍历使用listEnumerator.get_current()
方法返回的每个项目。在每个循环中,我们从当前项目中获取标题和创建日期。我们包含更多的 HTML,并使用+=
将内容添加到listInfo
变量中。这允许我们不断向listInfo
变量添加内容,而不是每次都覆盖它。
最后,我们使用$("#divGetListData").html(listInfo);
将listInfo
变量的内容输出到 HTML 页面中的 DIV。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。结果将显示当前站点的所有列表,如图 8-3 所示。
图 8-3。
Get List Data results in the Content Editor Web Part
创建新列表
在本例中,我们将创建一个新列表。我们不会做任何花哨的事情,只是创建一个新的列表并设置它的标题。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMCreateList.html。这个示例的 HTML 比上一个示例稍微复杂一些,它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/webparts/chapter 8/JSOMCreateList.js"></script>
<div>
<strong>Enter a name for the list:</strong>
<input type="text" id="txtListName" />
<input type="button" id="btnSubmitListName" value="Submit" />
</div>
<div id="divCreateListResults"></div>
和以前一样,我们需要加载sp.runtime.js
和sp.js
文件,以及对我们定制的 JavaScript 文件的引用。HTML 稍微复杂一点,页面上有几个元素。首先,一些简单的文本被包装在一个<strong>
标签中,使其在页面上加粗。接下来,有一个文本类型的输入,它只是一个简单的文本框,供用户输入他们希望创建的列表的名称。有一个按钮供用户提交新的列表请求,最后还有一个 DIV,我们可以在其中输出列表创建的结果。每个元素都有一个 ID,所以我们可以很容易地用 jQuery 找到它。
Note
为了通过 JSOM 创建新列表,执行代码的用户必须至少拥有 SharePoint 中的“管理列表”权限。无论权限级别如何,都将呈现该页面;但是,如果用户没有足够的权限,SharePoint 将引发错误。
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,并将其命名为 JSOMCreateList.js。相比之下,JavaScript 文件更复杂,它由以下几行组成:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
createList(listName);
});
}
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.genericList);
this.oList = oWebsite.get_lists().add(listCreationInfo);
clientContext.load(oList);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
var results = oList.get_title() + ' successfully created!';
$("#divCreateListResults").html(results);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
在这个例子中,我们不需要在页面加载上触发任何动作;然而,我们确实需要在页面加载时连接一个按钮点击事件。在Document.ready
函数中,我们触发了bindButtonClick
函数。在这个函数中,我们使用 jQuery on
操作符在 HTML 中的btnSubmitListName
按钮上连接一个点击事件。当用户点击按钮时,我们从页面上的文本框中获取文本,并使用以下代码行将其传递给createList()
函数:
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
createList(listName);
});
}
createList()
函数接受一个名为listName
的变量,它是用户在页面上输入的文本。接下来,我们获取对当前客户端上下文的引用,并获取当前 web。然后,我们使用以下代码创建列表:
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listName);
listCreationInfo.set_templateType(SP.ListTemplateType.genericList);
this.oList = oWebsite.get_lists().add(listCreationInfo);
clientContext.load(oList);
为了创建一个新的列表,我们使用了一个SP.ListCreationInformation()
对象。我们可以使用下面的代码实例化一个新的ListCreationInformation
对象:
var listCreationInfo = new SP.ListCreationInformation();
这一行所做的就是创建一个新对象,并给它分配一个名为listCreationInfo
的新变量。接下来,我们使用以下代码行设置标题和模板:
listCreationInfo.set_title(listName);
listCreationInfo.set_templateType(SP.ListTemplateType.genericList);
set_title
方法接受传递给函数的listName
。set_templateType
方法接受一个内置值SP.ListTemplateType
,在本例中,我们传入的是genericList
。如果使用 SharePoint UI 在浏览器中创建列表,这里的可用值将是您期望看到的任何值,例如:公告、日历、任务等等。接下来,我们使用以下代码行将列表添加到 web:
this.oList = oWebsite.get_lists().add(listCreationInfo);
clientContext.load(oList);
就像前面的例子一样,在我们将列表添加到站点之后,我们将列表“加载”到客户端上下文中。最后,我们调用executeQueryAsync
函数,该函数实际上会调用 SharePoint 来创建列表。调用完成后,我们使用以下函数处理结果:
function onQuerySucceeded() {
var results = oList.get_title() + ' successfully created!';
$("#divCreateListResults").html(results);
}
在这个函数中,使用oList.get_title()
方法,我们可以获得刚刚创建的列表的标题。这是一个很好的检查,可以确保列表确实被创建了,因为我们从列表本身获得标题,而不是使用用户输入的文本。一旦我们有了列表标题,我们使用 jQuery 将成功消息添加到页面上的divCreateListResults
DIV 中。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面现在将显示文本框和按钮,供用户输入新的列表名称。键入我的自定义列表,然后单击提交按钮。结果将显示成功信息,如图 8-4 所示。
图 8-4。
Create new list code after it has been run
因为这些都是使用 JavaScript 和 AJAX 完成的,所以列表会被创建,用户会得到预期的通知。但是,页面上的左侧导航将不会更新,因为页面尚未刷新。您完全可以更改这段代码,以便在成功时刷新页面,但是在本例中,我们只是在浏览器中刷新页面。图 8-5 显示了刷新后的页面,新列表显示在左侧导航中。
图 8-5。
The new list as displayed in the left navigation pane
删除列表
在本例中,我们将简单地删除我们在上一节中刚刚创建的列表。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMDeleteList.html。此示例的 HTML 与上一个示例几乎相同,它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/webparts/chapter 8/JSOMDeleteList.js"></script>
<div>
<strong>Enter the name of the list to delete:</strong>
<input type="text" id="txtListName" />
<input type="button" id="btnSubmitListName" value="Submit" />
</div>
<div id="divDeleteListResults"></div>
这里唯一的不同是,我们更新了页面上的文本,以表明这是将删除列表的 web 部件,并且我们将结果 DIV 的 ID 更改为divDeleteListResults
。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 JSOMDeleteList.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
deleteList(listName);
});
}
function deleteList(listName) {
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
this.oList = oWebsite.get_lists().getByTitle(listName);
oList.deleteObject();
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divDeleteListResults").html("List successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
该脚本从熟悉的 jQuery Document.ready
函数开始,它将按钮点击绑定到一个函数:
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
deleteList(listName);
});
}
这个函数与上一个例子几乎相同——除了删除列表的新函数名deleteList
。这个函数更小也更切题,只有几行相关的代码:
this.oList = oWebsite.get_lists().getByTitle(listName);
oList.deleteObject();
在获得对客户端上下文和当前 web 的引用后,我们使用 web 对象上的getByTitle()
方法来定位我们希望删除的列表,然后将它赋给一个名为oList
的变量。接下来,我们调用oList.deleteObject()
方法来实际执行删除。您会注意到,在客户端上下文对象上没有“load”方法。删除列表时,不需要执行此步骤。在deleteObject()
行之后,您可以简单地调用executeQueryAsync()
方法来执行删除操作。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面现在将显示文本框和按钮,供用户输入要删除的列表名称。键入我的自定义列表,然后单击提交按钮。结果将显示成功信息,如图 8-6 所示。
图 8-6。
Delete List code after it has successfully run
因为这些都是使用 JavaScript 和 AJAX 完成的,所以列表将被删除,用户将得到预期的通知。但是,页面上的左侧导航将不会更新,因为页面尚未刷新。和以前一样,我们可以更新这段代码以在成功时刷新页面,但是对于这个例子,我们只是在浏览器中刷新页面。图 8-7 显示了刷新后的页面,其中列表不再显示在左侧导航中。
图 8-7。
The deleted list has been removed from the left navigation
使用列表项目
SharePoint 中唯一比列表更丰富的是列表项。您会发现,您在 SharePoint 中的许多交互都与列表项有关,因此您的许多代码也会涉及到它们。在这一节中,我们将探索一些通过代码使用列表项的方法。
获取列表项目
在这个例子中,我们将简单地检索一些列表项,并将它们显示给用户。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMGetListItems.html。这个示例的 HTML 继续遵循前面示例的极简模式,它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/webparts/chapter 8/JSOMGetListItems.js"></script>
<div id="divListItems"></div>
对于这个例子,我们将简单地从演示列表中获取所有的列表项,并将它们显示在页面上的divListItems
DIV 中。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 JSOMGetListItems.js。检索列表项的脚本应该与我们到目前为止看到的其他脚本非常相似,它由以下几行组成:
$(function () {
retrieveListItems();
});
function retrieveListItems() {
var clientContext = new SP.ClientContext();
var oList = clientContext.get_web().get_lists().getByTitle('Demo List');
var camlQuery = new SP.CamlQuery();
this.collListItem = oList.getItems(camlQuery);
clientContext.load(collListItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded(sender, args) {
var listItemInfo = '';
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
listItemInfo += '<strong>ID: </strong> ' + oListItem.get_id() +
' <strong>Title:</strong> ' + oListItem.get_item('Title') +
'<br />';
}
$("#divListItems").html(listItemInfo);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
对于这个例子,由于我们将从列表中获取所有的条目,我们将使用 jQuery Document.ready
函数调用retrieveListItems()
函数。在获得对客户端上下文的引用后,我们用下面的代码行获得对演示列表的引用:
var oList = clientContext.get_web().get_lists().getByTitle('Demo List');
乍一看,这一行似乎很吓人,因为它很长。然而,它实际上很容易阅读。首先,我们获取当前网站,然后获取网站中的所有列表,最后,我们根据标题获取列表。JSOM 和 REST 在查询对象时都遵循这种类型的模式,使得代码易于理解。接下来,我们需要创建一个 CAML 查询,让 SharePoint 知道我们正在查找哪些项目:
var camlQuery = new SP.CamlQuery();
this.collListItem = oList.getItems(camlQuery);
CAML(协作应用标记语言)查询是一种在 SharePoint 中用于定义列表项查询的查询语言。您可以根据类似 SQL 查询的标准指定要返回的项目,尽管它们看起来一点也不像。在这个例子中,我们简单地使用新的SP.CamlQuery()
方法创建一个空查询。查询列表时,即使没有定义参数,也必须提供 CAML 查询。如果您传递一个空的查询,就像在这个例子中,您实际上是要求返回所有的条目。实际上,这不是一个好主意,因为很多列表包含成百上千的条目。在我们创建了查询之后,我们将它传递给oList.getItems()
方法来执行查询。正如在其他例子中一样,我们使用了一个名为collListItems
的全局变量,并使用了this
关键字。最后,我们“加载”查询并执行它。
Note
CAML 查询是一个相当复杂和深刻的话题。在这本书里,我们只触及 CAML 的皮毛;它有那么大。我们将在下一节更深入地探讨 CAML,但是您可以在 http://msdn.microsoft.com/en-us/library/ms467521(v=office.15).aspx
了解更多关于如何构建这些查询的信息。
一旦我们检索到列表项,我们就在onQuerySucceeded
函数中处理它们:
function onQuerySucceeded(sender, args) {
var listItemInfo = '';
var listItemEnumerator = collListItem.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
listItemInfo += '<strong>ID: </strong> ' + oListItem.get_id() +
' <strong>Title:</strong> ' + oListItem.get_item('Title') +
'<br />';
}
$("#divListItems").html(listItemInfo);
}
这个函数从声明一个名为listItemInfo
的空变量开始。这个变量将保存将在页面上显示的整个 HTML。接下来,我们获得了collListItem
变量的枚举器,您会记得它在从 SharePoint 返回的任何项目集合上都可用。我们使用listItemEnumerator.moveNext()
方法循环遍历条目。在循环内部,我们使用listItemEnumerator.get_current()
方法获取每个项目。然后,我们为结果集中显示 ID 和标题的每一项构建一些 HTML,并将其填充到listItemInfo
变量中。最后,我们用 jQuery 将 HTML 设置为页面上的divListItems
DIV。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面现在将显示演示列表中的所有项目,如图 8-8 所示。
图 8-8。
List items from the Demo List displayed in the Content Editor Web Part
用 CAML 查询限制结果
正如我提到的,查询列表中的所有项目通常不是一个好主意。当然,有时候这是需要的或者有意义的;例如,您可能有一个项目很少的列表,或者您有一个需要查看所有项目的管理员任务。如果您过去使用过 SharePoint,您应该知道 SharePoint 会自动限制列表结果,默认情况下一个查询会有 2,000 个结果。在任一情况下,大多数用户都不需要查看列表中的所有项目,并且查询将被限制为仅显示用户需要查看的项目。
CAML 允许您基于各种各样的参数来限制结果,这使您可以完全控制向用户显示什么。在前面的例子中,我们通过创建一个新的SP.CamlQuery
对象来传递一个空的 CAML 查询,该对象返回所有的列表项。您可以通过对CamlQuery
对象使用set_viewXml()
方法来传递 CAML 查询,如下面的“JavaScript”部分所示。
Java Script 语言
更新前一个示例中的JSOMGetListItems.js
,并用以下代码行更新声明SP.CamlQuery()
对象的部分:
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(
'<View><Query><Where><Geq><FieldRef Name=\'ID\'/>' +
'<Value Type=\'Number\'>5</Value></Geq></Where></Query>' +
'<RowLimit>10</RowLimit></View>'
);
this.collListItem = oList.getItems(camlQuery);
在本例中,我们通过指定只需要 ID 大于或等于 5 的项目来限制结果。这是通过使用代表“大于或等于”的GEQ
元素来完成的在GEQ
元素之前,我们使用一个Where
元素并指定 ID 的FieldRef
,它是列表项的 ID。如果这些看起来像拉丁语,不要担心,你可以下载一些工具来帮助你写 CAML。我们不会深入研究编写 CAML 查询的细节;对于这一部分,您应该明白,您可以非常详细地调整您的查询。
Note
乍一看,CAML 可能显得相当混乱和过于复杂。当你和 CAML 一起工作了一段时间后,你可能还在想同样的事情!幸运的是,有几个很棒的免费工具可以帮助你制作你的 CAML 报表。我个人喜欢 SharePoint CAML 查询助手,它是免费的,可以在 CodePlex 上下载。访问 https://spcamlqueryhelper.codeplex.com
下载一份。
结果
更新 JavaScript 文件并上传,覆盖之前的版本。使用内容编辑器 Web 部件刷新页面,您将看到结果现在只显示 ID 大于或等于 5 的项目,如图 8-9 所示。
图 8-9。
The results of the Demo List query limited by a CAML query
添加列表项目
在本例中,我们将向演示列表添加一个新项目。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为JSOMAddListItems.html
。该页面的标记将允许用户向演示列表添加一个项目,提供标题和描述。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMAddListItems.js"></script>
<div id="AddListData">
<div>
Title:
<br />
<input type="text" id="txtTitle" />
</div>
<div>
Description:
<br />
<textarea cols="20" id="txtDesc"></textarea>
</div>
<br />
<div>
<input id="btnSubmit" type="button" value="Submit" />
</div>
</div>
<div id="divResult"></div>
我们为列表项标题提供文本类型的输入,并为描述提供文本区域。页面上的每个元素都有一个 ID,这样我们就可以很容易地用 jQuery 找到它。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 JSOMADDListItems.js。它由以下几行组成:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
addListItem();
});
}
function addListItem() {
var title = $("#txtTitle").val();
var desc = $("#txtDesc").val();
var clientContext = new SP.ClientContext();
var oList = clientContext.get_web().get_lists().getByTitle('Demo List');
var itemCreateInfo = new SP.ListItemCreationInformation();
this.oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', title);
oListItem.set_item('Description', desc);
oListItem.set_item('Status', 'On-time');
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onAddSucceeded),
Function.createDelegate(this, this.onAddFailed)
);
}
function onAddSucceeded(sender, args) {
$("#divResult").html("Item successfully added!");
}
function onAddFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
在我们用 jQuery 附加了一个按钮点击事件之后,我们在点击事件上做的第一件事就是获取用户用下面几行提供的值:
var title = $("#txtTitle").val();
var desc = $("#txtDesc").val();
接下来,我们获取对当前客户端上下文的引用,以及演示列表。然后,为了创建一个新的列表项,我们必须实例化一个SP.ListItemCreationInformation
对象。此对象允许您为列表创建新的列表项并设置其属性。这是通过以下代码完成的:
var itemCreateInfo = new SP.ListItemCreationInformation();
this.oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', title);
oListItem.set_item('Description', desc);
oListItem.set_item('Status', 'On-time');
oListItem.update();
一旦我们创建了一个新的SP.ListItemCreationInformation
对象,我们使用 list 对象上的addItem()
方法将它添加到列表中。接下来,我们使用set_item()
方法在列表项对象上设置单独的属性。这个方法有两个参数。第一个参数是要为其设置值的字段或列,第二个参数是值本身。对于标题和描述,我们只需传入之前检索到的值。对于 Status 列,我们简单地将 On-time 硬编码为一个值。最后,我们使用update()
方法更新项目,然后将其加载到客户机上下文中并执行查询。在success
函数中,我们简单地向屏幕输出列表项创建成功。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示供用户输入详细信息的文本框,然后在添加项目时显示成功消息,如图 8-10 所示。
图 8-10。
Adding a new item to the Demo List
然后,我们可以导航到演示列表,以确认添加了新项目。图 8-11 显示了添加了新列表项和 HTML 页面提供的值的演示列表。
图 8-11。
A new list item added to the Demo List
删除列表项目
这个例子将向你展示如何删除列表项,在这种情况下,我们将删除我们在上一个例子中添加的项目。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMDeleteListItems.html。这个文件的 HTML 要小得多,因为我们需要从用户那里获取的只是一个对应于他们想要删除的列表项的 ID。这是通过以下代码行实现的:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMDeleteListItems.js"></script>
<div>
Enter ID to Delete: <input type="text" id="txtId" />
</div>
<div>
<input id="btnSubmit" type="button" value="Submit" />
</div>
<div id="divResult"></div>
这个例子过于简单,因为用户很可能不知道要删除的某个列表项的 ID。一个更真实的例子可能是向用户显示一个项目列表,并允许他们单击一个项目来删除它。在这种情况下,页面上会有列表项 id,并且可以很容易地访问它。我们将保留一个简单的文本框来简化这个例子。
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,并将其命名为 JSOMDeleteListItems.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteListItem();
});
}
function deleteListItem() {
var id = $("#txtId").val();
var clientContext = new SP.ClientContext();
var oList = clientContext.get_web().get_lists().getByTitle('Demo List');
this.oListItem = oList.getItemById(id);
oListItem.deleteObject();
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded(sender, args) {
$("#divResult").html("Item successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
页面上的按钮点击事件将调用deleteListItem()
函数。使用下面的代码行,我们要做的第一件事是获取用户在页面上输入的 ID:
var id = $("#txtId").val();
接下来,我们获得当前的客户端上下文和对演示列表的引用。删除项目是通过以下几行完成的:
this.oListItem = oList.getItemById(id);
oListItem.deleteObject();
我们在 list 对象上使用getItemById()
方法,传递用户提交的 ID。然后,我们调用deleteObject()
方法来实际执行删除。与本章前面的删除列表类似,这是删除列表项所需的全部内容。我们不需要将删除调用加载到客户端上下文中;我们只需要执行查询。success
函数将简单地通知用户删除成功。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面会显示供用户输入 ID 的文本框,当删除一项时会显示成功消息,如图 8-12 所示。
图 8-12。
Deleting a list item using JSOM
使用文档库
因为 SharePoint 的优势之一在于文档管理,所以您需要知道如何通过代码使用文档库。因为文档库实际上只是 SharePoint 中的列表,所以您在这方面已经有了一些经验!
创建新文件夹
在本例中,我们将演示如何在现有文档库中创建新文件夹。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMCreateFolder.html。这个页面的标记非常简单,允许用户输入他们希望创建的文件夹的名称。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMCreateFolder.js"></script>
<div>
<strong>Enter a name for the folder:</strong>
<input type="text" id="txtFolderName" />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMCreateFolder.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createFolder();
});
}
function createFolder() {
var folderName = $("#txtFolderName").val();
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
var oList = oWebsite.get_lists().getByTitle("Documents");
var folderCreateInfo = new SP.ListItemCreationInformation();
folderCreateInfo.set_underlyingObjectType(SP.FileSystemObjectType.folder);
folderCreateInfo.set_leafName(folderName);
this.oListItem = oList.addItem(folderCreateInfo);
this.oListItem.update();
clientContext.load(oList);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divResults").html("Folder successfully created!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
在使用 jQuery 连接按钮点击之后,createFolder()
函数从获取用户在页面上输入的文件夹名称开始:
var folderName = $("#txtFolderName").val();
接下来,我们获取一个对当前客户端上下文和当前站点的引用,然后用下面一行引用共享文档文件夹:
var oList = oWebsite.get_lists().getByTitle("Documents");
本示例将在共享文档库中新建一个文件夹。因为所有文档库实际上都是 SharePoint 中的列表,所以我们可以使用getLists().getByTitle()
方法来检索该库。接下来,我们为文件夹创建一个新的SP.ListItemCreationInformation
对象:
var folderCreateInfo = new SP.ListItemCreationInformation();
乍一看,这似乎很奇怪,因为我们正在创建一个新文件夹,而不是一个列表项。在 SharePoint 中,文件夹是列表项,尽管它们的外观和行为就像您对文件夹的期望一样。因此,使用相同的SP.ListItemCreationInformation
对象。既然已经创建了对象,我们需要使用下面几行设置一些属性:
folderCreateInfo.set_underlyingObjectType(SP.FileSystemObjectType.folder);
folderCreateInfo.set_leafName(folderName);
this.oListItem = oList.addItem(folderCreateInfo);
this.oListItem.update();
首先,由于这不是一个标准的列表项,我们需要使用set_underlyingObjectType()
方法指定对象类型,将SP.FileSystemObjectType.folder
作为参数传入。接下来,我们使用set_leafName()
方法设置文件夹名称,传递用户从页面提交的名称。最后,我们将新文件夹添加到列表中并更新它,然后在客户机上下文中加载查询。success
功能将简单地向屏幕输出一条消息,通知用户文件夹已成功创建。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面会显示文本框,供用户输入要创建的文件夹的名称,完成后会显示成功消息,如图 8-13 所示。
图 8-13。
Creating a new folder with JSOM
然后,我们可以导航到文档库,直观地验证新文件夹是否已创建,如图 8-14 所示。
图 8-14。
New folder created via JSOM
使用文件
列表和库并不是您的编码技能将被使用的唯一领域。在这一节中,我们将看看如何通过代码处理文件。
创建新文件
在本例中,我们将创建一个新的文本文件,并将其添加到文档库中。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMCreateDocument.html。该页面的标记将允许用户输入新文本文件的名称,以及文件本身的内容。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMCreateDocument.js"></script>
<div id="CreateFile">
<div>
<strong>Enter a title for the document:</strong>
<br />
<input type="text" id="txtDocumentTitle" />
</div>
<div>
<strong>Enter content for the document:</strong>
<br />
<textarea cols="20" id="txtDocumentContent"></textarea>
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMCreateDocument.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createDocument();
});
}
function createDocument() {
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var docContent = $("#txtDocumentContent").val();
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
var oList = oWebsite.get_lists().getByTitle("Documents");
var fileCreateInfo = new SP.FileCreationInformation();
fileCreateInfo.set_url(docTitle);
fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
for (var i = 0; i < docContent.length; i++) {
fileCreateInfo.get_content().append(docContent.charCodeAt(i));
}
this.newFile = oList.get_rootFolder().get_files().add(fileCreateInfo);
clientContext.load(this.newFile);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divResults").html("Document successfully created!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
我们需要做的第一件事是获取用户在页面上输入的文档标题和内容。这是通过以下代码行实现的:
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var docContent = $("#txtDocumentContent").val();
注意,我们在文档标题的末尾添加了.txt
。这将让 SharePoint 知道我们打算创建一个文本文件,因为它将使用名称中的扩展名来确定文件类型。接下来,我们获得对当前客户机上下文的引用,以及我们想要保存新文档的 web 和文档库。现在我们需要创建一个新的SP.FileCreationInformation
对象并设置它的属性:
var fileCreateInfo = new SP.FileCreationInformation();
fileCreateInfo.set_url(docTitle);
fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
现在,您应该开始看到使用 SharePoint 在 JavaScript 中创建对象的模式。您创建的任何东西都有一个与之相关联的CreationInformation
对象。一旦创建了对象,我们就使用set_url()
方法设置文件的 URL。最后,我们使用SP.Base64EncodedByteArray()
对象将文件的内容设置为一个空字节数组。你暂时不需要太担心这个对象的细节;要知道这是 JSOM 代码在设置新文件内容时所期望的。现在我们已经创建了空数组,我们需要使用以下代码填充它:
for (var i = 0; i < docContent.length; i++) {
fileCreateInfo.get_content().append(docContent.charCodeAt(i));
}
这是一个简单的循环,将用户提交的文本中的每个字符添加到文件内容的空数组中。一旦循环完成,文本被输入到文档中,我们就将它添加到库中:
this.newFile = oList.get_rootFolder().get_files().add(fileCreateInfo);
然后,我们在客户机上下文中加载查询并执行它。success
功能将简单地向屏幕输出文件创建成功。
Note
在本例中,我们正在创建一个简单的文本文件。在大多数实际情况下,文本文件可能不是预期的结果,但可能是 Word 文件或 Excel 文件。您完全可以通过简单地将.txt
更改为.docx
来更改这个示例以生成一个 Word 文档。实际上,这个简单的更改会创建一个包含内容的新 Word 文档。但是,它只能在客户端计算机上的 Word 中打开,而不能在 Office Web Apps 中打开。幸运的是,微软提供了 Office JavaScript 文件,允许您从浏览器创建和操作 Office 文件。你可以在 http://msdn.microsoft.com/en-us/library/office/fp160953%28v=office.15%29.aspx
找到更多信息。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本框,供用户输入文档的标题和内容,然后在新文档创建完成后显示成功消息,如图 8-15 所示。
图 8-15。
Creating a new document from a Content Editor Web Part
我们可以导航到 Documents 文件夹,发现新的文本文档已经创建。您可以单击该文档,它将在浏览器中打开,并显示用户从页面中输入的内容,如图 8-16 所示。
图 8-16。
New text document created in the Documents folder
阅读文件
在这一节中,我们将看到如何读取我们在前一个例子中创建的文件。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMReadDocument.html。这个页面的标记非常简单,只有一个对定制 JavaScript 文件的引用和一个输出文档内容的 DIV。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMReadDocument.js"></script>
<div id="divReadDocument" />
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMReadDocument.js 包括以下代码:
$(function () {
readDocument();
});
function readDocument() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var documentLibrary = "/Shared Documents/"
var fileUrl = "New Text Doc.txt";
var fullUrl = siteUrl + documentLibrary + fileUrl;
$.ajax({
url: fullUrl,
type: "GET"
})
.done(function (data) {
$("#divReadDocument").html(data);
})
.fail(function () {
alert("error");
});
}
乍一看,这段代码应该很简洁,您会注意到这里根本没有 JSOM 代码。从 SharePoint 读取文本文件的美妙之处在于,您所需要的只是 jQuery。因为这是关于 JSOM 的一章,这段代码应该在别的地方,但是因为我们创建了一个文档,你也应该知道如何阅读它。有一个简单的 jQuery Document.ready
函数,它将触发代码来读取文件。我们有意保持代码简单,并对我们刚刚创建的文档的文件名进行硬编码:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var documentLibrary = "/Shared Documents/"
var fileUrl = "New Text Doc.txt";
var fullUrl = siteUrl + documentLibrary + fileUrl;
我们做的第一件事是通过使用_spPageContextInfo.webAbsoluteUrl
获得当前网站的完整 URL。接下来,我们对 URL 的文档库部分和文件名进行硬编码。最后,我们将它们放入一个名为fullUrl
的新变量。您完全可以在一行中完成所有这些工作,但是您会发现,如果您将代码分成几行,以后调试代码会更容易。一旦我们有了文件的 URL,我们就使用 jQuery AJAX 调用来获取文档:
$.ajax({
url: fullUrl,
type: "GET"
})
.done(function (data) {
$("#divReadDocument").html(data);
})
.fail(function () {
alert("error");
});
当在 jQuery 中通过 AJAX 检索文本文件时,内容将以文本形式返回,我们可以简单地将它输出到页面,无需任何修改。我们使用 jQuery .done
函数,将文件内容设置为一个名为data
的新变量。然后,我们将数据设置为页面上结果 DIV 的 HTML。
Note
和以前一样,当创建一个新文件时,我们通过使用文本文件来保持事情的简单。这也适用于本节和读取文件。使用上述方法无法读取 Office 文件。您需要利用 Office JavaScript 文件在浏览器中正确读取 Word 文件或 Excel 文件。你可以在 http://msdn.microsoft.com/en-us/library/office/fp160953%28v=office.15%29.aspx
找到更多信息。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本文件的内容,如图 8-17 所示。
图 8-17。
Contents of the text file displayed on the page
更新文件
您还可以使用 JSOM 轻松更新文件。事实上,更新文件与创建文件的代码基本相同,只是增加了一行代码:
fileCreateInfo.set_overwrite(true);
这一行只是告诉 SharePoint 覆盖以前的同名文件。使用它,您可以轻松地将文本文件的内容读入页面上的文本框,并允许用户修改内容。当用户希望保存文件时,使用与创建文件相同的代码,并包含覆盖命令。
删除文件
在这个例子中,我们将看到如何删除一个文件。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMDeleteDocument.html。该页面的标记有一个文本框,用户可以输入他们希望删除的文件的名称。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMDeleteDocument.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of document to delete:</strong>
<br />
<input type="text" id="txtDocumentTitle" />
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMDeleteDocument.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteDocument();
});
}
function deleteDocument() {
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var clientContext = new SP.ClientContext();
var oWebsite = clientContext.get_web();
var fileUrl = _spPageContextInfo.webServerRelativeUrl +
"/Shared Documents/" + docTitle;
this.fileToDelete = oWebsite.getFileByServerRelativeUrl(fileUrl);
this.fileToDelete.deleteObject();
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divResults").html("Document successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
在连接了按钮点击事件之后,我们做的第一件事就是获取用户想要删除的文档的标题:
var docTitle = $("#txtDocumentTitle").val() + ".txt";
我们将保持这个例子的简单,删除之前创建的文本文件,从而将.txt
扩展硬编码到代码中。接下来,我们执行引用当前客户端上下文和 web 的惯例,然后我们构造文档的路径:
var fileUrl = _spPageContextInfo.webServerRelativeUrl +
"/Shared Documents/" + docTitle;
对于这个路径,我们只需要文档的相对路径,而不需要完整的 URL。我们可以通过使用_spPageContextInfo.webServerRelativeUrl
获得当前网页的相对路径。因为我们知道这个文档位于 Documents 文件夹中,所以我们将对其进行硬编码,并添加用户提交的文档标题。就像 SharePoint 中的其他删除操作一样,我们不需要在客户端上下文中加载这个请求,只需调用deleteObject
方法并执行查询。success
功能将向用户输出一条消息,通知他们文档已被删除。
与我们之前看到的创建、读取和更新文档的功能不同,假设用户拥有删除权限,您可以使用 JSOM 删除您想要的任何文件。SharePoint 在删除文档方面是相当不可知的。您可以很容易地使用相同的代码删除 Office 文档,而没有任何问题或额外的 JavaScript 库。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示一个文本框,供用户输入文档标题,并显示结果消息,如图 8-18 所示。
图 8-18。
Deleting a file via JSOM
使用站点
在这一点上,你可能会想,JSOM 是相当强大的!事实上是的,为了证明这一点,我们将创建一个新的网站!使用列表和库很酷,但是能够通过 JavaScript 创建一个新的站点将真正展示 JSOM 的力量。
创建网站
在本例中,我们将创建一个新的团队站点。除了创建新站点,我们还将设置它的许多属性,包括标题、描述和站点模板。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMCreateSite.html。该页面的标记有一个供用户输入新站点名称的文本框,以及一个用于站点描述的文本框。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMCreateSite.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of the site:</strong>
<br />
<input type="text" id="txtSiteTitle" />
</div>
<br />
<div>
<strong>Enter site description:</strong>
<br />
<textarea cols="20" id="txtSiteDescription"></textarea>
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMCreateSite.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createSite();
});
}
function createSite() {
var siteTitle = $("#txtSiteTitle").val();
var siteDesc = $("#txtSiteDescription").val();
var siteUrl = siteTitle.replace(/\s/g, "");
var clientContext = new SP.ClientContext();
var collWeb = clientContext.get_web().get_webs();
var webCreationInfo = new SP.WebCreationInformation();
webCreationInfo.set_title(siteTitle);
webCreationInfo.set_description(siteDesc);
webCreationInfo.set_language(1033);
webCreationInfo.set_url(siteUrl);
webCreationInfo.set_useSamePermissionsAsParentSite(true);
webCreationInfo.set_webTemplate('STS#0');
var oNewWebsite = collWeb.add(webCreationInfo);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divResults").html("Site successfully created!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
创建一个新的站点需要更多的代码,但是现在应该已经非常熟悉了。首先,我们使用下面几行获取用户提交的标题和描述:
var siteTitle = $("#txtSiteTitle").val();
var siteDesc = $("#txtSiteDescription").val();
var siteUrl = siteTitle.replace(/\s/g, "");
创建网站时,除了标题之外,还必须提供网站的 URL。对于这个例子,我们将简单地获取用户为标题输入的文本,并删除所有空格以生成 URL。这是使用 JavaScript 中的replace()
方法完成的,第一个参数是我们要搜索的内容,第二个参数是应该替换的内容。/\s/g
文本表示一个空格,必须用于此功能才能正常工作。
一旦我们有了创建站点所需的变量,我们就引用当前的客户端上下文,然后获取当前站点中的站点集合:
var collWeb = clientContext.get_web().get_webs();
方法返回当前站点中所有子站点的集合。我们最终要将新站点添加到这个集合中。接下来,我们创建一个SP.WebCreationInformation
对象:
var webCreationInfo = new SP.WebCreationInformation();
webCreationInfo.set_title(siteTitle);
webCreationInfo.set_description(siteDesc);
webCreationInfo.set_language(1033);
webCreationInfo.set_url(siteUrl);
webCreationInfo.set_useSamePermissionsAsParentSite(true);
webCreationInfo.set_webTemplate('STS#0');
就像我们之前看到的其他CreationInformation
对象一样,我们创建一个新的WebCreationInformation
对象并设置它的各种属性。幸运的是,在这个对象上配置属性所需的所有方法都是不言自明的;例如,set_useSamePermissionsAsParentSite()
决定这个新站点是否应该继承父站点的权限。有一些您可能不熟悉的棘手参数,例如1033
(在为站点设置语言时表示“英语”)和STS#0
(在设置站点模板时表示团队站点模板)。所有其他属性应该看起来很熟悉。
设置好属性后,我们只需将新站点添加到集合中:
var oNewWebsite = collWeb.add(webCreationInfo);
创建新站点也是另一个不需要在客户机上下文中加载查询的领域。您可以简单地执行查询来创建新站点。success
功能将简单地通知用户站点已经创建。
Note
同样,这些示例中的代码在当前用户的权限级别下运行。由于这些示例中有许多执行更高级的功能,如创建和删除 SharePoint 对象,因此用户需要有适当的权限来执行这些功能。值得再次指出这一点,因为站点创建需要用户对创建新站点的站点拥有完全控制权限。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本框供用户输入新的站点标题和描述,并显示结果消息,如图 8-19 所示。
图 8-19。
Creating a new site via JSOM
然后,我们可以打开创建新站点的站点内容页面,并滚动到底部。在子站点部分,我们可以看到新站点已经创建,如图 8-20 所示。
图 8-20。
The newly created subsite in the Site Contents page
删除网站
在这一节中,我们将删除我们在前一个例子中创建的站点。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMDeleteSite.html。这个页面的标记有一个文本框,用户可以输入他们想要删除的站点的名称。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMDeleteSite.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of the site to delete:</strong>
<br />
<input type="text" id="txtSiteTitle" />
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMDeleteSite.js 包括以下代码:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteSite();
});
}
function deleteSite() {
var siteTitle = $("#txtSiteTitle").val();
var siteTitleNoSpaces = siteTitle.replace(/\s/g, "");
var siteUrl = _spPageContextInfo.webAbsoluteUrl + "/" + siteTitleNoSpaces;
var clientContext = new SP.ClientContext(siteUrl);
var oWebsite = clientContext.get_web();
oWebsite.deleteObject();
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#divResults").html("Site successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
就像前面的例子一样,我们获取用户输入的网站标题,然后删除所有空格:
var siteTitle = $("#txtSiteTitle").val();
var siteTitleNoSpaces = siteTitle.replace(/\s/g, "");
var siteUrl = _spPageContextInfo.webAbsoluteUrl + "/" + siteTitleNoSpaces;
一旦我们有了标题,并删除了空格,我们需要构建一个完整的网站 URL。我们可以通过使用_spPageContextInfo.webAbsoluteUrl
获得当前站点的完整 URL,只需附加一个/
和站点标题,末尾不带空格。我们需要构造一个完整的 URL,以便我们可以请求我们希望删除的站点的客户端上下文,而不是用户所在的当前站点:
var clientContext = new SP.ClientContext(siteUrl);
var oWebsite = clientContext.get_web();
到目前为止,我们一直使用用户查看页面的当前站点的客户端上下文。但是,您可以通过将 URL 作为参数传递给SP.ClientContext()
方法来请求另一个站点的上下文,就像我们在本例中所做的那样。一旦我们有了站点的上下文,我们就可以通过使用clientContext.get_web()
获得对该站点中根站点的引用。就像所有其他删除操作一样,我们简单地调用deleteObject()
方法来请求删除操作:
oWebsite.deleteObject();
success
功能将向用户显示一条消息,通知他们删除已经发生。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面会显示一个文本框供用户输入站点标题,并显示结果信息,如图 8-21 所示。
图 8-21。
Deleting a subsite via JSOM
在本例中,我们将删除刚刚创建的站点。导航回站点内容页面将显示该子站点已被成功删除,如图 8-22 所示。
图 8-22。
The site has been removed from the root site
使用社交数据
SharePoint 的一大新领域是社交数据。如果你要为 SharePoint 编写定制的解决方案,你肯定会在某些时候遇到访问社交数据的需求。本节将演示如何提取这些数据用于您的解决方案。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 JSOMGetSocialData.html。这个页面的标记将包括几个 div 和一个输出数据的 SPAN。它由以下几行组成:
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.userprofiles.js"></script>
<script type="text/javascript" src="/apress/Webparts/chapter 8/JSOMGetSocialData.js"></script>
<link rel="stylesheet" type="text/css" href="/apress/Webparts/chapter 8/JSOMGetSocialData.css" />
<div id="WelcomeMessage">
Welcome back <span id="WelcomeMessageUserName"></span>
</div>
<div id="UserFollows" />
到目前为止,这个例子比其他任何例子都有更多的引用。你会注意到,除了引用sp.js
和sp.runtime.js
,我们还引用了sp.userprofiles.js
。正如本章前面提到的,JSOM 功能包含在许多满足特定需求的不同文件中。在这个例子中,因为我们想要获得用户的社交数据,所以我们必须包含对sp.userprofiles.js
文件的引用,以便访问该功能。
我们还将包含一个名为JSOMGetSocialData.css
的定制 CSS 文件。这将用于设置脚本输出的样式。所有其他的例子都可以很容易地包含 CSS 样式。在您的定制开发工作中,您会发现样式将在您的许多 web 部件中扮演重要角色;所以这个例子将向你展示包含它是多么容易。
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 JSOMGetSocialData.js 包括以下代码:
$(function () {
ExecuteOrDelayUntilScriptLoaded(getUserProfileProperties, "sp.userprofiles.js");
});
function getUserProfileProperties() {
var clientContext = new SP.ClientContext();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
this.userProperties = peopleManager.getMyProperties();
clientContext.load(userProperties);
var followingManager = new SP.Social.SocialFollowingManager(clientContext);
this.following = followingManager.getFollowed(15);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
function onQuerySucceeded() {
$("#WelcomeMessageUserName").text(userProperties.get_displayName());
var followedItems = "Items you are following:<br />";
$.each(following, function( index, value ) {
followedItems += "<a href='" + value.get_uri() + "'>" + value.get_name() + "</a><br />";
});
$("#UserFollows").append(followedItems);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
在 jQuery Document.ready
函数中,我们包含了ExecuteOrDelayUntilScriptLoaded
内置函数。我们需要使用它,因为我们的 JavaScript 代码依赖于在sp.userprofiles.js
中找到的功能,如果它在文件被加载之前运行会导致错误:
ExecuteOrDelayUntilScriptLoaded(getUserProfileProperties, "sp.userprofiles.js");
一旦触发了getUserProfileProperties
函数,我们就获得一个对当前客户端上下文的引用,然后用下面的代码创建一个新的PeopleManager
对象:
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
this.userProperties = peopleManager.getMyProperties();
clientContext.load(userProperties);
我们可以通过使用SP.UserProfiles.PeopleManager()
方法创建一个新的PeopleManager
对象,将客户端上下文作为其参数传入。PeopleManager
对象提供了访问用户数据的方法。在这种情况下,我们可以通过使用peopleManager.getMyProperties()
方法,并在客户端上下文中加载userProperties
变量来获取当前用户的所有属性。
接下来,我们将通过使用SocialFollowingManager()
对象获取用户关注的所有项目:
var followingManager = new SP.Social.SocialFollowingManager(clientContext);
this.following = followingManager.getFollowed(15);
我们可以使用SP.Social.SocialFollowingManager()
方法创建一个新的SocialFollowingManager
对象,将客户端上下文作为其参数传入。然后,我们可以通过使用getFollowed()
方法获得用户关注的所有“演员”。“参与者”实际上就是用户追随的任何东西,可以是用户、文档、站点或标签。当您调用getFollowed()
方法时,您需要传入一个数字,该数字对应于您想要返回的参与者。在这个例子中,我们使用 15,这表示所有的参与者。您可以在 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.social.socialactortypes(v=office.15).aspx
看到完整的值列表。
这个例子中的success
方法是迄今为止最复杂的,因为我们需要显示比其他例子更多的数据。首先,我们将获取当前用户的用户名以显示在页面上:
$("#WelcomeMessageUserName").text(userProperties.get_displayName());
userProperties
对象有许多方法来检索数据;为了获得用户名,我们可以调用get_displayName()
方法。接下来,我们将遍历所有跟随的项目,以构建一个列表来显示给用户:
var followedItems = "Items you are following:<br />";
$.each(following, function( index, value ) {
followedItems += "<a href='" + value.get_uri() + "'>" + value.get_name() + "</a><br />";
});
首先,我们创建一个新变量来保存所有后续的项目。接下来,我们使用 jQuery each
循环遍历每个项目。对于每一项,我们调用get_uri()
和get_name()
方法来构造一个链接,这样用户就可以从页面直接跳转到该项。最后,我们用下面一行将所有 HTML 附加到页面上:
$("#UserFollows").append(followedItems);
半铸钢ˌ钢性铸铁(Cast Semi-Steel)
在 Visual Studio 中创建新的 CSS 文件,并将其命名为 JSOMGetSocialData.css 包括以下代码:
#WelcomeMessage {
margin-bottom: 20px;
}
#WelcomeMessageUserName {
font-weight: bold;
}
#UserFollows {
border:dashed 1px #C0C0C0;
width:240px;
padding: 6px;
}
这个 CSS 非常简单,只是为了提供一个简单的样式演示。我们将对用户的欢迎消息应用底部边距,并将用户名用粗体显示。为了强调,下面的项目将用虚线边框包裹起来。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面将向用户显示“欢迎回来”的消息,并以粗体显示他们的姓名。正下方是他们关注的所有项目的列表,显示为超链接,如图 8-23 所示。
图 8-23。
Social data being retrieved via JSOM
摘要
在这一章中,我们深入探讨了 JavaScript 对象模型(JSOM ),并研究了如何使用 Etherson 方法来创建自定义 web 部件。我们查看了各种各样的示例:查询列表数据、创建新列表和网站,以及查询用户的社交数据。尽管与本书中的其他章节相比,这是一个很长的章节,但它只是触及了 JSOM 在 SharePoint 中的可能性的皮毛。然而,在完成了这里给出的所有示例之后,您应该对使用 JSOM 以及 HTML、JavaScript 和 CSS 如何在自定义 web 部件中协同工作有了非常深刻的理解。现在,你应该可以开始使用 JSOM 制作你自己的定制解决方案了。在下一章,我们将看很多相同的例子,并学习如何使用 REST API 执行任务。
九、使用 REST API
在前一章中,我们看到了如何使用 JavaScript 对象模型(JSOM)和 Etherson 方法执行大量的任务。在这一章中,我们将看看相同的任务,除了如何使用 REST API 来执行它们。为此,上一章的很多 HTML 都是相似的,结果也是一样的。然而,JavaScript 将完全不同。如果你跳过了 JSOM 那一章,不要担心;所有代码的解释都在,所以你不会对任何例子一无所知。
REST 代表具象状态转移,这是一种奇特的说法,“Web 服务允许任何东西通过 Web 连接到它们。”可以从任何能够通过互联网发出 HTTP 请求的设备上调用 REST 服务。这种类型的服务最近获得了很大的吸引力,因为它是任何系统都可以访问数据的简单方法。SharePoint 2013 引入了新的 REST API 来为应用公开数据。幸运的是,该 API 也可以通过 HTML 和 JavaScript 轻松使用。
Note
利用 REST API 的代码在登录用户的上下文中运行。这意味着代码只能执行用户权限级别允许的操作。例如,如果您有在网站集中创建新子网站的代码,但登录的用户没有该权限,则代码将运行,但会产生错误。在构建解决方案时请记住这一点,并确保不向用户展示他们无法利用的选项。
正在设置
本章中的例子继续使用第四章中介绍的 Etherson 方法。导航到您站点中的 Webparts 文件夹,创建一个名为 Chapter 9 的新文件夹,如图 9-1 所示。
图 9-1。
Chapter 9 folder in the Webparts document library
本章中的每个例子都将遵循相同的模式。我们将查看在内容编辑器 Web 部件中呈现的 HTML 文件、用于检索和呈现数据的 JavaScript 文件,以及最终的结果。我们将深入研究每个文件,同时我将解释每个文件中发生了什么。
使用列表
如前一章所述,列表在 SharePoint 中随处可见!没有列表,你的开发工作不会走得很远。在这一节中,我们将探索使用 REST API 与列表交互的一些方法。
获取列表数据
在这个例子中,我们将简单地检索一些列表数据来显示给用户。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTGetListData.html。这个例子中的 HTML 非常简单。它仅由以下几行组成:
<script type="text/javascript" src="/apress/webparts/chapter 9/RESTGetListData.js"></script>
<div id="divGetListData"></div>
如果您研究过 JSOM 的例子,您会注意到这个 HTML 更简洁,JavaScript 引用更少。这样做的主要原因是,当使用 REST API 时,您不需要像 JSOM 一样加载任何 SharePoint JavaScript 文件。对 REST API 的所有调用都是通过 JavaScript AJAX 调用来执行的。在我们的例子中,我们将使用 jQuery 的 AJAX 方法。
接下来,我们加载名为RESTGetListData
的自定义 JavaScript 文件。该文件包含将数据加载到页面上的 DIV 的所有代码,该页面的 ID 为divGetListData
。总而言之,这一页没有多少内容。
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,并将其命名为 RESTGetListData.js。它由以下几行组成:
$(function () {
getListData();
});
function getListData() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists";
$.ajax({
url: fullUrl,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded(data) {
var listItemInfo = '';
$.each(data.d.results, function (key, value) {
listItemInfo += 'Title: ' + value.Title + ' - Created: ' +
value.Created + '<br />';
});
$("#divGetListData").html(listItemInfo);
}
function onQueryFailed() {
alert('Error!');
}
对于这个文件,您会注意到的第一件事是这里只有很少的 SharePoint 代码。该文件中绝大多数代码是 JavaScript 和 jQuery,只有_spPageContextInfo.webAbsoluteUrl
调用引用任何 SharePoint JavaScript。对于那些不熟悉 SharePoint 前端开发,但有 jQuery 经验的人来说,这似乎是一条不错的道路!如果您熟悉 jQuery 和 AJAX 调用,它确实提供了一种更快的方式来开始创建定制解决方案。
本书中的大多数例子都遵循与这个例子相同的模式。让我们深入到每一行的细节,以充分了解发生了什么。该脚本以一个 jQuery Document.ready
方法开始,该方法简单地调用一个名为getListData
的定制函数,在这里我们首先构建 REST API 的 URL:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists";
我们使用_spPageContextInfo.webAbsoluteUrl
方法来获取用户当前所在的完整 URL。接下来,我们使用/_api/web/lists
为这个站点中的列表添加 REST API 的路径。这将生成一个类似于以下内容的 URL:
http://<DOMAIN>/<SITE>/_api/web/lists
这是所有 REST URLs 的基本结构。_api
表示这是对 REST API 的调用。当 SharePoint 将此视为 AJAX 调用中 URL 的一部分时,它知道将请求路由到 REST API 进行处理。对于这个特殊的例子,我们询问当前网站上的列表集合。如果您将此与 JSOM 的请求进行比较,您会发现一些相似之处:
var collList = clientContext.get_web().get_lists();
如您所见,REST API 遵循类似的模式“获取 web,然后获取列表”这种模式在整章中重复出现。接下来,我们进行一个标准的 jQuery AJAX 调用来获取 web 中的列表:
$.ajax({
url: fullUrl,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
},
success: onQuerySucceeded,
error: onQueryFailed
});
对于这个 AJAX 调用,我们传入的第一件事是调用的 URL。这是我们之前创建的fullUrl
变量,它保存了 REST API 的完整 URL。接下来,我们指定呼叫的“类型”,在本例中是一个GET
。我们必须在调用中提供一些“头”,以便 SharePoint 知道我们期待 JSON 返回结果。为此,我们为accept
和content-type
头传入了application/json;odata=verbose
。这两个头将出现在几乎所有的 REST 调用中。最后,我们指定一旦调用完成应该触发的success
和failure
函数。success
函数只是显示每个列表及其创建的时间戳:
function onQuerySucceeded(data) {
var listItemInfo = '';
$.each(data.d.results, function (key, value) {
listItemInfo += 'Title: ' + value.Title + ' - Created: ' +
value.Created + '<br />';
});
$("#divGetListData").html(listItemInfo);
}
一开始,从 REST 调用返回的数据结构可能会令人困惑。如果您打开 Firebug 并查看该对象,您会发现返回了大量数据。比你需要向用户展示的还要多。此外,您希望向用户显示的数据嵌套在一个名为d
的属性中。例如,在这个例子中,列表集合位于一个名为data.d.results
的属性中。如果您要查询单个列表,就不会有results
属性,您可以直接从d
属性访问数据,就像data.d.Title
一样。在这一章中,你会看到更多这样的例子。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。结果将显示当前站点的所有列表,如图 9-2 所示。
图 9-2。
Get List Data results in the Content Editor Web Part
创建新列表
我们可以很容易地使用 REST 创建新的列表,正如您将在这个例子中看到的。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTCreateList.html。这个例子的 HTML 比前一个例子稍微复杂一些。它由以下几行组成:
<script type="text/javascript" src="/apress/webparts/chapter 9/RESTCreateList.js"></script>
<div>
<strong>Enter a name for the list:</strong>
<input type="text" id="txtListName" />
<input type="button" id="btnSubmitListName" value="Submit" />
</div>
<div id="divCreateListResults"></div>
HTML 稍微复杂一点,页面上有几个元素。首先,有一些简单的文本包装在一个<strong>
标签中,使其在页面上加粗。接下来,有一个文本类型的输入,它只是一个简单的文本框,供用户输入他们希望创建的列表的名称。有一个按钮供用户提交新的列表请求,最后还有一个 DIV,我们可以在其中输出列表创建的结果。每个元素都有一个 ID,所以我们可以很容易地用 jQuery 找到它。
Note
为了通过 REST 创建新列表,执行代码的用户必须至少拥有 SharePoint 中的管理列表权限。无论权限级别如何,都将呈现该页面;但是,如果用户没有足够的权限,SharePoint 将引发错误。
Java Script 语言
在 Visual Studio 中创建新的 JavaScript 文件,命名为 RESTCreateList.js,相比之下 JavaScript 文件更复杂。它由以下几行组成:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
createList(listName);
});
}
function createList(listName) {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.List' },
'BaseTemplate': 100,
'Title': listName
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded(data) {
$("#divCreateListResults").html(data.d.Title + " successfully created!");
}
function onQueryFailed() {
alert('Error!');
}
在这个例子中,我们不需要在页面加载上触发任何动作;然而,我们确实需要在页面加载时连接一个按钮点击事件。在Document.ready
函数中,我们触发了bindButtonClick
函数,我们使用 jQuery on
操作符在 HTML 中的btnSubmitListName
按钮上连接一个点击事件。当用户点击按钮时,我们从页面的文本框中抓取文本,并将其传递给createList()
函数。这是使用以下代码行完成的:
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
createList(listName);
});
}
createList()
函数接受一个名为listName
的变量,它是用户在页面上输入的文本。接下来,我们使用以下代码构建 REST 调用的 URL:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists";
您会注意到,这与上一个示例中的 URL 相同,因为我们的目标是 web 中的列表集合。然而,AJAX 看起来完全不同:
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.List' },
'BaseTemplate': 100,
'Title': listName
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
就像前面的例子一样,我们将变量fullUrl
作为要调用的 URL 传入,现在类型是一个POST
。因为我们在这个例子中创建了一个新列表,所以我们使用POST
向 SharePoint 表明这是一个创建操作。接下来,我们使用以下代码行传入新列表的数据:
data: JSON.stringify({
'__metadata': { 'type': 'SP.List' },
'BaseTemplate': 100,
'Title': listName
})
当我们使用 REST API 而不是GET
执行任何类型的操作时,我们都是在向 SharePoint 传递数据。这些数据是 JSON 格式的。JSON.stringify
方法是一个标准的 JavaScript 方法,它将 JavaScript 数据结构转换成 JSON 文本。这有助于确保我们传递给 SharePoint 的数据格式正确。我们做的第一件事是将“类型”设置为“SP”。List”并将“BaseTemplate”设置为“100”,这是一个通用列表。最后,我们为标题传入listName
变量。接下来,我们添加头并包含一个名为X-RequestDigest
的新头:
"X-RequestDigest": $("#__REQUESTDIGEST").val()
这个头允许我们为页面上的 FormDigest 控件传入值。该控件在 SharePoint 中用作安全措施,以确保POST
请求确实来自有效的 SharePoint 页面。您不需要知道这个控件的所有细节,只需要使用 jQuery 行$("#__REQUESTDIGEST").val()
获取它的值。一旦头部就位,我们就指定成功和失败函数。success
函数只显示列表名和一条成功消息:
function onQuerySucceeded(data) {
$("#divGetListData").html(data.d.Title + " successfully created!");
}
这个函数接受一个名为data
的参数。这个变量将由刚刚创建的列表中的数据填充。这个变量的命名没有什么特别之处;我们可以称之为“列表”,或“我的数据”。如果您愿意,您甚至可以不指定参数,只显示一条成功消息!
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面现在将显示文本框和按钮,供用户输入新的列表名称。键入我的自定义 REST 列表,然后单击提交按钮。结果将显示成功消息,如图 9-3 所示。
图 9-3。
Create new list code after it has been run
因为这些都是使用 JavaScript 和 AJAX 完成的,所以列表会被创建,用户会得到预期的通知。但是,页面上的左侧导航将不会更新,因为页面尚未刷新。您完全可以更改这段代码,以便在成功时刷新页面,但是对于本例,我们只是在浏览器中刷新页面。图 9-4 显示了刷新后的页面,新列表显示在左侧导航中。
图 9-4。
The new list as displayed in the left navigation pane
删除列表
在本例中,我们将简单地删除刚刚创建的列表。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTDeleteList.html。这个例子的 HTML 几乎和前面的例子一样。它由以下几行组成:
<script type="text/javascript" src="/apress/webparts/chapter 9/RESTDeleteList.js"></script>
<div>
<strong>Enter the name of the list to delete:</strong>
<input type="text" id="txtListName" />
<input type="button" id="btnSubmitListName" value="Submit" />
</div>
<div id="divDeleteListResults"></div>
这里唯一的不同是,我们更新了页面上的文本以指示该 web 部件将删除一个列表,并将结果 DIV 的 ID 更改为divDeleteListResults
。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTDeleteList.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmitListName").on("click", function () {
var listName = $("#txtListName").val();
deleteList(listName);
});
}
function deleteList(listName) {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('" + listName + "')";
$.ajax({
url: fullUrl,
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "DELETE",
"IF-MATCH": "*"
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divDeleteListResults").html("List successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Error!');
}
jQuery 按钮连接与上一个示例中的相同。接下来,我们需要为 REST 调用创建 URL,这次请求一个特定的列表:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('" + listName + "')";
这个 URL 添加了额外的GetByTitle
命令,传入我们正在寻找的列表的名称。最终的 URL 将如下所示:
http://<DOMAIN>/<SITE>/_api/web/lists/GetByTitle('<LISTNAME>')
接下来,我们需要添加几个额外的头:
"X-HTTP-Method": "DELETE",
"IF-MATCH": "*"
您会注意到请求的类型是一个POST
,就像我们创建一个新列表一样。然而,这里我们想要发起一个“删除”请求,所以我们需要包含X-HTTP-Method
头,让 SharePoint 知道我们想要删除列表,而不是对它采取一些其他的动作。接下来,我们包括了IF-MATCH
头。当通过 REST 进行更新和删除时,需要这个头。该标题有助于防止并发更新的发生。例如,如果您试图更新一个列表项,您可以传入一个类似如下的etag
属性:
"If-Match": data.d.__metadata.etag
在这个头中传递*
基本上是告诉 SharePoint 不要担心并发性,只需执行更新。在这个例子中,我们删除了列表,所以我们不需要担心这个检查。success
函数只是通知用户删除成功。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面现在将显示文本框和按钮,供用户输入要删除的列表名称。键入我的自定义 REST 列表,然后单击提交按钮。结果将显示成功消息,如图 9-5 所示。
图 9-5。
Delete List code after it has successfully run
因为这些都是使用 JavaScript 和 AJAX 完成的,所以列表将被删除,用户将得到预期的通知。但是,页面上的左侧导航将不会更新,因为页面尚未刷新。如前所述,您可以更新此代码以在成功时刷新页面,但是对于本例,我们将简单地在浏览器中刷新页面。图 9-6 显示了刷新后的页面,其中列表不再显示在左侧导航中。
图 9-6。
Deleted list has been removed from the left navigation
使用列表项目
由于在 SharePoint 开发中使用列表是一项非常常见的任务,因此使用列表项更加常见。在这一节中,我们将探索一些使用 REST API 与列表项交互的方法。
获取列表项目
这个例子将向你展示如何使用 REST 来检索列表项。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTGetListItems.html。这个例子的 HTML 继续遵循前面例子的极简模式。它由以下几行组成:
<script type="text/javascript" src="/apress/webparts/chapter 9/RESTGetListItems.js"></script>
<div id="divListItems"></div>
对于这个例子,我们将简单地从演示列表中获取所有的列表项,并将它们显示在页面上的divListItems
DIV 中。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTGetListItems.js。检索列表项的脚本应该与我们到目前为止看到的其他脚本非常相似。它由以下几行组成:
$(function () {
retrieveListItems();
});
function retrieveListItems() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items";
$.ajax({
url: fullUrl,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded(data) {
var listItemInfo = '';
$.each(data.d.results, function (key, value) {
listItemInfo += '<strong>ID: </strong> ' + value.Id +
' <strong>Title:</strong> ' + value.Title +
'<br />';
});
$("#divListItems").html(listItemInfo);
}
function onQueryFailed(sender, args) {
alert('Error!');
}
此时,获取列表项的 REST 调用的 URL 应该看起来非常熟悉:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items";
与删除 URL 一样,我们通过使用GetByTitle
命令获得列表的标题,然后添加items
命令,该命令告诉 SharePoint 返回列表中的所有项目。AJAX 调用是一个简单的GET
,包含了熟悉的 JSON 头。success
函数使用 jQuery 遍历结果:
$.each(data.d.results, function (key, value) {
listItemInfo += '<strong>ID: </strong> ' + value.Id +
' <strong>Title:</strong> ' + value.Title +
'<br />';
});
就像我们访问站点中的列表一样,我们使用data.d.results
集合来访问查询结果。在 jQuery each
循环中,我们取出每个列表项的 ID 和标题,并在页面上显示这些结果。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面现在将显示演示列表中的所有项目,如图 9-7 所示。
图 9-7。
List items from the Demo List displayed in the Content Editor Web Part
使用查询运算符限制结果
在前一章中,我们讨论了这样一个事实:在大多数情况下,你不应该从一个列表中请求所有的项目;无论是使用 JSOM 还是休息,这都不是一个好主意。我们看到了如何使用 CAML 查询在 JSOM 限制结果。使用 REST API 时,可以使用查询操作符来限制返回的结果。查询操作符基本上是添加到 AJAX 调用中 REST URL 末尾的查询字符串参数。
Java Script 语言
更新前面示例中的RESTGetListItems.js
,并使用以下代码行更新声明 REST URL 的部分:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items?$filter=Id ge 4";
这里唯一的附加内容是在 URL 的末尾,带有下面的查询字符串:$filter=Id ge 4
。我们使用filter
操作符来过滤结果。我们指定要过滤大于或等于(ge
) 4 的 ID。这是一个非常简单的加法,但是对查询操作符是一个很好的介绍。
Note
查询操作符是一个很大的主题——对于本书来说太大了。这些运算符允许您进行选择、过滤、排序、排序等操作。通过使用这些运算符,您甚至可以告诉 SharePoint 仅返回有关 SharePoint 中项目的特定数据。有关使用查询运算符的更多信息,请访问 http://msdn.microsoft.com/en-us/library/office/fp142385%28v=office.15%29.aspx
。
结果
更新 JavaScript 文件并上传,覆盖之前的版本。使用内容编辑器 Web 部件刷新页面,您将看到结果现在只显示 ID 大于或等于 4 的项目,如图 9-8 所示。
图 9-8。
The results of the Demo List query limited by a query operator
添加列表项目
在这个例子中,我们将看看如何向列表中添加新的列表项。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTAddListItems.html。该页面的标记将允许用户向演示列表添加一个项目,提供标题和描述。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTAddListItems.js"></script>
<div id="AddListData">
<div>
Title:
<br />
<input type="text" id="txtTitle" />
</div>
<div>
Description:
<br />
<textarea cols="20" id="txtDesc"></textarea>
</div>
<br />
<div>
<input id="btnSubmit" type="button" value="Submit" />
</div>
</div>
<div id="divResult"></div>
我们为列表项标题提供文本类型的输入,并为描述提供文本区域。页面上的每个元素都有一个 ID,所以我们可以很容易地用 jQuery 找到它。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTADDListItems.js,添加列表项的脚本看起来类似于创建新列表的脚本。它由以下几行组成:
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
addListItem();
});
}
function addListItem() {
var title = $("#txtTitle").val();
var desc = $("#txtDesc").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.Data.Demo_x0020_ListListItem' },
'Title': title,
'Description': desc,
'Status':'On-time'
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded(sender, args) {
$("#divResult").html("Item successfully added!");
}
function onQueryFailed() {
alert('Error!');
}
在我们用 jQuery 附加了一个按钮点击事件之后,我们在点击事件上做的第一件事就是获取用户提供的值。这是通过以下代码行实现的:
var title = $("#txtTitle").val();
var desc = $("#txtDesc").val();
接下来,我们创建 REST URL,目标是演示列表和列表中的列表项:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items";
然后我们创建一个 jQuery AJAX POST
调用,为新的列表项传入数据:
data: JSON.stringify({
'__metadata': { 'type': 'SP.Data.Demo_x0020_ListListItem' },
'Title': title,
'Description': desc,
'Status':'On-time'
})
这段代码与本章前面的创建列表代码非常相似。我们做的第一件事是指定要创建的项目的类型;在这种情况下,一个SP.Data.Demo_x0020_ListListItem
。项目的类型总是包括创建它的列表的名称,它遵循以下模式:
SP.Data.<LISTNAME>ListItem
在本例中,由于我们的列表名为演示列表,我们必须包含 SharePoint 用来表示空间的_x0020_
。对于标题和描述,我们只需传入之前检索到的值。对于 Status 列,我们简单地将 On-time 硬编码为一个值。因为我们正在执行一个POST
,我们包括了X-RequestDigest
头。success
功能将简单地向用户显示一条消息,说明该项目已被添加到列表中。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面将显示供用户输入详细信息的文本框。当添加一个项目时,会显示一条成功信息,如图 9-9 所示。
图 9-9。
Adding a new item to the Demo List
然后,我们可以导航到演示列表,以确认添加了新项目。图 9-10 显示了添加了新列表项和 HTML 页面提供的值的演示列表。
图 9-10。
A new list item added to the Demo List
删除列表项目
对于这个例子,我们将简单地删除我们在上一节中创建的新列表项。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTDeleteListItems.html。这个文件的 HTML 要小得多,因为我们需要从用户那里获取的只是一个对应于他们想要删除的列表项的 ID。这是通过以下代码行实现的:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTDeleteListItems.js"></script>
<div>
Enter ID to Delete: <input type="text" id="txtId" />
</div>
<div>
<input id="btnSubmit" type="button" value="Submit" />
</div>
<div id="divResult"></div>
这个例子过于简单,因为用户很可能不知道要删除的某个列表项的 ID。一个更真实的例子可能是向用户显示一个项目列表,并允许他们单击一个项目来删除它。在这种情况下,页面上会有列表项 id,并且可以很容易地访问它。我们将保留一个简单的文本框来简化这个例子。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTDeleteListItems.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteListItem();
});
}
function deleteListItem() {
var id = $("#txtId").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items(" + id + ")";
$.ajax({
url: fullUrl,
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "DELETE",
"IF-MATCH": "*"
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded(sender, args) {
$("#divResult").html("Item successfully deleted!");
}
function onQueryFailed() {
alert('Error!');
}
页面上的按钮点击事件将调用deleteListItem()
函数。我们做的第一件事是获取用户在页面上输入的 ID。这是使用以下代码行完成的:
var id = $("#txtId").val();
接下来,我们创建 REST URL,通过 ID 定位特定的列表项:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Demo List')/items(" + id + ")";
您可以通过在 URL 末尾的括号中包含其 ID 来请求或定位单个列表项。完整的 URL 如下所示:
http://<DOMAIN>/<SITE>/_api/web/lists/GetByTitle('<LISTNAME>')/items(<ID>)
和以前一样,当删除一个列表时,我们在进行 AJAX 调用时包含了"X-HTTP-Method": "DELETE"
和IF-MATCH": "*"
头。success
方法将简单地向用户显示一条消息,通知他们删除已经完成。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示供用户输入 ID 的文本框,然后在删除项目时显示成功消息,如图 9-11 所示。
图 9-11。
Deleting a list item using REST
使用文档库
SharePoint 的主要优势之一在于文档管理及其文档库。您肯定会发现需要通过代码使用库的需求。在这一节中,我们将研究一些使用 REST API 与文档库交互的方法。
创建新文件夹
SharePoint 用户喜欢创建文件夹,在这个例子中,我们将看到如何通过代码创建一个文件夹。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTCreateFolder.html。这个页面的标记非常简单,允许用户输入他们希望创建的文件夹的名称。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTCreateFolder.js"></script>
<div>
<strong>Enter a name for the folder:</strong>
<input type="text" id="txtFolderName" />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTCreateFolder.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createFolder();
});
}
function createFolder() {
var folderName = $("#txtFolderName").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/folders";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.Folder' },
'ServerRelativeUrl': 'Shared Documents/' + folderName
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Folder successfully created!");
}
function onQueryFailed() {
alert('Error!');
}
在使用 jQuery 连接按钮点击之后,createFolder()
函数从获取用户在页面上输入的文件夹名称开始:
var folderName = $("#txtFolderName").val();
接下来,我们创建 REST URL,但这一次我们的目标是站点的文件夹集合:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/folders";
这打破了我们到目前为止看到的熟悉模式,因为我们请求的 URL 不是我们想要创建文件夹的特定位置。我们在data
属性中指定文件夹应该位于何处:
data: JSON.stringify({
'__metadata': { 'type': 'SP.Folder' },
'ServerRelativeUrl': 'Shared Documents/' + folderName
})
ServerRelativeUrl
属性用于告诉 SharePoint 应该在哪里创建文件夹。在本例中,我们将在 Shared Documents 文件夹中创建它,并附加用户在页面上输入的文件夹名称。与前面的例子一样,我们为项目指定一个“类型”,在本例中是一个SP.Folder
。我们包含了熟悉的标题,并在success
方法中通知用户文件夹的创建。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面会显示文本框,供用户输入要创建的文件夹的名称,完成后会显示成功消息,如图 9-12 所示。
图 9-12。
Creating a new folder with REST
然后,我们可以导航到文档库,直观地验证新文件夹是否已创建,如图 9-13 所示。
图 9-13。
New folder created via REST
使用文件
有时候,您需要在自定义解决方案中处理文件。在这一节中,我们将看到如何使用 REST 创建、读取和删除文本文件。
创建新文件
在这个例子中,我们将看到如何通过代码创建一个新的文本文件。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTCreateDocument.html。该页面的标记将允许用户输入新文本文件的名称,以及文件本身的内容。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTCreateDocument.js"></script>
<div id="CreateFile">
<div>
<strong>Enter a title for the document:</strong>
<br />
<input type="text" id="txtDocumentTitle" />
</div>
<div>
<strong>Enter content for the document:</strong>
<br />
<textarea cols="20" id="txtDocumentContent"></textarea>
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTCreateDocument.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createDocument();
});
}
function createDocument() {
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var docContent = $("#txtDocumentContent").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/GetFolderByServerRelativeUrl('Shared Documents')/Files/add(url='" + docTitle + "',overwrite=true)";
$.ajax({
url: fullUrl,
type: "POST",
data: docContent,
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Document successfully created!");
}
function onQueryFailed() {
alert('Error!');
}
我们需要做的第一件事是获取用户在页面上输入的文档标题和内容。这是通过以下代码行实现的:
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var docContent = $("#txtDocumentContent").val();
注意,我们在文档标题的末尾添加了.txt
。这将让 SharePoint 知道我们打算创建一个文本文件,因为它将使用名称中的扩展名来确定文件类型。接下来,我们构建 REST URL:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/GetFolderByServerRelativeUrl('Shared Documents')/Files/add(url='" + docTitle + "',overwrite=true)";
这是迄今为止我们制作的最复杂的 REST URL。为了引用我们想要创建文件的文件夹,我们需要包含GetFolderByServerRelativeUrl
命令,传递文件夹名;在这种情况下,共享文档。然后,我们将文件夹中的文件集合作为目标,并使用add
命令实际创建文件。我们可以传入文件的属性;在这种情况下,URL 和覆盖标志。文件的内容通过 AJAX 调用中的data
属性传入:
$.ajax({
url: fullUrl,
type: "POST",
data: docContent,
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
}
success
功能向用户显示文件已创建的消息。
Note
在本例中,我们正在创建一个简单的文本文件。在大多数实际情况下,文本文件可能不是预期的结果,但可能是 Word 文件或 Excel 文件。您完全可以通过简单地将.txt
更改为.docx
来更改这个示例以生成一个 Word 文档。这个简单的更改实际上会创建一个包含内容的新 Word 文档。但是,它只能在客户端计算机上的 Word 中打开,而不能在 Office Web Apps 中打开。幸运的是,微软提供了 Office JavaScript 文件,允许您从浏览器创建和操作 Office 文件。你可以在 http://msdn.microsoft.com/en-us/library/office/fp160953%28v=office.15%29.aspx
找到更多信息。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本框,供用户输入文档的标题和内容,然后在新文档创建完成后显示成功消息,如图 9-14 所示。
图 9-14。
Creating a new document from a Content Editor Web Part
我们可以导航到 Documents 文件夹,发现新的文本文档已经创建,如图 9-15 所示。您可以单击该文档,它将在浏览器中打开,并显示用户从页面输入的内容。
图 9-15。
New text document created in the Documents folder
阅读文件
在这个例子中,我们将看到如何读取我们刚刚创建的文本文件并向用户显示内容。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTReadDocument.html。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTReadDocument.js"></script>
<div id="divReadDocument" />
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTReadDocument.js。
$(function () {
readDocument();
});
function readDocument() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var documentLibrary = "/Shared Documents/"
var fileUrl = "New Text Doc.txt";
var fullUrl = siteUrl + documentLibrary + fileUrl;
$.ajax({
url: fullUrl,
type: "GET"
})
.done(function (data) {
$("#divReadDocument").html(data);
})
.fail(function () {
alert("error");
});
}
这是上一章的相同代码示例,因为它不需要 JSOM 或 REST!如果你跳过了 JSOM 这一章,请继续读下去;否则,唯一改变的是文件引用。
从 SharePoint 读取文本文件的美妙之处在于,您只需要 jQuery。有一个简单的 jQuery Document.ready
函数将触发代码来读取文件。我们有意保持代码简单,并对我们刚刚创建的文档的文件名进行硬编码:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var documentLibrary = "/Shared Documents/"
var fileUrl = "New REST Text Doc.txt";
var fullUrl = siteUrl + documentLibrary + fileUrl;
我们做的第一件事是使用_spPageContextInfo.webAbsoluteUrl
获取当前网站的完整 URL。接下来,我们对 URL 的文档库部分和文件名进行硬编码。最后,我们将它们放入一个名为fullUrl
的新变量。您完全可以在一行中完成所有这些工作,但是您会发现,如果您将代码分成几行,以后调试代码会更容易。一旦我们有了文件的 URL,我们就使用 jQuery AJAX 调用来获取文档:
$.ajax({
url: fullUrl,
type: "GET"
})
.done(function (data) {
$("#divReadDocument").html(data);
})
.fail(function () {
alert("error");
});
当在 jQuery 中通过 AJAX 检索文本文件时,内容将以文本形式返回,我们可以简单地将它输出到页面,无需任何修改。我们使用 jQuery .done
函数,将文件内容设置为一个名为data
的新变量。然后,我们将数据设置为页面上结果 DIV 的 HTML。
Note
和以前一样,当创建一个新文件时,我们通过使用一个文本文件来保持事情的简单。这也适用于本节和读取文件。使用前面介绍的方法无法读取 Office 文件。您需要利用 Office JavaScript 文件在浏览器中正确读取 Word 文件或 Excel 文件。你可以在 http://msdn.microsoft.com/en-us/library/office/fp160953%28v=office.15%29.aspx
找到更多信息。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本文件的内容,如图 9-16 所示。
图 9-16。
Contents of the text file displayed on the page
删除文件
在本例中,我们将简单地删除新创建的文本文件。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTDeleteDocument.html。该页面的标记有一个文本框,用户可以输入他们希望删除的文件的名称。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTDeleteDocument.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of document to delete:</strong>
<br />
<input type="text" id="txtDocumentTitle" />
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTDeleteDocument.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteDocument();
});
}
function deleteDocument() {
var docTitle = $("#txtDocumentTitle").val() + ".txt";
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var webRelUrl = _spPageContextInfo.webServerRelativeUrl;
var fullUrl = siteUrl + "/_api/web/GetFileByServerRelativeUrl('" + webRelUrl + "/Shared Documents/" + docTitle + "')";
$.ajax({
url: fullUrl,
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "DELETE",
"IF-MATCH": "*"
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Document successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Error!');
}
在连接按钮点击事件之后,我们做的第一件事是获取用户希望删除的文档的标题:
var docTitle = $("#txtDocumentTitle").val() + ".txt";
我们将保持这个例子的简单,删除之前创建的文本文件,从而将.txt
扩展硬编码到代码中。接下来,我们像在前面所有示例中一样构建 REST URL:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var webRelUrl = _spPageContextInfo.webServerRelativeUrl;
var fullUrl = siteUrl + "/_api/web/GetFileByServerRelativeUrl('" + webRelUrl + "/Shared Documents/" + docTitle + "')";
对于这个例子,除了获得网站的绝对 URLwebAbsoluteUrl
,我们还需要获得服务器相对 URLwebServerRelativeUrl
。绝对 URL 看起来像http://<DOMAIN>/<SITE>
,站点的服务器相对 URL 看起来像/<SITE>
。我们需要这个值来正确定位 REST URL 中的文件。为了删除文件,我们需要使用GetFileByServerRelativeUrl
命令,传递文件的相对 URL。在这种情况下,我们将服务器相对 URL、/Shared Documents/
和用户传入的文档标题结合起来。
与其他删除操作一样,我们包括了"X-HTTP-Method": "DELETE"
和"IF-MATCH": "*"
头。success
函数将简单地通知用户删除已经发生。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示一个文本框供用户输入文档标题,并显示结果消息,如图 9-17 所示。
图 9-17。
Deleting a file via REST
使用站点
在 SharePoint 中创建新网站是一项常见任务。在这一节中,我们将看到如何使用 REST API 创建和删除站点。前面的例子明确说明了 REST API 的强大,这一节应该让您明白它为您的开发工作提供了多大的力量。
创建网站
在本例中,我们将创建一个新站点并设置它的几个属性。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTCreateSite.html。该页面的标记有一个供用户输入新站点名称的文本框,以及一个用于站点描述的文本框。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTCreateSite.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of the site:</strong>
<br />
<input type="text" id="txtSiteTitle" />
</div>
<br />
<div>
<strong>Enter site description:</strong>
<br />
<textarea cols="20" id="txtSiteDescription"></textarea>
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTCreateSite.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
createSite();
});
}
function createSite() {
var newSiteTitle = $("#txtSiteTitle").val();
var newSiteDesc = $("#txtSiteDescription").val();
var newSiteUrl = newSiteTitle.replace(/\s/g, "");
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/webinfos/add";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'parameters': {
'__metadata': {'type': 'SP.WebInfoCreationInformation' },
'Url': newSiteUrl,
'Title': newSiteTitle,
'Description': newSiteDesc,
'Language':1033,
'WebTemplate':'sts#0',
'UseUniquePermissions': false
}
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Site successfully created!");
}
function onQueryFailed(sender, args) {
alert('Error!');
}
创建一个新的站点需要更多的代码,但是现在应该已经非常熟悉了。首先,我们获取用户提交的标题和描述。这是使用以下代码行完成的:
var newSiteTitle = $("#txtSiteTitle").val();
var newSiteDesc = $("#txtSiteDescription").val();
var newSiteUrl = newSiteTitle.replace(/\s/g, "");
创建网站时,除了标题之外,还必须提供网站的 URL。对于这个例子,我们将简单地获取用户为标题输入的文本,并删除所有空格以生成 URL。这是使用 JavaScript 中的replace()
方法完成的,第一个参数是我们要搜索的内容,第二个参数是应该替换的内容。/\s/g
文本表示一个空格,必须用于此功能才能正常工作。
一旦我们有了创建站点所需的变量,我们就创建 REST URL,但是这次我们的目标是站点的 Webinfos 集合:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/webinfos/add";
与我们创建新文件夹时类似,我们的目标位置不同于站点最终所在的位置。我们还在 URL 中包含了add
命令;这不同于迄今为止的其他创建脚本。接下来,我们在 jQuery 中创建 AJAX 调用:
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'parameters': {
'__metadata': {'type': 'SP.WebInfoCreationInformation' },
'Url': newSiteUrl,
'Title': newSiteTitle,
'Description': newSiteDesc,
'Language':1033,
'WebTemplate':'sts#0',
'UseUniquePermissions': false
}
})
当使用JSON.strigify()
方法传递数据时,这个例子不同于前面的例子。您会注意到我们必须创建一个parameters
对象,然后包含创建新站点的所有信息。其他示例不需要这样做。这个对象没有什么值得注意的,因为它只是作为内部数据的包装器;但是,SharePoint 期望它,并且不会创建没有此结构的网站。
首先,我们指定“类型”,在本例中是一个SP.WebInfoCreationInformation
类型。如果你研究过前一章中的 JSOM 例子,你会发现这和用 JSOM 创建站点的对象是一样的。其余的属性相当简单:我们传入先前创建的站点标题、URL 和描述变量。我们还传入了语言设置(1033
表示英语),以及 WebTemplate ( sts#0
,这是一个团队站点模板)。站点创建完成后,success
功能将显示成功消息。
Note
同样,这些示例中的代码在当前用户的权限级别下运行。由于这些示例中有许多执行更高级别的功能,如创建和删除 SharePoint 对象,因此用户需要有适当的权限来执行这些功能。值得再次指出这一点,因为站点创建要求用户对创建新站点的站点拥有完全控制权限。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面将显示文本框供用户输入新的站点标题和描述,并显示结果消息,如图 9-18 所示。
图 9-18。
Creating a new site via REST
然后,我们可以打开创建新站点的站点内容页面,并滚动到底部。在子站点部分,我们可以看到新站点已经创建,如图 9-19 所示。
图 9-19。
The newly created sub-site in the Site Contents page
删除网站
在本例中,我们将删除在上一节中创建的站点。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTDeleteSite.html。这个页面的标记有一个文本框,用户可以输入他们想要删除的站点的名称。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTDeleteSite.js"></script>
<div id="DeleteFile">
<div>
<strong>Enter the name of the site to delete:</strong>
<br />
<input type="text" id="txtSiteTitle" />
</div>
<br />
<input type="button" id="btnSubmit" value="Submit" />
</div>
<div id="divResults"></div>
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTDeleteSite.js。
$(function () {
bindButtonClick();
});
function bindButtonClick() {
$("#btnSubmit").on("click", function () {
deleteSite();
});
}
function deleteSite() {
var siteTitle = $("#txtSiteTitle").val();
var siteTitleNoSpaces = siteTitle.replace(/\s/g, "");
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/" + siteTitleNoSpaces + "/_api/web";
$.ajax({
url: fullUrl,
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"X-HTTP-Method": "DELETE",
"IF-MATCH": "*"
},
success: onQuerySucceeded,
error: onQueryFailed
});
}
function onQuerySucceeded() {
$("#divResults").html("Site successfully deleted!");
}
function onQueryFailed(sender, args) {
alert('Error!');
}
就像前面的例子一样,我们获取用户输入的网站标题,然后删除所有空格:
var siteTitle = $("#txtSiteTitle").val();
var siteTitleNoSpaces = siteTitle.replace(/\s/g, "");
一旦我们有了标题并删除了空格,我们需要构建站点的其余 URL:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/" + siteTitleNoSpaces + "/_api/web";
删除站点与迄今为止执行的任何其他删除操作没有什么不同。我们需要做的就是包含"X-HTTP-Method": "DELETE"
和"IF-MATCH": "*"
头。success
功能将向用户显示一条消息,通知他们删除已经发生。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。页面会显示一个文本框供用户输入站点标题,并显示结果信息,如图 9-20 所示。
图 9-20。
Deleting a subsite via REST
在本例中,我们将删除刚刚创建的站点。导航回站点内容页面将显示该子站点已被成功删除,如图 9-21 所示。
图 9-21。
Site has been removed from the root site
使用社交数据
社交数据是 SharePoint 2013 中的热门话题,在您开始创建自定义解决方案时,您应该对此有所了解。在这一节中,我们将看到如何检索一些社会数据,并将其显示给当前登录的用户。
超文本标记语言
在 Visual Studio 中创建新的 HTML 文件,并将其命名为 RESTGetSocialData.html。这个页面的标记将包括几个 div 和一个输出数据的 SPAN。它由以下几行组成:
<script type="text/javascript" src="/apress/Webparts/chapter 9/RESTGetSocialData.js"></script>
<link rel="stylesheet" type="text/css" href="/apress/Webparts/chapter 9/RESTGetSocialData.css" />
<div id="WelcomeMessage">
Welcome back <span id="WelcomeMessageUserName"></span>
</div>
<div id="UserFollows" />
我们将包含一个名为RESTGetSocialData.css
的定制 CSS 文件。它将用于设置脚本输出的样式。所有其他的例子都可以很容易地包含 CSS 样式。在您的自定义开发工作中,您会发现样式将在许多 web 部件中扮演重要角色,因此这个示例将向您展示包含样式是多么容易。
Java Script 语言
在 Visual Studio 中创建一个新的 JavaScript 文件,并将其命名为 RESTGetSocialData.js。
$(function () {
getUserProfileInfo();
getUserFollows();
});
function getUserProfileInfo() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/social.feed/my";
$.ajax({
url: fullUrl,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
},
success: onUserInfoQuerySucceeded,
error: onQueryFailed
});
}
function getUserFollows() {
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/social.following/my/followed(types=15)";
$.ajax({
url: fullUrl,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
},
success: onFollowQuerySucceeded,
error: onQueryFailed
});
}
function onUserInfoQuerySucceeded(data) {
$("#WelcomeMessageUserName").text(data.d.Me.Name);
}
function onFollowQuerySucceeded(data) {
var following = data.d.Followed.results;
var followedItems = "Items you are following:<br />";
$.each(following, function (index, value) {
followedItems += "<a href='" + value.Uri + "'>" + value.Name + "</a><br />";
});
$("#UserFollows").append(followedItems);
}
function onQueryFailed(sender, args) {
alert("Error");
}
这个例子给你的第一个印象是引入了第二个函数来检索数据。我们有一个函数来检索用户配置文件信息,另一个函数来检索“后续”信息。这是因为该数据的 REST 端点是不同的,因此需要两个调用来检索我们希望在页面上显示的所有内容。
Note
在前一章中,我们讨论了如何使用批处理来“批处理”JSOM 请求。这允许您将所有不同的数据请求打包到一个调用中,从而提高性能。当通过$batch
查询操作符使用 REST API 时,SharePoint Online 和 Office 365 支持批处理。使用它,您可以优化这个示例的性能。然而,使用 REST API 的批处理是一个深入的主题,超出了本书的范围。更重要的是你知道它是可用的。您可以在 http://msdn.microsoft.com/EN-US/library/office/dn903506%28v=office.15%29.aspx
了解更多信息。
第一个函数getUserProfileInfo
用于检索用户的显示名称。为了获得这些信息,我们将利用社交 feed REST API:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/social.feed/my";
这个 URL 看起来与 REST API 中的所有其他端点有点不同,因为 URL 的一部分有一个social.feed
。社交 feed 有两个组成部分,Feed 和 Following,这种格式是我们定位每个组成部分的方式。用户信息可以在my
端点下找到,您可以找到每个用户的其他信息,比如新闻、喜欢等等。
Note
社交 feed 暴露了大量用户数据。在本例中,我们将只显示用户的显示名称,但是您可以访问更多内容。您可以在 http://msdn.microsoft.com/EN-US/library/office/dn155789%28v=office.15%29.aspx
找到更多信息。
success
函数从结果中提取显示名称:
$("#WelcomeMessageUserName").text(data.d.Me.Name);
来自社交 feed 的结果也与之前的例子略有不同。正如你所看到的,我们有熟悉的data.d
对象,但是用户数据进一步嵌套在一个名为Me
的对象下,从中我们可以获得Name
属性。
第二个函数getUserFollows
用于检索用户正在关注的所有项目。为了获得这些信息,我们将利用social.following
提要:
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/social.following/my/followed(types=15)";
然后,我们可以使用followed
端点获得用户关注的所有参与者。参与者实际上就是用户关注的任何东西,可以是用户、文档、站点或标签。当您调用followed
端点时,您需要传入一个与您想要返回的参与者相对应的数字。在这个例子中,我们使用 15,这表示所有的参与者。
您可以在 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.social.socialactortypes(v=office.15).aspx
查看完整的值列表。
Note
下面的 feed 也暴露了很多关于用户的数据。你可以在 http://msdn.microsoft.com/EN-US/library/office/dn194080%28v=office.15%29.aspx
找到更多信息。
success
函数包含一个 jQuery 循环,我们在其中构建 HTML 来显示用户关注的所有项目:
var following = data.d.Followed.results;
var followedItems = "Items you are following:<br />";
$.each(following, function (index, value) {
followedItems += "<a href='" + value.Uri + "'>" + value.Name + "</a><br />";
});
$("#UserFollows").append(followedItems);
与用户信息非常相似,下面的数据嵌套在名为Followed
的对象中的data.d
对象内。这包含了我们熟悉的results
对象,它保存了所有的条目。我们创建一个新的变量来保存所有后续的项目。接下来,我们使用 jQuery each
循环遍历每个项目。对于每一项,我们获取 Uri、该项的 URL 和名称,以便构造一个链接,使用户可以从页面直接跳转到该项。最后,我们用下面一行将所有 HTML 附加到页面上:
$("#UserFollows").append(followedItems);
半铸钢ˌ钢性铸铁(Cast Semi-Steel)
在 Visual Studio 中创建一个新的 CSS 文件,并将其命名为 RESTGetSocialData.css。
#WelcomeMessage {
margin-bottom: 20px;
}
#WelcomeMessageUserName {
font-weight: bold;
}
#UserFollows {
border:dashed 1px #C0C0C0;
width:240px;
padding: 6px;
}
这个 CSS 是非常基础的,它只是为了提供一个简单的样式演示。我们将对用户的欢迎消息应用底部边距,并将用户名用粗体显示。为了强调,下面的项目将用虚线边框包裹起来。
结果
将内容编辑器 Web 部件的内容链接属性设置为 HTML 文件,并保存页面。该页面将向用户显示“欢迎回来”的消息,并以粗体显示他们的姓名。正下方是他们关注的所有项目的列表,显示为超链接,如图 9-22 所示。
图 9-22。
Social data being retrieved via REST
摘要
在这一章中,我们深入研究了 REST API,并了解了如何使用 Etherson 方法来创建定制 web 部件。我们查看了各种各样的例子:查询列表数据、创建新的列表和网站,以及查询用户的社交数据。尽管与本书中的其他章节相比,这是一个很长的章节,但它仅仅触及了 SharePoint 中 REST 的皮毛。然而,在学习完这里给出的所有示例之后,您应该对使用 REST API 以及 HTML、JavaScript 和 CSS 如何在一个定制 web 部件中协同工作有了很深的理解。现在,您应该可以开始使用 REST 创建自己的定制解决方案了。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?