现在的位置: 首页 > 综合 > 正文

征服Ajax——Web 2.0快速入门与项目实践(Java)

2018年02月11日 ⁄ 综合 ⁄ 共 9585字 ⁄ 字号 评论关闭

实现自动完成功能

本章实现的最后一个效果如图5-6所示。该页面实现的效果对读者并不陌生,我们在著名的搜索网站Google中已经非常熟悉自动完成功能的效果。本例中当用户在文本框中输入待查询的商品名称时,页面中将根据用户输入的文字信息,及时给出提示列表,以帮助用户快速进行选择,该提示信息来源于服务器端数据库中的数据。当用户选择了对应商品名称,单击“搜索”按钮后,将会在文本区域中显示商品相关的描述信息。
首先在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>
5-6  自动完成的效果
</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" onkeyup="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" onclick="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>
至此,本章相关的案例介绍完毕,通过本章的学习,读者对Ajax的实际应用方式和技巧都应有了一定程度的掌握和理解。

抱歉!评论已关闭.