我想大家在访问某些网站的时候都曾见到过基于Ajax的自动完成功能,比如http://www.google.com,www.56.com/.    

一、引出Ajax的自动完成
     现在要实现一个员工信息查询的功能,即根据输入的名字检索员工的详细信息。这是一个简单的数据表查询,在ASP.NET中实现这样的功能是比较简单的.                 
      从上面可以看出,这种员工信息查询功能还存在一些不足,比如用户可能记不全员工的名字,只记得前面几个字母是什么,这样用户只能根据记忆猜测,一遍遍地尝试。如果在用户输入的同时,输入框下方可以给出相应的提示,辅助用户输入,那么用户进行检索的速度和成功率就会大大提高.这就是基于Ajax的自动完成功能.
               

二、自动完成功能的实现
     实现这样的功能需要按以下的步骤进行。
·服务器端提供GetSearchItems方法给客户端,用来返回满足条件的员工列表。·客户端的输入框需要增加onkeydown响应函数,以便即时获取满足条件的员工列表。·通过客户端的JavaScript动态列出待选结果的列表,同时还要提供键盘和鼠标的响应。
三、服务器端实现
     本文采用AjaxPro.NET作为Ajax开发框架,首先为使用AjaxPro.NET做一些准备工作。 添加对AjaxPro.dll的引用,修改Web.config配置文件,在system.web节点下加入如下配置:

1<httpHandlers>2<!--Register the ajax handler-->3<addverb="POST,GET"path="ajaxpro/*.ashx"type="AjaxPro.AjaxHandlerFactory, AjaxPro"/>4</httpHandlers>

在页面后台代码(Default.aspx.cs)的Page_Load方法中增加下面的代码

1protectedvoidPage_Load(objectsender, EventArgs e)2{3        AjaxPro.Utility.RegisterTypeForAjax(typeof(_Default));4}

下面定义提供给客户端调用的方法GetSearchItems(),参数query为模糊查询的关键字值:

1[AjaxPro.AjaxMethod()]2publicArrayList GetSearchItems(stringquery)3{4    ArrayList items=newArrayList();5    StringBuilder queryString=newStringBuilder();6    queryString.Append("select employeeid,lastname,firstname,title,titleofcourtesy from dbo.Employees");7    queryString.Append("where firstname like '%"+query+"%'");89    DataSet ds=DataBase.Instance.ReturnDataSet(queryString.ToString());10for(inti=0; i<ds.Tables[0].Rows.Count; i++)11{12       items.Add(ds.Tables[0].Rows[i][2].ToString());13    }14returnitems;15}

GetSearchItems方法返回一个ArrayList对象,它将包含所有以用户输入字符串的员工名字。
四、客户端实现
相对于服务器端的方法而言,客户端的处理要复杂得多。首先来分析如何根据服务器端返回的ArrayList对象展示结果。这里用到了Web编程中“层”(div)的概念,通过JavaScriptDOM创建一个新的层div,将ArrayList中的每一个条目都作为其子节点加入到div中,而每一个条目也被看作是一个div,其中具体的文本内容则是一个span对象。除了显示待选的结果之外,下拉区域还要对键盘、鼠标事件做出响应;为了实时地显示待选结果,还需要定时更新待选结果的列表。这些功能都封装在lookup.js中。下面是lookeu.js的定义:

