Oracle神谕

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  284 随笔 :: 9 文章 :: 106 评论 :: 0 Trackbacks
"Ajax" is a buzzword that is gaining momentum and popularity. Applications such as Gmail and Google Suggest serve as massive advertisements for asynchronous JavaScript. As users gain familiarity and their expectations increase, the demand for such interfaces is rising.

"Ajax"是一个时髦词语,获得动力和普及。像Gmail和Google Suggest的服务为异步Javascript作了大量的广告。当用户获得熟悉和他们期望增长时,类似这些界面的需求也增长了。

In this article, I will show how to build Ajax-enabled applications using Dojo and JSON--two very different but complementary technologies that can significantly enhance the interface and usability of web applications. With the help of some simple examples, you will learn how to use Dojo and JSON to build Ajax applications. This article will also demonstrate how to create custom Dojo widgets by implementing the popular "autocomplete" feature for HTML text boxes.
Overview

在这边文章中,我将展示使用Dojo和JSON--两种不同但互相补充的可以重大地促进界面和Web应用程序可用性的技术来如何创建Ajax- enabled应用程序。在这些简单的例子的帮助下,你可以学会如何使用Dojo和JSON来创建Ajax应用程序。这篇文章也将示范如何为HTML text boxes通过实现流行的"autocomplete"特性创建定制的Dojo widgets 。

Ajax in the simplest sense is taken to mean the process of exchanging data between a web server and a web browser using JavaScript on a loaded web page. In the practical sense, it means avoiding browser requests in favor of asynchronous JavaScript processing, thus making the request/response process transparent to the user. To accomplish this, we can either write our own verbose JavaScript code or use already tested and functional libraries such as Dojo.
What Is Dojo?

在最简单的感觉中,Ajax是开始意味这在web服务器和浏览器之间使用在一个已加载的web页面上的JavaScript来交换数据的流程。在实际理解上,它意味着避免浏览器请求采用异步 JavaScript处理,这样产生request/response进程传递给用户。为了完成这,我们可以或编写详细的代码或使用已经经过测试的和实用的库例如Dojo.

Dojo is a set of powerful JavaScript libraries that provide a simple API to a plethora of features. One of these features is the ability to make HTTP requests and receive their responses. This is the main functionality of Dojo that we will utilize. Aside from providing Ajax functionality, Dojo also provides packages for string manipulation, DOM manipulation, drag-and-drop support, and data structures such as lists, queues, and stacks.

Dojo是一个强大的提供简单api到复杂的功能特性的Javascript库。这些特征之一就是产生HTTP 请求和接收他们的相应的能力。这是Dojo的主要功能性被使用。除提供Ajax功能性以外,Dojo也提供了诸如字符串操作、DOM操作、托放支持、和数据结构例如lists,queue,stack的库。

What Is JSON?
什么是JSON?

JSON is a Java library that helps convert Java objects into a string representation. This string, when eval()ed in JavaScript, produces an array that contains all of the information that the Java object contained. JSON's object notation grammar is suitable for encoding many nested object structures. Since this grammar is much smaller than its XML counterpart, and given the convenience of the eval() function, it is an ideal choice for fast and efficient data transport between browser and server.

JSON是一个Java库,它帮助转化Java对象成一个字符串表现。这字符串,当在JavaScript中eval()ed,产生一个包含所有Java 对象信息的数组。 JSON's对象符号语法是适合于编码许多嵌套对象结构。既然这个语法小于它的XML配对物,并且给于eval()函数的方便,它是在浏览器和服务器之间理想选择快速且有效数据传输。

JSON is designed to be used in conjunction with JavaScript code making HTTP requests. Since server-side code can be written in a variety of languages, JSON is available in many different languages such as C#, Python, PHP, and of course, Java!

JSON是被设计成可用于与JavaScript代码协力产生HTTP请求。既然服务器端代码可以被写成多种语言,JSON是可用于很多语言,例如C#,Python,PHP,并且当然适用于Java.

