In this article, we will give an example to introduce three methods to obtain data from the server using Ajax technology. This example is very simple. There are two selection boxes (the <select> tag in html). After you select one of the first select items, you will get some data from the server, and load it into 2nd select statements.
Obtain XML format data from the server
The easiest way to obtain data from the server is to add a certain format of data to the server, which is generally in XML format. Then, the server uses XMLDocument or other technologies to read the data, generate the format text (<option> label) of the options in the <select> label ). The following addOptions function is the core function in this example. It generates the <option> tag in the <select> tag based on the data obtained from the server. The method used here is to use the innerHTML attribute of the <select> tag (only for firefox). If it is IE, you need to use the outerHTML attribute (the innerHTML attribute of the <select> tag in IE has some minor bugs. You can try to use the innerHTML attribute in IE to see what will happen ). The implementation code of the addOptions method is as follows:
// Select indicates the <select> object, and xml indicates the XMLDocument object function addOptions (select, xml) {if (select) {var options = ""; for (var I = 0; I <xml. childNodes [0]. childNodes. length; I ++) {if (xml. childNodes [0]. childNodes [I]. nodeName = "list") {var s = ""; if (isIE () s = xml. childNodes [0]. childNodes [I]. text; else s = xml. childNodes [0]. childNodes [I]. textContent options + = "<option value = '" + s + "'>"; options + = s; options + = "</option>" }} var id = select. id; if (isIE () select. outerHTML = "<SELECT id = '" + id + "'onchange = 'onchange (this)'>" + options + "</SELECT>"; else select. innerHTML = options ;}}
The onReadState function is called when the XMLHttpRequest object asynchronously accesses the server. When readyState is 4, XML data is successfully returned from the server. The implementation code of this function is as follows:
// MyRequest indicates the XMLHttpRequest object, and selectId indicates the id attribute value of the <select> tag function onReadyState (myRequest, selectId) {if (myRequest. readyState = 4) // 4 indicates that the corresponding information is successfully obtained. {try {var xml = myRequest. responseXML; // get the XMLDocument object var kind = document. getElementById (selectId); // obtain the <select> Object addOptions (kind, xml); // Add the <option> tag} catch (e) to the <select> tag) {alert ("onReadyState:" + e );}}}
The getData function is responsible for sending requests to the server and setting asynchronous events. The implementation code is as follows:
Function getData (url, selectId) {var myRequest = getXMLHTTPRequest (); // obtain an XMLHttpRequest object if (myRequest) {myRequest. onreadystatechange = function () // receives the event function {onReadyState (myRequest, selectId);} try {myRequest. open ("post", url, true);} catch (e) {alert (e);} try {myRequest. send ("") ;}catch (e) {alert (e );}}}
Now the core code in this example has been implemented. The next step is to obtain 1st <select> tag data from the server during html loading, and load it into the 1st <select> labels. Let's take a look at the static html code.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
From the code above, we can see that the two <select> labels are bigKind and smallKind, and there is no <option> label in them, because the <option> label must be dynamically loaded in javascript. Next we will load the data in bigKind.
window.onload = onLoadfunction onLoad(){ try { getData("../GetXML", "bigKind"); } catch(e) { alert("onLoad:" + e); }}
GetXML is a Servlet Program (you can replace it with other server programs, such as asp.net and php ). The following is the implementation code of the GetXML program:
package servlet;import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import database.MyData;public class GetXML extends HttpServlet{ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/xml;charset=UTF-8"); PrintWriter out = response.getWriter(); try { String s = request.getParameter("kind"); out.println("<data>"); if (s == null) { for (String key : MyData.data.keySet()) { out.println("<list>" + key + "</list>"); } } else { s = java.net.URLDecoder.decode(s, "UTF-8"); System.out.println(s); java.util.List<String> smallKind = MyData.data.get(s); if (smallKind != null) { for (String kind : smallKind) { out.println("<list>" + kind + "</list>"); } } } out.println("</data>"); } finally { out.close(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } public String getServletInfo() { return "Short description"; }}
No matter whether the reader is java or servlet, we can see from the processRequest method in this program that the request parameter kind is obtained first. If this parameter does not exist, the data required by bigKind is returned, returned in xml format, similar to the following format:
<data> <list>data1</list> <list>data2</list></data>
If the kind parameter exists, query the data required for the first <select> label (smallKind) in MyData. data. Data is a Map type. For convenience, this example does not use a database, but defines a static Map type variable in the MyData class. The implementation code of MyData is as follows:
Package database; import java. util. *; public class MyData {public static Map <String, List <String> data; static {data = new HashMap <String, List <String> (); list <String> eProducts = new productlist <String> (); eProducts. add ("Mobile Phone"); eProducts. add ("digital/IT"); eProducts. add ("Household Appliances"); eProducts. add ("computer"); data. put ("Consumer Electronics", eProducts); List <String> goods = new consumer List <String> (); goods. add ("makeup"); goods. add ("healthy"); goods. add ("Toy"); goods. add ("office/style"); goods. add ("Kids clothes"); goods. add ("other"); data. put ("daily necessities", goods); List <String> books = new goods List <String> (); books. add ("novel"); books. add ("Anime"); books. add ("economical"); books. add ("legal"); books. add ("computer"); books. add ("English"); books. add (""); books. add ("other"); data. put ("books", books );}}
The key value in the data variable is the value in bigKind, and the value corresponding to each key (a List <String> object is the List of smallKind values ). Next we will update the smallKind label when the 1st <select> label bigKind changes. <Select> the onchange event Function Code is as follows:
function onChange(obj){ try { getData(encodeURI(encodeURI("../GetXML?kind=" +obj.options[obj.selectedIndex].value)), "smallKind"); } catch(e) { alert(e); }}
This function is the onchange event function of the <select> label. Obj indicates the <select> label itself. There is only one actual statement in this function, that is, the getData method is called. This method is similar when the onLoad method calls getData, only two encodeURI methods are used for url transfer. Because the XMLHttpRequest method sends data to the server using UTF-8, two encodeuris must be used to send UTF-8 encoding in the form of % xx to the server and then parse the data on the server. The following statement can be found in the processRequest method in GetXML:
s = java.net.URLDecoder.decode(s, "UTF-8");
Is to perform the decoding operation.
Note: In IE, the client can encode the URL with Chinese characters without using encodeURI, and the server does not need to decode the URL. Chinese characters can still be displayed on the server. However, in firefox, encoding and decoding are required. Therefore, you need to use the method described in this article to cross-browser.
Directly obtain the string of the content of <option>... </option>
The above method is to obtain an XML document from the server, convert it to an XMLDocument object, and then parse it. Although this method is good, it is still a little difficult to operate the XMLDocument object. Therefore, we can reverse the <option> tag string required by the <select> tag on the server side, then pass these strings to the innerHTML or outerHTML of the <select> object. The server-side code is similar to the above implementation code. You only need to remove <data>, change <list> to <option>, and use the following statement to set ContentType:
response.setContentType("text/html;charset=UTF-8");
The client can obtain the <option> text from the responseText attribute of the XMLHttpRequest object and assign it to the innerHTML or outerHTML attributes. This method is convenient but not flexible. If the client does not use the <select> label, but uses <table> or other labels to display data, the returned data is useless. The method described below is convenient and flexible.
Return javascript code from the server and run the eval function on the client.
We can return a string similar to the following on the server:
var options = new Array();options.push('data1');options.push('data2');
Then run the above string using the eval function, so that we can use the options array in javascript. I personally think that using arrays is easier and less code than using XMLDocument. To return more complex data, you can also use classes or other data structures in javascript. According to the above idea, the code of the new processRequest method is as follows:
Protected void processRequest (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response. setContentType ("text/html; charset = UTF-8"); PrintWriter out = response. getWriter (); out. println ("var options = new Array ();"); try {String s = request. getParameter ("kind"); if (s = null) {for (String key: MyData. data. keySet () {out. println ("options. push ('"+ ke Y + "');") ;}} else {s = java.net. URLDecoder. decode (s, "UTF-8"); System. out. println (s); java. util. list <String> smallKind = MyData. data. get (s); if (smallKind! = Null) {for (String kind: smallKind) {out. println ("options. push ('"+ kind +"'); ") ;}}} finally {out. close () ;}} the improved addOptions function of the client is as follows: // javascript indicates the javascript code string function addOptions (select, javascript) returned from the server {if (select) {if (select. id = "smallKind") {if (isIE () select. options. length = 0;} var myOptions = ""; eval (javascript); // execute the javascript code returned from the server for (var I = 0; I <options. leng Th; I ++) // obtain data from the options Array {var s = ""; if (isIE () {select. options [select. options. length] = new Option (options [I], options [I]);} else {myOptions + = "<option value = '" + options [I] + "'>"; myOptions + = options [I]; myOptions + = "</option>" }}} var id = select. id; if (! IsIE () select. innerHTML = myOptions ;}
In the preceding addOptions method, another difference is that the <select> object's options array is used in IE to add selection items, rather than outerHTML. The advantage of doing so is that the <select> option value can be obtained in the onLoad method. If outerHTML is used for loading html, the <select> label still has 0 options. In this way, the added items in <select> cannot be accessed in the onLoad method. Of course, this is acceptable in the onchange event.
When innerHTML is used in firefox, When html is not fully loaded, as long as the <select> label is fully loaded (that is, after the addOptions method is called ), you can access <option> In the <select> label. I personally think this should be done well from IE. By the way, I use IE6, but I don't know what ie7 will do.
In simple terms, there are several methods:
- Return XML
- Returns HTML
- Return Json
- Return some javascript code and execute it on the client.