DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> input輸入框的自動匹配(原生代碼)
input輸入框的自動匹配(原生代碼)
編輯:關於JavaScript     
今天看群裡有人發起了人人網以前一些面試題,我以前也轉載過一些,恰好閒著,挑選一題來做做,練個手。

本題有以下要求
1. 使用原生代碼實現,不可使用任何框架;
2. 對 input框中輸入的字符進行匹配,將匹配到的內容以菜單的形式展現在 input框的下方;
3. 只針對英文字符進行匹配,並且匹配到的內容在菜單中加粗;
4. 通過鍵盤上的上下箭頭可以對菜單進行選擇,按下回車後將選中的內容寫入到 input框中;
思 路
捕捉輸入變化,用用戶輸入的值(下稱輸入值)去匹配列表項,這裡假設列表項是查詢返回的一個數組(下稱列表),匹配方式為用輸入值作為開始值匹配每個列表值,將符合篩選條件的項輸出到頁面。
分 析
第三點要求中關鍵字是加粗,這裡用正則替換就好了。
第四點要求的關鍵字就比較多了,一句話暗藏許多殺機,這一部分主要是針對鍵盤,首先是上下按鍵,然後是回車,還有一個寫入到input框。

到這,如果你認為完了那就操之過急了,至少還有4個隱性的需求。
•第一項默認高亮顯示,上下按鍵的同時當前項高亮。
•按下Enter默認第一項被選中。
•鼠標經過時當前項高亮。
•支持點擊選中項。
也許還有所遺漏,這裡就不糾結了。
實 踐
這雖然是一道JS題,但這之前,頁面結構還是要先寫好。
復制代碼 代碼如下:
<div id="wrap">
<input type="text" id="put" />
</div>
<div id="menu">
<div>
<ul id="output">
<li>占位</li>
<li>占坑</li>
</ul>
</div>
</div>

由於不允許用框架,這裡對一些可能要到的方法作一個簡單的封裝。
首先創建一個封裝對象,暫且取名 dom,接下來的原生方法都放進這個對象以作復用。
復制代碼 代碼如下:
var dom = {
$ : function( id ){
return document.getElementById(id);
},
tag : function( tagName,root ){
root = root ? root : document;
return this.makeArray( root.getElementsByTagName(tagName) );
},
bind : function( element,type,handler ){
if( document.addEventListener ){
element.addEventListener( type,handler,false );
}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 < len ; 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 : element.innerText;
},
trim : function( string ){
return string.replace( /^\s*(.*)\s*$/,'$1' );
},
makeArray : function( tagList ){
for( var i = 0 , arr = [] , len = tagList.length ; i < len ; 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,'input' , this.inputProcess );

可是,IE又做了一回不走尋常路的事兒。它並不支持oninput。
空歡喜一場,白瞎了!
凡事總是有轉機的。角落裡的onpropertychange向我們緩緩走來…,它和oninput非常相似,有著一樣的特性,至少在捕捉input輸入方面,正是我想要的,對付IE,我們都用它,用了都說好。
再綁定一次:
復制代碼 代碼如下:
dom.bind( obj.input,'propertychange' , this.inputProcess );

接下來是按鍵,上,下,回車。對應的鍵編碼分別是38、40、13,唯一需要注意的是FF和IE的屬性名稱不一樣。
詳細的實現細節見Demo:
猛擊我查看Demo
真實業務場景中,可能要對用戶的輸入作實時Ajax查詢,這代表著每敲一個字母都會有一次查詢。
然而如此頻繁發送Ajax請求實在太不劃算,響應速度上也不容許這樣的實現。
我的思路是當用戶敲第一個字母時,發送一次請求(請求數據一般有數量限制,一般是10條),並將返回值儲存起來(下稱緩存)。
在第一個字母之後的用戶輸入,都在緩存裡面篩選,到這裡就如同本地查詢一樣了,每輸入一個字母,精確度越來越高,緩存越來越小。
當用戶清空,重新輸入時重復以上的步驟。
當然,不排除會有一些更加復雜的業務場景,比如,在匹配充足的情況下,要保證用戶每次輸入都有10條數據可選,這就需要更多的判斷以及請求。
所以,具體實現取決於真實的業務場景。
至此,本文結束。感謝閱讀,歡迎有血有肉的置評。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved