除了要求使用者按下按鈕之外,還有什麼更直覺的方式可以取得資料?以這個觀點出發,可以想到許多非同步請求回應的使用方式,例如,當使用者選擇書籍類別完
成後,觸發onchange事件,自動將使用者的選擇送出,取得下一個選單的資料並呈現在網頁上,這個功能在桌面應用程式上很常見,但在Web應用程式來
說,以前並不常見。
例如您設計的網頁如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=BIG5"> <title>動態載入清單</title> <script type="text/javascript" src=DynamicListEx-1.js></script> </head> <body> 種類… <select id="type" onchange="refreshBooklList();"> <option value="notTech">非關語言</option> <option value="language">語言技術</option> <option value="framework">開源框架</option> </select> <br/><br/> 書籍… <br/> <select id="books" size="6" style="width:300px;"> </select> </body> </html>
當使用者選擇完書籍種類之後,另一個選單就會自動填上符合該重類的書籍,來看看JavaScript如何撰寫:
var xmlHttp;
window.onload = refreshBooklList;
function createXMLHttpRequest() { if(window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } else if(window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } }
function refreshBooklList() { var type = document.getElementById("type").value; var url = "RefreshBookServlet?type=" + type; createXMLHttpRequest(); xmlHttp.onreadystatechange = handleStateChange; xmlHttp.open("GET", url); xmlHttp.send(null); }
function handleStateChange() { if(xmlHttp.readyState == 4) { if(xmlHttp.status == 200) { clearBookList(); updateBookList(); } } }
// 清除上一次的顯示結果 function clearBookList() { var books = document.getElementById("books"); while(books.childNodes.length > 0) { books.removeChild(books.childNodes[0]); } }
// 以回應更新資料 function updateBookList() { var results = xmlHttp.responseXML.getElementsByTagName("book"); var books = document.getElementById("books"); var option = null; for(var i = 0; i < results.length; i++) { option = document.createElement("option"); option.appendChild(document.createTextNode(results[i].firstChild.nodeValue)); books.appendChild(option); } }
從伺服端要傳回以下的XML,表示根據種類的查詢結果:
<books>
<book>Java 學習筆記</book>
<book>C++ 學習筆記</book>
<book>JSP/Servlet 學習筆記</book>
<book>Ajax 學習筆記</book>
</books>
您可以使用以下這個簡單的Servlet模擬資料查詢並傳回XML回應的過程:
package onlyfun.caterpillar; import java.util.*; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public class RefreshBookServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { private static Map inMemoryDB = new HashMap(); public void init() throws ServletException { inMemoryDB.put("notTech", new String[] {"學習筆記", "電腦圖學", "常見程式演算", "設計模式"}); inMemoryDB.put("language", new String[] {"Java 學習筆記", "JSP/Servlet 學習筆記", "C++ 學習筆記", "Ajax 學習筆記"}); inMemoryDB.put("framework", new String[] {"Struts 學習筆記", "Spring 學習筆記", "Hibernate 學習筆記", "JUnit 學習筆記"}); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String type = request.getParameter("type"); StringBuffer xml = new StringBuffer("<books>"); String[] books = (String[]) inMemoryDB.get(type); for(int i = 0; i < books.length; i++) { xml.append("<book>"); xml.append(books[i]); xml.append("</book>"); } xml.append("</books>"); response.setCharacterEncoding("UTF8"); response.setContentType("text/xml"); response.getWriter().write(xml.toString()); response.getWriter().close(); } }
|
|