作为web开发的一员,应该都不陌生,信息处理时,很多时候需要根据用户的输入实时反馈查询结果供其选择,这给了用户很好的人机交互体验,在各大门户网站上已经被使用的很成熟了,最近项目中用到此功能,网上有很多插件和样例,但用起来发现都多多少少与项目的需求有所出入,故自己写了一个,分享一下,希望能给你带来帮助,插件效果图如下:

原理

这个插件主要用来方便用户在信息查询和处理时快捷、简单,其原理分析下:

1. 信息处理需要前台和后台,前台有一个或者多个查询输入框(目前暂定为input标签)。

2. 用户在这些输入框中输入查询关键字时,系统根据用户实时的输入给页面后台发送数据查询请求。

3. 后台程序查询数据并排序,将最符合用户查询的记录(暂定为前10条)回传给前台插件。

4. 插件内部根据这些查询结果友好的展现出来给用户,用户选择展现出来的结果中某一条,该条记录关键字会自动补齐用户的输入。

功能

为了完成上述过程,这个插件需要帮用户做到以下一系列功能:

1. 能够根据标签id绑定一个或者多个输入标签,各标签的查询自定完成过程相互独立,互不影响。

2. 用户没有输入或者输入为空格等特殊字符时,不进行查询,以减少服务器的负担。

3. 根据用户的输入,实时展现查询结果,每次展现最符合的前10条记录,用菜单的方式,每条记录一行,结果列表浮动与输入标签的下方,宽度和标签宽度一致。

4. 浮动的查询结果可以用鼠标选择,也可以用键盘中的上下移动键进行选择,选择完毕后该条记录中的关键字将自动补齐输入框内容;鼠标移动上去后选中项的颜色要发生变化,上下键选择时可以循环列表,并保留用户输入的值。

5. 光标移入输入框时进行查询,查询结果浮动层和输入标签失去焦点时浮动层影藏。

实现

首先插件根据需要可以绑定一个或者多个页面输入标签,插件只需获取标签的id即可,绑定多个输入标签时重复该过程,并需要对标签进行编号,以便插件动态生成浮动结果列表时标记id。其次根据开发时不同的需求,插件中实时的结果查询支持两种方式:一种是通过请求中间页面获取,二是通过ajax获取。两种方式的实现要求插件暴露出来的接口将不一样:

1)通过请求中间页面获取:插件需要一个请求中间页的地址(URL),是否对鼠标选择添加处理事件的标记(true&false),是否对按键选择添加处理事件的标记(true&false),如果需要前两个标记有一个为true,则插件还需要一个处理事件的方法入口(ReturnAutoComplete)。

2)通过ajax获取:插件需要一个获取查询结果的ajax方法入口(CallAjaxFuntion),是否对鼠标选择添加处理事件的标记(true&false),是否对按键选择添加处理事件的标记(true&false),如果需要前两个标记有一个为true,则插件还需要一个处理事件的方法入口(ReturnAutoComplete)。

接下来,根据实现原理编写插件:

一、绑定标签

插件根据id绑定前台页面输入标签,一个或者多个,代码如下:

 /*
* 自动完成功能主函数(闭包)
*
* id:自动完成功能需要绑定的控件
*
* 版本:1.0
*/
function autoComplete(id) {
/****预留退路处理部分**begin**/
if (!document.getElementById) return false;
if (!document.createElement) return false;
if (!document.getElementsByTagName) return false;
/****预留退路处理部分**end**/ var me = this; //获取当前对象 /****变量初始化部分**begin**/
me.AutoCompleteControlID; //自动完成绑定控件客户端ID
me.handle = null; //自动完成绑定控件的对象
me.DivResult; //查询结果弹出层对象
me.currentIndex = -1; //当前选中的结果索引
me.LastIndex = -1; //上一条选中的结果索引
me.requestObj; //向服务器发送请求的对象
me.TableIndex = 0; //标记搜索结果的table的id,避免在同一个页面上出现两个相同id的table
me.OrgValue = ""; //记录用户当前输入的值
me.KeyType = true; //标记是上移(true)还是下移(false)
me.FocusInDiv = false; //标记当前焦点是否是搜索结果div
me.AllowEnterKeyFlag = false; //标记是否允许回车键接收事件
me.AllowClickFlag = false; //标记是否允许鼠标点击选择事件
me.AllowAutoComplete = true; //标记是否还需要继续实现自动完成功能(在用户传递参数有误的情况下使用,避免报错)
me.Requesttype = 1; //调用方式,使用请求页(1)\ajax函数(2)
me.RequestPageUrl = null; //请求页调用时的页面地址(包括参数)
me.ajaxCallBackFun = null; //ajax函数调用时的回调函数
me.AllowCallBackFun = null; //用户传递过来的接收回车或者鼠标点击事件的回调函数
//判断绑定控件的ID并赋值
if (id != null && typeof (id) != undefined) {
me.AutoCompleteControlID = id;
me.handle = document.getElementById(me.AutoCompleteControlID);
} if (me.DivResult == null || typeof (me.DivResult) == "undefined") {
me.DivResult = document.createElement("div");
var parent = document.getElementById(me.AutoCompleteControlID).parentElement;
if (typeof (parent) != "undefined") {
parent.appendChild(me.DivResult);
}
}
/****变量初始化部分**end**/ }

