IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Java technology | Web development  >

控制 DOM,第 1 部分

DirectDOM 如何使您掌握控制

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

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 树
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 树
SimpleButton DOM 树

这个示例清楚地说明了 DOM 可以平稳地更新客户机器上的 Web 页面。虽然所执行的操作很简单,但我们相信您可以构想出更复杂的应用程序,它可以尽可能根据需要在客户机级别上与用户交互,从而在只有需要新数据时才与服务器联系。





回页首


结束语

DOM 提供了一个公共框架,它可以使 Web 成为可以从世界的任何地方访问的功能强大且实用的应用程序。DirectDOM 可以让开发人员创建高度交互的应用程序,这些应用程序不会过多占用通信基础设施,同时还可以对浏览器内容实施意想不到的控制。

本系列中的下一篇文章将介绍一种简单的三步方法,这种方法可以用于编写发扬 HTML(静态 Web 页面元素)和 weblet(平稳交互性)两者优点的应用程序。



参考资料



作者简介

Gary Cole 和 William Phillips 在 IBM 纽约 Endicott 工作,主要从事诸如 DirectDOM 之类非常酷的项目。请通过 colegl@us.ibm.com 联系 Gary。请通过 billphil@us.ibm.com 联系 William。


William F. Phillips has co-authored this article




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?




回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款