使用 Dojo 工具包构建 AJAX 应用程序(远程访问、事件模型和部件的使用))

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.cn



您将通过本动手实验室了解如何使用 Dojo 工具包开发高响应、交互式、且基于 AJAX 的 Web 应用程序。本文旨在帮助您尽快入门。有关 Dojo 工具包的详细信息,请参见 Resources section of Dojo Toolkit。 

您将在本动手实验室接触到以下技术:(1)如何使用 dojo.io.bind() 调用进行远程访问(2)如何使用 dojo.event.connect() 调用处理包含函数调用在内的各种类型的事件(3)如何使用 Dojo 工具包随附的部件(4)如何使用 JSON 数据格式(5)如何从服务器中获取数据。  

有关创建 Dojo 工具包部件将在另一个动手实验室里进行介绍。

预计时间:120 分钟

前提条件

本动手实验室假定您拥有以下技术的基本知识或者具备相关编程经验:

软件需求

开始之前,需要在您的计算机上安装以下软件。 本动手实验室压缩文件中已经包含了 Dojo 工具包 0.4.3,不必自行下载。


可以使用的操作系统平台


变更记录


未来计划(由 Sang Shin 完成)


实验室练习



练习 1:修改 "Data Validation with AJAX" 示例应用程序,使用 dojo.io.bind() 调用

在本练习中,将要修改 "ajax-validation" 示例程序,来使用 dojo.io.bind() 调用。 也将使用 Dojo 工具包的 DOM 处理工具。您将要修改的这个示例应用程序,是一个可供打开的 NetBeans 项目,名称为 ajax-validation,是动手实验室压缩文件(4260_ajaxdojointro.zip)的组成部分。

  1. 通过 "Data Validation with AJAX" 示例应用程序创建和运行一个名称为 ajax-validation 的 NetBeans 项目
  2. 复制刚才创建的 ajax-validation 项目,创建一个新的 NetBeans 项目
  3. 将 Dojo 工具包  JavaScript 文件复制到新项目中
  4. 修改新项目的 index.jsp,让它使用 dojo.io.bind()
  5. 使用 Dojo 工具包的 DOM 处理方法
  6. 模拟错误处理
  7. mimetype 尝试
  8. 使用 formNode
  9. "前进"/"后退" 和书签
  10. 将 JavaScript 代码移动到单独文件中
  11. 修改 "Auto-completion with AJAX" 示例应用程序以使用 dojo.io.bind()
解决方案:针对此练习的解决方案作为可运行的 NetBeans 项目包含在动手实验室的压缩文件中。项目文件位于 <LAB_UNZIPPED_DIRECTORY>/ajaxdojointro/solutions/ajax-validation-dojo.io.bind.solution. 您可以打开并运行它。  如果在完成这个练习的过程中遇到不易发现的问题,请打开并运行 ajax-validation-dojo.io.bind.solution 项目,查看其运行结果。  

(1.1) 打开、构建和运行 "ajax-validation" 示例应用程序

0. 启动 NetBeans IDE。 
1. 打开 ajax-validation NetBeans 项目。 

2. 生成并运行 ajax-validation 项目。


图 1.12:运行项目

3.  注意到 Firefox 浏览器显示出来。 
4. 在 User Id: 字段处键入一些字符,如 sa
5. 注意到 Valid User Id 字符串显示在文本字段的右侧。(如下图 1.13 所示)本例是一个 AJAX 用法的示例,由服务器通过 AJAX 对输入数据进行验证。

Data Validation using AJAX
图 1.13:运行 "Data Validation using AJAX" 示例应用程序

                                                                                                                                        返回练习顶部

(1.2) 复制刚才创建的 ajax-validation 项目,创建一个新项目

可以直接修改 ajax-validation 项目。 但只要将原始项目保留在当前表单中,我们将通过把 ajax-validation 项目复制到一个新项目中来创建这个新项目。将新项目命名为 ajax-validation-dojo.io.bind

1. 右键单击ajax-validation 项目节点并选择 复制项目。  出现了 复制项目 对话框。
2. 在 项目名称:Project Name: 字段处键入 ajax-validation-dojo.io.bind。单击 复制 按钮。(下图 1.14)  ajax-validation-dojo.io.bind 项目出现在项目选项卡窗口中。


图 1.14:复制项目对话框

3. 更改新项目的上下文路径(只针对 NetBeans 5.0. 在 NetBeans 5.5.1 中这一步是自动完成的)


图 1.15:改变上下文路径来反映新项目的上下文路径

                                                                                                                                        返回练习顶部

(1.3) 将 Dojo 工具包 JavaScript 文件复制到新项目中


现在需要将 Dojo toolkit JavaScript 库文件复制到 Web 应用程序项目中。 JavaScript 文件的保存位置应和 JSP、HTML 或图片文件一样,因而应将库文件复制到 Web 应用程序结构的根目录(或根目录的子目录)下。

注意:如果您使用的是 NetBeans 6.0,可以直接从操作系统的文件系统中将文件复制到 NetBeans 项目,而不必如以上所示,将一个目录添加到收藏夹窗口中。

1. 右键单击 ajax-validation-dojo.io.bind 项目。
2. 在项目属性窗口,选择 "源" 选项。
3. 在项目属性窗口右侧的窗格中,单击 "Web 页文件夹" 的 "浏览"按钮。
4. 复制 "文件名称" 中的内容。这给出 web 文件夹的位置,Dojo toolkit JavaScript 库文件要复制到这个文件夹中。
5. 打开 Windows 浏览器,到以上所选的文件夹(例如 C:\Sang-Ajaxcourse\ajax-validation-dojo.io.bind\web)。
6. 将整个 dojo-release-1.0.1 文件夹复制到 ...\ajax-validation-dojo.io.bind\web。




图 1.16:复制 Web 文件夹路径

7. Netbeans 项目将自动刷新,并显示 netbeans 项目的新内容。

Folder update inside netbeans project
图 1.17:NetBeans 项目自动刷新并显示出复制的文件夹

                                                                                                                                        返回练习顶部


(1.4) 修改 index.jsp 文件使用 dojo.io.bind()

在本步骤中,将修改 index.jsp 文件以使用 dojo.io.bind(),而无需直接创建 XMlHttpRequest JavaScript 对象并用它来执行和服务器间的异步通信。

1. 双击 ajax-validation-dojo.io.bind 项目的 index.jsp,在源编辑器窗口中打开它。 (如图 1.18 所示)


图 1.18:在源编辑器中打开 index.jsp


2. 修改 index.jsp 文件,如下所示。 需要添加的新的代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则突出显示为 红色粗体字。 保持不变的代码段显示为常规字体。 请留意注释,其解释了为什么有些代码段被删除,而有些被添加进来。 (这是 index.jsp 文件的完整代码。 因此您可以对其进行复制粘贴。)

在 dojo 1.0.x 中,dojo.io.bind()(用于 dojo 0.9 之前的版本)被替换为更加具体的函数,更明确地指示出使用哪种 IO 传输。然而,使用一个对象参数,其具有属性细化 IO 调用的这种形式仍在使用。 新的 xhr 函数如下所示:

 

<html>
<head>