Getting Started
开始

Download the sample application and do an ant war to generate dojo_json.war. You will need a servlet container like Apache Tomcat. Copy dojo_json.war into the webapps directory and, assuming you're running Tomcat on port 8080 on localhost, browse to the following URL:

下载例子程序并且使用ant war 产生dojo_json.war。你将需要一个Servlet容器像Apache Tomcat。复制dojo_json.war到你webapps目录下并且,将设你运行在localhost的端口8080的,浏览如下网址:

http://localhost:8080/dojo_json/index.jsp


If you see a page with a welcome message, all is well.
如果你看到一个欢迎的信息的页面,一切都好了。

A Simple HTTP Request
一个简单的HTTP 请求

In the first example, we will use Dojo to provide a welcome message when the user clicks on a button. This will illustrate the steps involved with making an Ajax call using Dojo. Browse to http://localhost:8080/dojo_json/example1.jsp and after entering your name, click the Submit button. The JavaScript alert box that pops up contains a welcome message that was generated on the server. Let's look at the source for example1.jsp.

在第一个例子中,我们将使用Dojo当用户点击一个按钮时,提供一个欢迎的信息。这将示例使用Dojo有关产生一个Ajax调用的步骤。浏览http: //localhost:8080/dojo_json/example1.jsp并且输入你的名字,点击提交按钮。Javascript对话框弹出显示一个在服务器上产生的欢迎信息。让我们看看example1.jsp的源代码。

<html>
<body onLoad="onLoad();">
<head>
 <title>Example 1</title>
 <script language="javascript" src="js/dojo.js"></script>
 <script language="javascript">
  dojo.require("dojo.io.*");
  dojo.require("dojo.event.*");

  function onLoad() {
   var buttonObj = document.getElementById("myButton");
   dojo.event.connect(buttonObj, "onclick",
          this, "onclick_myButton");
  }

  function onclick_myButton() {
   var bindArgs = {
    url: "welcome.jsp",
    error: function(type, data, evt){
     alert("An error occurred.");
    },
    load: function(type, data, evt){
     alert(data);
    },
    mimetype: "text/plain",
    formNode: document.getElementById("myForm")
   };
   dojo.io.bind(bindArgs);
  }
 </script>
</head>
<body>
<form id="myForm">
 <input type="text" name="name"/>
 <input type="button" id="myButton" value="Submit"/>
</form>
</body>
</html>

The first order of business is to import the Dojo libraries, namely dojo.js. This contains all of the Dojo classes needed to use most of its features. Dojo libraries are organized in packages just like Java code. For this example, we will need to import two packages. The dojo.io package contains classes that allow us to make HTTP requests using protocols such as XMLHTTPTransport. The dojo.event package is designed to provide a unified event system for DOM and programmatic events.

事务的第一个顺序是导入Dojo库,被命名为dojo.js。这涉及所有的dojo的需要使用它的特性的大部分类。Dojo库像Java代码一样在包内进行组织。例如我们将需要导入两个包。 dojo.io包包含了允许我们来利用协议例如XMLHTTPTransport来创建HTTP请求。dojo.event包被设计成为DOM和计划性事件提供一个统一的事件系统。

Next, we assign an onclick event handler to our button. Traditionally, we might do something like:
接着,我们赋值一个单击事件句柄给我们的按钮。传统地,我们像这样做:

<input type="submit" onclick="someFunc();"/>

which serves its purpose but has the nasty side effect of associating only one event handler per event. The dojo.event.connect() method allows us to associate functions in different classes to HTML elements. Here, we assign onclick_myButton as the handler for the onclick event for myButton.

它服务于它的目的但是拥有令人厌恶的每事件只有一个事件句柄联系的副影响。dojo.event.connect()方法允许我们联系在不同的功能给HTML元素。这里,我们赋值onlick_myButton 作为myButton的单击事件句柄。

