级别: 初级 Gary Cole (colegl@us.ibm.com), 软件工程师, IBM William F. Phillips (billphil@us.ibm.com), 软件工程师, IBM
2001 年 4 月 01 日 Web 已经从静态 HTML 页面集合发展成可以用于银行业、旅馆房间预定和许多其它日常任务的工具。随着这种变换的发展,开发人员将需要与用户进行日趋复杂的交互,而且以一种不会对服务器网络提出不合理要求的方式进行交互。文档对象模型 (DOM) 将成为这种交互的框架,DirectDOM 可以让 Java 开发人员完全控制 DOM。这个三步曲系列的第一部分介绍了 DOM,并为使用 DirectDOM 直接访问 DOM 提供了基础知识。
用户-浏览器交互的最终目的是可以在用户的本地机器上平稳且轻松地操作浏览器内容。可惜,当前工具难以实现这个目的。诸如更新由浏览器显示的文本这种看似简单的任务要求您找到文本、进行更改、强制浏览器重新分析
HTML,然后重新生成页面。这些过程甚至可能要求您从网络重新装入页面,从而进一步减慢本来就已缓慢的过程。
DOM 简介
要消除这个问题,万维网联盟,或称作 W3C(请参阅
参考资料 ),开发了一组独立于语言和平台的接口,叫作文档对象模型
(DOM)。DOM 可以让您将文档当作树状数据结构,而不是一串带标记的 HTML
文本,进行访问和操作。
文档中的所有内容 --
包括字、段落和标题 --
都可以作为节点树来描述和访问。假设一个文档包含了一个段落,而这个段落包含了两个字,那么这个文档就有一个位于顶部的文档节点,一个主体节点,一个从主体节点分支出的段落节点,以及从段落节点分支出的两个文本节点。更新文档时只要找到特定节点并对它进行更改;然后在文档中就会自动反映出这些更改。因此,假设要使用
DOM
更改某些文本,那么只要直接根据名称找到节点,然后更改该节点的文本即可。文档树会立即更新,而且浏览器的显示也会立即更新。
什么是 DirectDOM?
DirectDOM 是来自 IBM 的 alphaWorks 技术,它可以让用户使用
weblet (DirectDOM 版本的 Applet)直接操作浏览器上显示的
DOM。与 Applet(它是浏览器不动产的一部分)不同,weblet 只操作 DOM
本身,它可以让用户:
- 插入、删除或移动对象
- 更改属性,如颜色、大小和字体
- 组合来自其它 DOM 树的片段
而且每次更改都不必重新装入页面。
由于使用了 DirectDOM 技术,weblet
使服务器不必接受利用任何必需的信息来更新浏览器内容,从而除去了服务器的许多负担。例如,weblet
可以通过一次大的下载来收集许多航线的航班调度信息,可以让用户在本地选择航班,然后上载用户的选择。这与每次用户进行新的选择时都要用服务器的新页面来更新浏览器形成了鲜明的对比。
小引擎
DirectDOM 的核心是 DirectDOM 引擎,这是由包含了带有 MIME 属性(在
Netscape 中)或 CLSID 属性(在 Internet Explorer 中)的
<object> 标记的 HTML 页面激活的插件。清单 1
提供了一个示例。启动了 DirectDOM 引擎之后,它使用 <object>
标记中的 WEBLET_CLASSNAME 和 WEBLET_CODEBASE 参数确定 weblet
的名称和位置。然后引擎创建 weblet 对象,该对象使用标准 W3C 接口对
DOM 执行任何期望的更改。
清单 1. HelloWorld.html
<HTML>
<BODY>
<H1>Hello World Example </H1>
<object id="HelloWorld" classid="clsid:F88A5D85-29A0-11D3-AE55-0000861DDC26" >
<param name="WEBLET_CLASSNAME" value="HelloWorld">
<param name="WEBLET_CODEBASE" value="file:\ddom\common\samples\HelloWorld.jar">
<comment>
<object type="application/x-weblet" width="0" height="0">
<param name="WEBLET_CLASSNAME" value="HelloWorld">
<param name="WEBLET_CODEBASE" value="file:\ddom\common\samples\HelloWorld.jar">
</object>
</comment>
</object>
</BODY>
</HTML>
|
该示例中的 <comment>
标记看起来很怪,但是排除浏览器非兼容性问题时必须要使用它们。因为 IE
使用 CLSID 来启动插件,而 Netscape 浏览器使用 MIME
类型,<comment> 标记提供了一种简单的方法分割代码,而不必编写
一些 JavaScript 来查询哪个浏览器在读取 HTML。Netscape
浏览器在读取页面时会忽略 CLSID 属性;而 IE
浏览器在读取页面时,它会忽略 <comment>
标记之间的所有内容。
如果用户以前从未访问过 DirectDOM 页面,那么 DirectDOM
引擎及其支持的 jar
文件会被自动下载并安装到用户的机器上,正如其它任何插件一样。(为简便起见,清单
1 中显示的示例没有包含使这段代码能够运行所必需的附加标记。DirectDOM
SDK 附带的示例 -- 请参阅
参考资料 --
包含了正确的标记。)
由浅入深
清单 2 和图 1
中显示的示例非常简单;它所做的就是在屏幕上打印一行。但是,它说明了开发更复杂文档需要使用的所有概念。weblet
最初实现了四个必要的方法:
init() 、
start() 、
stop() 和
destroy() 。
如果创建了 weblet 对象,并且向这个对象传递了
WebletContext ,那么 DirectDOM 引擎会调用
init() 方法。
WebletContext 是 weblet
用于存取插件服务的接口。当然,最重要的服务是提供 DOM
文档。文档节点是整个 DOM 树的基础,也称作“根”。
当 DirectDOM 引擎准备好让 weblet 操作 DOM 时,会调用
start() 方法。
目前还没有使用
stop() 和
destroy()
方法,但这些方法对于 weblet 接口是必不可少的。
清单 2. HelloWorld.java
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.html.HTMLDocument;
import com.ibm.weblet.*;
public class HelloWorld implements Weblet
{
private WebletContext m_context; // Plugin services
private HTMLDocument m_document; // Root node
// The init() method is called when the weblet object is created
// and sets the Document node interface which is the root of
// the entire document tree.
public void init( WebletContext context )
{
m_context = context;
// This is the document interface on which the entire
// document is built.
m_document = m_context.getOwnerDocument();
}
// The start() method is called by the DirectDOM engine to signal
// that it's ready to receive DOM updates.
public void start()
{
// Create a paragraph node
Element paragraph = m_document.createElement("P");
// Create a text node
Text helloText =
m_document.createTextNode("Hello world from the DOM!");
// Append the text node to the paragraph node
paragraph.appendChild(helloText);
// Get the body node. This is the area on the HTML page between
// the <BODY></BODY> tags
Element body = m_document.getBody();
// Append the paragraph to the body.
body.appendChild(paragraph);
}
// Not currently used but required for applets
public void stop()
{
}
// Not currently used but required for applets
public void destroy()
{
}
}
|
图 1 显示了这个非常简单的 HelloWorld DOM 树的外观。
图 1. HelloWorld DOM
树
对
start() 方法的第一次调用使用
createElement()
方法创建了一个段落节点。
createTextNode()
创建了文本节点,然后由
appendChild()
方法将文本节点添加到段落节点。对文档调用
getBody()
方法可以获取 <BODY> 和 </BODY>
标记之间的内容。这里正是示例要添加段落节点的位置。最后一个
appendChild()
将段落节点添加到主体,这个更改会自动在浏览器显示的文档中反映出来。
更复杂的示例
清单 3 中显示的示例说明了 weblet 可以在浏览器级别操作
DOM,却不必重新装入 Web 页面或向服务器发送请求。在这个示例中,Web
页面将显示一个按钮和一些文本。当用户单击按钮时,会弹出一个要求输入的对话框。当用户单击对话框的
OK 按钮时,Web 页面上的文本会被用户输入的文本替换。
清单 3. SimpleButton.java
import org.w3c.dom.*;
import org.w3c.dom.events.*;
import org.w3c.dom.html.*;
import com.ibm.weblet.*;
public class SimpleButton implements Weblet
{
private WebletContext m_context;
private HTMLDocument m_document;
private Text m_helloText;
public void init( WebletContext context )
{
m_context = context;
m_document = m_context.getOwnerDocument();
}
public void start()
{
// Create the textnode that will be updated here (just
// like the HelloWorld sample)
Element paragraph = m_document.createElement("p");
m_helloText = m_document.createTextNode("Hello world.");
paragraph.appendChild(m_helloText);
m_document.getBody().appendChild(paragraph);
// Create the button element.
HTMLButtonElement promptButton =
(HTMLButtonElement)m_document.createElement( "button" );
// Create a listener for the click event.
EventListener promptListener = new EventListener()
{
public void handleEvent( Event event )
{
// When a click event is received, pop up a dialog
// which accepts some text from the user.
String userText =
m_context.showModalPrompt( "Enter Some Text", "" );
// Update the text node with the new text.
m_helloText.setData( userText );
}
};
// Add the click event listener to the button
((EventTarget)promptButton).addEventListener("click", promptListener, true);
// Create a text node for the button text
Text buttonText = m_document.createTextNode( "Pop up dialog" );
// Add the text node to the button node
promptButton.appendChild( buttonText );
// Add the button node to the body
m_document.getBody().appendChild( promptButton );
}
public void stop()
{
}
public void destroy()
{
}
} |
图 2 显示了稍微复杂的 SimpleButton DOM 树的外观。
图 2. SimpleButton DOM
树
这个示例清楚地说明了 DOM 可以平稳地更新客户机器上的 Web
页面。虽然所执行的操作很简单,但我们相信您可以构想出更复杂的应用程序,它可以尽可能根据需要在客户机级别上与用户交互,从而在只有需要新数据时才与服务器联系。
结束语
DOM 提供了一个公共框架,它可以使 Web
成为可以从世界的任何地方访问的功能强大且实用的应用程序。DirectDOM
可以让开发人员创建高度交互的应用程序,这些应用程序不会过多占用通信基础设施,同时还可以对浏览器内容实施意想不到的控制。
本系列中的下一篇文章将介绍一种简单的三步方法,这种方法可以用于编写发扬
HTML(静态 Web 页面元素)和
weblet(平稳交互性)两者优点的应用程序。
参考资料
作者简介
 | |  | William F. Phillips has co-authored this article |
对本文的评价
|