ajax + java 实现类似网易邮箱邮件地址自动完成功能



2008-04-02 18:30



********************************************************************

源代码下载链接: http://www.javaeye.com/topic/150778

********************************************************************

用java+ajax做的一个类似于google输入栏版提示的ajax小功能.
稍改进了下.现在类似于163.126的邮件地址自动完成功能.

结构描述:
1.前台页面: autoComplete.js autoComplete.jsp
2.配置: 把web.xml文件的内容配置到你web工程的web.xml文件.
3.后台程序: 在com文件夹下.

运行: 在tomcat中打开autoComplete.jsp,键入字符a , y ,g都可以弹出.
要想内容更丰富.
请您自己完善.
在IE和firefox 下测试通过.

演示截图:

IE:




ajax + java 实现类似网易邮箱邮件地址自动完成功能_html


Firefox:



ajax + java 实现类似网易邮箱邮件地址自动完成功能_java_02


JS代码: autoComplete.js

// JavaScript Document
 var xmlHttp;
 var completeDiv;
 var nameTable;
 var nameTableBody;
 var inputField;
 var divIframe;
    var isDivShow = false; //2007-12-23
 var inTbodyLineNO = -1; //2007-12-23

 function createXMLHttpRequest(){
       if(window.ActiveXObject){
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
    }else if(window.XMLHttpRequest){
           xmlHttp = new XMLHttpRequest();
    }
 }
 function initVars(){
      nameTableBody = document.getElementById("name_table_body");
 nameTable = document.getElementById("name_table");
 completeDiv = document.getElementById("popup");
 inputField = document.getElementById("names");
 divIframe = document.getElementById("diviframe");
 }

 /* post html 页面 调用接口,此方法异步调用Servlet方法 AutoCompleteServlet */
 function findNames(e){
      initVars();    //alert("00000: "+e.keyCode);
 if(e.keyCode!=40 && e.keyCode!=38 && e.keyCode!=13 && e.keyCode!=27)
 {
       if(inputField.value.length > 0)
    { 
        createXMLHttpRequest();
     var url = "/AutoCompleteServlet";
     var postPara = "names="+inputField.value;
     postPara = encodeURI(postPara);
     postPara = encodeURI(postPara);
     xmlHttp.open("post",url,true);
              xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
     xmlHttp.send(postPara);
     xmlHttp.onreadystatechange = callback;
       }else
    {
        clearNames(); 
       }
 }

 }


 /* setNames 方法处理返回回来的数据 */
 function callback(){           
      if(xmlHttp.readyState == 4){          // alert("status: "+xmlHttp.status+"   text: "+xmlHttp.statusText);
    if(xmlHttp.status == 200){
     setNames(xmlHttp.responseXML.getElementsByTagName("name"),xmlHttp.responseXML.getElementsByTagName("value"));
    
    }else{
     clearNames(); 
     alert("Exception-status: "+xmlHttp.status+"   text: "+xmlHttp.statusText); 
    }
 } 
 }

 function setNames(the_names,the_values){
 clearNames(); 
 var size = the_names.length;      //alert(size);
 setOffsets();

 var row,cell,txtNode;
 for(var i=0;i<size;i++){
    isDivShow = true;
    var nextNode = "\""+the_names[i].firstChild.data+"\" <"+the_values[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(){populateNames(this);};
    
    divIframe.style.display="";
    txtNode = document.createTextNode(nextNode);
    cell.appendChild(txtNode);
    row.appendChild(cell);
    nameTableBody.appendChild(row);
    
    if(inTbodyLineNO == -1)
       {
     inTbodyLineNO = 0;
     nameTableBody.rows[inTbodyLineNO].cells[0].className = "mouseOut";
       }
 }
 } 

 // div 的显示位置设置
 function setOffsets(){
 var end = inputField.offsetWidth;
 var left = calculateOffsetLeft(inputField);
 var top = calculateOffsetTop(inputField) + inputField.offsetHeight;

 completeDiv.style.border = "black 1px solid";
 completeDiv.style.left = left + "px";
 completeDiv.style.top = top + "px";
 nameTable.style.width = end + "px";
 divIframe.style.border="none";
 }

 function calculateOffsetLeft(field){
 return calculateOffset(field,"offsetLeft"); 
 }

 function calculateOffsetTop(field){
 return calculateOffset(field,"offsetTop"); 
 }

 function calculateOffset(field,attr){
 var offset = 0;
 while(field){
    offset += field[attr]; 
    field = field.offsetParent;
 }
 return offset;
 }

 // 对用户输入框取值 用户选择时调用
 function populateNames(cell){
      var oldInputValue = inputField.value.substring(0,inputField.value.lastIndexOf(",")+1);
 var newInputValue = cell.firstChild.nodeValue;
 if(oldInputValue.indexOf(newInputValue) > -1)
 {
     inputField.value = oldInputValue;
 }else
 {
        inputField.value = oldInputValue + newInputValue+",";
 }
    
      clearNames();
 }

 // 清空操作
 function clearNames(){
      var ind = nameTableBody.childNodes.length;
      for(var i = ind - 1; i >= 0; i--){
          nameTableBody.removeChild(nameTableBody.childNodes[i]);
      }
      divIframe.style.display="none";
      completeDiv.style.border = "none";
      inTbodyLineNO = -1; //2007-12-23
 isDivShow = false; //2007-12-23
 } 

 function getKeyCode(oEvent)
 { 
     /* if(oEvent.keyCode!=40 && oEvent.keyCode!=38 && oEvent.keyCode!=13 && oEvent.keyCode!=27)
 {
    //window.setTimeout("findNames()",2000); 
    findNames();
 } */
     
 if(isDivShow) // 如果自动完成的层显示出来了
 {
    if(oEvent.keyCode == 40)
       {
           MoveCursor(1);
       }else if(oEvent.keyCode == 38) // 
       {
           MoveCursor(-1);
       }else if(oEvent.keyCode == 13) // enter
       {
           selectValue();
 //    oEvent.keyCode=9;
       }else if(oEvent.keyCode == 27) // esc
       {
           clearNames();
       }
 }



 }

    //2007-12-23
 function MoveCursor(nFlag)
 {
    var lineNum = nameTableBody.rows.length;   //alert(lineNum);
    nameTableBody.rows[inTbodyLineNO].cells[0].className = "mouseOver";
    inTbodyLineNO = (inTbodyLineNO + nFlag + lineNum) % lineNum;
    nameTableBody.rows[inTbodyLineNO].cells[0].className = "mouseOut";
    nameTableBody.rows[inTbodyLineNO].cells[0].scrollIntoView(true);
 }//2007-12-23
 function selectValue()
 {
    if(inTbodyLineNO == -1)
    {
      return; 
    }else
    {
     populateNames(nameTableBody.rows[inTbodyLineNO].cells[0]);
    }
 }





JSP页面: autoComplete.jsp

<%@ page contentType="text/html; charset=GBK" pageEncoding="GBK" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
 <title>Ajax Auto Complete Example</title>
 <script language="javascript" src="autoComplete.js"></script>
 <script language="javascript"></script>
 <style type="text/css">
 .mouseOut{
 background:#708090;
 color:#FFFAFA; 
 }
 .mouseOver{
 background:#FFFAFA;
 color:#000000;
 }
 </style>
 </head><body>
 <h1>Ajax Auto Complete Example</h1><p/><p/>
 Names:<input type="text" name="names" id="names" size="60" οnkeydοwn="getKeyCode(event);" οnkeyup="findNames(event);" οnblur="clearNames();"/>
 <div id="popup" style="position:absolute; cursor: pointer; z-index:100; ">
 <table id="name_table" bgcolor="#FFFAFA" border="0" cellpadding="0" cellspacing="0">
 <tbody id="name_table_body"></tbody>
 </table>
 <iframe src="#" id="diviframe" name="diviframe" style="z-index:-1; filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0); left:0px;   visibility:inherit; width:110px; position:absolute; top:0px; height:100px; display:none;"> </iframe>
 </div>
 <input type="text" size="60" οnfοcus="clearNames();"/><br />
 00000000000000000000000
 <select name="aa"></select>
 </body>
 </html>

java代码: 用了Servlet实现: AutoCompleteServlet.java供Ajax调用. 辅助类: AutoCompleteService.java

package com.yidwo;
import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URLDecoder;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;import javax.servlet.*;
 import javax.servlet.http.*; public class AutoCompleteServlet extends HttpServlet {

 private Map autoMap = new HashMap();

 public void init(ServletConfig config) throws ServletException{
    autoMap.put("yidwo","yidwo@126.com");
    autoMap.put("gkim","gkimyidt@163.com");
    autoMap.put("gkimyidt","gkimyidt@163.com");
    autoMap.put("a","gkimyidt@163.com");
    autoMap.put("b","gkimyidt@163.com");
 }

 protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
   
    String prefix = URLDecoder.decode(request.getParameter("names"),"utf-8");
   
    AutoCompleteService service = AutoCompleteService.getMapInstance(autoMap);
    Map resultMap = service.getSuitedMap(prefix);
   
    if(resultMap.size()>0)
    {
     response.setContentType("text/xml;charset=GB2312");
     response.setHeader("Cache-Control","no-cache");  
     response.setCharacterEncoding("GB2312");
    
     PrintWriter out = response.getWriter();    if(resultMap.size()>0)
     {
      out.println("<?xml version=\"1.0\" encoding=\"GB2312\" ?>");
      out.println("<response>");
     
 //     为什么这里用keySet()方法就不会迭代呢.用entrySet就可以?
      for(Iterator iter = resultMap.entrySet().iterator(); iter.hasNext();)
      {
       Map.Entry element = (Map.Entry)iter.next();
      
       String keyName = (String)element.getKey();
       String keyValue = (String)element.getValue();
                     System.out.println("keyName="+keyName+"   keyValue="+keyValue);
       out.println("<name>" + keyName + "</name>");
       out.println("<value>" + keyValue + "</value>");
      }
     
      out.println("</response>");
      out.flush();
      resultMap = null;
      service = null;
      out.close();
      }else
       {
        System.out.println(System.currentTimeMillis()+" can't find suited info.");
        response.setStatus(HttpServletResponse.SC_NO_CONTENT);
       }
    }  
 }

 public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
    doGet(request,response);}  
 }

辅助类: AutoCompleteService.java

package com.yidwo;
import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;public class AutoCompleteService {
   
     private Map namesMap;


 private AutoCompleteService(Map list_of_names){
   
    this.namesMap = list_of_names;
 }

 public static AutoCompleteService getMapInstance(Map list_of_names){
   
    return new AutoCompleteService(list_of_names);
 }

 public Map getSuitedMap(String prefix){
    if(prefix.split(",").length>0)
    {
     prefix = prefix.split(",")[prefix.split(",").length-1];
    }
    Map matches = new HashMap();
   
    for(Iterator iter = namesMap.entrySet().iterator(); iter.hasNext();)
    {
     Map.Entry element = (Map.Entry)iter.next();
    
     String keyName = (String)element.getKey();
     String keyValue = (String)element.getValue();
    
     String keyValue_uppercase = keyValue.toUpperCase();
    
     if(keyName.startsWith(prefix) || keyValue.startsWith(prefix) || keyValue_uppercase.startsWith(prefix))
     {
      matches.put(keyName,keyValue);
     }
    }  
   
    return matches;
 }
 }