作为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绑定前台页面输入标签,一个或者多个,代码如下:

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

二、初始化插件

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

 1 /*
 2      *    初始化函数,负责初始化部分可选成员变量
 3      *  requestType:调用方式(1为请求页,2为ajax函数)
 4      *  pageUrl:如果是请求页的方式调用,则此参数必不能为空,若为ajax函数调用,则此参数为null
 5      *  ajaxCallBackFun:如果是ajax函数的方式调用,则此参数必不能为空,若为请求页方式调用,则此参数为null
 6      *  enterKeyFlag:标记是否允许回车事件
 7      *  mouseClickFlag:标记是否允许鼠标选择事件
 8      *  callBackFun:回调函数,与前两个参数配合使用,如果前两个参数有一个设置为true,则此处必须实现回调函数,否则为null
 9      *  tabIndex:绑定控件的编号,标记搜索结果table的id,以避免同页面的两个绑定控件的搜索结果id相同
10      */
11     this.Init = function(requestType, pageUrl, ajaxCallBackFun, enterKeyFlag, mouseClickFlag, callBackFun, tabIndex) {
12         //初始化变量
13         me.Requesttype = requestType;
14         me.RequestPageUrl = pageUrl;
15         me.ajaxCallBackFun = ajaxCallBackFun;
16         me.AllowEnterKeyFlag = enterKeyFlag;
17         me.AllowClickFlag = mouseClickFlag;
18         me.TableIndex = tabIndex;
19         //判断请求方式
20         if (me.Requesttype == 1) {
21             me.ajaxCallBackFun = null;
22             if (me.RequestPageUrl == null) {
23                 alert("传递的参数有误,请求页的地址不能为null!");
24                 me.AllowAutoComplete = false;
25             }
26         }
27         else if (me.Requesttype == 2) {
28             me.RequestPageUrl = null;
29             if (me.ajaxCallBackFun == null) {
30                 alert("传递的参数有误,ajax回调函数不能为null!");
31                 me.AllowAutoComplete = false;
32             }
33         }
34         //判断标志位
35         if (!me.AllowEnterKeyFlag && !me.AllowClickFlag) {
36             callBackFun = null;
37         }
38         else {
39             if (callBackFun == null) {
40                 alert("传递的参数有误,回调函数不能为null!");
41                 me.AllowAutoComplete = false;
42             }
43             else {
44                 me.AllowCallBackFun = callBackFun;
45             }
46         }
47     }