Once onclick_myButton executes, we will make the call to welcome.jsp and receive the response. The magical dojo.io.bind() function is where the power lies. It takes as argument bindArgs, an array of name/value pairs. In this example, we specify five pairs:
一旦onclick_myButton执行,我们制造调用welcome.jsp并且接收响应。这个不可思议的dojo.io.bind()函数是力量强大的位置。它采用bindArgs参数,一个名称/值对的数组。在这个例子中,我们指定了5个对:

   1. url: The URL to make the request to.  url: 请求的网址
   2. mimetype: The response type expected. mimetype:期待响应的类型
   3. load: Code to execute upon success. load: 执行成功的代码
   4. error: Code to execute upon error.  error:执行出错的代码
   5. formNode: The ID of the form whose fields to submit as parameters to the URL.
      formNode: 作为一个参数提交字段的URL的表单的ID.

A complete list of possible arguments can be found here.
一个完整的可能参数的列表可以在这里发现。

Once the call to dojo.io.bind(bindArgs) is made, the wheels are set in motion and, depending on whether the request encountered any errors, either the load or error code is executed. Both load and error take three arguments:

一旦调用dojo.io.bind(bindArgs)被制造,动力被设置在运行中,依赖请求遭遇任何错误,或加载或失败被执行。加载和失败包含三个参数:

   1. type: The type of function; it will always be set to load for load() and error for error().
   2. data: The response received. If mimetype is specified as text/plain, data contains the raw response. If, however, text/json is used, data contains the value of eval('(' + responseReceived + ')'), where responseReceived is what the call returned.
   3. evt: The event object.
   
   1.类型:功能的类型;它将总是设置为load()成加载和error()成失败。
   2.数据:响应接收。如果mimetype被指定为text/plan,数据包含未加工响应。如果,然而,text/json被使用,数据包含eval ('('+responseReceived+')'),这里responseReceived 是调用返回的。
   3.事件:事件对象。

Alternately, we could have also specified event handlers using dojo.event.connect() by creating a handleResponse(type,data,evt) function and associating it with the request:
可替代的,我们也可以拥有指定事件句柄使用dojo.event.connect()通过创建一个handleResponse(type,data,event)函数并且通过request联系.

var req = dojo.io.bind(bindArgs);
dojo.event.connect(req, "load", this, "handleResponse");

In this case, we wouldn't need to specify the load attribute in bindArgs.
既然这样,我们不需要在绑定参数中指定加载属性。

Note: For security reasons, Firefox does not allow the value for url in bindArgs to reference a URL on another domain. Internet Explorer is more lenient and allows cross-domain requests.
Using JSON to Transport Java Objects

注意:为安全原因,Firefox不允许在绑定参数中为url的值指定一个URL在另一个域中。IE更宽松且允许超域请求。

As alluded to earlier, JSON helps us transform Java objects into eval()able JavaScript strings. In this example, the user is viewing a list of books. When the user's mouse hovers over a book title, we also retrieve and display all other relevant information about the book using Ajax. Example 2, found at http://localhost:8080/dojo_json/example2.jsp, illustrates this behavior.

早些提到的那样,JSON帮助我们转换Java对象到eval()able JavaScript字符串。在这个例子中,用户查看书的列表。当用户的鼠标放在书的标题上,我们获得和显示所有其他相关的使用Ajax的书的信息。例子 2,在http://localhost:8080/dojo_json/example2.jsp,示例了这个事件。

Let us take a closer look at the steps involved in achieving this effect.
Creating and Instrumenting the Java Objects
让我们近距离注视涉及完成这个效果的步骤。

The Book class is a POJO with four fields. The BookManager has a method that returns a Book object based on a bookId and another that returns List of all books. In this simple example, I've hardcoded five books into the BookManager.