<!-- Include Dojo toolkit library file dojo.js, make sure the directory path is set correctly -->
<script language="JavaScript"
            type="text/javascript"
            src="dojo-release-1.0.1/dojo/dojo.js">
</script>
   

<script type="text/javascript">
//var req;   // No longer needed since we don't need to deal with XMLHttpRequest
var target;
//var isIE;   // No longer needed since wd don't need to deal with browser difference

/********************* Commented out *******************
  * We don't need to do the low-level XMLHttpRequest handling anymore
  * since it is handled by dojo.io.bind().

function initRequest(url) {
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        isIE = true;
        req = new ActiveXObject("Microsoft.XMLHTTP");
    }
}

function validateUserId() {
    if (!target) target = document.getElementById("userid");
    var url = "validate?id=" + escape(target.value);   
    initRequest(url);
    req.onreadystatechange = processRequest;
    req.open("GET", url, true);
    req.send(null);
}
******************************************************/

// This is the modified validateUserId() function
function validateUserId() {
   if (!target) target = document.getElementById("userid");
   var sampleFormNode = document.getElementById("submit_btn");

   // Use dojo.xhrGet() for remoting
   dojo.xhrGet( {
        // URL - location of the data you want to get
        url: "validate?id=" + escape(target.value),
        handleAs: "xml",
        timeout: 5000, // Time in milliseconds

        load: function(response, ioArgs) {
           processRequest(response);
        },

//The ERROR function will be called in an error case.
        error: function(response, ioArgs) {
           alert("dojo Error alert !!");
        },
    });

}


/********************* commented out **************************************
  * We don't need to check the status and readyState anymore
since it is handled by dojo.io.bind()
function processRequest() {
    if (req.readyState == 4) {
        if (req.status == 200) {
            var message = req.responseXML.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
            setMessageUsingDOM(message);
            var submitBtn = document.getElementById("submit_btn");
            if (message == "false") {
              submitBtn.disabled = true;
            } else {
              submitBtn.disabled = false;
            }
        }
    }
}
***********************************************************************/

// This is the modified processRequest() function.  Note that you don't need to
// check if the readyState of the XMLHttpRequest is 4 or not.
function processRequest(data) {
            var message = data.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
            setMessageUsingDOM(message);
            var submitBtn = document.getElementById("submit_btn");
            if (message == "false") {
              submitBtn.disabled = true;
            } else {
              submitBtn.disabled = false;
            }
}

function setMessageUsingInline(message) {
    mdiv = document.getElementById("userIdMessage");
    if (message == "false") {
       mdiv.innerHTML = "<div style='color:red; font-family:Arial; font-size:14px; font-weight:bold;'>Invalid User Id</div>";
    } else {
       mdiv.innerHTML = "<div style='color:green; font-family:Arial; font-size:14px; font-weight:bold;'>Valid User Id</div>";
    } 
}

 function setMessageUsingDOM(message) {
     var userMessageElement = document.getElementById("userIdMessage");
     var messageText;
     if (message == "false") {
          userMessageElement.style.color = "red";
          userMessageElement.style.fontFamily = "Arial";
          userMessageElement.style.fontSize = "14px";
          userMessageElement.style.fontWeight = "bold";
          messageText = "Invalid User Id";
     } else {
          userMessageElement.style.color = "green";
          userMessageElement.style.fontFamily = "Arial";
          userMessageElement.style.fontSize = "14px";
          userMessageElement.style.fontWeight = "bold";
          messageText = "Valid User Id";
     }

     /***********   commented out ******************
     var messageBody = document.createTextNode(messageText);
     // if the messageBody element has been created simple replace it otherwise
     // append the new element
     if (userMessageElement.childNodes[0]) {
         userMessageElement.replaceChild(messageBody, userMessageElement.childNodes[0]);
     } else {
         userMessageElement.appendChild(messageBody);
     }
     *******************************************/
      // Use innerHTML instead of raw DOM API
      userMessageElement.innerHTML = messageText;
  }

   function disableSubmitBtn() {
     var submitBtn = document.getElementById("submit_btn");
     submitBtn.disabled = true;
   }

        </script>
        <title>Form Data Validation using AJAX</title>
    </head>
    <body onload="disableSubmitBtn()">
       
        <h1>Form Data Validation using AJAX</h1>
        <hr/>
        <p><font face="Arial" size="2">
                This example shows how you can use AJAX to do server-side form data validation without
                a page reload.
                <br><br>
                In the form below enter a user id. By default the user ids "greg" and "duke"
                are taken. If you attempt to enter a user id that has been taken an error message will be
                displayed next to the form field and the "Create Account" button will be
                disabled. After entering a valid user id and selecting the "Create Account"
                button that user id  will be added to the list of user ids that are taken.
        </font></p>
       
        <form name="updateAccount" action="validate" method="post">
            <input type="hidden" name="action" value="create"/>
            <table border="0" cellpadding="5" cellspacing="0">
                <tr>
                    <td><b>User Id:</b></td>
                    <td>
                        <input type="text"
                                   size="20" 
                                   id="userid"
                                   name="id"
                                   onkeyup="validateUserId()">
                    </td>
                    <td>
                        <div id="userIdMessage"></div>
                    </td>
                </tr>
                <tr>
                    <td align="right" colspan="2">
                        <input id="submit_btn" type="Submit" value="Create Account">
                    </td>
                    <td></td>
                </tr>
            </table>
        </form>
    </body>
</html>

3. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  新项目应和 以上 ajax-validation 项目的运行方式一样。  

故障排除:  如果您遇到问题,例如,在 User Id: 字段处键入一个字符串,而没有生成 Valid User Id 消息(如下图 1.19 所示),请打开 JavaScript 控制台,查看所显示的调试消息(下图 1.19 所示)。

Firebug Console
图 1.19:打开 Firebug 控制台进行调试


Firebug Console error display
图 1.20:Firebug 控制台显示出在 JavaScript 中发现的错误。 以上显示出您还没有将 dojo.js 文件复制到项目,或者在 index.jsp 页面中没有正确指定将文件复制到的目录。

                                                                                                                                        返回练习顶部

(1.5) 使用 Dojo 工具包的 DOM 处理方法


在本步骤中,将使用 Dojo 工具包中的一些 DOM 处理方法。

1. 修改 index.jsp 文件,如以下代码 1.50 所示。 请注意代码 1.50 只显示 <script> 和 </script> 间的代码。  需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 保持一样的代码段显示为常规字体。 请留意注释,其解释了为什么有些代码段被删除而有些代码段则被添加。
在 dojo 发布版 1.0.X 版中,dom 函数不再是核心包的一部分,而移至 dojox.data.dom 包中。因而需要将这一行代码包括进来,"dojo.require("dojox.data.dom");"。在引用 dom 功能时,需要使用:var message = dojox.data.dom.textContent(....)

<!-- Include Dojo toolkit library file dojo.js, make sure the directory path is set correctly -->
<script language="JavaScript"
        type="text/javascript"
        src="dojo-release-1.0.1/dojo/dojo.js">
</script>
  

<script type="text/javascript">
dojo.require("dojox.data.dom");
var target;