二、初始化插件

选择插件的数据查询方式及各方式所需的参数,代码如下:

 /*
* 初始化函数,负责初始化部分可选成员变量
* requestType:调用方式(1为请求页,2为ajax函数)
* pageUrl:如果是请求页的方式调用,则此参数必不能为空,若为ajax函数调用,则此参数为null
* ajaxCallBackFun:如果是ajax函数的方式调用,则此参数必不能为空,若为请求页方式调用,则此参数为null
* enterKeyFlag:标记是否允许回车事件
* mouseClickFlag:标记是否允许鼠标选择事件
* callBackFun:回调函数,与前两个参数配合使用,如果前两个参数有一个设置为true,则此处必须实现回调函数,否则为null
* tabIndex:绑定控件的编号,标记搜索结果table的id,以避免同页面的两个绑定控件的搜索结果id相同
*/
this.Init = function(requestType, pageUrl, ajaxCallBackFun, enterKeyFlag, mouseClickFlag, callBackFun, tabIndex) {
//初始化变量
me.Requesttype = requestType;
me.RequestPageUrl = pageUrl;
me.ajaxCallBackFun = ajaxCallBackFun;
me.AllowEnterKeyFlag = enterKeyFlag;
me.AllowClickFlag = mouseClickFlag;
me.TableIndex = tabIndex;
//判断请求方式
if (me.Requesttype == 1) {
me.ajaxCallBackFun = null;
if (me.RequestPageUrl == null) {
alert("传递的参数有误,请求页的地址不能为null!");
me.AllowAutoComplete = false;
}
}
else if (me.Requesttype == 2) {
me.RequestPageUrl = null;
if (me.ajaxCallBackFun == null) {
alert("传递的参数有误,ajax回调函数不能为null!");
me.AllowAutoComplete = false;
}
}
//判断标志位
if (!me.AllowEnterKeyFlag && !me.AllowClickFlag) {
callBackFun = null;
}
else {
if (callBackFun == null) {
alert("传递的参数有误,回调函数不能为null!");
me.AllowAutoComplete = false;
}
else {
me.AllowCallBackFun = callBackFun;
}
}
}

三、数据查询处理

根据初始化好的数据查询方式给后台发送数据查询请求,后台查询到数据后回馈给插件,这个过程的触发点是用户在输入标签中输入了查询关键字,实现该标签的键盘提起事件,代码如下:

 //绑定控件的键盘弹起事件
document.getElementById(me.AutoCompleteControlID).onkeyup = function(evt) {
if (me.AllowAutoComplete) {
try {
evt = evt || window.event;
if (evt.keyCode != 40 && evt.keyCode != 38 && evt.keyCode != 39 && evt.keyCode != 37) {
me.OrgValue = me.handle.value;
}
else {//向下\向上
if (evt.keyCode == 38) me.KeyType = true;
else if (evt.keyCode == 40) me.KeyType = false;
}
me.Auto();
} catch (e) { }
}
}

