input輸入框的自動(dòng)匹配(原生代碼)
更新時(shí)間:2013年03月19日 16:05:41 作者:
功能要求:使用原生代碼實(shí)現(xiàn),不可使用任何框架、只針對(duì)英文字符進(jìn)行匹配,并且匹配到的內(nèi)容在菜單中加粗、通過鍵盤上的上下箭頭可以對(duì)菜單進(jìn)行選擇等等,感興趣的你可以參考下
今天看群里有人發(fā)起了人人網(wǎng)以前一些面試題,我以前也轉(zhuǎn)載過一些,恰好閑著,挑選一題來做做,練個(gè)手。
本題有以下要求:
1. 使用原生代碼實(shí)現(xiàn),不可使用任何框架;
2. 對(duì) input框中輸入的字符進(jìn)行匹配,將匹配到的內(nèi)容以菜單的形式展現(xiàn)在 input框的下方;
3. 只針對(duì)英文字符進(jìn)行匹配,并且匹配到的內(nèi)容在菜單中加粗;
4. 通過鍵盤上的上下箭頭可以對(duì)菜單進(jìn)行選擇,按下回車后將選中的內(nèi)容寫入到 input框中;
思 路
捕捉輸入變化,用用戶輸入的值(下稱輸入值)去匹配列表項(xiàng),這里假設(shè)列表項(xiàng)是查詢返回的一個(gè)數(shù)組(下稱列表),匹配方式為用輸入值作為開始值匹配每個(gè)列表值,將符合篩選條件的項(xiàng)輸出到頁面。
分 析
第三點(diǎn)要求中關(guān)鍵字是加粗,這里用正則替換就好了。
第四點(diǎn)要求的關(guān)鍵字就比較多了,一句話暗藏許多殺機(jī),這一部分主要是針對(duì)鍵盤,首先是上下按鍵,然后是回車,還有一個(gè)寫入到input框。
到這,如果你認(rèn)為完了那就操之過急了,至少還有4個(gè)隱性的需求。
•第一項(xiàng)默認(rèn)高亮顯示,上下按鍵的同時(shí)當(dāng)前項(xiàng)高亮。
•按下Enter默認(rèn)第一項(xiàng)被選中。
•鼠標(biāo)經(jīng)過時(shí)當(dāng)前項(xiàng)高亮。
•支持點(diǎn)擊選中項(xiàng)。
也許還有所遺漏,這里就不糾結(jié)了。
實(shí) 踐
這雖然是一道JS題,但這之前,頁面結(jié)構(gòu)還是要先寫好。
<div id="wrap">
<input type="text" id="put" />
</div>
<div id="menu">
<div>
<ul id="output">
<li>占位</li>
<li>占坑</li>
</ul>
</div>
</div>
由于不允許用框架,這里對(duì)一些可能要到的方法作一個(gè)簡(jiǎn)單的封裝。
首先創(chuàng)建一個(gè)封裝對(duì)象,暫且取名 dom,接下來的原生方法都放進(jìn)這個(gè)對(duì)象以作復(fù)用。
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';
}
};
接著再創(chuàng)建一個(gè)對(duì)象,用于存放具體的處理邏輯,作者英文比較狗血,就叫autoMatch吧。
這個(gè)對(duì)象要做的事情可多了:
•確定好菜單的位置;
•實(shí)時(shí)處理用戶輸入;
•處理鼠標(biāo)和鍵盤按鍵動(dòng)作;
確定菜單的位置 用封裝對(duì)象dom的getBound方法,返回一個(gè)邊界對(duì)象,此對(duì)象有兩個(gè)屬性left和top。眼熟吧,它類似jQuery里的offset()方法。
處理用戶輸入這里值得一提,由于是實(shí)時(shí)處理,開始考慮用onchange事件,但是它只會(huì)在失去焦點(diǎn)時(shí)才觸發(fā),所以是不合理的。
這時(shí)我的目光轉(zhuǎn)向了oninput,它完全能夠勝任工作。
dom.bind( obj.input,'input' , this.inputProcess );
可是,IE又做了一回不走尋常路的事兒。它并不支持oninput。
空歡喜一場(chǎng),白瞎了!
凡事總是有轉(zhuǎn)機(jī)的。角落里的onpropertychange向我們緩緩走來…,它和oninput非常相似,有著一樣的特性,至少在捕捉input輸入方面,正是我想要的,對(duì)付IE,我們都用它,用了都說好。
再綁定一次:
dom.bind( obj.input,'propertychange' , this.inputProcess );
接下來是按鍵,上,下,回車。對(duì)應(yīng)的鍵編碼分別是38、40、13,唯一需要注意的是FF和IE的屬性名稱不一樣。
詳細(xì)的實(shí)現(xiàn)細(xì)節(jié)見Demo:
猛擊我查看Demo
真實(shí)業(yè)務(wù)場(chǎng)景中,可能要對(duì)用戶的輸入作實(shí)時(shí)Ajax查詢,這代表著每敲一個(gè)字母都會(huì)有一次查詢。
然而如此頻繁發(fā)送Ajax請(qǐng)求實(shí)在太不劃算,響應(yīng)速度上也不容許這樣的實(shí)現(xiàn)。
我的思路是當(dāng)用戶敲第一個(gè)字母時(shí),發(fā)送一次請(qǐng)求(請(qǐng)求數(shù)據(jù)一般有數(shù)量限制,一般是10條),并將返回值儲(chǔ)存起來(下稱緩存)。
在第一個(gè)字母之后的用戶輸入,都在緩存里面篩選,到這里就如同本地查詢一樣了,每輸入一個(gè)字母,精確度越來越高,緩存越來越小。
當(dāng)用戶清空,重新輸入時(shí)重復(fù)以上的步驟。
當(dāng)然,不排除會(huì)有一些更加復(fù)雜的業(yè)務(wù)場(chǎng)景,比如,在匹配充足的情況下,要保證用戶每次輸入都有10條數(shù)據(jù)可選,這就需要更多的判斷以及請(qǐng)求。
所以,具體實(shí)現(xiàn)取決于真實(shí)的業(yè)務(wù)場(chǎng)景。
至此,本文結(jié)束。感謝閱讀,歡迎有血有肉的置評(píng)。
本題有以下要求:
1. 使用原生代碼實(shí)現(xiàn),不可使用任何框架;
2. 對(duì) input框中輸入的字符進(jìn)行匹配,將匹配到的內(nèi)容以菜單的形式展現(xiàn)在 input框的下方;
3. 只針對(duì)英文字符進(jìn)行匹配,并且匹配到的內(nèi)容在菜單中加粗;
4. 通過鍵盤上的上下箭頭可以對(duì)菜單進(jìn)行選擇,按下回車后將選中的內(nèi)容寫入到 input框中;
思 路
捕捉輸入變化,用用戶輸入的值(下稱輸入值)去匹配列表項(xiàng),這里假設(shè)列表項(xiàng)是查詢返回的一個(gè)數(shù)組(下稱列表),匹配方式為用輸入值作為開始值匹配每個(gè)列表值,將符合篩選條件的項(xiàng)輸出到頁面。
分 析
第三點(diǎn)要求中關(guān)鍵字是加粗,這里用正則替換就好了。
第四點(diǎn)要求的關(guān)鍵字就比較多了,一句話暗藏許多殺機(jī),這一部分主要是針對(duì)鍵盤,首先是上下按鍵,然后是回車,還有一個(gè)寫入到input框。
到這,如果你認(rèn)為完了那就操之過急了,至少還有4個(gè)隱性的需求。
•第一項(xiàng)默認(rèn)高亮顯示,上下按鍵的同時(shí)當(dāng)前項(xiàng)高亮。
•按下Enter默認(rèn)第一項(xiàng)被選中。
•鼠標(biāo)經(jīng)過時(shí)當(dāng)前項(xiàng)高亮。
•支持點(diǎn)擊選中項(xiàng)。
也許還有所遺漏,這里就不糾結(jié)了。
實(shí) 踐
這雖然是一道JS題,但這之前,頁面結(jié)構(gòu)還是要先寫好。
復(fù)制代碼 代碼如下:
<div id="wrap">
<input type="text" id="put" />
</div>
<div id="menu">
<div>
<ul id="output">
<li>占位</li>
<li>占坑</li>
</ul>
</div>
</div>
由于不允許用框架,這里對(duì)一些可能要到的方法作一個(gè)簡(jiǎn)單的封裝。
首先創(chuàng)建一個(gè)封裝對(duì)象,暫且取名 dom,接下來的原生方法都放進(jìn)這個(gè)對(duì)象以作復(fù)用。
復(fù)制代碼 代碼如下:
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';
}
};
接著再創(chuàng)建一個(gè)對(duì)象,用于存放具體的處理邏輯,作者英文比較狗血,就叫autoMatch吧。
這個(gè)對(duì)象要做的事情可多了:
•確定好菜單的位置;
•實(shí)時(shí)處理用戶輸入;
•處理鼠標(biāo)和鍵盤按鍵動(dòng)作;
確定菜單的位置 用封裝對(duì)象dom的getBound方法,返回一個(gè)邊界對(duì)象,此對(duì)象有兩個(gè)屬性left和top。眼熟吧,它類似jQuery里的offset()方法。
處理用戶輸入這里值得一提,由于是實(shí)時(shí)處理,開始考慮用onchange事件,但是它只會(huì)在失去焦點(diǎn)時(shí)才觸發(fā),所以是不合理的。
這時(shí)我的目光轉(zhuǎn)向了oninput,它完全能夠勝任工作。
復(fù)制代碼 代碼如下:
dom.bind( obj.input,'input' , this.inputProcess );
可是,IE又做了一回不走尋常路的事兒。它并不支持oninput。
空歡喜一場(chǎng),白瞎了!
凡事總是有轉(zhuǎn)機(jī)的。角落里的onpropertychange向我們緩緩走來…,它和oninput非常相似,有著一樣的特性,至少在捕捉input輸入方面,正是我想要的,對(duì)付IE,我們都用它,用了都說好。
再綁定一次:
復(fù)制代碼 代碼如下:
dom.bind( obj.input,'propertychange' , this.inputProcess );
接下來是按鍵,上,下,回車。對(duì)應(yīng)的鍵編碼分別是38、40、13,唯一需要注意的是FF和IE的屬性名稱不一樣。
詳細(xì)的實(shí)現(xiàn)細(xì)節(jié)見Demo:
猛擊我查看Demo
真實(shí)業(yè)務(wù)場(chǎng)景中,可能要對(duì)用戶的輸入作實(shí)時(shí)Ajax查詢,這代表著每敲一個(gè)字母都會(huì)有一次查詢。
然而如此頻繁發(fā)送Ajax請(qǐng)求實(shí)在太不劃算,響應(yīng)速度上也不容許這樣的實(shí)現(xiàn)。
我的思路是當(dāng)用戶敲第一個(gè)字母時(shí),發(fā)送一次請(qǐng)求(請(qǐng)求數(shù)據(jù)一般有數(shù)量限制,一般是10條),并將返回值儲(chǔ)存起來(下稱緩存)。
在第一個(gè)字母之后的用戶輸入,都在緩存里面篩選,到這里就如同本地查詢一樣了,每輸入一個(gè)字母,精確度越來越高,緩存越來越小。
當(dāng)用戶清空,重新輸入時(shí)重復(fù)以上的步驟。
當(dāng)然,不排除會(huì)有一些更加復(fù)雜的業(yè)務(wù)場(chǎng)景,比如,在匹配充足的情況下,要保證用戶每次輸入都有10條數(shù)據(jù)可選,這就需要更多的判斷以及請(qǐng)求。
所以,具體實(shí)現(xiàn)取決于真實(shí)的業(yè)務(wù)場(chǎng)景。
至此,本文結(jié)束。感謝閱讀,歡迎有血有肉的置評(píng)。
您可能感興趣的文章:
- jQuery實(shí)現(xiàn)表單input中提示文字value隨鼠標(biāo)焦點(diǎn)移進(jìn)移出而顯示或隱藏的代碼
- 基于jQuery的input輸入框下拉提示層(自動(dòng)郵箱后綴名)
- js監(jiān)聽輸入框值的即時(shí)變化onpropertychange、oninput
- input 輸入框內(nèi)的輸入事件詳細(xì)分析
- jQuery 版本的文本輸入框檢查器Input Check
- 制作符合用戶體驗(yàn)的漂亮的input輸入框
- javascritp實(shí)現(xiàn)input輸入框相關(guān)限制用法
- input 輸入框獲得/失去焦點(diǎn)時(shí)隱藏/顯示文字(jquery版)
相關(guān)文章
js實(shí)現(xiàn)適用于素材網(wǎng)站的黑色多級(jí)菜單導(dǎo)航條效果
這篇文章主要介紹了js實(shí)現(xiàn)適用于素材網(wǎng)站的黑色多級(jí)菜單導(dǎo)航條效果,涉及javascript鼠標(biāo)事件及頁面元素樣式的動(dòng)態(tài)切換技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08JS支持帶x身份證號(hào)碼驗(yàn)證函數(shù)
身份證號(hào)碼驗(yàn)證-支持新的帶x身份證2008-08-08JS保留小數(shù)點(diǎn)(四舍五入、四舍六入)實(shí)現(xiàn)思路及實(shí)例
保留兩位小數(shù):將浮點(diǎn)數(shù)四舍五入,取小數(shù)點(diǎn)后2位;如:2,會(huì)在2后面補(bǔ)上00.即2.00,感興趣的朋友看下具體的實(shí)現(xiàn)思路及代碼2013-04-04javaScript中with函數(shù)用法實(shí)例分析
這篇文章主要介紹了javaScript中with函數(shù)用法,實(shí)例分析了javascript中with的功能、定義及相關(guān)使用技巧,需要的朋友可以參考下2015-06-06微信小程序?qū)崿F(xiàn)禁止分享代碼實(shí)例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)禁止分享代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10