三、数据查询处理

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

 1 //绑定控件的键盘弹起事件
 2     document.getElementById(me.AutoCompleteControlID).onkeyup = function(evt) {
 3         if (me.AllowAutoComplete) {
 4             try {
 5                 evt = evt || window.event;
 6                 if (evt.keyCode != 40 && evt.keyCode != 38 && evt.keyCode != 39 && evt.keyCode != 37) {
 7                     me.OrgValue = me.handle.value;
 8                 }
 9                 else {//向下\向上
10                     if (evt.keyCode == 38) me.KeyType = true;
11                     else if (evt.keyCode == 40) me.KeyType = false;
12                 }
13                 me.Auto();
14             } catch (e) { }
15         }
16     }

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

 1 this.Auto = function() {
 2         var evt = evt || window.event;
 3         //如果按下 向上, 向下 或 回车 
 4         if (evt.keyCode == 38 || evt.keyCode == 40 || evt.keyCode == 13) {
 5             me.SelectItem();
 6         }
 7         //左右移动键
 8         else if (evt.keyCode == 39 || evt.keyCode == 37) {
 9             return;
10         }
11         else {
12             //恢复下拉选择项为 -1
13             currentIndex = -1;
14             //设置结果弹出层的样式
15             me.DivResult.style.position = "absolute";
16             me.DivResult.style.top = me.handle.getBoundingClientRect().top + 19;
17             me.DivResult.style.left = me.handle.getBoundingClientRect().left - 2;
18             me.DivResult.style.width = me.handle.offsetWidth;
19             me.DivResult.style.height = 20;
20             me.DivResult.style.backgroundColor = "#ffffff";
21 
22             if (me.Requesttype == 1) {//页面请求
23 
24                 if (window.XMLHttpRequest) {
25                     me.requestObj = new XMLHttpRequest();
26                     if (me.requestObj.overrideMimeType)
27                         me.requestObj.overrideMimeType("text/xml");
28                 }
29                 else if (window.ActiveXObject) {
30                     try {
31                         me.requestObj = new ActiveXObject("Msxml2.XMLHTTP");
32                     }
33                     catch (e) {
34                         me.requestObj = new ActiveXObject("Microsoft.XMLHTTP");
35                     }
36                 }
37                 if (me.requestObj == null)
38                     return;
39                 me.requestObj.onreadystatechange = me.ShowResult;
40                 var strUrl = me.RequestPageUrl + "?InputValue=" + escape(me.handle.value) + "&TableIndex=" + me.TableIndex;
41                 me.requestObj.open("GET", strUrl, true);
42                 me.requestObj.send();
43             }
44             else {//ajax函数请求
45                 try {
46                     me.ajaxCallBackFun(me.handle.value, me.TableIndex, me.AjaxCallBack);
47                 } catch (e) { }
48             }
49         }
50     }

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

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

 1 //搜索结果处理函数(页面请求调用时)
 2     this.ShowResult = function() {
 3         if (me.requestObj.readyState == 4) {
 4             if (me.requestObj.status == 200)//ok
 5             {
 6                 me.DivResult.innerHTML = me.AlynasisContent(me.requestObj.responseText);
 7                 //判断是否有搜索结果
 8                 var result = me.DivResult.getElementsByTagName("td");
 9                 if (result.length > 0) {
10                     me.DivResult.style.height = result.length * 15;
11                     me.DivResult.style.display = "";
12                     //给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
13                     for (var i = 0; i < result.length; i++) {
14                         var bb = new BiBaoOnMouseResult(i, me);
15                         result[i].onmouseover = bb.OnMouseOverEx;
16                         result[i].onmouseout = bb.OnMouseOutEx;
17                         result[i].onclick = bb.OnMouseClickEx;
18                     }
19                 }
20                 else {
21                     me.DivResult.style.display = "none";
22                     return;
23                 }
24                 me.requestObj = null; //销毁对象
25             }
26             else if (me.requestObj.status == 404) {
27                 //alert("请求的页面未找到!");
28                 me.DivResult.style.display = "none";
29                 me.requestObj = null; //销毁对象
30                 return;
31             }
32         }
33     }

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

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

四、查询结果展现

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

 1 //解析搜索返回的结果
 2     this.AlynasisContent = function(strObj) {
 3         if (strObj == null || strObj == "") {
 4             return "";
 5         }
 6 
 7         var itemList = strObj.split("@|@");
 8         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%;'>";
 9         for (var i = 0; i < itemList.length; i++) {
10             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>";
11         }
12         strResult += "</table>";
13         return strResult;
14     }

 

 

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

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

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

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

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

