ajax+jquery实现类似百度搜索提示框
需求:
1、 输入某一关键字后,在搜索框下会显示出与此关键字相关的提示信息
2、 可以通过键盘的上下键以及回车键进行操作
思路:
1、 输入关键字后,通过ajax异步的方式将关键字提交给相应的处理模块,获得处理结果(主要是通过查询数据库中某张表获得以此关键字开头的符合要求的数据),然后再加载到页面上。
2、 通过获取用户操作键盘的event.keyCode值来进行不同的操作。(up:38 down: 40 enter:13)
下面给出主要的代码:
页面html代码: <div class="searchformdiv"> <form id="searchform" action="<%=basePath%>web/search-list.shtml" onsubmit="return f_search()" target="_self"> <div><input type="text" id="keywords" class="inputtextsearch2" autocomplete="off" value="${pagerestrict.keywords}" /> <input type="image" src="<%=basePath%>web/imgs/button_searcha.png" align="absmiddle"> </div></form></div> <script> function f_search(){ var keywords = document.getElementById("keywords").value.Trim();//Trim()方法在String.perporty.Trim()中写了,剔除字符串前后的空格 if(keywords==null||keywords==''){ return false; } document.getElementById("searchform").action="<%=basePath%>web/search-list.shtml"; } </script> |
后台获取处理结果的部分代码(我是写在servlet中的): response.setContentType("text/xml;charset=utf-8");//设置返回信息的格式 request.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String keywords = request.getParameter("key").replaceAll("<[/a-zA-Z]*>", "").replaceAll("[^a-zA-Z0-9_\u4e00-\u9fa5 ]*", ""); //剔除关键字中html标签以及非空格的特殊字符;这样做是为后面通过xml的形式返回数据做准备,因为在xml中出现< >这些符号的时候不好处理,所以为了简单点就在这给剔除了。O(∩_∩)O~ StringBuilder sql = new StringBuilder(); sql.append("select kw,totalcount, kwid from tproductkw where totalcount > 0 and ( kw like '").append(keywords).append("%' or sep like '").append(keywords).append("%' ) order by length(kw),searchtimes desc"); //用的mysql数据库 order by length(kw)是按照kw的长度进行排序,不知道其它数据库是否有这个方法,木有的话可以自己写个滴 StringBuilder xml = new StringBuilder();
//下面是通过查询数据库获取符合要求的信息的,我是通过hibernate来操作的,你也可以通过自己的方法来对数据库进行操作 PageRestrict res = new PageRestrict(); res.setLimit(15); List list = HibernateUtil.getListForPageBySql(sql.toString(), res).getDataList(); xml.append("<results>"); if(list != null){ for(Object item:list){ Object o[] = (Object[])item; String sug =o[0].toString().toLowerCase().replaceAll("<[/a-zA-Z]*>", "").replaceAll("[^a-zA-Z0-9_\u4e00-\u9fa5 ]*", ""); String count = o[1].toString(); int pos =sug.indexOf(keywords.toLowerCase());//提示信息中是否包含关键字信息(因为我的数据库表中存的关键字以及关键字全转拼音后的数据sep字段,所以在这里就有可能在源提示信息中不包含关键字) if(pos>-1){//提示内容包含关键字时 sug = sug.substring(pos+keywords.length()).toLowerCase(); xml.append("<result key='").append(keywords.toLowerCase()).append("' sug='").append(sug).append("'");//包含关键字时,将关键字的值赋给key,提示信息中剔除关键字后的值赋给sug }else{//提示内容不包含关键字时 xml.append("<result key='' sug='").append(sug).append("'"); } xml.append(" count ='").append(count).append("' ></result>"); } } xml.append("</results>"); out.print(xml.toString()); out.flush(); out.close(); |
下面给出js代码
var line = 0;//定义一个全局的line以用于记录当前显示的是哪一行 function replace(obj,src,str){//用str替换掉源(obj)中的src if(obj.indexOf(src)==-1)return obj; var array = obj.split(src); var result=""; for(var i=0;i<array.length;i++){ result +=array[i]; result+=str; } return result; }
var mychange = function () {//进行ajax请求以及显示提示信息 del();//如果存在提示框则移除 if ($("#keywords").val() == "")return; var top = $("#keywords").offset().top;//搜索框与页面顶部的距离 var left = $("#keywords").offset().left;//搜索框与页面左侧的距离
//构造信息提示的div var newDiv = $("<div/>").width($("#keywords").width() + 10).css("position", "absolute").css("backgroundColor", "white").css("left", left).css("top", top + $("#keywords").height() + 10).css("border", "1px solid #DFDFDF").attr("id", "newDiv"); var table = $("<table width='100%'/>").attr("cellpadding", "0").attr("cellspacing", "0");
$.post(basePath+"autocompleteServlet.select", {key:$("#keywords").val()}, function (xml) {//发送请求,并通过xml的格式返回处理信息 $(xml).find("results result").each(function () {//获取处理信息中所有的result节点 var key = $(this).attr("key");//result中的key属性 var sug = $(this).attr("sug");//result中的sug属性,记录提示信息 var count = $(this).attr("count");//result中的count属性,记录通过该关键字的最后一次查询所得的总数
var tr = $("<tr/>").css("cursor", "pointer").mouseout(function () {//鼠标移到提示信息上时的样式变换 $(this).css("backgroundColor", "white").css("color", "black"); }).mouseover(function () {//鼠标移出提示信息时的样式变换 $(this).css("backgroundColor", "#DFDFDF").css("color", "white"); }).click(function () {//点击提示信息 var html = $(this).find("td").eq(0).html();//获取提示信息中的有效值
//剔除提示信息中的<B><b>标签 html = replace(html,"<B>",""); html = replace(html,"</B>",""); html = replace(html,"<b>","");//firefox html = replace(html,"</b>","");//firfox
$("#keywords").val(html);//将提示信息赋给搜索框 del();//移除提示框 $("#searchform").submit();//表单提交 }); //提示信息中的有效值,将非关键字部分加粗显示 var td1 = $("<td/>").html(key+"<b>"+sug+"</b>").css("fontSize", "14px").css("color", "black").css("margin", "5 5 5 5").css("padding","0 5px"); var td2 = $("<td/>").html("约"+count+"条结果").attr("align", "right").css("fontSize", "13px").css("color", "green").css("margin", "5 5 5 5"); tr.append(td1).append(td2); table.append(tr); newDiv.append(table);
}); if($(xml).find("results result").length==0){//没有提示结果时 del();//移除提示框 } });
$(document.body).append(newDiv);//显示提示框
if ($("#keywords").val() == "") { $("#newDiv").remove(); } }
function del() {//如果存在提示框则移除 if ($("#newDiv")) { $("#newDiv").remove(); line = 0;
} }
var keywords = "";//用于记录用户输入的关键字,因为在上下键操作的过程中会改变搜索框的值,用户在通过键盘上下键操作时应该还可以返回到他最初的状态 $(document).ready(function () {
//提示框失去焦点时层消失 $(document.body).click(function () { del(); }); $(document).keyup(function(event){//用户通过键盘进行操作,按键弹起时 $("#keywords").bind("propertychange", mychange);//将mychange事件绑定到propertychange事件上 $("#keywords").bind("input", mychange);//firefox 与上面的效果类似,只是在firefox中是input事件 if(event.keyCode != 40 && event.keyCode != 38 && event.keyCode != 13){//当用户不是在按上下与回车键时,将搜索框中的值赋给keywords,记录用户的初始状态 keywords = $("#keywords").val(); } }); $(document).keydown(function (event) { // 38 上 40下 13 回车
if ($("#newDiv")) {//当提示框存在时
if (event.keyCode == 40) {//down $("#keywords").unbind("propertychange");//移除propertychange事件 $("#keywords").unbind("input");//firefox 与上面类似 var html = ""; if(line==$("#newDiv table tbody tr").length){//如果line值为当前提示信息行数的值时,将用户最初输入的信息赋给搜索框 html = keywords; $("#newDiv table tbody tr").eq($("#newDiv table tbody tr").length-1).css("backgroundColor", "white").css("color", "black");//消除选中样式 }else{//当有提示信息行选中时 $("#newDiv table tbody tr").eq(line).css("backgroundColor", "#DFDFDF").css("color", "white");//改变样式 html = $("#newDiv table tbody tr").eq(line).find("td").eq(0).html();//获取有效提示信息 html = replace(html,"<B>",""); html = replace(html,"</B>",""); html = replace(html,"<b>","");//firefox html = replace(html,"</b>","");//firfox if( $("#newDiv table tbody tr").length != 1){//改变样式 $("#newDiv table tbody tr").eq(line < 0 ? 0 : line - 1).css("backgroundColor", "white").css("color", "black"); } } line = (line == $("#newDiv table tbody tr").length ? 0 : line + 1);//line值不为提示信息行数的值时line值加1,否则line归0 $("#keywords").val(html);//将结果赋给搜索框
} else { if (event.keyCode == 38) {//up $("#keywords").unbind("propertychange"); $("#keywords").unbind("input");//firefox var html = ""; line = (line == 0 ? $("#newDiv table tbody tr").length : line-1 ); if(line == 0){ html = keywords; $("#newDiv table tbody tr").eq(0).css("backgroundColor", "white").css("color", "black"); }else{
$("#newDiv table tbody tr").eq(line-1).css("backgroundColor", "#DFDFDF").css("color", "white"); $("#newDiv table tbody tr").eq(line > $("table tbody tr").length? 0 : line ).css("backgroundColor", "white").css("color", "black"); html = $("#newDiv table tbody tr").eq(line-1).find("td").eq(0).html(); html = replace(html,"<B>",""); html = replace(html,"</B>",""); html = replace(html,"<b>","");//firefox html = replace(html,"</b>","");//firfox }
$("#keywords").val(html); } else { if (event.keyCode == 13) {//enter if($("#newDiv table tbody tr")&& $("#newDiv table tbody tr").length>0){//有提示信息时 var html = ""; if(line==0){//当line=0时 if($("#newDiv table tbody tr").eq(0).css("backgroundColor")=="#DFDFDF"){//第一行被选中 html =$("#newDiv table tbody tr").eq(0).find("td").eq(0).html(); }else{//没有进行选择时 return; } }else{ html = $("#newDiv table tbody tr").eq(line - 1).find("td").eq(0).html(); } html = replace(html,"<B>",""); html = replace(html,"</B>",""); html = replace(html,"<b>","");//firefox html = replace(html,"</b>","");//firfox $("#keywords").unbind("propertychange");//移除propertychange事件 $("#keywords").unbind("input");//firefox 与上面的操作类似 $("#keywords").val(html); } del();//移除提示框 } } } } }); $("#keywords").bind("propertychange", mychange);//ie 将mychange绑定到propertychange事件上 $("#keywords").bind("input", mychange);//firefox 与上面类似 });
|
上面就是主要的代码了,其中就是在用户操作键盘的时候对mychang方法的绑定与移除,还有记录用户最初输入的数据信息这些地方要稍稍注意一下。
搜索框中的autocomplete="off"一定要加上,否则在某些浏览器中你的自动提示功能将不能实现的哦
可能上面的代码有一些不足之处,还请给位点评O(∩_∩)O~