1//下拉区背景色2varDIV_BG_COLOR="#EEE";3//高亮显示条目颜色4varDIV_HIGHLIGHT_COLOR="#C30";5//字体6varDIV_FONT="Arial";7//下拉区内补丁大小8varDIV_PADDING="2px";9//下拉区边框样式10varDIV_BORDER="1px solid #CCC";111213//文本输入框14varqueryField;15//下拉区id16vardivName;17//IFrame名称18varifName;19//记录上次选择的值20varlastVal="";21//当前选择的值22varval="";23//显示结果的下拉区24varglobalDiv;25//下拉区是否设置格式的标记26vardivFormatted=false;2728/**//**29InitQueryCode函数必须在<body onload>事件的响应函数中调用,其中:30queryFieldName为文本框控件的id,31hiddenDivName为显示下拉区div的id32*/33functionInitQueryCode (queryFieldName, hiddenDivName)34{35//指定文本输入框的onblur和onkeydown响应函数36queryField=document.getElementById(queryFieldName);37    queryField.onblur=hideDiv;38    queryField.onkeydown=keypressHandler;3940//设置queryField的autocomplete属性为"off"41queryField.autocomplete="off";4243//如果没有指定hiddenDivName,取默认值"querydiv"44if(hiddenDivName)45{46        divName=hiddenDivName;47    }48else49{50        divName="querydiv";51    }5253//IFrame的name54ifName="queryiframe";5556//100ms后调用mainLoop函数57setTimeout("mainLoop()",100);58}5960/**//**61获取下拉区的div,如果没有则创建之62*/63functiongetDiv (divID)64{65if(!globalDiv)66{67//如果div在页面中不存在,创建一个新的div6869if(!document.getElementById(divID))70{71varnewNode=document.createElement("div");72            newNode.setAttribute("id", divID);73            document.body.appendChild(newNode);74        }7576//globalDiv设置为div的引用77globalDiv=document.getElementById(divID);7879//计算div左上角的位置80varx=queryField.offsetLeft;81vary=queryField.offsetTop+queryField.offsetHeight;82varparent=queryField;83while(parent.offsetParent)84{85            parent=parent.offsetParent;86            x+=parent.offsetLeft;87            y+=parent.offsetTop;88        }8990//如果没有对div设置格式,则为其设置相应的显示样式91if(!divFormatted)92{93            globalDiv.style.backgroundColor=DIV_BG_COLOR;94            globalDiv.style.fontFamily=DIV_FONT;95            globalDiv.style.padding=DIV_PADDING;96            globalDiv.style.border=DIV_BORDER;97            globalDiv.style.width="100px";98            globalDiv.style.fontSize="90%";99100            globalDiv.style.position="absolute";101            globalDiv.style.left=x+"px";102            globalDiv.style.top=y+"px";103            globalDiv.style.visibility="hidden";104            globalDiv.style.zIndex=10000;105106            divFormatted=true;107        }108    }109110returnglobalDiv;111}112113/**//**114根据返回的结果集显示下拉区115*/116functionshowQueryDiv(resultArray)117{118//获取div的引用119vardiv=getDiv(divName);120121//如果div中有内容,则删除之122while(div.childNodes.length>0)123        div.removeChild(div.childNodes[0]);124125//依次添加结果126for(vari=0; i<resultArray.length; i++)127{128//每一个结果也是一个div129varresult=document.createElement("div");130//设置结果div的显示样式131result.style.cursor="pointer";132        result.style.padding="2px 0px 2px 0px";133//设置为未选中134_unhighlightResult(result);135//设置鼠标移进、移出等事件响应函数136result.onmousedown=selectResult;137        result.onmouseover=highlightResult;138        result.onmouseout=unhighlightResult;139140//结果的文本是一个span141varresult1=document.createElement("span");142//设置文本span的显示样式143result1.className="result1";144        result1.style.textAlign="left";145        result1.style.fontWeight="bold";146        result1.innerHTML=resultArray[i];147148//将span添加为结果div的子节点149result.appendChild(result1);150151//将结果div添加为下拉区的子节点152div.appendChild(result);153    }154155//如果结果集不为空,则显示,否则不显示156showDiv(resultArray.length>0);157}158159/**//**160用户点击某个结果时,将文本框的内容替换为结果的文本,161并隐藏下拉区162*/163functionselectResult()164{165    _selectResult(this);166}167168//选择一个条目169function_selectResult(item)170{171varspans=item.getElementsByTagName("span");172if(spans)173{174for(vari=0; i<spans.length; i++)175{176if(spans[i].className=="result1")177{178                queryField.value=spans[i].innerHTML;179                lastVal=val=escape(queryField.value);180                mainLoop();181                queryField.focus();182                showDiv(false);183return;184            }185        }186    }187}188189/**//**190当鼠标移到某个条目之上时,高亮显示该条目191*/192functionhighlightResult()193{194    _highlightResult(this);195}196197function_highlightResult(item)198{199    item.style.backgroundColor=DIV_HIGHLIGHT_COLOR;200}201202/**//**203当鼠标移出某个条目时,正常显示该条目204*/205functionunhighlightResult()206{207    _unhighlightResult(this);208}209210function_unhighlightResult(item)211{212    item.style.backgroundColor=DIV_BG_COLOR;213}214215/**//**216显示/不显示下拉区217*/218functionshowDiv (show)219{220vardiv=getDiv(divName);221if(show)222{223        div.style.visibility="visible";224    }225else226{227        div.style.visibility="hidden";228    }229//adjustiFrame();230}231232/**//**233隐藏下拉区234*/235functionhideDiv ()236{237    showDiv(false);238}239240/**//**241调整IFrame的位置,这是为了解决div可能会显示在输入框后面的问题242*/243functionadjustiFrame()244{245//如果没有IFrame,则创建之246if(!document.getElementById(ifName))247{248varnewNode=document.createElement("iFrame");249        newNode.setAttribute("id", ifName);250        newNode.setAttribute("src","javascript:false;");251        newNode.setAttribute("scrolling","no");252        newNode.setAttribute("frameborder","0");253        document.body.appendChild(newNode);254    }255256    iFrameDiv=document.getElementById(ifName);257vardiv=getDiv(divName);258259//调整IFrame的位置与div重合,并在div的下一层260try261{262        iFrameDiv.style.position="absolute";263        iFrameDiv.style.width=div.offsetWidth;264        iFrameDiv.style.height=div.offsetHeight;265        iFrameDiv.style.top=div.style.top;266        iFrameDiv.style.left=div.style.left;267        iFrameDiv.style.zIndex=div.style.zIndex-1;268        iFrameDiv.style.visibility=div.style.visibility;269    }270catch(e)271{272    }273}274275/**//**276文本输入框的onkeydown响应函数277*/278functionkeypressHandler (evt)279{280//获取对下拉区的引用281vardiv=getDiv(divName);282283//如果下拉区不显示,则什么也不做284if(div.style.visibility=="hidden")285{286returntrue;287    }288289//确保evt是一个有效的事件290if(!evt&&window.event)291{292        evt=window.event;293    }294varkey=evt.keyCode;295296varKEYUP=38;297varKEYDOWN=40;298varKEYENTER=13;299varKEYTAB=9;300301//只处理上下键、回车键和Tab键的响应302if((key!=KEYUP)&&(key!=KEYDOWN)&&(key!=KEYENTER)&&(key!=KEYTAB))303{304returntrue;305    }306307varselNum=getSelectedSpanNum(div);308varselSpan=setSelectedSpan(div, selNum);309310//如果键入回车和Tab,则选择当前选择条目311if((key==KEYENTER)||(key==KEYTAB))312{313if(selSpan)314{315            _selectResult(selSpan);316        }317        evt.cancelBubble=true;318returnfalse;319    }320else//如果键入上下键,则上下移动选中条目321{322if(key==KEYUP)323{324            selSpan=setSelectedSpan(div, selNum-1);325        }326if(key==KEYDOWN)327{328            selSpan=setSelectedSpan(div, selNum+1);329        }330if(selSpan)331{332            _highlightResult(selSpan);333        }334    }335336//显示下拉区337showDiv(true);338returntrue;339}340341/**//**342获取当前选中的条目的序号343*/344functiongetSelectedSpanNum(div)345{346varcount=-1;347varspans=div.getElementsByTagName("div");348if(spans)349{350for(vari=0; i<spans.length; i++)351{352            count++;353if(spans[i].style.backgroundColor!=div.style.backgroundColor)354{355returncount;356            }357        }358    }359360return-1;361}362363/**//**364选择指定序号的结果条目365*/366functionsetSelectedSpan(div, spanNum)367{368varcount=-1;369varthisSpan;370varspans=div.getElementsByTagName("div");371if(spans)372{373for(vari=0; i<spans.length; i++)374{375if(++count==spanNum)376{377                _highlightResult(spans[i]);378                thisSpan=spans[i];379            }380else381{382                _unhighlightResult(spans[i]);383            }384        }385    }386387returnthisSpan;388}389

InitQueryCode函数必须在页面的onload响应中执行,该函数最后调用setTimeout方法执行了mainLoop方法。注意,mainLoop方法并没有在lookup.js中定义,必须在包含lookup.js文件的页面文件中增加该函数的定义。于此,我们就需要在Default.aspx页面上加入如下定义:

1<script language="javascript"src="lookup.js"></script>2<script language="javascript">3mainLoop=function()4{5    val=escape(queryField.value);6if(lastVal!=val)7{8varresponse=_Default.GetSearchItems(val);9                    showQueryDiv(response.value);10lastVal=val;11    }12        setTimeout('mainLoop()',100);13returntrue;14    }15</script>

由上述代码可以看到mainLoop函数每隔100ms会执行一次,它会判断当前文本输入框的值和上次提交查询的值是否相同,如果不同,它会重新向服务器发送请求进行查询,并且更新下拉区域的显示。    于此,一个基于 Ajax的自动完成功能就实现了。

本文借鉴于《ajax web2.0快速入门与项目实践》。
这本书上还使用了控件将该功能进行了封装,这样要实现Ajax的自动完成功能就更加方便了。在此就不做过多解说。

本文示例代码下载:AutoComplete.rar

---------------------------------------------------------------------------------------------------------

转载于:https://www.cnblogs.com/beniao/archive/2008/05/03/1171515.html