ReturnAutoComplete方法实现如下:

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

 

 

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

  1 /*
  2  *    自动完成功能主函数(闭包)
  3  *
  4  *  id:自动完成功能需要绑定的控件
  5  *
  6  *  版本:1.0
  7  */
  8  function autoComplete(id) {
  9     /****预留退路处理部分**begin**/
 10     if (!document.getElementById) return false;
 11     if (!document.createElement) return false;
 12     if (!document.getElementsByTagName) return false; 
 13     /****预留退路处理部分**end**/
 14     
 15     var me = this;            //获取当前对象
 16     
 17     /****变量初始化部分**begin**/
 18     me.AutoCompleteControlID; //自动完成绑定控件客户端ID
 19     me.handle = null;         //自动完成绑定控件的对象
 20     me.DivResult;             //查询结果弹出层对象
 21     me.currentIndex = -1;     //当前选中的结果索引
 22     me.LastIndex = -1;        //上一条选中的结果索引
 23     me.requestObj;            //向服务器发送请求的对象
 24     me.TableIndex = 0;        //标记搜索结果的table的id,避免在同一个页面上出现两个相同id的table
 25     me.OrgValue = "";         //记录用户当前输入的值
 26     me.KeyType = true;        //标记是上移(true)还是下移(false)
 27     me.FocusInDiv = false;    //标记当前焦点是否是搜索结果div
 28     me.AllowEnterKeyFlag = false;   //标记是否允许回车键接收事件
 29     me.AllowClickFlag = false;      //标记是否允许鼠标点击选择事件
 30     me.AllowAutoComplete = true;    //标记是否还需要继续实现自动完成功能(在用户传递参数有误的情况下使用,避免报错)
 31     me.Requesttype = 1;             //调用方式,使用请求页(1)\ajax函数(2)
 32     me.RequestPageUrl = null;       //请求页调用时的页面地址(包括参数)
 33     me.ajaxCallBackFun = null;      //ajax函数调用时的回调函数
 34     me.AllowCallBackFun = null;     //用户传递过来的接收回车或者鼠标点击事件的回调函数
 35     //判断绑定控件的ID并赋值
 36     if (id != null && typeof (id) != undefined) {
 37         me.AutoCompleteControlID = id;
 38         me.handle = document.getElementById(me.AutoCompleteControlID);
 39     }
 40 
 41     if (me.DivResult == null || typeof (me.DivResult) == "undefined") {
 42         me.DivResult = document.createElement("div");
 43         var parent = document.getElementById(me.AutoCompleteControlID).parentElement;
 44         if (typeof (parent) != "undefined") {
 45             parent.appendChild(me.DivResult);
 46         }
 47     }
 48     /****变量初始化部分**end**/
 49 
 50 
 51     /*
 52      *    初始化函数,负责初始化部分可选成员变量
 53      *  requestType:调用方式(1为请求页,2为ajax函数)
 54      *  pageUrl:如果是请求页的方式调用,则此参数必不能为空,若为ajax函数调用,则此参数为null
 55      *  ajaxCallBackFun:如果是ajax函数的方式调用,则此参数必不能为空,若为请求页方式调用,则此参数为null
 56      *  enterKeyFlag:标记是否允许回车事件
 57      *  mouseClickFlag:标记是否允许鼠标选择事件
 58      *  callBackFun:回调函数,与前两个参数配合使用,如果前两个参数有一个设置为true,则此处必须实现回调函数,否则为null
 59      *  tabIndex:绑定控件的编号,标记搜索结果table的id,以避免同页面的两个绑定控件的搜索结果id相同
 60      */
 61     this.Init = function(requestType, pageUrl, ajaxCallBackFun, enterKeyFlag, mouseClickFlag, callBackFun, tabIndex) {
 62         //初始化变量
 63         me.Requesttype = requestType;
 64         me.RequestPageUrl = pageUrl;
 65         me.ajaxCallBackFun = ajaxCallBackFun;
 66         me.AllowEnterKeyFlag = enterKeyFlag;
 67         me.AllowClickFlag = mouseClickFlag;
 68         me.TableIndex = tabIndex;
 69         //判断请求方式
 70         if (me.Requesttype == 1) {
 71             me.ajaxCallBackFun = null;
 72             if (me.RequestPageUrl == null) {
 73                 alert("传递的参数有误,请求页的地址不能为null!");
 74                 me.AllowAutoComplete = false;
 75             }
 76         }
 77         else if (me.Requesttype == 2) {
 78             me.RequestPageUrl = null;
 79             if (me.ajaxCallBackFun == null) {
 80                 alert("传递的参数有误,ajax回调函数不能为null!");
 81                 me.AllowAutoComplete = false;
 82             }
 83         }
 84         //判断标志位
 85         if (!me.AllowEnterKeyFlag && !me.AllowClickFlag) {
 86             callBackFun = null;
 87         }
 88         else {
 89             if (callBackFun == null) {
 90                 alert("传递的参数有误,回调函数不能为null!");
 91                 me.AllowAutoComplete = false;
 92             }
 93             else {
 94                 me.AllowCallBackFun = callBackFun;
 95             }
 96         }
 97     }
 98 
 99     this.Auto = function() {
100         var evt = evt || window.event;
101         //如果按下 向上, 向下 或 回车 
102         if (evt.keyCode == 38 || evt.keyCode == 40 || evt.keyCode == 13) {
103             me.SelectItem();
104         }
105         //左右移动键
106         else if (evt.keyCode == 39 || evt.keyCode == 37) {
107             return;
108         }
109         else {
110             //恢复下拉选择项为 -1
111             currentIndex = -1;
112             //设置结果弹出层的样式
113             me.DivResult.style.position = "absolute";
114             me.DivResult.style.top = me.handle.getBoundingClientRect().top + 19;
115             me.DivResult.style.left = me.handle.getBoundingClientRect().left - 2;
116             me.DivResult.style.width = me.handle.offsetWidth;
117             me.DivResult.style.height = 20;
118             me.DivResult.style.backgroundColor = "#ffffff";
119 
120             if (me.Requesttype == 1) {//页面请求
121 
122                 if (window.XMLHttpRequest) {
123                     me.requestObj = new XMLHttpRequest();
124                     if (me.requestObj.overrideMimeType)
125                         me.requestObj.overrideMimeType("text/xml");
126                 }
127                 else if (window.ActiveXObject) {
128                     try {
129                         me.requestObj = new ActiveXObject("Msxml2.XMLHTTP");
130                     }
131                     catch (e) {
132                         me.requestObj = new ActiveXObject("Microsoft.XMLHTTP");
133                     }
134                 }
135                 if (me.requestObj == null)
136                     return;
137                 me.requestObj.onreadystatechange = me.ShowResult;
138                 var strUrl = me.RequestPageUrl + "?InputValue=" + escape(me.handle.value) + "&TableIndex=" + me.TableIndex;
139                 me.requestObj.open("GET", strUrl, true);
140                 me.requestObj.send();
141             }
142             else {//ajax函数请求
143                 try {
144                     me.ajaxCallBackFun(me.handle.value, me.TableIndex, me.AjaxCallBack);
145                 } catch (e) { }
146             }
147         }
148     }
149     //搜索结果处理函数(ajax函数请求方式)
150     this.AjaxCallBack = function(response) {
151         if (response.error != null) {
152             return;
153         }
154         me.DivResult.innerHTML = me.AlynasisContent(response.value);
155         //判断是否有搜索结果
156         var result = me.DivResult.getElementsByTagName("td");
157         if (result.length > 0) {
158             me.DivResult.style.height = result.length * 15;
159             me.DivResult.style.display = "";
160             //给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
161             for (var i = 0; i < result.length; i++) {
162                 var bb = new BiBaoOnMouseResult(i, me);
163                 result[i].onmouseover = bb.OnMouseOverEx;
164                 result[i].onmouseout = bb.OnMouseOutEx;
165                 result[i].onclick = bb.OnMouseClickEx;
166             }
167         }
168         else {
169             me.DivResult.style.display = "none";
170             return;
171         }
172     }
173     //搜索结果处理函数(页面请求调用时)
174     this.ShowResult = function() {
175         if (me.requestObj.readyState == 4) {
176             if (me.requestObj.status == 200)//ok
177             {
178                 me.DivResult.innerHTML = me.AlynasisContent(me.requestObj.responseText);
179                 //判断是否有搜索结果
180                 var result = me.DivResult.getElementsByTagName("td");
181                 if (result.length > 0) {
182                     me.DivResult.style.height = result.length * 15;
183                     me.DivResult.style.display = "";
184                     //给每个Td动态绑定事件(新建了一个闭包,用来传递参数,否则所有元素的一下三个鼠标事件的参数i会是相同的值)
185                     for (var i = 0; i < result.length; i++) {
186                         var bb = new BiBaoOnMouseResult(i, me);
187                         result[i].onmouseover = bb.OnMouseOverEx;
188                         result[i].onmouseout = bb.OnMouseOutEx;
189                         result[i].onclick = bb.OnMouseClickEx;
190                     }
191                 }
192                 else {
193                     me.DivResult.style.display = "none";
194                     return;
195                 }
196                 me.requestObj = null; //销毁对象
197             }
198             else if (me.requestObj.status == 404) {
199                 //alert("请求的页面未找到!");
200                 me.DivResult.style.display = "none";
201                 me.requestObj = null; //销毁对象
202                 return;
203             }
204         }
205     }
206     //解析搜索返回的结果
207     this.AlynasisContent = function(strObj) {
208         if (strObj == null || strObj == "") {
209             return "";
210         }
211 
212         var itemList = strObj.split("@|@");
213         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%;'>";
214         for (var i = 0; i < itemList.length; i++) {
215             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>";
216         }
217         strResult += "</table>";
218         return strResult;
219     }
220     //移动上下键选择搜索结果选项事件
221     this.SelectItem = function() {
222         //结果 
223         var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
224         if (!result)
225             return;
226         if (result.rows[me.LastIndex] != null) {
227             result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF";
228             result.rows[me.LastIndex].style.color = "#000000";
229         }
230         var maxRow = result.rows.length;
231         //向上
232         if (event.keyCode == 38 && me.currentIndex >= 0) {
233             me.currentIndex--;
234             if (me.currentIndex == -1) {
235                 me.handle.value = me.OrgValue;
236             }
237             else {
238                 me.handle.value = result.rows[me.currentIndex].ReturnValue;
239             }
240         }
241         //向下
242         if (event.keyCode == 40 && me.currentIndex < maxRow) {
243             me.currentIndex++;
244             me.handle.value = result.rows[me.currentIndex].ReturnValue;
245         }
246         //回车 
247         if (event.keyCode == 13) {
248             me.Select();
249             me.InitItem();
250             return false;
251         }
252         if (result.rows[me.currentIndex] != undefined) {
253             //选中颜色
254             result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE";
255             result.rows[me.currentIndex].style.color = "#FFFFFF";
256         }
257         me.LastIndex = me.currentIndex;
258         
259         if (!me.KeyType) {
260 
261             if ((me.currentIndex + 1) >= maxRow) {//如果达到最大值,则循环(向下)
262                 me.currentIndex++;
263                 if (me.currentIndex == (maxRow + 1)) me.currentIndex = -1;
264                 if (me.currentIndex == -1) {
265                     me.handle.value = me.OrgValue;
266                 }
267             }
268         }
269         else {
270             if (me.currentIndex == -1) me.currentIndex = maxRow; //如果达到最小值,则循环(向上)
271         }
272     }
273     
274     //回车选择事件
275     this.Select = function() {
276         var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
277         if (!result || result.rows.length <= 0)
278             return;
279         //取出选中的值
280         var ReturnValue = "";
281         if (me.currentIndex < 0)//直接取输入框中的值
282             ReturnValue = me.handle.value;
283         else                    //取用户选中的值
284             ReturnValue = result.rows[me.currentIndex].ReturnValue;
285         //自动完成功能出口,向主程序发送值信息
286         if (ReturnValue != undefined) {
287             me.DivResult.style.display = "none";
288             //自动完成处理事件--由用户自己完成实现
289             if (me.AllowEnterKeyFlag)
290                 me.AllowCallBackFun(ReturnValue);
291         }
292     }
293     
294     this.Hide = function() {
295         me.DivResult.style.display = "none";
296         me.currentIndex = -1;
297     }
298     this.InitItem = function() {
299         me.DivResult.style.display = "none";
300         me.DivResult.innerHTML = "";
301         me.currentIndex = -1;
302     }
303     //搜索结果的鼠标事件
304     this.OnTdMouseOver = function(i) {
305         if (me.AllowAutoComplete) {
306             me.currentIndex = i;
307             var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
308             result.rows[me.currentIndex].style.cursor = "point";
309             if (!result || result.rows.length <= 0)
310                 return;
311             //取消之前选中项的颜色
312             if (result.rows[me.LastIndex] != null) {
313                 result.rows[me.LastIndex].style.backgroundColor = "#FFFFFF";
314                 result.rows[me.LastIndex].style.color = "#000000";
315             }
316             //改变选中项的颜色
317             if (result.rows[me.currentIndex] != undefined) {
318                 result.rows[me.currentIndex].style.backgroundColor = "gray"; //"#3161CE";
319                 result.rows[me.currentIndex].style.color = "#FFFFFF";
320             }
321             me.LastIndex = me.currentIndex;
322         }
323     }
324     this.OnTdMouseOut = function(i) {
325         if (me.AllowAutoComplete) {
326             var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
327             if (!result || result.rows.length <= 0)
328                 return;
329             if (result.rows[me.currentIndex] != undefined) {
330                 result.rows[me.currentIndex].style.backgroundColor = "#FFFFFF";
331                 result.rows[me.currentIndex].style.color = "#000000";
332             }
333         }
334     }
335     this.OnTdMouseClick = function(i) {
336         if (me.AllowAutoComplete) {
337             var evt = fixEvent(window.event);
338             var result = document.getElementById("Tmp_AutoComplete_tblResult_" + me.TableIndex);
339             if (!result || result.rows.length <= 0)
340                 return;
341             //给输入框赋值
342             var ReturnValue = result.rows[me.currentIndex].ReturnValue;
343             me.handle.value = ReturnValue;
344             //隐藏搜索结果
345             me.Hide();
346             //自动完成处理事件--由用户自己完成实现
347             if (me.AllowClickFlag)
348                 me.AllowCallBackFun(ReturnValue);
349         }
350     }
351     //弹出层的鼠标移入/出事件
352     me.DivResult.onmouseout = function() {
353         if (me.AllowAutoComplete) {
354             me.currentIndex = -1;
355             me.FocusInDiv = false;
356         }
357     }
358     me.DivResult.onmouseover = function() {
359         if (me.AllowAutoComplete) {
360             me.FocusInDiv = true;
361         }
362     }
363     //绑定控件的点击事件
364     document.getElementById(me.AutoCompleteControlID).onclick = function() {
365         if (me.AllowAutoComplete) {
366             try {
367                 if (me.handle.value != "") {
368                     me.Auto();
369                 }
370                 me.currentIndex = -1; //还原当前索引
371             } catch (e) { }
372         }
373     }
374     //绑定控件的键盘弹起事件
375     document.getElementById(me.AutoCompleteControlID).onkeyup = function(evt) {
376         if (me.AllowAutoComplete) {
377             try {
378                 evt = evt || window.event;
379                 if (evt.keyCode != 40 && evt.keyCode != 38 && evt.keyCode != 39 && evt.keyCode != 37) {
380                     me.OrgValue = me.handle.value;
381                 }
382                 else {//向下\向上
383                     if (evt.keyCode == 38) me.KeyType = true;
384                     else if (evt.keyCode == 40) me.KeyType = false;
385                 }
386                 me.Auto();
387             } catch (e) { }
388         }
389     }
390     //绑定控件的键盘按下事件
391     document.getElementById(me.AutoCompleteControlID).onkeydown = function() {
392         if (me.AllowAutoComplete) {
393             if (event.keyCode == 13) {//回车
394                 try {
395                     me.Select()
396                     me.InitItem();
397                 } catch (e) { }
398             } 
399         }
400     }
401     //绑定控件的鼠标经过事件
402     document.getElementById(me.AutoCompleteControlID).onmouseover = function() {
403         if (me.AllowAutoComplete) {
404             me.currentIndex = -1;
405         }
406     }
407     //当绑定控件失去焦点时,隐藏弹出层
408     document.getElementById(me.AutoCompleteControlID).onblur = function() {
409         if (me.AllowAutoComplete) {
410             if (!me.FocusInDiv) {
411                 me.Hide();
412             }
413         } 
414     }
415 }
416 
417 
418 /*
419 * 新建一个闭包,用于实现鼠标点击搜索结果时的事件,以解决通过训练传递的参数一直是最后一个索引的问题    
420 *
421 * writter:zhangyu 2012-01-03
422 */
423 function BiBaoOnMouseResult(i, me) {
424     this.OnMouseClickEx = function() {
425         me.OnTdMouseClick(i);
426     };
427     this.OnMouseOverEx = function() {
428         me.OnTdMouseOver(i);
429     };
430     this.OnMouseOutEx = function() {
431         me.OnTdMouseOut(i);
432     };
433 }
View Code

 

posted on 2013-11-19 15:47  Fish-Paul  阅读(3406)  评论(0编辑  收藏  举报