javascript suggest效果 自動完成實現代碼分享

來源:互聯網
上載者:User

首先,用到的架構當然是我的架構mass Framework,當然你用其他架構也可以,如jQuery,沒有什麼複雜的東西。只要弄懂原理,一下子就能搞出來。想必,以後你們工作也遇到做搜尋方塊的活兒。

由於本人沒有後端,因此取用一個對象作為本機資料庫。而我現在要做的,其實遠遠比suggest進階,類似IDE的文法提示的東西。當前成品已放到github上。

好了,我們動手吧。首先是結構層,裝了FF的同學可以在百度首頁查看源碼,當輸入幾個字母時,會動態產生了那些HTML。不過怎麼也好,其成就是一個DIV放到搜尋欄的下方,裡面放了一個table,table動態存放候選詞。並且候選詞如果不是使用者輸入的部分,也就是說,JS自動補充的部分它會把它們放到一個b標籤加粗顯示出來。不過, 我覺得用table太重量化,改用了ul列表,為了讓IE6也支援掠過變色效果,我還在裡面套了一個a標籤。為了放便取詞,我還為它(a標籤),添加了一個屬性,專門用於存放補充元整後的詞彙。大抵是這個樣子:

複製代碼 代碼如下:<div id="search_wrapper">
<div>
<input id="search" autocomplete="off">
</div>
<div id="suggest_wrapper">
<ul id="suggest_list">
<li>
<a data-value="完整的詞彙" href="javascript:void(0)">
使用者輸入部分
<b>自動提示部分</b>
</a>
</li>
<li>
<a data-value="完整的詞彙" href="javascript:void(0)">
使用者輸入部分
<b>自動提示部分</b>
</a>
</li>
<!-- 更多li 最多10個 -->
</ul>
</div>
</div>

看一看結構,其實就是兩部分,div#search_wrapper為可見,div#suggest_wrapper為“不可見”(只要裡面沒有li元素,它就不佔空間,顯示不出來了)。input搜尋方塊有個屬性autocomplete,用於關掉瀏覽器內建的提示功能。關於data-value,這種命名方法是HTML5推薦的方式,用於定義要緩衝的資料,data-*在新銳瀏覽器中會放到一個叫dataset的對象中。比如: 複製代碼 代碼如下:<div id="司徒正美"
data-drink="coffee"
data-meal-time="12:00">12:00</div>

我們可以通過如下方式訪問到它: 複製代碼 代碼如下:var el= document.getElementById('司徒正美');
alert( el.dataset.drink );
alert( el.dataset.mealTime );

當然,你也可以不用設定屬性,直接取a標籤的innerText或textContext。
注意:完整的詞彙 = 使用者輸入部分 + 自動提示部分。因此你不要在a標籤裡面加這麼多東西,防止出現空格什麼的,導致檢索失敗!
接著是樣式部分,不過不詳述了。很簡單: 複製代碼 代碼如下:#search_wrapper {
height:50px;
}
#search{
width:300px;
}
#suggest_wrapper{
position:relative;
}
#suggest_list{
position:absolute;
z-index:100;
list-style: none;
margin:0;
padding:0;
background:#fffafa;
border:1px solid #ccc;
border-bottom:0 none;
}
#suggest_list li a{
display: block;
height:20px;
width:304px;
color: #000;
border-bottom:1px solid #ccc;
line-height:20px;
text-decoration: none;
}
#suggest_list li a:hover, .glow_suggest {
background:#ffff80;
}