书类是一个有四个字段的POJO. BookManager有一个方法,它返回一个基于bookId和其他返回所有书的列表的书对象。在这个简单例子中,我已经硬编码5本书给BookManager.

The Book.toJSONString() method is responsible for converting a Book object into a JavaScript eval()able String using the JSON API.
Book.toJSONString()方法使用JSON API转换一个书对象JavaScript的 eval()able字符串是可靠的  .


public String toJSONString() throws JSONException {
 JSONObject jsonObj = new JSONObject();
 jsonObj.put("bookId", new Integer(this.bookId));
 jsonObj.put("title", this.title);
 jsonObj.put("isbn", this.isbn);
 jsonObj.put("author", this.author);
 return jsonObj.toString();
}

The JSONObject class acts as a converter for the Book object into a string wrapped in curly braces, with colons between the names and values and commas between the values and names--in other words, an eval()able JavaScript string. In a similar manner as shown above, the JSONArray class can convert collections of Java objects into JavaScript arrays.

JSONObject 类作为一个将书对象转换为包装在curly支持的字符串的转换器,在名字和值使用冒号,在值和名称之间用逗号,换句话说,,一个eval()able的 JavaScript字符串。在一个像上面显示的格式,JSONArray类可以转化一个Java对象集合类型到一个JavaScript数组。


Transferring and Handling JSON-Encoded Data
传输和处理JSON编码数据。

Based on a bookId, the book.jsp page returns a Book object in the form of a JSON string. The JSP does a lookup for the bookId using the BookManager.getBook(bookId) method and prints out the results of the Book.toJSONString() method. So accessing http://localhost:8080/dojo_json/book.jsp?bookId=1 will print out the JSON string for the Book with the bookId value of 1.

基于bookId,book.jsp页返回一个书对象组成JSON字符串。jsp 使用BookMananger.getBook(bookId)方法为指定的bookId查找并且打印出Book.toJSONString()方法的结果。所以通过http://localhost:8080/dojo_json/book.jsp?bookId=1将打印出JSON为bookId值为 1的书的字符串.


Back on the client side, book information is displayed in a list. Each element in the list has a mouseover (trMouseOver) and mouseout (trMouseOut) event handler attached to its <tr>. On each mouseover, we call book.jsp and pass in the bookId as a parameter. The resulting data will be the JSON String for that Book. We have specified the mime-type as text/json so that the returned value is automatically eval()ed. Let's look at the JavaScript code responsible for sending the request and processing the response:

返回到客户端一边,书的信息被显示在一个列表中。在列表中的每一个元素都有一个mouseover(trMouseOver)和mouseout (trMouseOut)事件处理追加到它的<tr>。在每一个mouseover,我们调用book.jsp并且传递bookID作为一个参数。这个结果数据将是那本书的JSON字符串。我们指定mimetype为text/json以致返回值是自动eval()ed. 让我们看JavaScript代码为发送请求和传递返回的responsible.

function trMouseOver(bookId) {
 getBookInfo(bookId);
}

function trMouseOut(evt) {
 var bookDiv = document.getElementById("bookInfo");
 bookDiv.style.display = "none";
}

function getBookInfo(bookId) {
 var params = new Array();
 params['bookId'] = bookId;
 var bindArgs = {
  url: "book.jsp",
  error: function(type, data, evt){
          alert("error");
         },
  mimetype: "text/json",
  content: params
 };
 var req = dojo.io.bind(bindArgs);
 dojo.event.connect(req, "load", this, "populateDiv");
}

function populateDiv(type, data, evt) {
 var bookDiv = document.getElementById("bookInfo");
 if (!data) {
  bookDiv.style.display = "none";
 } else {
  bookDiv.innerHTML = "ISBN: " + data.isbn +
                "<br/>Author: " + data.author;
  bookDiv.style.display = "";
 }
}

Another subtle difference in this example is the use of the content property of bindArgs instead of formNode. The content attribute is a key/value mapping of properties to be constructed into parameters passed with the data request.

