@H_403_1@最近项目需要作一个类似google suggest的搜索提示功能,在网上找了一些资料,自己弄弄就出来了。项目的关键是JS。
实际运行效果:
即使在输入的时候前面有空格,也可以正确判断。
工程结构:
Keywords.java
package com.bird.bean; public class Keywords { private String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Keywords(String content) { this.content = content; } public Keywords() { } }
DBManager.java
package com.bird.common; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.sqlException; public class DBManager { public DBManager() { } public static Connection getConnection() { // String driver = "oracle.jdbc.driver.OracleDriver"; String driver = "com.MysqL.jdbc.Driver"; // String url = "jdbc:oracle:thin:@133.0.129.6:1521:oracle"; String url = "jdbc:MysqL://127.0.0.1:3306/itbird"; // String username = "nrmdb"; // String passwd = "nrmoptr"; String username = "root"; String passwd = "root"; Connection connection = null; try { Class.forName(driver); connection = DriverManager.getConnection(url,username,passwd); } catch (Exception ex) { ex.printStackTrace(); } return connection; } public static void closeAll(Connection con,PreparedStatement pstmt,ResultSet rs) { try { if (rs != null) { rs.close(); } if (pstmt != null) { pstmt.close(); } if (con != null) { con.close(); } } catch (sqlException ex) { ex.printStackTrace(); } } }GetKeywordsResults.java
package com.bird.DAO; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import com.bird.bean.Keywords; import com.bird.common.DBManager; public class GetKeywordsResults { @SuppressWarnings("null") public ArrayList<Keywords> getKeywordsResults(String keyword) { ArrayList<Keywords> list = new ArrayList<Keywords>(); Keywords key = null; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; String sql = "select content from keywords where content like '%" + keyword + "%'"; try { conn = DBManager.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()) { key = new Keywords(); System.out.println("类似关键词:" + rs.getString(1)); key.setContent(rs.getString(1)); list.add(key); } } catch (Exception e) { e.printStackTrace(); } finally { DBManager.closeAll(conn,pstmt,rs); } return list; } }GetKeywordServlet.java
package com.bird.servlet; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.bird.DAO.GetKeywordsResults; import com.bird.bean.Keywords; public class GetKeywordServlet extends HttpServlet { /** * 2014-12-18 * * @author GHYZ */ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { System.out.println("123"); resp.setContentType("text/xml;charset=UTF-8"); resp.setHeader("Cache-Control","no-cache"); // save keyword String param = null; String rawQueryStr = req.getQueryString(); String queryStr = java.net.URLDecoder.decode(rawQueryStr,"utf-8"); String[] result = queryStr.split("="); // keyword try { param = result[1]; String pattern = "([\'\"-+*/^()\\]\\[])"; param = param.replaceAll(pattern,""); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("error input!"); return ; } param = param.trim(); System.out.println("--->" + param); ArrayList<Keywords> list = null; try { System.out.println("in list Size"); list = new ArrayList<Keywords>(); list = (new GetKeywordsResults().getKeywordsResults(param)); System.out.println(list.size() + "listSize"); } catch (Exception e) { System.out.println("input error!"); } String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; xml += "<message>"; Iterator<Keywords> iter = list.iterator(); String content; while (iter.hasNext()) { Keywords key = iter.next(); content = key.getContent(); xml += "<info>" + content + "</info>"; } xml += "</message>"; resp.getWriter().write(xml); } @Override protected void doPost(HttpServletRequest req,IOException { this.doGet(req,resp); } }
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>getKeywordServlet</servlet-name> <servlet-class>com.bird.servlet.GetKeywordServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getKeywordServlet</servlet-name> <url-pattern>/getKeywordServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
build.js
/* * 判断按键的JavaScript代码 */ var arrOptions = new Array(); //定义一个保存服务器返回的数组 var strLastValue = ""; //定义保存每次向服务器发送请求的参数 var theTextBox; //定义表示文本输入变量 var currentValueSelect = -1; //定义下拉提示框中默认的选项 window.onload = function() { var elemSpan = document.createElement("span"); elemSpan.id = "spanOutput"; elemSpan.className = "spanTextDropdown"; document.body.appendChild(elemSpan); document.Form1.txtUserInput.onkeyup = GiveOptions; }; function GiveOptions() { //按下键的调用方法 var intKey = -1; if (window.event) { intKey = event.keyCode; theTextBox = event.srcElement; } if (theTextBox.value.length == 0) { //文本框内容为空 HideTheBox(); strLastValue = ""; return false; } if (intKey == 13) { //按下Enter键 GrabHighlighted(); theTextBox.blur(); return false; } else if (intKey == 38) { //按下 up 键 MoveHightlighted(-1); return false; } else if (intKey == 40) { //按下 down 键 MoveHightlighted(1); return false; } //进行内容比较 if (theTextBox.value.indexOf(strLastValue) != 0 || arrOptions.length == 0 || (strLastValue.length == 0 && theTextBox.value.length > 0) || (theTextBox.value.length <= strLastValue.length) ) { strLastValue = theTextBox.value; strLastValue = strLastValue.replace(/^\s*\'|\s*$/g,""); TypeAhead(theTextBox.value); } else { BuildList(theTextBox.value); } }; function removeAllSpace(str) { return str.replace(/\s+/g,""); }; function TypeAhead(xStrText) { //发送请求方法 xStrText = removeAllSpace(xStrText); if (xStrText == "") return; //判断如果输入框内容为空 var url = "getKeywordServlet?param=" + xStrText; //创建发送地址变量 if ( window.XMLHttpRequest ) { //判断浏览器 req = new XMLHttpRequest(); } else if (window.ActiveXObject()) { req = new ActiveXObject("Microsoft.XMLHTTP"); } if (req) { req.open("GET",url,true); //打开连接 //设置回调函数 req.onreadystatechange = function() { if (req.readyState==4 && req.status==200) { parseMessage(); } }; req.send(null); //实现发送 } }; function parseMessage() { //分析服务器返回数据 var xmlDoc = req.responseXML.documentElement; //获取返回的XML文件对象 var nodeInfo = xmlDoc.getElementsByTagName("info"); //获取标记<info> arrOptions = new Array(); //创建一个数组对象 for (var i = 0; i < nodeInfo.length; i ++) { arrOptions[i] = nodeInfo[i].firstChild.nodeValue; //存储<info>到数组对象中 } BuildList(theTextBox.value); strLastValue = theTextBox.value; }; function BuildList(theText) { //创建下拉提示框方法 //alert("buidList"); theText = removeAllSpace(theText); SetElementPosition(); var inner = ""; var theMatches = MakeMatches(theText); //获取索要匹配的对象 for (var i = 0; i < theMatches.length; i++) { inner += theMatches[i]; } if (theMatches.length > 0) { document.getElementById("spanOutput").innerHTML = inner; document.getElementById("OptionsList_0").className = "spanHighElement"; currentValueSelect = 0; } else { HideTheBox(); } }; function SetElementPosition() { var selectedPosX = 0; var selectedPosY = 0; //创建关于提示框的长度和宽度的变量 var theElement = document.Form1.txtUserInput; //var theTextBoxInt = document.Form1.txtUserInput; if (!theElement) { alert("not found"); return; } //为提示框的长度和宽度赋值 var theElemHeight = theElement.offsetHeight; var theElemWidth = theElement.offsetWidth; //设置提示框的位置 while ( theElement != null ) { selectedPosX += theElement.offsetLeft; selectedPosY += theElement.offsetTop; theElement = theElement.offsetParent; } xPosElement = document.getElementById("spanOutput"); xPosElement.style.left = selectedPosX; xPosElement.style.width = theElemWidth; xPosElement.style.top = selectedPosY + theElemHeight; xPosElement.style.display = "block"; }; var countForId = 0; function MakeMatches(xCompareStr) { countForId = 0; var matchArray = new Array(); for ( var i = 0; i < arrOptions.length; i++) { //遍历arrOptions对象 var regExp = new RegExp(xCompareStr,"ig"); if ((arrOptions[i].search(regExp)) >= 0 ) { //当有匹配的项,调用CreatUnderline()方法返回字符串 matchArray[matchArray.length] = CreateUnderline(arrOptions[i],xCompareStr,i); } else { continue; } } return matchArray; }; function MoveHightlighted(xDir) { if (currentValueSelect >= 0) { //获取按键的值 newValue = parseInt(currentValueSelect) + parseInt(xDir); if (newValue > -1 && newValue < countForId) { currentValueSelect = newValue; SetHighColor(null); } } }; function ReDraw() { BuildList(document.Form1.txtUserInput.value); }; function GrabHighlighted() { if (currentValueSelect >= 0) { xVal = document.getElementById("OptionsList_" + currentValueSelect).getAttribute("theArrayNumber"); SetText(xVal); HideTheBox(); } }; function HideTheBox() { document.getElementById("spanOutput").style.display = "none"; currentValueSelect = -1; }; var undeStart = "<span class='spanMatchText'>"; var undeEnd = "</span>"; var selectSpanStart = "<span style='width:100%;display:block;' " + " class='spanNormalElement' onmouSEOver='SetHighColor(this)'"; var selectSpanEnd = "</span>"; function CreateUnderline(xStr,xTextMatch,xVal) { selectSpanMid = "onclick='SetText(" + xVal + ")'" + " id='OptionsList_" + countForId + "' theArrayNumber='" + xVal + "'>"; countForId++; var regExp = new RegExp(xTextMatch,"ig"); var start = xStr.search(regExp); var matchedText = xStr.substring(start,start + xTextMatch.length); var Replacestr = xStr.replace(regExp,undeStart + matchedText + undeEnd); return selectSpanStart + selectSpanMid + Replacestr + selectSpanEnd; }; function SetHighColor(theTextBox) { if (theTextBox) { currentValueSelect = theTextBox.id.slice( theTextBox.id.indexOf("_") + 1,theTextBox.id.length ); } for (var i = 0; i< countForId; i++) { document.getElementById('OptionsList_' + i).className = 'spanNormalElement'; } document.getElementById('OptionsList_' + currentValueSelect).className = 'spanHighElement'; }; function SetText(xVal) { theTextBox = document.Form1.txtUserInput; theTextBox.value = arrOptions[xVal]; document.getElementById("spanOutput").style.display = "none"; currentValueSelect = -1; };index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>Google Suggest</title> <Meta http-equiv="pragma" content="no-cache"> <Meta http-equiv="cache-control" content="no-cache"> <Meta http-equiv="expires" content="0"> <Meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <Meta http-equiv="description" content="This is my page"> <script type="text/javascript" src="build.js"></script> <style type="text/css"> .spanTextDropdown { left: 88px; width: 171px; top: 29px; display: none; margin-left: 80px; border: 1px solid gray; margin-top: -18px; } .spanHighElement { background:navajowhite; } </style> </head> <body onResize="ReDraw()"> <div> <form name="Form1" autocomplete="off" id="Form1"> Text Box: <input type="text" name="txtUserInput" style="width: 182px;"/> <!-- hidden zone --> <input type="hidden" name="txtUserValue" id="hidden1"/> <!-- help text input --> <input type="text" name="txtIgnore" style="display: none;"/> </form> </div> </body> </html>原文链接:https://www.f2er.com/ajax/163975.html