作为 Domino 开发人员,浏览器应用的开发是其中重要的一部分。而浏览器应用开发方面会有许多新的技术和方法出现。如何将这些新的技术和方法运用到 Domino 环境中是 Domino 开发人员需要面对的一个重要问题。
目前,我们正处于在 Web 2.0 的时代,在这个伟大的时代出现了大量的浏览器技术,其中有代表性的就是 Ajax。通过 Ajax,我们可以让客户端在不刷新网页的情况下与服务器交换数据,从而生成真正动态的网页。对 Ajax 的使用包括一定的低层编码工作,为了简化这一工作,人们提出了 Ajax 框架的概念,将 Ajax 相关的低层编码封装起来,装配成简单易用的小组件。而 Dojo 则是 Ajax 框架中极为优秀的一个。
本文并不会详细地介绍 Ajax 与 Dojo,有关 Ajax 与 Dojo 的具体内容请参考 相关资源。同时,本文也不会详细介绍 Domino 的设计方法,本文的读者需要对 Domino 开发有一定的经验。本文主要是介绍如何在 Domino 环境中使用 Dojo 这一框架,并将 Dojo 与 Domino 的设计元素结合起来。
![]() |
|
Ajax 的英文全名是: Asynchronous JavaScript and XML,中文意思就是“异步的 JavaScript 和 XML”。其中 JavaScript 用于前台处理,XML 用于前台与后台的数据传递。之所以称之为“异步”,是因为 Ajax 使用了异步的方式与服务器交互,当前台处理的 JavaScript 向后台发送完数据请求后,程序控制权会返回给 JavaScript。当服务器在后台对请求进行响应的时候,前台的 JavaScript 可以继续运行,执行其它操作。当服务器端处理完请求并返回结果后,会在前台触发事先指定的方法,通过这一方法对返回结果进行处理。
Ajax 所拥有的这种异步通讯能力在低层而言得益于一个新的 JavaScript 对象:XmlHttpRequest。它的核心功能是向指定的服务器发送一个 HTTP 请求,同时指定一个 JavaScript 方法作为回调函数。当这个 HTTP 请求被发送后,当前网页不需要被刷新。同时,虽然被指定的回调函数会等待服务器的处理结果,但是前台的 JavaScript 可以继续工作,响应用户在前台的其它操作。
使用 Ajax 技术,开发人员需要建立 XmlHttpRequest 对象,并实现回调函数。如果在每一个需要的网页元素上都实现这样细节,会有很大工作量,同时代码也不易管理。在这种情况下,人们提出的 Ajax 框架的概念,通过 Ajax 技术实现了大量实用的小组件,开发人员只需要调用小组件就可以和服务器进行异步交互。
在 Ajax 框架中,Dojo 是其中极为优秀的一个。Dojo 是一个开源项目,虽然在 Dojo 的主页上,他们只是把 Dojo 定义成一个开源的 DHTML 项目,但是它无疑是一个充分发挥 Ajax 优势的框架。
![]() ![]() |
![]()
|
因为 Domino 是一个完整的 HTTP 服务器,在不添加其它框架的情况下,开发人员都可以在 Domino 环境里通过编写代码实现 Ajax 调用,从而实现复杂的异步应用。为了让读者集中了解在 Domino 上实现 Ajax 调用的关键,下面用最简单的例子进行说明。
首先,为了测试需要,我们在测试服务器上建立一个测试数据库,名为:ajaxsample.nsf。 然后,在该数据库创建一个表单,名为:SampleAJAX。此外,在同一数据库创建一个页面名为 samplepage,里面输入文本“testing page”作为内容。我们将在表单 SampleAJAX 里实现 Ajax 调用,在不刷新当前页面的情况下动态获取页面“samplepage”的内容。
在表单 SampleAJAX 中的“JS Header”事件中输入如下代码:
var oXHR; function mycallback() { if (oXHR.readyState == 4) { if (oXHR.status == 200) { alert(oXHR.responseText); } else { alert('error'); } } } |
然后在表单中创建一个按钮和一个可编辑的文本域,按钮用于触发 Ajax 调用,可编辑的文本域用于证明当前页面是否被刷新。完成以上步骤后的结果如下图所示:
然后,在按钮的 onclick 事件中加入以下代码:
oXHR = new ActiveXObject("Microsoft.XMLHTTP"); oXHR.onreadystatechange = mycallback; oXHR.open('GET', 'samplepage?openpage', true); oXHR.send(null); |
完成后的结果如下图所示:
现在,第一个调用 Ajax 的表单已经创建好了,可以开始在浏览器上测试它。通过 URL http://<服务器名>/ajaxsample/SampleAJAX?openform
打开名为 SampleAJAX 的表单。在测试输入框中随意输入一些字符,然后点击按钮。我们可以发现,在测试输入框的内容没有被清除的情况下,浏览器获得了页面 sampleage 的内容,并通过提示框显示出来。结果如下:
图 3. 通过 Ajax 调用获得页面 sampleage 的 HTML 代码内容
在成功实现第一个调用 Ajax 的表单后,我们回过头来看看它是怎么工作的。
当用户点击表单中的按钮时,该按钮的 onclick
事件被触发,在该按钮的 onclick
事件中我们加入了以下代码,这些代码所做的工作,正如注释所解释的,向服务器发送了一个动态 HTTP 请求:
oXHR = new ActiveXObject("Microsoft.XMLHTTP"); // 通过 new ActiveXObject 创建 XmlHttpRequest 对象 //ActiveXObject 是微软对 XmlHttpRequest 对象的实现,在 IE 上可以支持 oXHR.onreadystatechange = mycallback; // 指定回调函数为 mycallback,这一函数是在 JS Header 中定义好的 oXHR.open('GET', 'samplepage?openpage', true); // 指定这次动态 http 请求的目标 URL,本例中是打开同一服务器上相同数据库中名为 samplepage 的页面 oXHR.send(null); // 发送请求 |
在请求发送之后,当前的表单不需要刷新,所以测试输入框中的内容不会被清空。服务器接收到请求后对请求进行处理并将结果返回给浏览器。根据上面的代码,浏览器在接收到返回结果后会调用名为 mycallback
的函数。mycallback
函数对返回的数据进行了处理,如下面注释所解释的:
function mycallback() { if (oXHR.readyState == 4) { if (oXHR.status == 200) { // 如果返回的结果码是 200,表示服务器处理请求成功 // 将返回结果的文本信息通过提示框显示出来 alert(oXHR.responseText); } else { // 如果返回的结果码不是 200,表示服务器处理请求时出错,显示“error” alert('error'); } } } |
![]() ![]() |
![]()
|
通过上面的样例我们知道在 Domino 上实现 Ajax 调用需要一系列的工作,如果将它用于表单设计中则会要求大量的编码工作。为了简化这些工作,我们可以直接使用 Dojo 框架。
下面描述的是在 Domino 上配置使用 Dojo 的详细步骤:
- 下载 Dojo 包
在 Dojo 项目的 官方主页 上有一个紫色的“0.4.x Ajax Edition”按钮,点击可以直接下载 Dojo 包。
- 解压 Dojo 包
Dojo 包下载后是一个后缀为 tar1.gz 的文件,可以通过 winzip 进行解压,解压后出现一个后缀为 tar 的文件,可以通过 winzp 再次进行解压。解压出现的 dojo-0.4.3-ajax 目录包含了 Dojo 包的所有文件。
- 将 Dojo 包部署在 Domino 上
将 Dojo 包部署在 Domino 上主要是将 Dojo 包里的文件放入 Domino 的 html 目录中。缺省情况下,Domino 的 html 目录是数据目录下的 domino/html 目录,比如,假设 Domino 安装时指定的数据目录是:C:/Lotus/Domino/data/,则 Domino 的 html 目录为 C:/Lotus/Domino/data/domino/html。为了便于管理,一般是在 html 目录下再创建一个目录,如 dojo,然后将 Dojo 包里的所有文件拷贝到这个新建的目录中,如下图所示:
图 4. html 目录下创建的 dojo 目录 - 在设计元素中引入 Dojo 包
为了在 Domino 的设计元素中使用 Dojo 元素,需要将 Dojo 包引入到设计元素中。在标准的 html 页面中,引入 Dojo 包的方式是在
header
标签内通过<script>
标签指定。在 Domino 设计元素中有对应的“HTML 首页内容”设置,可以通过它指定生成的 html 页面中header
的内容。以在表单中加入 Dojo 按钮为例,在表单的“HTML 首页内容”中加入以下内容,注意加入内容前后的引号:
清单 5. 在页面中引入 Dojo 包
"<title>Ajax Dojo Domino!</title> <script type=/"text/javascript/" src=/"/dojo/dojo.js/"> </script> <script type=/"text/javascript/"> dojo.require(/"dojo.widget.Button/"); </script>"
其中各部分的主要作用如下:
<title></title>
部分是为表单指定标题,这一行对于实现 Dojo 而言是可选的。src=/"/dojo/dojo.js/"
是为表单指定 Dojo 包所在的位置,如果在第三步中将 Dojo 包部署到了其它目录,在这里需要作对应的调整。dojo.require(/"dojo.widget.Button/");
为表单引入了 Dojo 组件中的按钮组件,根据使用组件的不同,这一行会有所变化,如dojo.widget.Dialog
等。
- 在设计元素中使用 Dojo 元素
在设计元素中引入 Dojo 包后可以开始使用 Dojo 组件了。在标准的 html 中使用 Dojo 组件是通过标签属性指定的,在 Domino 设计元素中则可以通过内置 html 的方式或者是指定元素 html 属性的方式使用 Dojo 组件。以内置 html 方式为例,在表单中加入 Dojo 按钮的代码如下:
<button dojoType="button" οnclick="alert('click')">Click here</button>
输入后注意选中这些内容,再选择“文本 -> 内置 html”将它们设置成内置 html。其中
dojoType="button"
用于指定按钮是一个 Dojo 按钮,其它元素与标准的 html 按钮相同。
完成第四步和第五步后的结果示意图如下:
以上面提到的表单为例,完成后进行测试时可以看见表单中出现了 Dojo 的按钮组件,点击后出面“click”字样,如下图所示:
![]() ![]() |
![]()
|
在以上的 Dojo 例子中,我们实现了一个 Dojo 按钮。在这个例子中,Dojo 组件并没有体现动态页面访问,因为它没有进行 Ajax 调用。
在 Dojo 组件中,有部分组件直接体现了 Ajax 调用,其中 ComboBox 组件是有代表性的一个。ComboBox 组件是一个组合框。对于普通的 html 组合框,页面设计者需要在设计组合框的时候指定组合框的选择项。而 Dojo 的 ComboBox 组件不同,在页面中使用它的时候只是指定了选择项的来源,当用户点击组合框的下拉按钮时浏览器才从服务器动态获得选择项。下面就以 Dojo 的 ComboBox 为例说明 Dojo 中的 Ajax 调用。
根据上面的描述,在 Domino 设计元素中使用 Dojo 组件需要五个步骤,其中前三个步骤属于在 Domino 服务器层面的设置,对于这个服务器上的所有设计元素而言是可以共享的,前三个步骤在一个服务器上只需要完成一次。由于我们在上面的章节中已经完成了前三个步骤,下面只需要完成后两个步骤:
- 在设计元素中引入 Dojo 包。
- 在设计元素中使用 Dojo 元素。
为了在表单中使用 Dojo 的 ComboBox 元素,我们需要在表单的“HTML 首页内容”中指定 Dojo 包的位置,同时引入 dojo.widget.ComboBox
元素,代码如下:
"<title>Insert title here</title> <script type=/"text/javascript/" src=/"/dojo/dojo.js/"> </script> <script type=/"text/javascript/"> dojo.require(/"dojo.widget.ComboBox/"); </script>" |
在表单中使用 Dojo 的 ComboBox 元素,我们可以通过内置 html 的方式在表单中使用 html 编码,代码如下:
<select dojoType="ComboBox" value="this should never be seen - it is replaced!" dataUrl="comboBox.js" style="width: 300px;" name="foo.bar1" maxListLength="15"> </select> |
其中 dojoType="ComboBox"
指定了这个元素是一个 Dojo 的 ComboBox,value=
所指定的内容是给 Dojo 代码进行处理的。dataUrl="comboBox.js"
指定了该组合框的选择项的来源,这里的 comboBox.js
我们需要通过 Domino 数据库的共享资源创建,具体的步骤在后面描述。
完成以上两步后的结果如下图:
此时对表单进行测试已经可以在浏览器上看到 Dojo 的 ComboBox 的显示效果,但是当我们点击下拉框时会发现选择框是空的。因为我们通过 dataUrl="comboBox.js"
所指定的选择项来源“comboBox.js”并不存在。
在 Dojo 包中有一个目录,名为 tests/widget,里面包含了一些用于演示的样例文档,其中的 comboBoxData.js 包含了一些样例选择项。我们可以通过 Domnio 的“共享资源 -> 文件”将文件 comboBoxData.js 引入至 Domino 数据库。在 Lotus Domino 设计端,选择“共享资源 -> 文件 -> 新建文件资源”,然后选择 Dojo 包所在的目录下的以下文件:tests/widget/comboBoxData.js,注意,引入后一定要将文件资源名称改为“comboBox.js”。如下图所示:
完成 ComboBox.js 的引入后再次对 ComboBox 表单进行测试则可以看到 Dojo 的 ComboBox 是如何从后台动态获得选择项的。结果如下图:
![]() ![]() |
![]()
|
在以上的样例中,我们在表单中使用了 Dojo 的元素,但是我们没有将 Dojo 元素和 Domino 的对应元素结合起来。如组合框 ComboBox,能否将用户所选择的内容保存到 Domino 文档中呢?
这样一个问题引出一系列的相似问题。在 Domino 数据库中有各种各样的设计元素,大的如表单、视图、页面、大纲等等,小的有计算文本、文本域、组合框、富文本框、操作、按钮等等。对于 Domino 应用开发人员而言,这些设计元素是 Domino 应用的构成关键,通过它们可以形成前台表达与后台数据之间的互动。Dojo 的元素主要集中在前台的表达上,它们不能与 Domino 服务器形成有效的数据交互。因为 Domino 平台上的数据获取方式与提交方式与一般的 Web 应用平台不同。如表单的保存,是由 Domino 根据 @command([filesave])
命令生成动态的 submit
方法。又如表单中的域,如果在前台通过 html 生成一个输入框,在表单中没有对应的域,输入框的信息是不会被保存在 Domino 的文档中的。
所以,在 Domino 上有效使用 Dojo 的方式是将 Domino 设计元素与 Dojo 元素结合起来,在前台表达时使用 Dojo 元素,在与后台进行数据交互时借助 Domino 原有的设计元素。
结合 Domino 设计元素与 Dojo 元素的方式有两种,一种比较简单,可以直接在 Domino 设计元素的 html 属性中使用 Dojo 属性,使 Domino 设计元素在浏览器上直接表现为 Dojo 元素。另一种同时创建 Domino 设计元素与 Dojo 元素,通过名称或者是其它方式将两个元素连接起来。
下面通过两个例子简要说明第一种方法,将 Dojo 里的时间选择框使用在 Domino 表单中原有的时间域中。
- 首先创建一个表单,并在表单中加入一个时间域,因为时间域在浏览器上无法直接表达,它在浏览器上会表现成为一个可输入的文本框。
- 然后,为了使用 Dojo,在该表单的“HTML 首页内容”中加入相应的引入 Dojo 的代码,为了方便,可以在
require
语句中通过dojo.widget.*
引入所有元素。 - 最后,在时间域的 HTML 属性页的“类”一栏中填入“dojo-DropDownDatePicker”,这一设置说明该域使用 Dojo 的时间选择框。
完成后的结果如下图:
测试结果如下:
![]() ![]() |
![]()
|
对于 Domino 开发人员而言,Dojo 是一个 Web 应用开发的有力工具,它可以帮助 Domino 开发人员实现丰富的界面和更强大的功能。当然,在 Domino 上有效地使用 Dojo 需要更多的工作,需要更多的人进行创新的工作。本文只是介绍了我们需要迈出的第一步,希望可以帮助读者更快地开展工作。
学习
- 开始了解 IBM Lotus Notes and Domino V8 技术内容。
- 阅读 developerWorks 文章 “使用 Ajax 操纵 Lotus Notes 文档”。
- 阅读 developerWorks 文章 “开发 IBM Lotus Domino Web 2.0 客户机”。
- 阅读关于 IBM Lotus Notes 和 Domino 的更多信息。
- Ajax 技术资源中心:developerWorks 上所有有关 Ajax 的问题都可以在这里找到解答。
- 订阅 Ajax 相关文章和教程 的 RSS 提要:获得即将发表的 Ajax 相关文章和教程的通知(查看 developerWorks 内容 RSS 提要 了解更多的信息)。
讨论