subtle 『sub.tle』微秒的   采用了content而不是formNode, content的属性是键/值映射
construct『con.struct』建造 构造

Once data is transformed into a JavaScript object, we can easily access properties of a Book and display it to the user in a <div> element, as shown above.
Advanced Dojo: Creating an Autocompletion Widget

数据转换成JavaScript对象,我们可以容易通过书的属性显示在一个div上。

The two examples seen above cover the core of most Ajax applications: exchanging data with a web server using JavaScript. Once the basics are understood, it is up to the developer to deliver powerful and useful UIs using Ajax tools such as Dojo. Dojo's extensible framework for widget and module development can greatly ease this process. In this section, we will create a custom widget that will allow us to offer autocompletion for our form fields.
What Is a Dojo Widget?

In the general sense, widget is a name given to a UI element such as a button, text box, scroll bar, etc. When creating a Dojo widget, we have the entire HTML language at our disposal and can create widgets that have multiple input elements, custom styles, and more. You may define event handlers for your widgets, customize their behavior, and even reuse them when creating other widgets. In this example, we will create a widget that will provide an autocompletion feature for any text box in an HTML form.
Components of a Widget

When developing widgets, the developer must decide which UI elements the widget has and how they will work. When using Dojo, this means deciding on what HTML elements to use and writing the JavaScript code to make these elements behave as needed. The autocomplete example has four files associated with it:

    *

      dojo.js: All required Dojo libraries.
    *

      js/dojo/utils/templates/AutoComplete.html: Contains UI elements, including HTML tags such as <div> and <input>. The template file can contain any valid HTML and is bound by the single requirement that it contain one root element. If more than one element is found at the top level, the first one is considered the root.
    *

      js/dojo/utils/AutoComplete.js: JavaScript code for the widget. Usually a class extending one of the Dojo Widget classes.
    *

      example3.jsp: The file where the widget is used. Usually contains a tag exported by the widget.

Learning and understanding how UI elements can be accessed and manipulated using JavaScript is the key to creating custom widgets. Once Ajax functionality is baked into the JavaScript, creating rich UIs becomes a task of creativity rather than difficulty.
Accessing UI Elements

As mentioned above, specifying a root element of the UI is mandatory. In the autocomplete example, the root element is a <div>. This element can be accessed in the AutoComplete class using this.domNode. The variable this.domNode stores a reference to the HTML object, so code like the following is possible:

this.domNode.style.display = "none";

To access any other element of the UI from the JavaScript, you may traverse this.domNode until you find what you're looking for, or instead use the dojoAttachPoint property.

<input type="text" name="someTextField" dojoAttachPoint="myTextField"/>

If the above has been defined in the HTML file, it can be accessed using this.myTextField in the JavaScript. Like this.domNode, this.myTextField is also a reference to the HTML object.

Dojo makes it easier to attach multiple event handlers to UI elements, both using JavaScript and element attributes. As illustrated earlier, to programatically attach an event handler to an element, we can use dojo.event.connect():

dojo.event.connect(this.domNode, "onclick", this, "myFunction")

The above will attach an onclick event handler myFunction() from the current class to the root element of the UI. Alternately, we may also specify this in the HTML code for the <div>:

<div dojoAttachEvent="onclick: myFunction">

<div dojoAttachEvent="onclick, onmouseover: myFunction">

Programming the Widget

Now that there is a way to access and manipulate the UI and detect all types of user actions, all that's left is writing the JavaScript code to make the widget behave as desired. Each widget is backed by a corresponding class that has access to its UI elements and is responsible for responding to user actions. The following snippet of the JavaScript code from the AutoComplete class is enough to illustrate the skeleton of the widget.

dojo.provide("utils.AutoComplete");

dojo.require("dojo.dom");
...

dojo.widget.tags.addParseTreeHandler("dojo:AutoComplete");

