引入 JavaScript 和 CSS
前面提过,iWidget 是 Web 窗口小部件的一种格式,而 Web 窗口小部件实际上是小型的 Web 应用。通常来说,Web 应用由结构、展示和行为三部分组成,分别用 HTML、CSS 和 JavaScript 来描述。上一章中 清单 1 给出的 iWidget 定义文件中,<content> 元素的内容是描述结构的 HTML 代码。虽然 JavaScript 和 CSS 代码也可以直接写在 <content> 元素中,但是比较好的实践是将 JavaScript 和 CSS 代码存放在单独的文件中,并在 iWidget 中以超链接的形式引入这些文件。iWidget 规范定义了 <resource> 元素,用来声明 iWidget 引用的外部资源文件。如 清单 2 所示。
清单 2. <resource> 元素使用实例
<iw:iwidget
name="HelloWorld"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view"
mode="view"
iScope="HelloWorld"
lang="en">
<iw:resource uri="main.css" />
<iw:resource uri="helloworld.js" />
<iw:content mode="view">
<![CDATA[
<div class="hello_world">
<span id="_IWID_message"></span>
</div>
]]>
</iw:content>
</iw:iwidget>
|
<resource> 元素的 uri 属性用来声明外部资源的 URI。此处既可以使用相对于定义文件的相对路径,也可以使用绝对路径。清单 2 中使用了两个 <resource> 元素,分别用来引入 main.css 和 helloworld.js 两个外部资源。main.css 文件的内容与一般的 CSS 文件并没有区别,见 清单 3。
清单 3. main.css
.hello_world {
font-family : arial,sans-serif;
font-size : 1.2em;
}
.hello_world span {
font-size : 1em;
} |
清单 3 中只给出了基本的 CSS 定义的内容。需要注意的是,一个好的实践是把你的 iWidget 的 HTML 片断封装在一个 <div> 元素中,并赋予一个有意义且不容易重复的 class 属性。在对应的 CSS 文件中,所有的规则都放在该 class 属性对应的类选择器下。如 清单 3 中,所有的 CSS 规则都在类选择器 hello_world 下。这种实践的好处是当该 iWidget 与其它 iWidget 存在于同一页面中时,其样式不会受到其它 iWidget 的样式的影响。
清单 4 给出了 helloworld.js 的内容。
清单 4. helloworld.js
dojo.declare("HellWorld", null, {
onLoad : function() {
var messageDom = document.getElementById("_" +
this.iContext.widgetId + "_" + "message");
messageDom.innerHTML = "Hello World";
}
}); |
 |
iContext
iContext 表示的是支持 iWidget 运行所需的运行环境。从 iWidget 开发者的角度出发,在 iWidget 的 JavaScript 代码中,iContext 对象应该是 iWidget 惟一与运行环境交互的接口。iContext 对象可以提供很多 iWidget 开发中所需的实用方法。运行环境在 iWidget 加载的时候,会将 iContext 对象直接注入到与该 iWidget 关联的 JavaScript 对象中。
|
|
根据 iWidget 规范,每个 iWidget 实例都可以与一个 JavaScript 对象相关联。由该 JavaScript 对象负责处理 iWidget 实例的行为。这种关联是通过 <iwidget> 元素的 iScope 属性来实现的。<iwidget> 元素的 iScope 属性把 iWidget 的定义文件与 JavaScript 类关联起来。关联完成之后,每当从一个 iWidget 定义文件中实例化一个 iWidget 的时候,会实例化相应的 JavaScript 对象。两者被绑定在一起。这里需要注意的是 iScope 属性的值必须是一个 JavaScript 构造器(constructor),也就是说能够通过 new 操作符创建一个新的对象出来。一般来说,声明一个新的 function 即可;另外,该构造器必须是在全局对象中可以访问的。清单 4 中使用 Dojo 框架提供的 dojo.declare 来创建 JavaScript 类。关于在 iWidget 开发中使用 Ajax 框架的详细信息,请参看 使用 Ajax 框架。
在上述 JavaScript 对象中,有一个重要的 onLoad 方法。该方法在 iWidget 被实例化完成之后会被自动调用,其作用类似于 DOM 中的 onload 事件。当 onLoad 方法被调用时,就说明 iWidget 已经被成功加载,它的表示结构的 HTML 片断已经被添加到当前页面的 DOM 结构中。一般来说 onLoad 方法是 iWidget 中 JavaScript 代码运行的起点。
在 清单 4 中可以看到,JavaScript 中使用了 iContext 这个对象。这个对象由 iWidget 运行环境提供,是 iWidget 与其交互的接口。通过此对象,iWidget 可以访问运行环境提供给它使用的一系列功能,从而可以与当前页面以及页面中的其它 iWidget 进行交互。关于 iContext 的细节,请参考 侧栏。
通过 iContext 对象可以使用的方法有很多,同时 iContext 本身也是可以扩展的,不同的 iWidget 运行环境可以提供额外的附加功能。表 1 中给出了 iContext 中的常用方法和属性,其它方法会在后面的章节中介绍。
表 1. iContext 的常用方法和属性
| 名称 | 说明 |
|---|
| widgetId | 该属性是 iWidget 在实例化之后的标识符,是当前页面惟一的。 | | getElementById() | 该方法会根据 DOM 元素的 id 来查找元素,查找的范围是在 iWidget 的 HTML 片断中。 | | getElementByClass() | 该方法会根据 DOM 元素的 class 属性来查找元素,查找的范围是在 iWidget 的 HTML 片断中。 | | getRootElement() | 该方法返回 iWidget 的 HTML 片断的根元素。 | | iScope() | 该方法返回与当前 iWidget 实例关联的 JavaScript 对象。 | | iEvents | 该属性表示的对象可以用来访问运行环境提供的事件处理服务。 | | io | 该属性表示的对象可以用来访问运行环境提供的与 IO 操作相关的服务。 |
在 清单 4 中可以看到,<span> 元素的 id 属性的值是 _IWID_message,这里的 _IWID_ 是一个特殊的占位符。在 iWidget 被实例化完成之后,IWID 会被替换成该 iWidget 的 ID 。比如,上述 <span> 元素的 id 属性的值会变成 _ns_4e59746027db11debe12ee5c99529700_message,其中 ns_4e59746027db11debe12ee5c99529700 是由运行环境生成的。因此,在 iWidget 的 JavaScript 代码中根据 ID 来查找 HTML 元素的时候,需要使用类似 document.getElementById("_" + this.iContext.widgetId + "_" + "message") 这样的代码。给 iWidget 中的 HTML 元素的 ID 都加上这样一个自动生成的前缀之后,可以保证这些 ID 不会发生冲突。在 Google gadget 中,也提供了与 _IWID_ 类似的 __MODULE_ID__,两者的作用是一样的。
小结
本章介绍了如果通过 <resource> 元素来为 iWidget 引入 JavaScript 和 CSS 文件,以及如何将一个 JavaScript 对象与 iWidget 关联起来,从而为 iWidget 添加行为。下一章将介绍 iWidget 的编辑模式与配置信息的持久化。
|