// This is the modified validateUserId() function
function validateUserId() {
    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");
    //var sampleFormNode = document.getElementById("submit_btn");
    var sampleFormNode = dojo.byId("submit_btn");
   
    // Use dojo.xhrGet() for remoting
    dojo.xhrGet( {
        // URL -  location of the data you want to get
        url: "validate?id=" + escape(target.value),
        handleAs: "xml",
        timeout: 5000, // Time in milliseconds

        load: function(response, ioArgs) {
            processRequest(response);
        },

        // The ERROR function will be called in an error case.
        error: function(response, ioArgs) {
            alert("dojo Error alert !!");
        },
     });
}

// This is the modified processRequest() function
function processRequest(data) {
       // var message = data.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
       var message = dojox.data.dom.textContent(data.getElementsByTagName("valid")[0]);
       setMessageUsingDOM(message);
       //var submitBtn = document.getElementById("submit_btn");
       var submitBtn = dojo.byId("submit_btn");
       setMessageUsingDOM(message);
       if (message == "false") {
           submitBtn.disabled = true;
       } else {
           submitBtn.disabled = false;
       }
}

function setMessageUsingInline(message) {
    //mdiv = document.getElementById("userIdMessage");
    mdiv = dojo.byId("userIdMessage");
    if (message == "false") {
       mdiv.innerHTML = "<div style=\"color:red\">Invalid User Id</div>";
    } else {
       mdiv.innerHTML = "<div style=\"color:green\">Valid User Id</div>";
    } 
}

 function setMessageUsingDOM(message) {
     //var userMessageElement = document.getElementById("userIdMessage");
     var userMessageElement = dojo.byId("userIdMessage");
     var messageText;
     if (message == "false") {
         userMessageElement.style.color = "red";
         messageText = "Invalid User Id";
     } else {
         userMessageElement.style.color = "green";
         messageText = "Valid User Id";
     }
     userMessageElement.innerHTML = messageText;
 }

function disableSubmitBtn() {
    //var submitBtn = document.getElementById("submit_btn");
    var submitBtn = dojo.byId("submit_btn");
    submitBtn.disabled = true;
}
</script>

代码 1.50:使用 Dojo 工具包中的 DOM 实用方法

2. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  新项目应和 以上 看到的 ajax-validation 运行方式一样。

                                                                                                                                        返回练习顶部

(1.6) 模拟错误处理


在本步骤中,将模拟一个 HTTP 错误条件,看看 dojo.xhrGet() 中的错误句柄是否被调用。

1. 修改 index.jspvalidateUserId() 函数,如以下代码 1.60 所示。 需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 这么做是要通过传递无效路径来生成 HTTP 错误条件。

// This is the modified validateUserId() function
function validateUserId() {
    //if (!target) target = document.getElementById("userid");
        if (!target) target = dojo.byId("userid");
        //var sampleFormNode = document.getElementById("submit_btn");
        var sampleFormNode = dojo.byId("submit_btn");

    dojo.xhrGet( {
        // URL -  location of the data you want to get
        //url: "validate?id=" + escape(target.value),
        url: "validateInvalidURL?id=" + escape(target.value),
        handleAs: "xml",
        timeout: 5000, // Time in milliseconds

        load: function(response, ioArgs) {
            processRequest(response);
        },

        // The ERROR function will be called in an error case.
        error: function(response, ioArgs) {
            alert("dojo Error alert !!");
        },
    });
}
代码 1.60:通过传递无效 URL 模拟错误条件

2. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。 显示出 Firefox 浏览器。
3. 在浏览器的 User Id 字段处键入一个字符。
4. 您会看到一条警告消息。(如下图 1.32 所示)


图 1.32:错误句柄显示出一条警告消息

5. 通过删除您在以上代码 1.60 中对 index.jspvalidateUserId() 函数所做的修改,删除错误条件。

                                                                                                                                        返回练习顶部

(1.7) mimetype 尝试

请注意您过去将 "text/xml" 作为 "mimetype" 的值。它所做的是当接收到来自于服务器的数据时,将其解析为一个 XML 文档。这就是在如下所示的 proceRequest(data) 函数中可以将数据作为 DOM 对象来提取的原因。既然它是一个 DOM 对象,您就可以使用 getElementByTagName(..) 或 dojo.dom.textContent(..) DOM 方法。

// This is the modified processRequest() function. Note that you don't need to
// check if the readyState of the XMLHttpRequest is 4 or not.
function processRequest(data) {
    // var message = data.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
    var message = dojox.data.dom.textContent(data.getElementsByTagName("valid")[0]);
    setMessageUsingDOM(message);
    //var submitBtn = document.getElementById("submit_btn");
    var submitBtn = dojo.byId("submit_btn");
    setMessageUsingDOM(message);
    if (message == "false") {
        submitBtn.disabled = true;
    } else {
        submitBtn.disabled = false;
    }
}
代码 1.70:对接收到的数据进行 XML 解析

现在把 mimetype 改成 "text",看看会发生什么。

1. 根据代码 1.71 修改 index.jspvalidateUserId() 函数。 需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 

// This is the modified validateUserId() function
function validateUserId() {
    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");
        //var sampleFormNode = document.getElementById("submit_btn");
        var sampleFormNode = dojo.byId("submit_btn");         

    // Use dojo.xhrGet() for remoting
     dojo.xhrGet( {
         // URL - location of the data you want to get
        url: "validate?id=" + escape(target.value),
         //handleAs: "xml",
         handleAs: "text",
         timeout: 5000, // Time in milliseconds

                                                                                                                                                                                                        load: function(response, ioArgs) {
            processRequest(response);
        },     

ERROR 函数将在发生错误时调用。
        error: function(response, ioArgs) {
            alert("dojo Error alert !!");
        },
    });
}

代码 1.71:通过传递无效 URL 模拟错误条件

2. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  显示出 Firefox 浏览器。
3. 按 F12 键查看 FireBug 调试器。
5. 在浏览器的 User Id 字段中键入字符。
6. 注意到 FireBug 调试器报告的错误条件。(如下图 1.72 所示)该错误指示出由于您的目的是以纯文本格式接收数据,从服务器接收到的数据不再被解析为 XML 文档。 


图 1.72:数据未被解析为 XML

7. 将 mimetype 改为 "text/xml"  ,让其再次运行。

                                                                                                                                        返回练习顶部

(1.8) 使用 formNode


在本步骤中,将使用 "formNode" 将整个表单(输入表单字段集)发送至服务器。

1. 根据代码 1.80 修改 index.jspvalidateUserId() 函数。需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 

// This is the modified validateUserId() function
function validateUserId() {
    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");
    //var sampleFormNode = document.getElementById("submit_btn");
    var sampleFormNode = dojo.byId("submit_btn");

     // Use dojo.xhrGet() for remoting
     dojo.xhrGet( {
         // URL - location of the data you want to get
         //url: "validate?id=" + escape(target.value),
         // Since the form data is passed to the server via formNode
         // parameter below, no need to pass target.value here.
         url: "validate",

         // Send form data."myform" 是输入表单的 ID。
         form: dojo.byId("myform"),
         handleAs: "xml",
         timeout: 5000, // Time in milliseconds

         load: function(response, ioArgs) {
             processRequest(response);
         },

ERROR 函数将在发生错误时调用。
         error: function(response, ioArgs) {
             alert("dojo Error alert !!");
         },
});
}