utils.AutoComplete = function() {

 // call super constructor
 dojo.widget.HtmlWidget.call(this);

 // load template
 this.templatePath =
    dojo.uri.dojoUri("utils/templates/AutoComplete.html");

 this.widgetType = "AutoComplete";

 // Instance variables
 this.action = "";
 this.formId = "";
 this.form = {};
 ...

 this.postCreate = function() {
  this.form = document.getElementById(this.formId);
  this.textbox = document.getElementById(this.textboxId);
  dojo.event.connect(this.textbox, "onkeyup",
                    this, "textboxOnKeyUp");
  ...
 }

 this.textboxOnKeyUp = function(evt) {
  if (this.isKey(evt.keyCode, 38, 40)) {
   this.checkUpDownArrows(evt.keyCode);
  } else {
   bindArgs = {
    url:  this.action,
    mimetype:   "text/javascript",
    formNode:   this.form
   };
   var req = dojo.io.bind(bindArgs);
   dojo.event.connect(req, "load", this, "populateChoices");
  }
 }

 // Handler for "load" action of dojo.io.bind() call.
 this.populateChoices = function(type, data, evt) {
  ...
 }
}

// define inheritance
dj.inherits(utils.AutoComplete, dojo.widget.HtmlWidget);

We have defined a JavaScript class, AutoComplete, that is the "code behind" the widget. When defining a custom widget, Dojo requires the developer to explicitly specify the class being provided using the dojo.provide() function. The inheritance is indicated using the dj.inherits() function, and is realized via the call to dojo.widget.HtmlWidget.call(this). The template file for the widget is loaded by assigning a value to the this.templatePath variable of the parent class.

Dojo widgets are used on HTML pages using custom tags. Tags can be defined when writing the associated widget class. In the above example, the exported tag is dojo:AutoComplete, which is used in the HTML file in the following manner:

<dojo:AutoComplete
 action="getBooks.jsp"
 textboxId="bookName"
 formId="bookForm"/>

The above will output the contents of the AutoComplete.html template to the browser. Any attributes specified in the tag can be accessed using the this.<attribute> syntax in the JavaScript class.

The nature of the autocomplete is to detect user input and provide a list of possible values that the user might be trying to enter. When a user enters any input, the textboxOnKeyUp is executed, and a call to the web server is made with the user input passed through. The web server returns a list of values to be displayed to the user as choices. We display these choices to the user in a <div> tag.

Any code omitted from the listing is just JavaScript that populates the <div> tag, choices. It also detects user key strokes, such as Tab to move to the next form field and other such details.

It's important to understand the role each of these four files plays in defining and using a widget, so take a look at them and see how they fit into the big picture. The creators of Dojo have made an honest effort to separate UI, programming, and usage into distinct files and, best of all, this methodology is easily extensible when developing powerful UIs.

The autocomplete example can be seen at http://localhost:8080/dojo_json/example3.jsp.
Conclusion

Dojo is a fine choice for a toolkit when developing Ajax and other JavaScript-intensive applications. However, there are other products, such as Scriptaculous and AjaxAnywhere, that offer similar functionality and need to be considered when writing small- to mid-size applications. Dojo's usefulness lies in a core set of libraries that features not just Ajax functionality but an entire API geared towards full-scale application development.
Resources

    * Sample application: Complete source of all examples
    * Dojo Toolkit: Official website
    * JSON: Official website for JSON
    * Dojo manual: Growing documentation
    * Custom widget example: Creating a slideshow using Dojo widgets
    * Dojo FAQ
    * Building dojo.js: Building a custom dojo.js using profiles

posted on 2006-05-06 17:38 java世界畅谈 阅读(1578) 评论(1)  编辑  收藏 所属分类: JavaScript

评论

# re: Use Dojo and JSON to Build Ajax Applications 2007-07-13 11:09 yao
几处翻译不妥  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: