程式碼如下:
var dom = { <. f5>$ : function( ){
return document.getElementById(id);
},
tag : function( tagName,root ){
root = root ? root : document;
return this.rootmakeArray(t. 。
}else if( document.attachEvent ){
element.attachEvent( 'on' type,handler );
};
},
removeClass : function( list,name ){
var el = list[i],
r = new RegExp('\s*\b' name '\b\s*','g');
for( var i = 0 , len = list.length ; i var cur = list[i];
if( r.test( cur.className ) ){
cur.className = cur.className.replace (r,'');
};
};
},
height : function( element ){
return element.offsetHeight;
},
getBound : function( element ){
return element.getBoundingClientRect();
},
getText : function( element ){
return element.textContent ? element.textContent Text:ementel. ,
trim : function( string ){
return string.replace( /^s*(.*)s*$/,'$1' );
},
makeArray : function( tag ){
for( var i = 0 , arr = [] , len = tagList.length ; i arr.push( tagList[i] );
};
};
return arr;
},
isVisible : function( element ){
return element.style.display == 'block';
}
};
接著再創建一個對象,用來存放具體的處理邏輯,作者英文比較狗血,就叫autoMatch吧。
這個物件要做的事情可多了:
•確定好選單的位置;
•即時處理使用者輸入;
•處理滑鼠和鍵盤按鍵動作;
決定選單的位置用封裝對象dom的getBound方法,傳回一個邊界對象,此物件有兩個屬性left和top。眼熟吧,它類似jQuery裡的offset()方法。
處理使用者輸入這裡值得一提,由於是即時處理,開始考慮用onchange事件,但是它只會在失去焦點時才觸發,所以是不合理的。
這時我的目光轉向了oninput,它完全能夠勝任工作。
dom.bind( obj.input,'obj.input,' this.inputProcess );
可是,IE又做了一回不走尋常路的事兒。它並不支援oninput。
空歡喜一場,白瞎了!
凡事總是有轉機的。角落裡的onpropertychange向我們緩緩走來…,它和oninput非常相似,有著一樣的特性,至少在捕捉input輸入方面,正是我想要的,對付IE,我們都用它,用了都說好。
再綁定一次:
. obj.input,'propertychange' , this.inputProcess );
接下來是按鍵,上,下,回車。對應的鍵編碼分別是38、40、13,唯一要注意的是FF和IE的屬性名稱不一樣。
詳細的實作細節請見Demo:
猛擊我查看Demo
真實業務場景中,可能要對用戶的輸入作實時Ajax查詢,這代表著每敲一個字母都會有查詢一次。
然而如此頻繁發送Ajax請求實在太不划算,回應速度上也不容許這樣的實現。
我的想法是當使用者敲第一個字母時,發送一次請求(請求資料一般有數量限制,一般是10條),並將回傳值儲存起來(下稱快取)。
在第一個字母之後的使用者輸入,都在快取裡面篩選,到這裡就如同本地查詢一樣了,每輸入一個字母,精確度越來越高,快取越來越小。
當使用者清空,重新輸入時重複以上的步驟。
當然,不排除會有一些更複雜的業務場景,例如,在匹配充足的情況下,要保證用戶每次輸入都有10條資料可選,這就需要更多的判斷以及請求。
所以,具體實作取決於真實的業務場景。
至此,本文結束。感謝閱讀,歡迎有血有肉的置評。