代码 1.80:使用 formNode

2. 根据代码 1.81 修改 <form ..> 元素,给其添加一个 id 属性。注意到  id="myform" 被添加为一个属性。

<form id="myform" name="updateAccount" action="validate" method="post">
    <input type="hidden" name="action" value="create"/>
    <table border="0" cellpadding="5" cellspacing="0">
    <tr>
        <td><b>User Id:</b></td>
        <td>
        <input type="text"
               size="20" 
               id="userid"
               name="id"
               onkeyup="validateUserId()">
        </td>
        <td>
        <div id="userIdMessage"></div>
        </td>
    </tr>
    <tr>
        <td align="right" colspan="2">
        <input id="submit_btn" type="Submit" value="Create Account">
        </td>
        <td></td>
    </tr>
    </table>
</form>
代码 1.81:为 <form ..> 元素添加一个 id 属性

3. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  显示出 Firefox 浏览器。
4. 按 F12 键查看 FireBug 调试器。
5. 在浏览器的 User Id 字段中键入字符。
6. 观察浏览器和服务器间的 HTTP 传输。(如下图 1.32 所示)


图 1.32:formNode 的用法

                                                                                                                                        返回练习顶部

(1.9) "前进"/"后退" 和书签


1. 根据代码 1.90 修改 index.jsp。需要添加的新代码段突出显示为 蓝色粗体字

    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory path is set correctly -->
    <script language="JavaScript"
            type="text/javascript"
            src="dojo-release-1.0.1/dojo/dojo.js">
    </script>

    <script type="text/javascript">
    dojo.require("dojox.data.dom");
    dojo.require("dojo.back");
    djConfig = {
        //dojoIframeHistoryUrl: "dojo-1.0.0/dojo/resources/iframe_history.html", //for xdomain
        preventBackButtonFix: false
    };
    var state = {
        back: function() { alert("BackButton was pressed !"); },
        forward: function() { alert("Forward Button was pressed !"); },
    };
    dojo.back.init();
    dojo.back.setInitialState(state);
   
    //var req;   // No longer needed since we don't need to deal with XMLHttpRequest
    //var isIE;   // No longer needed since wd don't need to deal with browser difference
    var target;

    /********************* Commented out *******************
     * We don't need to do the low-level XMLHttpRequest handling anymore
     * since it is handled by dojo.io.bind().
    function initRequest(url) {
        if (window.XMLHttpRequest) {
            req = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            isIE = true;
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }

    function validateUserId() {
        if (!target) target = document.getElementById("userid");
        var url = "validate?id=" + escape(target.value);  
        initRequest(url);
        req.onreadystatechange = processRequest;
        req.open("GET", url, true);
        req.send(null);
    }
    ******************************************************/

   
    // This is the modified validateUserId() function
    function validateUserId() {
        dojo.back.addToHistory(state);

    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");
    //var sampleFormNode = document.getElementById("submit_btn");
    var sampleFormNode = dojo.byId("submit_btn");

    // Use dojo.xhrGet() for remoting
    dojo.xhrGet( {
        // URL -  location of the data you want to get
        //url: "validate?id=" + escape(target.value),
        // Since the form data is passed to the server via formNode
        // parameter below, no need to pass target.value here.
        url: "validate",  

        // Send form data."myform" 是输入表单的 ID。
        form: dojo.byId("myform"),   
        handleAs: "xml",
        timeout: 5000, // Time in milliseconds


        load: function(response, ioArgs) {
        processRequest(response);
        },

        // The ERROR function will be called in an error case.
        error: function(response, ioArgs) {
        alert("dojo Error alert !!");
        },
    });
    }
     

    /********************* commented out **************************************
     * We don't need to check the status and readyState anymore since it is handled by dojo.io.bind()
    function processRequest() {
        if (req.readyState == 4) {
            if (req.status == 200) {
                var message = req.responseXML.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
                setMessageUsingDOM(message);
                var submitBtn = document.getElementById("submit_btn");
                if (message == "false") {
                  submitBtn.disabled = true;
                } else {
                  submitBtn.disabled = false;
                }
            }
        }
    }
    ***********************************************************************/

    // This is the modified processRequest() function.  Note that you don't need to
    // check if the readyState of the XMLHttpRequest is 4 or not.
    function processRequest(data) {
    // var message = data.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
    var message = dojox.data.dom.textContent(data.getElementsByTagName("valid")[0]);
    setMessageUsingDOM(message);
    //var submitBtn = document.getElementById("submit_btn");
    var submitBtn = dojo.byId("submit_btn");
    setMessageUsingDOM(message);
    if (message == "false") {
      submitBtn.disabled = true;
    } else {
      submitBtn.disabled = false;
    }
    }

    function setMessageUsingInline(message) {
    //mdiv = document.getElementById("userIdMessage");
        mdiv = dojo.byId("userIdMessage");
    if (message == "false") {
       mdiv.innerHTML = "<div style='color:red; font-family:Arial; font-size:14px; font-weight:bold;'>Invalid User Id</div>";
    } else {
       mdiv.innerHTML = "<div style='color:green; font-family:Arial; font-size:14px; font-weight:bold;'>Valid User Id</div>";
    } 
    }

    function setMessageUsingDOM(message) {
        //var userMessageElement = document.getElementById("userIdMessage");
        var userMessageElement = dojo.byId("userIdMessage");
        var messageText;
        if (message == "false") {
            userMessageElement.style.color = "red";
            userMessageElement.style.fontFamily = "Arial";
            userMessageElement.style.fontSize = "14px";
            userMessageElement.style.fontWeight = "bold";
            messageText = "Invalid User Id";
        } else {
            userMessageElement.style.color = "green";
            userMessageElement.style.fontFamily = "Arial";
            userMessageElement.style.fontSize = "14px";
            userMessageElement.style.fontWeight = "bold";
            messageText = "Valid User Id";
        }

    /*********** commented out ******************
    var messageBody = document.createTextNode(messageText);
    // if the messageBody element has been created simple replace it otherwise
    // append the new element
    if (userMessageElement.childNodes[0]) {
        userMessageElement.replaceChild(messageBody, userMessageElement.childNodes[0]);
    } else {
        userMessageElement.appendChild(messageBody);
    }
    *******************************************/
    // Use innerHTML instead of raw DOM API
    userMessageElement.innerHTML = messageText;
     }

    function disableSubmitBtn() {
    //var submitBtn = document.getElementById("submit_btn");
        var submitBtn = dojo.byId("submit_btn");
    submitBtn.disabled = true;
    }
   
    </script>
    <title>Form Data Validation using AJAX</title>
    </head>


代码 1.90:添加 Dojo 配置

2. 请验证  dojo-release-1.0.1\dojo\resources 目录下有一个 iframe_history.html 文件。
3. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  显示出 Firefox 浏览器。
4. 按 F12 键查看 FireBug 调试器。
5. 在浏览器的 User Id 字段中键入字符。
6. 按下 backward 按钮。(如下图 1.91 所示) 
7. 观察该警告消息(如下图 1.91 所示)单击 OK 按钮关闭该警告消息框。