通过实现Auto事件实现数据查询,代码如下:

 this.Auto = function() {
var evt = evt || window.event;
//如果按下 向上, 向下 或 回车
if (evt.keyCode == 38 || evt.keyCode == 40 || evt.keyCode == 13) {
me.SelectItem();
}
//左右移动键
else if (evt.keyCode == 39 || evt.keyCode == 37) {
return;
}
else {
//恢复下拉选择项为 -1
currentIndex = -1;
//设置结果弹出层的样式
me.DivResult.style.position = "absolute";
me.DivResult.style.top = me.handle.getBoundingClientRect().top + 19;
me.DivResult.style.left = me.handle.getBoundingClientRect().left - 2;
me.DivResult.style.width = me.handle.offsetWidth;
me.DivResult.style.height = 20;
me.DivResult.style.backgroundColor = "#ffffff"; if (me.Requesttype == 1) {//页面请求 if (window.XMLHttpRequest) {
me.requestObj = new XMLHttpRequest();
if (me.requestObj.overrideMimeType)
me.requestObj.overrideMimeType("text/xml");
}
else if (window.ActiveXObject) {
try {
me.requestObj = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
me.requestObj = new ActiveXObject("Microsoft.XMLHTTP");
}
}
if (me.requestObj == null)
return;
me.requestObj.onreadystatechange = me.ShowResult;
var strUrl = me.RequestPageUrl + "?InputValue=" + escape(me.handle.value) + "&TableIndex=" + me.TableIndex;
me.requestObj.open("GET", strUrl, true);
me.requestObj.send();
}
else {//ajax函数请求
try {
me.ajaxCallBackFun(me.handle.value, me.TableIndex, me.AjaxCallBack);
} catch (e) { }
}
}
}

Auto函数实现了数据查询这一过程,根据查询方式的不同,数据请求的方法也不同:

 1.如果是页面请求:插件根据初始化时提供的页面url内部进行ajax访问,并将响应的结果用方法me.ShowResult处理,该方法实现如下:

 //搜索结果处理函数(页面请求调用时)
this.ShowResult = function() {
if (me.requestObj.readyState == 4) {
if (me.requestObj.status == 200)//ok
{
me.DivResult.innerHTML = me.AlynasisContent(me.requestObj.responseText);
//判断是否有搜索结果
var result = me.DivResult.getElementsByTagName("td");
if (result.length > 0) {
me.DivResult.style.height = result.length * 15;
me.DivResult.style.display = "";
//给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
for (var i = 0; i < result.length; i++) {
var bb = new BiBaoOnMouseResult(i, me);
result[i].onmouseover = bb.OnMouseOverEx;
result[i].onmouseout = bb.OnMouseOutEx;
result[i].onclick = bb.OnMouseClickEx;
}
}
else {
me.DivResult.style.display = "none";
return;
}
me.requestObj = null; //销毁对象
}
else if (me.requestObj.status == 404) {
//alert("请求的页面未找到!");
me.DivResult.style.display = "none";
me.requestObj = null; //销毁对象
return;
}
}
}

2.ajax函数请求:插件直接调用初始化时提供的外部ajax函数,并将结果处理函数me.AjaxCallBack作为最后一个参数传递到该ajax函数中,以便在数据查询完成时调用,该方法实现如下:

 //搜索结果处理函数(ajax函数请求方式)
this.AjaxCallBack = function(response) {
if (response.error != null) {
return;
}
me.DivResult.innerHTML = me.AlynasisContent(response.value);
//判断是否有搜索结果
var result = me.DivResult.getElementsByTagName("td");
if (result.length > 0) {
me.DivResult.style.height = result.length * 15;
me.DivResult.style.display = "";
//给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
for (var i = 0; i < result.length; i++) {
var bb = new BiBaoOnMouseResult(i, me);
result[i].onmouseover = bb.OnMouseOverEx;
result[i].onmouseout = bb.OnMouseOutEx;
result[i].onclick = bb.OnMouseClickEx;
}
}
else {
me.DivResult.style.display = "none";
return;
}
}

四、查询结果展现

上述两种数据查询代码中,都通过方法me.AlynasisContent来对查询结果进行解析,该函数用表格的方式展现该查询结果,每条一行,代码如下:

 //解析搜索返回的结果
this.AlynasisContent = function(strObj) {
if (strObj == null || strObj == "") {
return "";
} var itemList = strObj.split("@|@");
var strResult = "<table cellSpacing='0' cellPadding='0' align='center' border='0' id='Tmp_AutoComplete_tblResult_" + me.TableIndex + "' style='padding-left:5;padding-right:5; background-color:#FFFFFF;border:1px solid #999999;text-align:left;width:100%;'>";
for (var i = 0; i < itemList.length; i++) {
strResult += "<tr ReturnValue=" + itemList[i] + "><td height='15' nowrap><div style='width:" + (me.handle.offsetWidth - 12) + ";overflow:hidden;text-overflow:ellipsis;white-space:nowrap;'>" + itemList[i] + "<div></td></tr>";
}
strResult += "</table>";
return strResult;
}

