做爲web開發的一員,應該都不陌生,信息處理時,不少時候須要根據用戶的輸入實時反饋查詢結果供其選擇,這給了用戶很好的人機交互體驗,在各大門戶網站上已經被使用的很成熟了,最近項目中用到此功能,網上有不少插件和樣例,但用起來發現都多多少少與項目的需求有所出入,故本身寫了一個,分享一下,但願能給你帶來幫助,插件效果圖以下:web
原理ajax
這個插件主要用來方便用戶在信息查詢和處理時快捷、簡單,其原理分析下:服務器
1. 信息處理須要前臺和後臺,前臺有一個或者多個查詢輸入框(目前暫定爲input標籤)。閉包
2. 用戶在這些輸入框中輸入查詢關鍵字時,系統根據用戶實時的輸入給頁面後臺發送數據查詢請求。app
3. 後臺程序查詢數據並排序,將最符合用戶查詢的記錄(暫定爲前10條)回傳給前臺插件。ide
4. 插件內部根據這些查詢結果友好的展示出來給用戶,用戶選擇展示出來的結果中某一條,該條記錄關鍵字會自動補齊用戶的輸入。函數
功能網站
爲了完成上述過程,這個插件須要幫用戶作到如下一系列功能:this
1. 可以根據標籤id綁定一個或者多個輸入標籤,各標籤的查詢自定完成過程相互獨立,互不影響。url
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)。
接下來,根據實現原理編寫插件:
1、綁定標籤
插件根據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 }
2、初始化插件
選擇插件的數據查詢方式及各方式所需的參數,代碼以下:
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 }
3、數據查詢處理
根據初始化好的數據查詢方式給後臺發送數據查詢請求,後臺查詢到數據後回饋給插件,這個過程的觸發點是用戶在輸入標籤中輸入了查詢關鍵字,實現該標籤的鍵盤提起事件,代碼以下:
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 }
4、查詢結果展示
上述兩種數據查詢代碼中,都經過方法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 }