图 1.91:调用 Backward 按钮功能

9. 按下 forward 按钮。(如下图 1.92 所示)
10. 观察该警告消息。(如下图 1.92 所示)


图 1.92:调用 forward 按钮功能

现在,假设我们想使 backward 按钮有同 "starting new" 同样的行为。 Now let's suppose that we want the behavior of the backward button to be something like "starting new". 

11. 根据代码 1.93 修改 index.jspvalidateUserId() 函数。需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 

// This is the modified validateUserId() function
function validateUserId() {

    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");

    //var sampleFormNode = document.getElementById("submit_btn");
    var sampleFormNode = dojo.byId("submit_btn");
   
    // Use dojo.io.bind() for remoting
    dojo.io.bind({
          // URL -  location of the data you want to get
          //url: "validate?id=" + escape(target.value),
          // Since the form data is passed to the server via formNode
          // parameter below, no need to pass target.value here.
          url: "validate",   

          // The server code in this ajax-validation
          // sample application expects "GET".  It
          // uses "POST" for account creation. Probably
          // not a good practice but that is the way
          // the server side code is written for now.
          method: "GET", 

          // Send form data. "myform" is the id of the input form.
 
          formNode: dojo.byId("myform"),    

         
          // Callback function that you'd like to have called
          // when you actually do get the data
          load: function(type, data, evt){ processRequest(data);},
         
          // Error handling
          error: function(type, error){ alert("error"); },
         
          // Backward and forward button handling
         // backButton: function() { alert("back button pressed"); },
          // New backward button behavior
          backButton: function() {
                 // Blank out the User Id field value
                 target.value="";

                 // Display a message indicating Backward button is pressed
                 var userMessageElement = dojo.byId("userIdMessage");
                 userMessageElement.innerHTML = "Backward button pressed. Start again!";

                 // Disable the submit button
                 var submitBtn = dojo.byId("submit_btn");
                 submitBtn.disabled = true;
          },
          forwardButton: function() { alert("forward button pressed");},
         
          // Type of data you want to receive
          mimetype: "text/xml"         
    }); 
}
代码 1.93:修改过运行方式的 backward 按钮

12. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行。  显示出 Firefox 浏览器。
13. 在浏览器的 User Id 字段中键入字符。
14. 按下 backward 按钮。(如下图 1.94 所示)
15. 注意到 User Id 被清空,而显示出 "Backward button pressed, Start again!" 消息,Created Account 被禁用。


图 1.94:新 Backward 按钮的行为


                                                                                                                                        返回练习顶部

(1.10) 将 JavaScript 代码移动到单独文件中

在本步骤中,将把 JavaScript 代码移入另一个名称为 myjavascript.js 的文件。这是一个可选步骤。

1. (假设您安装了 NetBeans JavaScript 编辑器插件),右键单击 ajax-validation-dojo.io.bind 项目节点下的 Web 页 并选择 New->JSTemplate.js
2. 注意到出现了 New JSTemplate.js 对话框。
3. 在文件名称字段处键入 myjavascript。单击 完成 按钮。(如图 1.100 所示)


图 1.100:创建 myjavascript.js 文件

注意:如果还没安装 NetBeans JavaScript 编辑器插件,请在 Web Pages 目录下创建一个名称为 myjavacript.js 的新文件。

4. 将以下代码 1.101 所示的代码段从 index.jsp 移至新创建的 myjavascript.js 文件中。您基本上是把 JavaScript 代码移至一个独立文件。请注意您不需要用 <script..></script> 标签将 JavaScript 代码封装在 myjavascript.js 文件中。

dojo.require("dojox.data.dom");
dojo.require("dojo.back");
djConfig = {
    //dojoIframeHistoryUrl: "dojo-1.0.0/dojo/resources/iframe_history.html",
    preventBackButtonFix: false
};
var state = {
    back: function() {
    // Blank out the User Id field value
    target.value="";

    // Display a message indicating Backward button is pressed
    var userMessageElement = dojo.byId("userIdMessage");
    userMessageElement.innerHTML = "Backward button pressed. Start again!";

    // Disable the submit button
    var submitBtn = dojo.byId("submit_btn");
    submitBtn.disabled = true;
    },
    forward: function() { alert("Forward Button was pressed !"); },
};
dojo.back.init();
dojo.back.setInitialState(state);

//var req;   // No longer needed since we don't need to deal with XMLHttpRequest
//var isIE;   // No longer needed since wd don't need to deal with browser difference
var target;

/********************* Commented out *******************
 * We don't need to do the low-level XMLHttpRequest handling anymore
 * since it is handled by dojo.io.bind().
function initRequest(url) {
    if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
    isIE = true;
    req = new ActiveXObject("Microsoft.XMLHTTP");
    }
}

function validateUserId() {
    if (!target) target = document.getElementById("userid");
    var url = "validate?id=" + escape(target.value);  
    initRequest(url);
    req.onreadystatechange = processRequest;
    req.open("GET", url, true);
    req.send(null);
}
******************************************************/


// This is the modified validateUserId() function
function validateUserId() {
    dojo.back.addToHistory(state);

    //if (!target) target = document.getElementById("userid");
    if (!target) target = dojo.byId("userid");
    //var sampleFormNode = document.getElementById("submit_btn");
    var sampleFormNode = dojo.byId("submit_btn");

    // Use dojo.xhrGet() for remoting
    dojo.xhrGet( {
    // URL -  location of the data you want to get
    //url: "validate?id=" + escape(target.value),
    // Since the form data is passed to the server via formNode
    // parameter below, no need to pass target.value here.
    url: "validate",  

    // Send form data."myform" 是输入表单的 ID。
    form: dojo.byId("myform"),   
    handleAs: "xml",
    timeout: 5000, // Time in milliseconds


    load: function(response, ioArgs) {
        processRequest(response);
    },

    // The ERROR function will be called in an error case.
    error: function(response, ioArgs) {
        alert("dojo Error alert !!");
    },
    });
}


/********************* commented out **************************************
 * We don't need to check the status and readyState anymore since it is handled by dojo.io.bind()
function processRequest() {
    if (req.readyState == 4) {
    if (req.status == 200) {
        var message = req.responseXML.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
        setMessageUsingDOM(message);
        var submitBtn = document.getElementById("submit_btn");
        if (message == "false") {
          submitBtn.disabled = true;
        } else {
          submitBtn.disabled = false;
        }
    }
    }
}
***********************************************************************/

// This is the modified processRequest() function.  Note that you don't need to
// check if the readyState of the XMLHttpRequest is 4 or not.
function processRequest(data) {
    // var message = data.getElementsByTagName("valid")[0].childNodes[0].nodeValue;
    var message = dojox.data.dom.textContent(data.getElementsByTagName("valid")[0]);
    setMessageUsingDOM(message);
    //var submitBtn = document.getElementById("submit_btn");
    var submitBtn = dojo.byId("submit_btn");
    setMessageUsingDOM(message);
    if (message == "false") {
      submitBtn.disabled = true;
    } else {
      submitBtn.disabled = false;
    }
}

