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 相关文章推荐
jquery禁止输入数字以外的字符的示例(纯数字验证码)
Apr 10 Javascript
修改或扩展jQuery原生方法的代码实例
Jan 13 Javascript
JavaScript实现在标题栏上显示当前日期的方法
Mar 19 Javascript
在浏览器中打开或关闭JavaScript的方法
Jun 03 Javascript
js图片卷帘门导航菜单特效代码分享
Sep 10 Javascript
js行号显示的文本框实现效果(兼容多种浏览器 )
Oct 23 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
Oct 28 Javascript
js微信支付实现代码
Dec 22 Javascript
微信小程序云开发之数据库操作
May 18 Javascript
详解Vue 如何监听Array的变化
Jun 06 Javascript
Vue实现购物车实例代码两则
May 30 Javascript
JavaScript实现烟花绽放动画效果
Aug 04 Javascript
同一页面多个商品倒计时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
PHP动态图像的创建
2006/10/09 PHP
探讨PHP中OO之静态关键字以及类常量的详解
2013/06/07 PHP
PHP eval函数使用介绍
2013/12/08 PHP
详谈PHP编码转换问题
2015/07/28 PHP
Yii2简单实现给表单添加验证码的方法
2016/07/18 PHP
jQuery 行背景颜色的交替显示(隔行变色)实现代码
2009/12/13 Javascript
动态创建script标签实现跨域资源访问的方法介绍
2014/02/28 Javascript
使用原生js封装webapp滑动效果(惯性滑动、滑动回弹)
2014/05/06 Javascript
javascript算法题:求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2015/04/01 Javascript
实现非常简单的js双向数据绑定
2015/11/06 Javascript
JS中dom0级事件和dom2级事件的区别介绍
2016/05/05 Javascript
浅谈AngularJs指令之scope属性详解
2016/10/24 Javascript
js实现自动图片轮播代码
2017/03/22 Javascript
JavaScript中this的用法及this在不同应用场景的作用解析
2017/04/13 Javascript
[原创]js实现保存文本框内容为本地文件兼容IE,chrome,火狐浏览器
2018/02/14 Javascript
electron + vue项目实现打印小票功能及实现代码
2018/11/25 Javascript
js的各种数据类型判断的介绍
2019/01/19 Javascript
openlayers实现图标拖动获取坐标
2020/09/25 Javascript
[01:10:24]DOTA2-DPC中国联赛 正赛 VG vs Aster BO3 第一场 2月28日
2021/03/11 DOTA
使用浏览器访问python写的服务器程序
2019/10/10 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
pycharm解决关闭flask后依旧可以访问服务的问题
2020/04/03 Python
django ORM之values和annotate使用详解
2020/05/19 Python
Vision Directa智利眼镜网:框架眼镜、隐形眼镜和名牌太阳眼镜
2016/11/23 全球购物
Bugatchi官方网站:男士服装在线
2019/04/10 全球购物
Fanatics法国官网:美国体育电商
2019/08/27 全球购物
幼儿园小班家长寄语
2014/04/02 职场文书
贷款担保申请书
2014/05/20 职场文书
乡镇精神文明建设汇报材料
2014/08/15 职场文书
学生检讨书范文
2014/10/30 职场文书
幼儿园老师新年寄语2015
2014/12/08 职场文书
青涩记忆观后感
2015/06/18 职场文书
幼儿园托班教育随笔
2015/08/14 职场文书
python基础之爬虫入门
2021/05/10 Python
Python绘制散乱的点构成的图的方法
2022/04/21 Python