本例中当用户在文本框中输入待查询的商品名称时,页面中将根据用户输入的文字信息,及时给出提示列表,以帮助用户快速进行选择,该提示信息来源于服务器端数据库中的数据。当用户选择了对应商品名称,单击“搜索”按钮后,将会在文本区域中显示商品相关的描述信息。
首先在Eclipse中新建一个Web项目,项目名称为P56_AutoComplete,对应的浏览器端页面代码如下:
源文件:autoComplete.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<HTML><HEAD><TITLE>Shopping Online</TITLE>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
<LINK href="images/css.css" type=text/css rel=stylesheet>
</HEAD>
<script language="javascript">
var XMLHttpReq;
var completeDiv;
var inputField;
var completeTable;
var completeBody;
//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e){
try{
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
//发送匹配请求函数
function findNames() {
inputField = document.getElementById("names");
completeTable = document.getElementById("complete_table");
completeDiv = document.getElementById("popup");
completeBody = document.getElementById("complete_body");
if (inputField.value.length > 0) {
createXMLHttpRequest();
var url = "autoComplete?action=match&names=" + escape(inputField.value);
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processMatchResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
} else {
clearNames();
}
}
// 处理返回匹配信息函数
function processMatchResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
setNames(XMLHttpReq.responseXML.getElementsByTagName("res"));
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
//生成与输入内容匹配行
function setNames(names) {
clearNames();
var size = names.length;
setOffsets();
var row, cell, txtNode;
for (var i = 0; i < size; i++) {
var nextNode = names[i].firstChild.data;
row = document.createElement("tr");
cell = document.createElement("td");
cell.onmouseout = function() {this.className='mouseOver';};
cell.onmouseover = function() {this.className='mouseOut';};
cell.setAttribute("bgcolor", "#FFFAFA");
cell.setAttribute("border", "0");
cell.onclick = function() { completeField(this); } ;
txtNode = document.createTextNode(nextNode);
cell.appendChild(txtNode);
row.appendChild(cell);
completeBody.appendChild(row);
}
}
//设置显示位置
function setOffsets() {
completeTable.style.width = inputField.offsetWidth; + "px";
var left = calculateOffset(inputField, "offsetLeft");
var top = calculateOffset(inputField, "offsetTop") + inputField. offsetHeight;
completeDiv.style.border = "black 1px solid";
completeDiv.style.left = left + "px";
completeDiv.style.top = top + "px";
}
//计算显示位置
function calculateOffset(field, attr) {
var offset = 0;
while(field) {
offset += field[attr];
field = field.offsetParent;
}
return offset;
}
//填写输入框
function completeField(cell) {
inputField.value = cell.firstChild.nodeValue;
clearNames();
}
//清除自动完成行
function clearNames() {
var ind = completeBody.childNodes.length;
for (var i = ind - 1; i >= 0 ; i--) {
completeBody.removeChild(completeBody.childNodes[i]);
}
completeDiv.style.border = "none";
}
//搜索请求函数
function search() {
var sortName = document.getElementById("names");
createXMLHttpRequest();
var url = "autoComplete?action=search&names=" + escape(inputField.value);
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processSearchResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
}
// 处理返回匹配信息函数
function processSearchResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
var res=XMLHttpReq.responseXML.getElementsByTagName("res");
if (res.length>0){
document.getElementById("content").value=res[0].firstChild.data;
}
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
</script>
<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=2 width=400 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4 colspan="3"><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19 colspan="3"><B>商品信息搜索</B>
</TD>
</TR>
<tr>
<td height="20">
输入品牌关键字:
</td>
<td height="20">
<input type="text" size="15" id="names" οnkeyup="findNames();" style=
"height:20;">
<div style="position:absolute;" id="popup">
<table id="complete_table" bgcolor="#FFFAFA" border="0" cellspacing=
"0" cellpadding="0"/>
<tbody id="complete_body"></tbody>
</table>
</div>
</td>
<td height="20">
<img src="images/search.gif" οnclick="search();">
</td>
</tr>
<tr>
<td height="20" valign="top" align="center">
产品描述:
</td>
<td id="pos_1" height="80">
<textarea id="content">
</textarea>
</td>
</tr>
</table>
在该页面中一旦用户开始在文本框中输入待查询商品的名称,即触发“onkeyup”事件,调用“findNames()”函数,在该函数中首先获取到用户已经在文本框中输入的信息,然后借助Ajax提交请求,同时提交文本框中用户已经填写的信息,请求的格式为" autoComplete? action=match&names=" + escape(inputField.value),可以看到,为了表明请求的类型,使用了参数action,其值为“match”,等待服务器端的处理。当服务器端后续处理完成后,将返回获取到的与用户已输入信息相匹配的信息列表,在Ajax提供的处理函数中调用“setNames(names)”函数以动态方式在页面的对应位置进行显示,在进行显示时还调用了“setOffsets()”函数以及“calculateOffsets()”函数。
此外,当用户录入完待查询的商品名称,单击“搜索”按钮后,将调用“search()”,该函数将首先获取待查询的商品名称信息,然后提交请求,同时提交待查询商品信息到服务器端,请求的格式为" autoComplete?action=search&names=" + escape(inputField.value),可以看到,为了表明请求的类型,使用了参数action,其值为“search”。等待服务器端的处理。当服务器端后续处理完成后,将调用“processSearchResponse()”函数在对应的文本区域中显示查询的商品描述信息。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“autoComplete”请求时,将由服务器端的类名为“classmate.AutoCompleteAction”的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.AutoCompleteAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/autoComplete</url-pattern>
</servlet-mapping>
<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>autoComplete.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序AutoCompleteAction.java中对应的程序代码。当接收到浏览器端提交的请求后,首先获取请求的类型及相关的数据信息,然后借助封装了数据库操作的JavaBean完成数据库的操作,例如:获取候选商品名称信息,或者查询指定商品的描述信息等。
package classmate;
import java.io.IOException;
……
public class AutoCompleteAction extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
}
……
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置接收信息的字符集
request.setCharacterEncoding("UTF-8");
//接收浏览器端提交的信息
String action = request.getParameter("action");
String name = request.getParameter("names");
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");
//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
//匹配
if ("match".equals(action)){
strSql = "select * from product where name like'" + name + "%'";
rs = db.executeQuery(strSql);
try {
while(rs.next()) {
out.println("<res>" + rs.getString("name") + "</res>");
}
}catch (SQLException e) {
e.printStackTrace();
}
}
else if ("search".equals(action)){
strSql = "select contents from product where name ='" + name + "'";
rs = db.executeQuery(strSql);
try {
if ( rs.next()) {
out.println("<res>" + rs.getString("contents") + "</res>");
}
}catch (SQLException e) {
e.printStackTrace();
}
}
out.println("</response>");
out.close();
}
}
在本例中,完成match类型的请求处理之后,返回的XML文档的格式如下所示:
<response>
<res>候选商品名称1</ res>
<res>候选商品名称1</ res>
<res>候选商品名称1</ res>
</response>
完成search类型的请求处理之后,返回的XML文档的格式如下所示:
<response>
<res>商品描述信息</ res>
</response>