function setMessageUsingInline(message) {
    //mdiv = document.getElementById("userIdMessage");
    mdiv = dojo.byId("userIdMessage");
    if (message == "false") {
       mdiv.innerHTML = "<div style='color:red; font-family:Arial; font-size:14px; font-weight:bold;'>Invalid User Id</div>";
    } else {
       mdiv.innerHTML = "<div style='color:green; font-family:Arial; font-size:14px; font-weight:bold;'>Valid User Id</div>";
    } 
}

function setMessageUsingDOM(message) {
    //var userMessageElement = document.getElementById("userIdMessage");
    var userMessageElement = dojo.byId("userIdMessage");
    var messageText;
    if (message == "false") {
    userMessageElement.style.color = "red";
    userMessageElement.style.fontFamily = "Arial";
    userMessageElement.style.fontSize = "14px";
    userMessageElement.style.fontWeight = "bold";
    messageText = "Invalid User Id";
    } else {
    userMessageElement.style.color = "green";
    userMessageElement.style.fontFamily = "Arial";
    userMessageElement.style.fontSize = "14px";
    userMessageElement.style.fontWeight = "bold";
    messageText = "Valid User Id";
    }

    /*********** commented out ******************
    var messageBody = document.createTextNode(messageText);
    // if the messageBody element has been created simple replace it otherwise
    // append the new element
    if (userMessageElement.childNodes[0]) {
    userMessageElement.replaceChild(messageBody, userMessageElement.childNodes[0]);
    } else {
    userMessageElement.appendChild(messageBody);
    }
    *******************************************/
    // Use innerHTML instead of raw DOM API
    userMessageElement.innerHTML = messageText;
 }

function disableSubmitBtn() {
    //var submitBtn = document.getElementById("submit_btn");
    var submitBtn = dojo.byId("submit_btn");
    submitBtn.disabled = true;
}

代码 1.101:myjavascript.js

5. 根据代码 1.102 所示,修改 index.jsp 将 myjavascript.js 包含进去。  

<%-- Copyright 2005 Sun Microsystems, Inc. All rights reserved. You may not modify, use, reproduce, or distribute this software except in compliance with the terms of the License at: http://developer.sun.com/berkeley_license.html
$Id: index.jsp,v 1.4 2005/06/15 05:39:43 gmurray71 Exp $ --%>
<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory path is set correctly -->
    <script language="JavaScript"
            type="text/javascript"
            src="dojo-release-1.0.1/dojo/dojo.js">
    </script>

    <script language="JavaScript"
        type="text/javascript"
        src="myjavascript.js">
    </script>
    <title>Form Data Validation using AJAX</title>
    </head>
    <body onload="disableSubmitBtn()">
       
        <h1>Form Data Validation using AJAX</h1>
        <hr/>
        <p><font face="Arial" size="2">
                This example shows how you can use AJAX to do server-side form data validation without
                a page reload.
                <br><br>
                In the form below enter a user id. By default the user ids "greg" and "duke"
                are taken. If you attempt to enter a user id that has been taken an error message will be
                displayed next to the form field and the "Create Account" button will be
                disabled. After entering a valid user id and selecting the "Create Account"
                button that user id  will be added to the list of user ids that are taken.
        </font></p>
       
    <form id="myform" name="updateAccount" action="validate" method="post">
        <input type="hidden" name="action" value="create"/>
        <table border="0" cellpadding="5" cellspacing="0">
        <tr>
            <td><b>User Id:</b></td>
            <td>
            <input type="text"
                   size="20" 
                   id="userid"
                   name="id"
                   onkeyup="validateUserId()">
            </td>
            <td>
            <div id="userIdMessage"></div>
            </td>
        </tr>
        <tr>
            <td align="right" colspan="2">
            <input id="submit_btn" type="Submit" value="Create Account">
            </td>
            <td></td>
        </tr>
        </table>
    </form>
    </body>
</html>

代码 1.102:不含 JavaScript 代码的 index.jsp

12. 右键单击 ajax-validation-dojo.bo.bind 项目并选择 运行


                                                                                                                                        返回练习顶部


练习 1 的解决方案


此练习的解决方案位于 <LAB_UNZIPPED_DIRECTORY>/ajaxdojointro/solutions/ajax-validation-dojo.io.bind.solution。 你可以打开并运行该项目。

结束语

在本练习中,修改了使用 XMLHttpRequest  的示例应用程序,而代替为使用 Dojo 工具包中的 dojo.io.bind()。 

                                                                                                                                                返回顶部



练习 2:Dojo 事件模型

在本练习中,将练习 Dojo 工具包的几个事件编程模型。


(2.1) 通过复制之前创建的 "ajax-validation-dojo.io.bind" 项目,创建一个名称为 "dojo-event1" 的新项目

您可以从头创建一个新 NetBeans 项目,但也可以通过复制 ajax-validation-dojo.io.bind 项目,来创建一个包含 Dojo 工具包库文件的项目。我们将其命名为 dojo-event1 项目。

1. 右键单击 ajax-validation-dojo.io.bind 项目并选择 复制项目。  出现了 复制项目 对话框。
2. 在 项目名称: 字段处键入 dojo-event1。(如下图 2.10 所示)复制项目可能需要一些时间。dojo-event1 项目出现在 项目 选项卡窗口中。


图 2.10:通过复制创建 dojo-event1 项目

3. 改变新项目的上下文路径。(您做此操作,只针对 NetBeans 5.0。在 NetBeans 5.5 中是自动完成的。)


图 2.11:将上下文路径改为 /dojo-event1

                                                                                                                                        返回练习顶部

(2.2) 在用户初始化事件中使用 dojo.event.connect() 调用

现在我们要修改 index.jsp,我们将在其中使用 dojo.event.connect()。  

注意:如果不想改变原始代码,可以通过复制当前项目创建一个新项目。但如果您决定要这样做的话,要确保将 上下文路径: 加以改变,以反映新项目名称。

1. 右键单击 dojo-event1 项目的 index.jsp 文件,在  源编辑器  中打开它。除非您想要改变 ajax-validation-dojo.io.bind 项目的 index.jsp 文件,否则请确保其不变。

2. 用下面代码(代码 2.20)替换 index.jsp 文件的完整内容。请仔细研究 dojo.event.connect() 调用是如何把 myHandler 事件处理程序注册到 mylink 节点的 onclick 属性中的。

<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory is correct -->
    <script language="JavaScript"
        type="text/javascript"
        src="dojo-release-1.0.1/dojo/dojo.js">
    </script>  

    <script type="text/javascript">
    window.onload = function () {
        var link = document.getElementById("mylink");

        // "myHandler" event handler is registered to the
       // "onclick" property of the "mylink" node.
       dojo.connect(link, "onclick", myHandler);
    }

    // Define an event handler named as "myHandler"
    function myHandler(evt) {
       alert("myHandler: invoked - this is a named event handler" +
               "\r\n" +
               "If you see this, that means calling dojo.connect() was successful.");
    }

    </script>
    <title>Simple Dojo Event Handler</title>
    </head>
    <body>
   
    <h1>Simple Dojo Event Handler</h1>
    <hr/>
    <p><font face="Arial" size="2">
        This example shows the usage of dojo.event.connect()
        registering an event handler to a DOM node. When a user clicks on
        "Click Me" link, it should pop up an alert, which is
        invoked within the event handler.
    </font></p>
   
    <a href="#" id="mylink">Click Me</a>
   
    </body>