至此,插件的流程全部完成,但还有很多细节功能,比如鼠标选择、键盘上下键选择、给查询结果中每条记录添加鼠标和键盘事件并响应等,全部代码将在后面给出,下面以.net开发为例来演示此插件的调用方法:

【用法1】请求aspx页面(“AutoComplete.aspx”),必须要实现页面,如果选择了接收回车键和鼠标选择事件,则必须要实现ReturnAutoComplete()函数。

 var auto1 = new autoComplete("txt");
auto1.Init(1, "AutoComplete.aspx", null, true, false, ReturnAutoComplete, 1);

【用法2】ajax方法请求,必须要实现CallAjaxFuntion函数,如果选择了接收回车键和鼠标选择事件,则必须要实现ReturnAutoComplete()函数,下面ajax请求是通过ajaxpro来实现的,当然,可以根据需要可以使用其他ajax方式调用。

 var auto2 = new autoComplete("text");
auto2.Init(2, null, CallAjaxFuntion, false, true, ReturnAutoComplete, 1);
function CallAjaxFuntion(strTxtValue, resultTableIndex, ajaxCallBack) {
_Default.GetDataSource(strTxtValue, resultTableIndex, ajaxCallBack);
}

ReturnAutoComplete方法实现如下:

 //接收回车或鼠标点击事件(returnValue:为选中的textbox的值)
function ReturnAutoComplete(returnValue) {
alert(returnValue);
//do something else
}

