Ajax实现仿Google自动补全功能

    技术2024-08-03  64

    完整版见https://jadyer.github.io/

    这是一个Servlet应用。。

    这里分别通过<div>和<select>两种方式实现仿Google自动补全功能

    首先是通过<div>实现的。。autoCompleteUseDIV.jsp

    思想:各自新建DIV层以存放每一个提示出来的补齐文本

    取值:目前只能用鼠标点击来选值

    缺点:虽同时支持Firefox和IE,但功能不够人性化,用户体验度不高

    <%@ page language="java" pageEncoding="UTF-8"%> <style> #auto { position: absolute; display: none; background-color: #FFFFC0; border: solid 1px #808080; font-size: 12px; color: green; cursor: pointer; padding: 3px; } </style> <script type="text/javascript"> var xmlHTTP = new XMLHttpRequest(); //支持Internet Explorer-8.0.6001.18702 function getGoogleList(txt){ if("" == txt){ return; } xmlHTTP.open('GET', encodeURI('${pageContext.request.contextPath}/servlet/GoogleListServlet?txt='+txt), true); xmlHTTP.onreadystatechange = callback; //${pageContext.request.contextPath}为EL表达式,等效于<%=request.getContextPath()%> xmlHTTP.send(null); } function callback(){ if(4==xmlHTTP.readyState && 200==xmlHTTP.status){ var txt = document.getElementById('txt'); var auto = document.getElementById('auto'); var s = xmlHTTP.responseText; if("" == s){ auto.style.display = 'none'; //隐藏该层 return; } auto.innerHTML = ''; //清空auto层的内容 var ss = s.split(","); //分割服务器返回的字符串,得到ss数组 //(ss.length-1)是为了解决服务器端返回的字符串中,最后一个逗号的问题 for(var i=0; i<(ss.length-1); i++){ //新建层。也就是让弹出的每一行文本都各占一个div层,即子层 var div = document.createElement('DIV'); //经测试,其在Firefox3.6.13和IE8中均有效。。或者使用div.innerText = ss[i];但它在Firefox无效 div.appendChild(document.createTextNode(ss[i])); //将新建的子层,放到父层中。即放到id="auto"的div层中 auto.appendChild(div); //关于该层的三个事件处理的函数,一个是鼠标移动到层上,一个是鼠标从该层移出,一个是鼠标单击选项卡取值 div.onmouseover = function(){ this.style.backgroundColor = 'red'; //当鼠标放到上面的时候,令其背景色为红色 }; div.onmouseout = function(){ this.style.backgroundColor = '#FFFFC0'; //当鼠标移走之后,恢复背景色 }; div.onclick = function(){ //处理onclick事件的函数,鼠标单击取值 txt.value = this.innerHTML; //或者使用txt.value = ss[i];也可以 this.parentNode.style.display = 'none'; //隐藏父层。即隐藏id="auto"的div层 }; } //设置id="auto"的层的显示位置 var left = txt.offsetLeft; //得到id="txt"的文本框与浏览器左侧之间的距离 var top = txt.offsetTop; //得到id="txt"的文本框与浏览器顶部之间的距离 auto.style.left = left; //指定id="auto"的层与浏览器左侧的距离。即与文本框的左侧对齐 auto.style.top = top + txt.offsetHeight; //txt.offsetHeight能够取得文本框的高度 auto.style.width = txt.offsetWidth; //令id="auto"的div层的宽度,与文本框的宽度一致 auto.style.display = 'block'; //令auto层显示 } } </script> 我要搜索:<input type="text" id="txt" οnkeyup="getGoogleList(this.value)"/> <div id="auto"></div>

    接下来是通过<select>实现的。。autoCompleteUseSELECT.jsp

    思想:在一个父DIV层中新建一个select下拉列表框,并指明长度

              如此实现的效果就是:能够使用上下键来选择所要补齐的文本

    取值:允许使用回车键和鼠标点击两种方式来选值

    缺点:由于window.event在Firefox中无效,故其不支持Firefox,详情参阅下面第25行的代码注释

    <%@ page language="java" pageEncoding="UTF-8"%> <style> #auto{ position: absolute; display: none; } #se{ color: green; border-width: 1px; border-style: solid; background-color: #FFFFC0; } </style> <script type="text/javascript"> var xmlHTTP = new XMLHttpRequest(); //支持Internet Explorer-8.0.6001.18702 function getGoogleList(txt){ if("" == txt){ return; } var auto = document.getElementById('auto'); //window.event.keyCode可以用来设置或者获取,与导致事件的按键,关联的ASCII码 //但其只对IE有效,原因是Firefox的window对象没有event属性,所以window.event在Firefox中是无效的 //那么,在Firefox中的解决办法是:在事件句柄函数的第一个参数上,获取事件对象 //详情,请参见我的博文http://blog.csdn.net/jadyer/archive/2011/01/27/6167244.aspx if(40==event.keyCode && 'block'==auto.style.display){ //40代表向下键 var selectValues = document.getElementById('se'); //得到选项卡 selectValues.focus(); //让选项卡获得焦点 selectValues.selectedIndex = 0; //让选项卡中的第一个元素选中 document.getElementById('txt').value = selectValues.value; //让文本框显示的值为选项卡的第一个元素值 return; } auto.style.display == 'none'; //隐藏<div id="auto">层 xmlHTTP.open('GET', encodeURI('${pageContext.request.contextPath}/servlet/GoogleListServlet?txt='+txt), true); xmlHTTP.onreadystatechange = callback; xmlHTTP.send(null); } function callback(){ if(4==xmlHTTP.readyState && 200==xmlHTTP.status){ var txt = document.getElementById('txt'); //得到文本框 var auto = document.getElementById('auto'); //获取选项卡的层 var selectValues = document.getElementById('se'); //得到选项卡 selectValues.length = 0; //删除<option>选项卡。或者使用selectValues.options.length=0; var s = xmlHTTP.responseText; if("" == s){ auto.style.display = 'none'; return; } var ss = s.split(","); //指定<select>的长度,即返回的字符串的长度。注意返回的字符串的尾部还包含一个逗号,所以要减一 selectValues.size = ss.length-1; for(var i=0; i<(ss.length-1); i++){ selectValues.options[i] = new Option(ss[i], ss[i]); } //指定<select>的事件处理的函数,令其支持回车键选值和鼠标单击选值 selectValues.onkeyup = function(){ txt.value = this.value; //这里this指的是<select>下拉列表框,而不是某个<option>选项卡 if(13 == event.keyCode){ //13代表回车键 this.parentNode.style.display = 'none'; //隐藏<option>选项卡 } }; selectValues.onclick = function(){ //鼠标单击选值 txt.value = this.value; this.parentNode.style.display = 'none'; //隐藏<option>选项卡 }; //设置<div id="auto">层的位置 var left = txt.offsetLeft; var top = txt.offsetTop; auto.style.left = left; auto.style.top = top + txt.offsetHeight; auto.style.width = txt.offsetWidth; auto.style.display = 'block'; } } </script> 我要搜索:<input type="text" id="txt" οnkeyup="getGoogleList(this.value)"/> <div id="auto"> <select id="se"></select> </div>

    然后是web.xml文件

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>GoogleListServlet</servlet-name> <servlet-class>com.jadyer.ajax.GoogleListServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GoogleListServlet</servlet-name> <url-pattern>/servlet/GoogleListServlet</url-pattern> </servlet-mapping> </web-app>

    最后是用来处理Ajax请求操作的GoogleListServlet.java

    package com.jadyer.ajax; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import java.util.Vector; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class GoogleListServlet extends HttpServlet { List<String> users = new Vector<String>(); @Override public void init() throws ServletException { users.add("我爱学习"); users.add("我喜欢Java"); users.add("我也喜欢money"); users.add("我想找一个女朋友"); users.add("神乎其神"); users.add("神马最给力"); users.add("神仙长生不老"); users.add("神奇的心有灵犀"); } @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String txt = request.getParameter("txt"); response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); for(String user : users){ if(user.startsWith(txt)){ //此时返回给客户端的是类似【我爱学习,我喜欢Java,我也喜欢money,】的字符串 //注意其还尾部包含一个逗号,所以前台页面在处理时,判断的是i<(ss.length-1) out.print(user + ","); } } out.close(); } }

    最新回复(0)