</html>
代码 2.20:使用 dojo.event.connect() 调用的新 index.jsp

3. 右键单击 dojo-event1 项目并选择 清理并生成
4. 右键单击 Rdojo-event1 项目并选择 运行。  将会看到以下页面。(如图 2.21 所示)


图 2.21:简单 Dojo 事件处理程序页面

4. 单击 Click Me 连接。 您将会看到在事件处理程序里触发的一条警告消息。(下图 2.22)单击 OK 关闭该警告框。


图 2.22:事件处理程序中的警告消息


(2.3) 在窗口加载事件中使用 dojo.event.connect() 调用

1. 修改 index.jsp,将 dojo.connect() 调用用于窗口加载事件。(如下面 2.30 所示)需要添加的新代码段突出显示为 蓝色粗体字,而需要删除的旧代码段则显示为 红色粗体字。 保持一样的代码段显示为常规字体。

<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory is correct -->
    <script language="JavaScript"
        type="text/javascript"
        src="dojo-release-1.0.1/dojo/dojo.js">
    </script>  
    <script type="text/javascript">
    //window.onload = function () {
    function myInit() {
        var link = document.getElementById("mylink");

        // "myHandler" event handler is registered to the
        // "onclick" property of the "mylink" node.
        dojo.connect(link, "onclick", myHandler);
    }

    // Use dojo.connect to register "myInit" function to "onload" event.
    dojo.connect(window, "onload", myInit);        

    // Define an event handler named as "myHandler"
    function myHandler(evt) {
        alert("myHandler: invoked - this is a named event handler" +
                "\r\n" +
                "If you see this, that means calling dojo.connect() was successful." +
                "\r\n" +
                "In this call we are using dojo.connect to register \"myInit\" function to \"onload\" event.");
    }

    </script>
    <title>Simple Dojo Event Handler</title>
    </head>
    <body>
       
        <h1>Simple Dojo Event Handler</h1>
        <hr/>
        <p><font face="Arial" size="2">
                This example shows the usage of dojo.event.connect()
                 registering an event handler to a DOM node. When a user clicks on
                 "Click Me" link, it should pop up an alert, which is
                 invoked within the event handler.  This example also
                 shows how to use dojo.event.connect to register "myInit" function to "onload" event.
        </font></p>
        </p>
       
        <a href="#" id="mylink">Click Me</a>
       
    </body>
</html>
代码 2.30:经过修改的 index.jsp

2. 右键单击 dojo-event1 项目并选择 运行项目 。您将看到与此相同的结果。(如上面图 2.21 和图 2.22 所示) 

                                                                                                                                        返回练习顶部

(2.4) 将对象函数附加到 DOM 节点的事件处理程序

1. 修改 index.jsp 来使用 dojo.connect() 调用,这是用于将一个 JavaScript 对象的函数附加到 DOM 节点的事件处理程序中,从而,当调用 DOM 节点的事件处理程序时,JavaScript 对象的那个函数也被调用。  

需要添加的新代码段将突出显示为 蓝色粗体字,而需要删除的原始代码段将突出显示为 红色粗体字。保留不变的代码段将显示为常规字体。

<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory is correct -->
    <script language="JavaScript"
        type="text/javascript"
        src="dojo-release-1.0.1/dojo/dojo.js">
    </script>   
    <script type="text/javascript">
       function myInit() {
        var link = document.getElementById("mylink");

        // Create exampleObj JavaScript object, which contains foo function
        var exampleObj = {
            foo: function(){
                alert("exampleObj.foo: invoked !!" +
                         "\r\n" +
                        "If you see this alert, it means the attachment of the exampleObj.foo function " +
                        "to the event handler of a DOM node succeeded" );
             },

        };

        // The "foo" function of the exampleObj is registered for the
        // "onclick" property of "mylink" node.
        dojo.connect(link, "onclick", exampleObj, "foo");

        // "myHandler" event handler is registered to the
        // "onclick" property of the "mylink" node.
        //dojo.connect(link, "onclick", myHandler);
    }

    // Define an event handler named as "myHandler"
    function myHandler(evt) {
        alert("myHandler: invoked - this is a named event handler" +
                "\r\n" +
                "If you see this, that means calling dojo.connect() was successful." +
                "\r\n" +
                "In this call we are using dojo.connect to register \"myInit\" function to \"onload\" event.");
    }

    // Use dojo.connect to register "myInit" function to "onload" event.
    dojo.connect(window, "onload", myInit);         

    </script>
    <title>Attaching a function of an object to a DOM node's event handler</title>
    </head>
    <body>
    
    <h1>Attaching a function of an object to a DOM node's event handler</h1>
    <hr/>
    <p><font face="Arial" size="2">
        This example shows the usage of dojo.event.connect()
        attaching a function of an object to DOM node's event handler. When a user clicks on
        "Click Me" link, it should pop up an alert, which is
        invoked within the function of the object.
    </font></p>
    
    <a href="#" id="mylink">Click Me</a>
    
    </body>
</html>
代码 2.40:为将一个对象的函数附加到 DOM 节点的事件处理程序而修改过的 index.jsp

2. 右键单击 dojo-event1 项目与选择 运行。
3. 在浏览器中单击 Click Me 连接。  您会看到一条在一个 JavaScript 对象的函数中触发的警告消息。(如下图 2.42 所示)  单击 OK 关闭该警告消息框。


图 2.42:运行结果

                                                                                                                                        返回练习顶部


(2.5) 附加多事件处理程序

1. 修改 index.jsp 来使用 dojo.event.connect() 调用,这样做是为了注册多事件处理程序。 

需要添加的新代码段将突出显示为 蓝色粗体字,而需要删除的原始代码段将突出显示为 红色粗体字。保持不变的代码段将显示为常规字体。

<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory is correct -->
    <script language="JavaScript"
        type="text/javascript"
        src="dojo-release-1.0.1/dojo/dojo.js">
    </script>   
    <script type="text/javascript">
    function myInit() {
        var link = document.getElementById("mylink");
    
        // Create exampleObj JavaScript object, which contains foo function
        var exampleObj = {
            foo: function(){
                alert("exampleObj.foo: invoked !!" +
                        "\r\n" +
                        "If you see this alert, it means the attachment of the exampleObj.foo function " +
                        "to the event handler of a DOM node succeeded" );
                },
    
        };
    
        var exampleObj2 = {
            bar: function(){
                alert("exampleObj2.bar: invoked !!" +
                        "\r\n" +
                        "If you see this alert, it means the attachment of the exampleObj2.bar function " +
                        "to the event handler of a DOM node succeeded" );
                },
        }; 

        // The "foo" function of the exampleObj is registered for the
        // "onclick" property of "mylink" node.
        dojo.connect(link, "onclick", exampleObj, "foo");

        // The "bar" function of the exampleObj2 is registered for the
        // "onclick" property of "mylink" node.
        dojo.connect(link, "onclick", exampleObj2, "bar");     
    }

    // Define an event handler named as "myHandler"
    function myHandler(evt) {
    alert("myHandler: invoked - this is a named event handler" +
          "\r\n" +
          "If you see this, that means calling dojo.connect() was successful." +
          "\r\n" +
          "In this call we are using dojo.connect to register \"myInit\" function to \"onload\" event.");
    }

    // Use dojo.connect to register "myInit" function to "onload" event.
    dojo.connect(window, "onload", myInit);         

    </script>
    <title>Registration of multiple handlers</title>
    </head>
    <body>
    
    <h1>Registration of multiple handlers</h1>
    <hr/>
    <p><font face="Arial" size="2">
        This example shows how to register multiple handlers. When a user clicks on
        "Click Me" link, it should pop up three alerts, one from exampleObj.foo, and the second one from
        exampleObj2.bar, and the third one from myHandler.
    </font></p>
    
    <a href="#" id="mylink">Click Me</a>
    
    </body>
