javascript suggest效果 自动完成实现代码分享


Posted in Javascript onFebruary 17, 2012

首先,用到的框架当然是我的框架mass Framework,当然你用其他框架也可以,如jQuery,没有什么复杂的东西。只要弄懂原理,一下子就能搞出来。想必,以后你们工作也遇到做搜索框的活儿。

由于本人没有后端,因此取用一个对象作为本地数据库。而我现在要做的,其实远远比suggest高级,类似IDE的语法提示的东西。当前成品已放到github上。

javascript suggest效果 自动完成实现代码分享

好了,我们动手吧。首先是结构层,装了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元素的格式就行了。
Javascript 相关文章推荐
JavaScript中令你抓狂的魔术变量
Nov 30 Javascript
jquery formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
Jan 04 Javascript
用jquery的方法制作一个简单的导航栏
Jun 23 Javascript
jquery单击事件和双击事件冲突解决方案
Mar 02 Javascript
jQuery Mobile 触摸事件实例
Jun 04 Javascript
js 获取经纬度的实现方法
Jun 20 Javascript
xmlplus组件设计系列之选项卡(Tabbar)(5)
May 03 Javascript
基于webpack.config.js 参数详解
Mar 20 Javascript
angularJs中ng-model-options设置数据同步的方法
Sep 30 Javascript
基于layui的下拉列表的数据回显方法
Sep 24 Javascript
微信小程序自定义弹出层效果
May 26 Javascript
Vue通过懒加载提升页面响应速度
May 10 Vue.js
同一页面多个商品倒计时JS 基于面向对象的javascript
Feb 16 #Javascript
Js从头学起(基本数据类型和引用类型的参数传递详细分析)
Feb 16 #Javascript
通过JS获取用户本地图片路径并显示的代码
Feb 16 #Javascript
javascript简易缓动插件(源码打包)
Feb 16 #Javascript
基于jquery的textarea发布框限制文字字数输入(添加中文识别)
Feb 16 #Javascript
js URL参数的拼接方法比较
Feb 15 #Javascript
javascript题目,重写函数让其无限相加
Feb 15 #Javascript
You might like
使用 eAccelerator加速PHP代码的目的
2007/03/16 PHP
解析PayPal支付接口的PHP开发方式
2010/11/28 PHP
PHP 杂谈《重构-改善既有代码的设计》之五 简化函数调用
2012/05/07 PHP
PHP两种去掉数组重复值的方法比较
2014/06/19 PHP
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
2016/03/30 PHP
PHP后台实现微信小程序登录
2018/08/03 PHP
PHP设计模式之适配器模式(Adapter)原理与用法详解
2019/12/12 PHP
jQuery formValidator表单验证插件开源了 含API帮助、源码、示例
2008/08/14 Javascript
cookie丢失问题(认证失效) Authentication (用户验证信息)也会丢失
2009/06/04 Javascript
js获取时间(本周、本季度、本月..)
2013/11/22 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
2013/12/11 Javascript
jQuery老黄历完整实现方法
2015/01/16 Javascript
JavaScript中的acos()方法使用详解
2015/06/14 Javascript
果断收藏9个Javascript代码高亮脚本
2016/01/06 Javascript
深入理解node exports和module.exports区别
2016/06/01 Javascript
浅谈javascript:两种注释,声明变量,定义函数
2016/09/29 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
分析在Python中何种情况下需要使用断言
2015/04/01 Python
python实现从ftp服务器下载文件的方法
2015/04/30 Python
Python日志无延迟实时写入的示例
2019/07/11 Python
Python属性和内建属性实例解析
2020/01/14 Python
用pytorch的nn.Module构造简单全链接层实例
2020/01/14 Python
Django实现从数据库中获取到的数据转换为dict
2020/03/27 Python
django实现模板中的字符串文字和自动转义
2020/03/31 Python
解决Django Haystack全文检索为空的问题
2020/05/19 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
CSS3实现多样的边框效果
2018/05/04 HTML / CSS
员工拾金不昧表扬信
2014/01/09 职场文书
总经理岗位职责描述
2014/02/08 职场文书
2014年宣传部工作总结
2014/11/12 职场文书
小学班主任事迹材料
2014/12/17 职场文书
安阳殷墟导游词
2015/02/10 职场文书
工作态度怎么写
2015/06/25 职场文书
《观察物体》教学反思
2016/02/17 职场文书
Unicode中的CJK(中日韩统一表意文字)字符小结
2021/12/06 HTML / CSS
Windows server 2016服务器基本设置
2022/08/14 Servers