好了,到重點了。由於我沒有後台,要使用一個本機物件作為本機資料庫。這對象當然是個JS對象了。我們遍曆對象一般都是obj.aaa.bbb.ccc,這樣一直點下去,其實每到一個點號時,就是用for in 迴圈進行遍曆。因此我們監聽常值內容的輸入的情況,一但發生變化就取得輸入框的內容,然後在for in 迴圈中比較。如果是與這個輸入值開頭的屬性就取出來,放到一個數組中,一直取夠十個,然後把這些數組的內容拼接成上述描繪的li元素格式,一併貼到ul元素之內。當中,我們還要注意點中,如果一開始就輸入焦點號,我們就取window對象的十個屬性吧,以後遇到點號就切換這個對象。
好了,開始寫碼,由於用到我的架構,大家可以到這裡去下。在項目首頁有README,教你是怎麼安裝微型.Net伺服器與查看文檔的。一開始,你就姑且把它當成是添加了模組載入功能的jQuery,API 90%神似。我們要用到它的事件模組與屬性模組,它會把相關依賴載入好的,再添加ready參數,它就會在domReady後執行。我們選擇輸入框後為它綁定一個input事件,這是一個標準瀏覽器都支援的事件,IE下我的架構已經相容好了,用jQuery與原生的同學請用propertychange事件類比。 複製代碼 代碼如下://by 司徒正美
$.require("ready,event,attr",function(){
var search = $("#search"), hash = window, prefix = "", fixIE = NaN;
search.addClass("search_target");
search.input(function(){//監聽輸入
var
input = this.value,//原始值
val = input.slice( prefix.length),//比較值
output = []; //用來放置輸出內容
if( fixIE === input){
return //IE下肅使是通過程式改變輸入框裡面的值也會觸發propertychange事件,導致我們無法進行上下翻操作
}
for(var prop in hash){
if( prop.indexOf( val ) === 0 ){//取得以輸入值開頭的API
if( output.push( '<li><a href="javascript:void(0)" data-value="'+prefix +
prop+'">'+ input + "<b>" + (prefix + prop ).slice( input.length ) +"</b></a></li>" ) == 10){
break;
}
}
}
//如果向前遇到點號,或向後取消點號
if( val.charAt(val.length - 1) === "." || (input && !val) ){
var arr = input.split("."); hash = window;
for(var j = 0; j < arr.length; j++){
var el = arr[j];
if(el && hash[ el ]){
hash = hash[ el ];//重新設定要遍曆API的對象
}
}
prefix = input == "." ? "" : input;
for( prop in hash){
if( output.push( '<li><a href="javascript:void(0)" class="search_target" data-value="'+prefix +
prop+'">'+ input + "<b>" + (prefix + prop ).slice( prefix.length ) +"</b></a></li>" ) == 10){
break;
}
}
}
$("#suggest_list").html( output.join("") );
if(!input){//重設所有
hash = window;
fixIE = prefix = output = [];
}
});
});

當提示列表出來後,我們就監聽上下翻效果。也就是點擊鍵盤的方位鍵時,會上下高亮提示的條目,並且它填進搜尋方塊中。這時需要綁定keyup事件,檢查其keyCode,標準瀏覽器管它為which,可以看我的這篇博文《javascript 鍵盤事件總結》。實現原理很簡單,定義一個外圍的變數,用於存放高亮的位置(索引值),然後用上翻時就減一,用下翻時就加一,然後取得提示列表中的所有a標籤,用索引值定位到某一個a標籤中,高亮它,然後去掉原先高亮的a標籤。 複製代碼 代碼如下://by 司徒正美
$.require("ready,event,attr",function(){
var search = $("#search"), hash = window, prefix = "";
search.input(function(){//監聽輸入
//.....
});
var glowIndex = -1;
$(document).keyup(function(e){//監聽上下翻
if(/search_target/i.test( e.target.className)){//只代理特定元素,提高效能
var upOrdown = 0
if(e.which === 38 || e.which === 104){ //up 8
upOrdown --;
}else if(e.which === 40 || e.which === 98){//down 2
upOrdown ++;
}
if(upOrdown){
var list = $("#suggest_list a");
//轉移高亮的欄目
list.eq(glowIndex).removeClass("glow_suggest");
glowIndex += upOrdown;
var el = list.eq( glowIndex ).addClass("glow_suggest");
fixIE = el.attr("data-value")
search.val( fixIE )
if(glowIndex === list.length - 1){
glowIndex = -1;
}
}
}
});
});

最後是斷行符號提交。我又寫到一個keyup事件中去。當然你們可以設法把兩個keyup合成一個(監聽window),我這樣寫純粹是為了教學的需要。 複製代碼 代碼如下://by 司徒正美
$.require("ready,event,attr",function(){
var search = $("#search"), hash = window, prefix = "";
search.input(function(){//監聽輸入
//.....
});
var glowIndex = -1;
$(window).keyup(function(e){//監聽上下翻
//.....
});
search.keyup(function(e){//監聽提交
var input = this.value;
if(input && (e.which == 13 || e.which == 108)){ //如果按下ENTER鍵
alert(input)//實際項目中,應該是進行頁面跳轉,跑到搜尋結果頁中去的!
}
});
});

到此,suggest效果就完成了。如果下了我的架構的同學,開啟伺服器,開啟文檔首頁就能看到這個效果。而在實際項目,suggest其實更簡單些,就是當輸入框文本變化時,AJAX請求後台一個數組,然後再把它拼接成li元素的格式就行了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.