</html>
代码 2.50:为注册多事件处理程序而修改过的 index.jsp

2. 右键单击 dojo-event1 项目与选择 运行。
3. 在浏览器中单击 Click Me 连接。 您会看到一条在一个 JavaScript 对象的函数中触发的警告消息。(如下图 2.51 所示)  单击 确定 按钮关闭警告消息框。


图 2.51:来自第一个事件处理程序的警告消息

4.  观察从第二个事件处理程序中触发的第二条警告消息。(如下图 2.52 所示)  单击 确定 按钮关闭警告消息框。


图 2.52:来自第二个事件处理程序的警告消息


                                                                                                                                        返回练习顶部


(2.6) 连接和断开事件处理程序

1. 修改 index.jsp 以使用 dojo.connect() 和 disconnect。

修改过的代码显示在以下部分中,请注意我们创建了两个按钮,一个用于创建 dojo 连接,而另一个则用于断开一个现有连接。

和之前的例子一样,我们也使用 dojo.connect 将 "myInit" 函数注册到"onload" 事件,这反过来也将 "mylink" 的 "onclick: 事件连接到 exampleObj 函数。

当用户单击 "Connect New Function",将调用 callDojoConnect,它将 exampleObj.bar 和 exampleObj.foo 连接起来。Dojo 连接返回一个连接句柄,它被存储起来用于在以后断开连接。

当用户单击 "Disconnect Functions",它调用 dojo.disconnect,使用之前存储的 connectionHandle。这样做将把 example.bar 从和 example.foo 的连接中断开。

需要添加的新代码段将突出显示为 蓝色粗体字,而需要删除的原始代码段将突出显示为 红色粗体字。保持不变的代码片段将显示为常规字体。

<html>
    <head>
    <!-- Include Dojo toolkit library file dojo.js, make sure the directory is correct -->
    <script language="JavaScript"
            type="text/javascript"
            src="dojo-release-1.0.1/dojo/dojo.js">
    </script>   
    <script type="text/javascript">
        var connectionHandle;
        var link = document.getElementById("mylink");
       // Create exampleObj JavaScript object
        var exampleObj = {
            counter: 0,
            foo: function(){
                    this.counter++;
                    alert("exampleObj.foo: invoked, counter = " + this.counter );
                 },
            bar: function(){
                    this.counter++;
                    alert("exampleObj.bar: invoked, counter = " + this.counter );
                 },                        
        };          
        
        function myInit() {
            connectionHandle = dojo.connect(link, "onclick", exampleObj, "foo");
        }

        function callDojoConnect() {
            alert("Connected exampleObj.foo with exampleObj.bar");
            connectionHandle = dojo.connect(exampleObj, "foo", exampleObj, "bar");
        }   
        
        function callDojoDisConnect() {
            alert("Disconnected exampleObj.bar from exampleObj.foo");
            dojo.disconnect(connectionHandle);
        }
        
        // Use dojo.event.connect to register "myInit" function to "onload" event.
        dojo.connect(window, "onload", myInit);
        
    </script>
    <title>Registration of multiple handlers</title>
    </head>
    <body>
        
        <h1>Registration of multiple handlers</h1>
        <hr/>
        <p><font face="Arial" size="2">
                This example shows how to connect dojo functions and disconnect those.
                When the user clicks on "Connect new function" button, the bar function is connected to the
                foo function. register multiple handlers. When a user clicks on
                "Click Me" link, it should pop up three alerts, one from exampleObj.foo, and the second one from
                exampleObj2.bar, and the third one from myHandler.
        </font></p>
        
        <a href="#" id="mylink">Click Here to test dojo handler</a>
        <br><br>
        <form name="myTestForm">
            <input type="button" name="btnTestConnect" onclick="callDojoConnect()" value="Connect New  Function ">
            <br><br>
            <input type="button" name="btnTestDisConnect" onclick="callDojoDisConnect()" value="Disconnect Functions">
        </form>
        
    </body>
</html>

2. 右键单击 dojo-event1 项目并选择 运行项目。
3. 在浏览器中单击 Click Me 连接。  您会在 exampleObj JavaScript 对象的 foo 函数中看到一条警告消息。(如图 2.61 所示所示)  单击 确定 按钮关闭警告消息框。


图 2.61:单击 "mylink" 时调用的 foo 函数

4. 现在单击 "Connect New Function" 按钮。将出现一条警告,表示 exampleObj.foo 已经连接到了 exampleObj.bar。 


图 2.62:bar 函数连接到了 foo 函数。

5. 现在单击 "Click Here 连接来测试 dojo 处理程序。将看到 "exampleObj.foo" 的警告,紧随其后的是 "exampleObj.bar" 的警告。

Dojo Function Connect
图 2.63:dojo 函数连接

6. 现在单击 "Disconnect Functions"。单击完成按钮关闭警告消息框。如果您现在单击的是 "Click Here to test dojo handler" 这个连接,将只看到针对 "exampleObj.foo" 的警告,这意味着 "exampleObj.bar" 的警告被断开。


图 2.64:dojo.disconnect() 中断了处理程序。

                                                                                                                                   返回练习顶部


结束语

在本练习中,您通过 dojo.event.connect() 调用,实验了几种编程模型。
   
                                                                                                                                   返回顶部

(未修改)

课外练习(针对 Sang Shin“AJAX 在线课程”的学习者)


1. 课外练习是按照以下描述修改 ajax-hello 项目,该项目是您在 "AJAX 基础和开发" 中的课外练习 中所建的。那些手边没有这个项目的人,可以使用 <LAB_UNZIPPED_DIRECTORY>/ajaxdojointro/samples/ajax-hello。 (可以通过复制 ajax-hello 项目来创建一个新项目。可以将新项目命名为您喜欢的名字,但此处我将称其为 ajax-hello-dojo。)解决问题:当运行 ajax-hello-dojo 项目时,IDE 会警告 ajax-hello 项目已存在,请将 sun-web.xml 文件的上下文路径(见于 WEB-INF 目录)改为 ajax-hello-dojo,或解除对 ajax-hello 项目的部署。
2. 请将以下文件以 AJAXHomework-ajaxdojointro 作为 发送主题 发送至 ajaxhomework@sun.com





原文链接: http://www.javapassion.com/handsonlabs/ajaxdojo1intro/