最后,插件源码如下(下载文件请点击Download):

 /*
* 自动完成功能主函数(闭包)
*
* id:自动完成功能需要绑定的控件
*
* 版本:1.0
*/
function autoComplete(id) {
/****预留退路处理部分**begin**/
if (!document.getElementById) return false;
if (!document.createElement) return false;
if (!document.getElementsByTagName) return false;
/****预留退路处理部分**end**/ var me = this; //获取当前对象 /****变量初始化部分**begin**/
me.AutoCompleteControlID; //自动完成绑定控件客户端ID
me.handle = null; //自动完成绑定控件的对象
me.DivResult; //查询结果弹出层对象
me.currentIndex = -1; //当前选中的结果索引
me.LastIndex = -1; //上一条选中的结果索引
me.requestObj; //向服务器发送请求的对象
me.TableIndex = 0; //标记搜索结果的table的id,避免在同一个页面上出现两个相同id的table
me.OrgValue = ""; //记录用户当前输入的值
me.KeyType = true; //标记是上移(true)还是下移(false)
me.FocusInDiv = false; //标记当前焦点是否是搜索结果div
me.AllowEnterKeyFlag = false; //标记是否允许回车键接收事件
me.AllowClickFlag = false; //标记是否允许鼠标点击选择事件
me.AllowAutoComplete = true; //标记是否还需要继续实现自动完成功能(在用户传递参数有误的情况下使用,避免报错)
me.Requesttype = 1; //调用方式,使用请求页(1)\ajax函数(2)
me.RequestPageUrl = null; //请求页调用时的页面地址(包括参数)
me.ajaxCallBackFun = null; //ajax函数调用时的回调函数
me.AllowCallBackFun = null; //用户传递过来的接收回车或者鼠标点击事件的回调函数
//判断绑定控件的ID并赋值
if (id != null && typeof (id) != undefined) {
me.AutoCompleteControlID = id;
me.handle = document.getElementById(me.AutoCompleteControlID);
} if (me.DivResult == null || typeof (me.DivResult) == "undefined") {
me.DivResult = document.createElement("div");
var parent = document.getElementById(me.AutoCompleteControlID).parentElement;
if (typeof (parent) != "undefined") {
parent.appendChild(me.DivResult);
}
}
/****变量初始化部分**end**/ /*
* 初始化函数,负责初始化部分可选成员变量
* requestType:调用方式(1为请求页,2为ajax函数)
* pageUrl:如果是请求页的方式调用,则此参数必不能为空,若为ajax函数调用,则此参数为null
* ajaxCallBackFun:如果是ajax函数的方式调用,则此参数必不能为空,若为请求页方式调用,则此参数为null
* enterKeyFlag:标记是否允许回车事件
* mouseClickFlag:标记是否允许鼠标选择事件
* callBackFun:回调函数,与前两个参数配合使用,如果前两个参数有一个设置为true,则此处必须实现回调函数,否则为null
* tabIndex:绑定控件的编号,标记搜索结果table的id,以避免同页面的两个绑定控件的搜索结果id相同
*/
this.Init = function(requestType, pageUrl, ajaxCallBackFun, enterKeyFlag, mouseClickFlag, callBackFun, tabIndex) {
//初始化变量
me.Requesttype = requestType;
me.RequestPageUrl = pageUrl;
me.ajaxCallBackFun = ajaxCallBackFun;
me.AllowEnterKeyFlag = enterKeyFlag;
me.AllowClickFlag = mouseClickFlag;
me.TableIndex = tabIndex;
//判断请求方式
if (me.Requesttype == 1) {
me.ajaxCallBackFun = null;
if (me.RequestPageUrl == null) {
alert("传递的参数有误,请求页的地址不能为null!");
me.AllowAutoComplete = false;
}
}
else if (me.Requesttype == 2) {
me.RequestPageUrl = null;
if (me.ajaxCallBackFun == null) {
alert("传递的参数有误,ajax回调函数不能为null!");
me.AllowAutoComplete = false;
}
}
//判断标志位
if (!me.AllowEnterKeyFlag && !me.AllowClickFlag) {
callBackFun = null;
}
else {
if (callBackFun == null) {
alert("传递的参数有误,回调函数不能为null!");
me.AllowAutoComplete = false;
}
else {
me.AllowCallBackFun = callBackFun;
}
}
} this.Auto = function() {
var evt = evt || window.event;
//如果按下 向上, 向下 或 回车
if (evt.keyCode == 38 || evt.keyCode == 40 || evt.keyCode == 13) {
me.SelectItem();
}
//左右移动键
else if (evt.keyCode == 39 || evt.keyCode == 37) {
return;
}
else {
//恢复下拉选择项为 -1
currentIndex = -1;
//设置结果弹出层的样式
me.DivResult.style.position = "absolute";
me.DivResult.style.top = me.handle.getBoundingClientRect().top + 19;
me.DivResult.style.left = me.handle.getBoundingClientRect().left - 2;
me.DivResult.style.width = me.handle.offsetWidth;
me.DivResult.style.height = 20;
me.DivResult.style.backgroundColor = "#ffffff"; if (me.Requesttype == 1) {//页面请求 if (window.XMLHttpRequest) {
me.requestObj = new XMLHttpRequest();
if (me.requestObj.overrideMimeType)
me.requestObj.overrideMimeType("text/xml");
}
else if (window.ActiveXObject) {
try {
me.requestObj = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
me.requestObj = new ActiveXObject("Microsoft.XMLHTTP");
}
}
if (me.requestObj == null)
return;
me.requestObj.onreadystatechange = me.ShowResult;
var strUrl = me.RequestPageUrl + "?InputValue=" + escape(me.handle.value) + "&TableIndex=" + me.TableIndex;
me.requestObj.open("GET", strUrl, true);
me.requestObj.send();
}
else {//ajax函数请求
try {
me.ajaxCallBackFun(me.handle.value, me.TableIndex, me.AjaxCallBack);
} catch (e) { }
}
}
}
//搜索结果处理函数(ajax函数请求方式)
this.AjaxCallBack = function(response) {
if (response.error != null) {
return;
}
me.DivResult.innerHTML = me.AlynasisContent(response.value);
//判断是否有搜索结果
var result = me.DivResult.getElementsByTagName("td");
if (result.length > 0) {
me.DivResult.style.height = result.length * 15;
me.DivResult.style.display = "";
//给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
for (var i = 0; i < result.length; i++) {
var bb = new BiBaoOnMouseResult(i, me);
result[i].onmouseover = bb.OnMouseOverEx;
result[i].onmouseout = bb.OnMouseOutEx;
result[i].onclick = bb.OnMouseClickEx;
}
}
else {
me.DivResult.style.display = "none";
return;
}
}
//搜索结果处理函数(页面请求调用时)
this.ShowResult = function() {
if (me.requestObj.readyState == 4) {
if (me.requestObj.status == 200)//ok
{
me.DivResult.innerHTML = me.AlynasisContent(me.requestObj.responseText);
//判断是否有搜索结果
var result = me.DivResult.getElementsByTagName("td");
if (result.length > 0) {
me.DivResult.style.height = result.length * 15;
me.DivResult.style.display = "";
//给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
for (var i = 0; i < result.length; i++) {
var bb = new BiBaoOnMouseResult(i, me);
result[i].onmouseover = bb.OnMouseOverEx;
result[i].onmouseout = bb.OnMouseOutEx;
result[i].onclick = bb.OnMouseClickEx;
}
}
else {
me.DivResult.style.display = "none";
return;
}
me.requestObj = null; //销毁对象
}
else if (me.requestObj.status == 404) {
//alert("请求的页面未找到!");
me.DivResult.style.display = "none";
me.requestObj = null; //销毁对象
return;
}
}
}
//解析搜索返回的结果
this.AlynasisContent = function(strObj) {
if (strObj == null || strObj == "") {
return "";
} var itemList = strObj.split("@|@");
var strResult = "<table cellSpacing='0' cellPadding='0' align='center' border='0' id='Tmp_AutoComplete_tblResult_" + me.TableIndex + "' style='padding-left:5;padding-right:5; background-color:#FFFFFF;border:1px solid #999999;text-align:left;width:100%;'>";
for (var i = 0; i < itemList.length; i++) {
strResult += "<tr ReturnValue=" + itemList[i] + "><td height='15' nowrap><div style='width:" + (me.handle.offsetWidth - 12) + ";overflow:hidden;text-overflow:ellipsis;white-space:nowrap;'>" + itemList[i] + "<div></td></tr>";
}
strResult += "</table>";
return strResult;
}
//移动上下键选择搜索结果选项事件
this.SelectItem = function() {
//结果
var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
if (!result)
return;
if (result.rows[me.LastIndex] != null) {
result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF";
result.rows[me.LastIndex].style.color = "#000000";
}
var maxRow = result.rows.length;
//向上
if (event.keyCode == 38 && me.currentIndex >= 0) {
me.currentIndex--;
if (me.currentIndex == -1) {
me.handle.value = me.OrgValue;
}
else {
me.handle.value = result.rows[me.currentIndex].ReturnValue;
}
}
//向下
if (event.keyCode == 40 && me.currentIndex < maxRow) {
me.currentIndex++;
me.handle.value = result.rows[me.currentIndex].ReturnValue;
}
//回车
if (event.keyCode == 13) {
me.Select();
me.InitItem();
return false;
}
if (result.rows[me.currentIndex] != undefined) {
//选中颜色
result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE";
result.rows[me.currentIndex].style.color = "#FFFFFF";
}
me.LastIndex = me.currentIndex; if (!me.KeyType) { if ((me.currentIndex + 1) >= maxRow) {//如果达到最大值,则循环(向下)
me.currentIndex++;
if (me.currentIndex == (maxRow + 1)) me.currentIndex = -1;
if (me.currentIndex == -1) {
me.handle.value = me.OrgValue;
}
}
}
else {
if (me.currentIndex == -1) me.currentIndex = maxRow; //如果达到最小值,则循环(向上)
}
} //回车选择事件
this.Select = function() {
var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
if (!result || result.rows.length <= 0)
return;
//取出选中的值
var ReturnValue = "";
if (me.currentIndex < 0)//直接取输入框中的值
ReturnValue = me.handle.value;
else //取用户选中的值
ReturnValue = result.rows[me.currentIndex].ReturnValue;
//自动完成功能出口,向主程序发送值信息
if (ReturnValue != undefined) {
me.DivResult.style.display = "none";
//自动完成处理事件--由用户自己完成实现
if (me.AllowEnterKeyFlag)
me.AllowCallBackFun(ReturnValue);
}
} this.Hide = function() {
me.DivResult.style.display = "none";
me.currentIndex = -1;
}
this.InitItem = function() {
me.DivResult.style.display = "none";
me.DivResult.innerHTML = "";
me.currentIndex = -1;
}
//搜索结果的鼠标事件
this.OnTdMouseOver = function(i) {
if (me.AllowAutoComplete) {
me.currentIndex = i;
var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
result.rows[me.currentIndex].style.cursor = "point";
if (!result || result.rows.length <= 0)
return;
//取消之前选中项的颜色
if (result.rows[me.LastIndex] != null) {
result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF";
result.rows[me.LastIndex].style.color = "#000000";
}
//改变选中项的颜色
if (result.rows[me.currentIndex] != undefined) {
result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE";
result.rows[me.currentIndex].style.color = "#FFFFFF";
}
me.LastIndex = me.currentIndex;
}
}
this.OnTdMouseOut = function(i) {
if (me.AllowAutoComplete) {
var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
if (!result || result.rows.length <= 0)
return;
if (result.rows[me.currentIndex] != undefined) {
result.rows[me.currentIndex].style.backgroundColor = "#FFFFFF";
result.rows[me.currentIndex].style.color = "#000000";
}
}
}
this.OnTdMouseClick = function(i) {
if (me.AllowAutoComplete) {
var evt = fixEvent(window.event);
var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
if (!result || result.rows.length <= 0)
return;
//给输入框赋值
var ReturnValue = result.rows[me.currentIndex].ReturnValue;
me.handle.value = ReturnValue;
//隐藏搜索结果
me.Hide();
//自动完成处理事件--由用户自己完成实现
if (me.AllowClickFlag)
me.AllowCallBackFun(ReturnValue);
}
}
//弹出层的鼠标移入/出事件
me.DivResult.onmouseout = function() {
if (me.AllowAutoComplete) {
me.currentIndex = -1;
me.FocusInDiv = false;
}
}
me.DivResult.onmouseover = function() {
if (me.AllowAutoComplete) {
me.FocusInDiv = true;
}
}
//绑定控件的点击事件
document.getElementById(me.AutoCompleteControlID).onclick = function() {
if (me.AllowAutoComplete) {
try {
if (me.handle.value != "") {
me.Auto();
}
me.currentIndex = -1; //还原当前索引
} catch (e) { }
}
}
//绑定控件的键盘弹起事件
document.getElementById(me.AutoCompleteControlID).onkeyup = function(evt) {
if (me.AllowAutoComplete) {
try {
evt = evt || window.event;
if (evt.keyCode != 40 && evt.keyCode != 38 && evt.keyCode != 39 && evt.keyCode != 37) {
me.OrgValue = me.handle.value;
}
else {//向下\向上
if (evt.keyCode == 38) me.KeyType = true;
else if (evt.keyCode == 40) me.KeyType = false;
}
me.Auto();
} catch (e) { }
}
}
//绑定控件的键盘按下事件
document.getElementById(me.AutoCompleteControlID).onkeydown = function() {
if (me.AllowAutoComplete) {
if (event.keyCode == 13) {//回车
try {
me.Select()
me.InitItem();
} catch (e) { }
}
}
}
//绑定控件的鼠标经过事件
document.getElementById(me.AutoCompleteControlID).onmouseover = function() {
if (me.AllowAutoComplete) {
me.currentIndex = -1;
}
}
//当绑定控件失去焦点时,隐藏弹出层
document.getElementById(me.AutoCompleteControlID).onblur = function() {
if (me.AllowAutoComplete) {
if (!me.FocusInDiv) {
me.Hide();
}
}
}
} /*
* 新建一个闭包,用于实现鼠标点击搜索结果时的事件,以解决通过训练传递的参数一直是最后一个索引的问题
*
* writter:zhangyu 2012-01-03
*/
function BiBaoOnMouseResult(i, me) {
this.OnMouseClickEx = function() {
me.OnTdMouseClick(i);
};
this.OnMouseOverEx = function() {
me.OnTdMouseOver(i);
};
this.OnMouseOutEx = function() {
me.OnTdMouseOut(i);
};
}

JavaScript 输入自动完成插件的更多相关文章

  1. 【sublime】sublime Text 3 javaScript代码自动提示插件&安装步骤 &启动Debug模式

    最近使用sublime开发node.js,但是sublime的js代码在书写的时候并没有提示功能. 因此搜到资料,用于安装代码自动提示插件. 1.打开sublime,然后快捷键Ctrl+Shift+P ...

  2. 30+最佳Ajax jQuery的自动完成插件的例子

    在这篇文章中,我们将介绍35个jQuery AJAX的自动完成提示例子. jQuery 的自动完成功能,使用户快速找到并选择一定的价值.每个人都想要快速和即时搜索输入栏位,因为这个原因,许 流行的搜索 ...

  3. jQuery实现用户输入自动完成功能

    jQuery实现用户输入自动完成功能 利用jQuery UI中Auto-complete插件实现输入自动完成功能,大家在使用诸如淘宝.京东等电商平台搜索商品时,往往只要输入商品的一些特殊字符,就可以显 ...

  4. Awesomplete - 零依赖的简单自动完成插件

    Awesomplete 是一款超轻量级的,可定制的,简单的自动完成插件,零依赖,使用现代化标准构建.你可以简单地添加 awesomplete 样式,让它自动处理(你仍然可以通过指定 HTML 属性配置 ...

  5. 【精心推荐】几款极好的 JavaScript 文件上传插件

    文件上传功能作为网页重要的组成部分,几乎无处不在,从简单的单个文件上传到复杂的批量上传.拖放上传,需要开发者花费大量的时间和精力去处理,以期实现好用的上传功能.这篇文章向大家推荐几款很棒的 JavaS ...

  6. jquery 实现邮箱输入自动提示功能:(二)

    上篇文章写到了一个不错的jquery实现邮箱输入自动提示功能,发现还有一个不错的自动提示插件: 先展示结果如图: html代码: <center> <h1>输入邮箱试试!< ...

  7. jquery 实现邮箱输入自动提示功能:(一)

    记得去年做某个项目的时候,用到了邮箱输入自动提示功能,于是网上搜了一下,发现了这个写得不错,现在回想起来,转载一下,方便查阅. 邮箱的广泛使用得益于它的免费,因此很多网站在注册的时候都会直接使用邮箱作 ...

  8. jQuery图片自动添加水印插件

    JS脚本(jQuery)为图片加水印效果预览:http://hovertree.com/texiao/jquery/94/ 本功能使用HTML5实现,可为图片加上文字水印,可设置文字,设置颜色,位置等 ...

  9. javascript跟随滚动效果插件代码(javascript Follow Plugin)

    这篇文章介绍了javascript跟随滚动效果插件代码(javascript Follow Plugin),有需要的朋友可以参考一下Js 跟随滚动效果插件支持定义多个跟随ID,采用css fixed属 ...

随机推荐

  1. C语言求x的y次方,自定义函数,自己的算法

    我是一名高二中学生,初中时接触电脑,非常酷爱电脑技术,自己百度学习了有两年多了,编程语言也零零散散的学习了一点,想在大学学习计算机专业,所以现在准备系统的学习C语言,并在博客中与大家分享我学习中的心得 ...

  2. 日常使用 Git 的 19 个建议

    如果你对git一无所知,那么我建议先去读一下Git 常用命令速查.本篇文章主要适合有一定 git 使用基础的人群. 目录: 日志输出参数 查看文件的详细变更 查看文件中指定位置的变更 查看尚未合并(m ...

  3. mv、umask、chattr、lsattr命令

    mv命令行,即move 将文件移动到目录下 对文件或目录重命名 umask chattr 设置文件或目录的隐藏属性 lsattr显示文件或目录的隐藏属性 ls mv 1.txt aa ls cd aa ...

  4. date 、cal、bc

    date cal date是显示日期与时间 date +%Y/%M/%D date +%Y/%m/%d date +%H:%M cal cal 2016

  5. jvm参数设置大全

    转自:http://blog.csdn.net/kthq/article/details/8618052 参数说明 -Xmx3550m:设置JVM最大堆内存为3550M. -Xms3550m:设置JV ...

  6. 使用PHPmailer发送邮件的详细代码

    一.使用PHPMailer发送邮件的原因 PHP有内置的mail()方法,但是由于一些主机空间不支持该方法,所以经常会遇到无法发送邮件的情况. 所以,可以下载PHPMailer类,实现邮件发送. 二. ...

  7. DateTime.TryParseExact 万能时间格式转化

    本文转载:http://blog.csdn.net/gaofang2009/article/details/6073231 前天同事问C#有没有相关的方法能把"年月日时分秒"这样的 ...

  8. 备战“软考”之软件project

    说到"软件project"就有一种非常纠结的感觉!为什么呢?由于刚进入软考复习阶段,大家都把它放到了"比較"次要的地位,由于已经学过两遍,再加上它没有非常难理解 ...

  9. Android - 封装Fragment不依赖于Activity

    封装Fragment不依赖于Activity 本文地址:http://blog.csdn.net/caroline_wendy Fragment直接托管activity的intent会破坏Fragme ...

  10. GDB 调试程序系列

    http://blog.csdn.net/haoel/article/category/9197