基于AJAX的自动完成相关推荐

  1. php yii2自动给值,Yii2基于Ajax自动获取表单数据的方法

    本文实例讲述了Yii2基于Ajax自动获取表单数据的方法.分享给大家供大家参考,具体如下: 这里有两张表,表结构如下,locations表存放的省份和邮编等信息,两张表的model和curd均使用gi ...

  2. php考试倒计时提交系统,AJAX_基于Ajax技术实现考试倒计时并自动提交试卷,1.概述在开发网络考试系统 - phpStudy...

    基于Ajax技术实现考试倒计时并自动提交试卷 1.概述 在开发网络考试系统时,考试计时并自动提交试卷是必不可少的功能.由于在答卷过程中,试卷不能刷新,所以需要使用Ajax实现无刷新操作.运行本实例,访 ...

  3. ajax获取表单php,Yii2基于Ajax自动获取表单数据的方法

    本文实例讲述了Yii2基于Ajax自动获取表单数据的方法.分享给大家供大家参考,具体如下: 这里有两张表,表结构如下,locations表存放的省份和邮编等信息,两张表的model和curd均使用gi ...

  4. php ajax 考试倒计时,基于Ajax技术实现考试倒计时并自动提交试卷

    1.概述 在开发网络考试系统时,考试计时并自动提交试卷是必不可少的功能.由于在答卷过程中,试卷不能刷新,所以需要使用Ajax实现无刷新操作.运行本实例,访问准备考试页面index.jsp,在该页面中, ...

  5. think php ajax分页,thinkPHP5框架实现基于ajax的分页功能示例

    本文实例讲述了thinkPHP5框架实现基于ajax的分页功能.分享给大家供大家参考,具体如下: 最近一个页面的选项卡又牵扯到ajax分页,所以研究了一下tp5的ajax分页使用方法 首先看一下tp5 ...

  6. 移动端ajax,jQuery基于$.ajax设置移动端click超时处理方法

    本文实例讲述了jQuery基于$.ajax设置移动端click超时处理方法.分享给大家供大家参考,具体如下: 这里介绍jquery click事件如何在移动端自动转换成touchstart事件. 因为 ...

  7. (转)基于Ajax的应用程序架构汇总

    浏览器端框架被划分成两大类: ·应用程序框架:提供浏览器的功能,但是常以包括窗口小部件抽象和另外的部件而出名,其功能主要围绕桌面GUI框架. ·基本结构框架:提供基本的管道和可移植的浏览器抽象,让开发 ...

  8. 基于ajax毕业设计题目50例

    基于ajax毕业设计题目1-10题 1.基于AJAX的Web应用构件组装技术及工具 2.基于AJAX技术对Web考试系统性能改进研究与实现 3.基于AJAX技术协作知识建构学习平台的研究与设计 4.基 ...

  9. ajax无刷新聊天室,实现一个无刷新的基于ajax的简易聊天室

    实现一个基于ajax的简易聊天室 1 程序主页面 在线交流对话 include_once("server1.server.php"); #servidor para XAJAX $ ...

最新文章

  1. 进阶学习(3.6) Prototype Pattern 原型模式
  2. 区块链BaaS云服务(20)百度超级链BaaS
  3. 还在到处集五福?支付宝其实埋了一个鲜为人知的集福利器!
  4. 计算机操作系统——页面置换算法
  5. Angular Component的DOM级别的单元测试方法
  6. 前端学习(1882)vue之电商管理系统电商系统之设置字体颜色并添加标签
  7. OpenShift 4 - Knative教程(2) 基于Revision/Tag/Traffic实现蓝绿部署和恢复发布
  8. 今天在webcasts上看sql server 2008的新功能介绍,无意中发现在连接sql server 数据库时,还有一个...
  9. 获取多个复选框的value
  10. 系统学习机器学习之特征工程(二)--离散型特征编码方式:LabelEncoder、one-hot与哑变量*
  11. 计算机多媒体制作三级证书,多媒体作品制作员(师)国家职业标准
  12. gitlab-runner配置与注册
  13. ckplayer x2去logo,改右键
  14. 单克隆抗体WuT9/甘草次酸-氟尿嘧啶偶联顺铂/RGD肽修饰聚谷氨酸-顺铂复合物的制备
  15. 利用javadoc制作API文档
  16. 【论文阅读】DeepGauge: multi-granularity testing criteria for deep learning systems.
  17. matlab 点云根据法向量投影到六个平面
  18. 单体测试使用Assert.assertThat(expected,Matcher matcher)来对比结果和预期
  19. pptv首页导航效果
  20. [C#]JCoder.Mock4Net,可用于模拟数据的c#类库

热门文章

  1. android onserviceconnected_2019最新Android面试题
  2. 向左向右向后转python_Turbot与python教程-实现左向旋转
  3. android LinearLayout和RelativeLayout实现精确布局
  4. JS的基本语法知识概括(ECMA、DOM、BOM)
  5. ES6-symbol-使用symbol
  6. wangEditor3菜单修改之如何添加分割线
  7. 二维数组(解引用、指针数组、数组的指针)——C语言
  8. 复制K2流程图实现记录
  9. App for Android (1) —— 环境搭建
  10. 解决VS2005“无法启动调试,绑定句柄失效”