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 相关文章推荐
html读出文本文件内容
Jan 22 Javascript
Vue常用指令V-model用法
Mar 08 Javascript
js+html5实现侧滑页面效果
Jul 15 Javascript
Angular 4.0学习教程之架构详解
Sep 12 Javascript
基于vue监听滚动事件实现锚点链接平滑滚动的方法
Jan 17 Javascript
web前端vue实现插值文本和输出原始html
Jan 19 Javascript
使用vue点击li,获取当前点击li父辈元素的属性值方法
Sep 12 Javascript
可能被忽略的一些JavaScript数组方法细节
Feb 28 Javascript
详解小程序云开发数据库
May 20 Javascript
vue实现移动端项目多行文本溢出省略
Jul 29 Javascript
vue 内联样式style中的background用法说明
Aug 05 Javascript
JavaScript实现随机点名小程序
Oct 29 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
将OICQ数据转成MYSQL数据
2006/10/09 PHP
php入门学习知识点三 PHP上传
2011/07/14 PHP
如何在symfony中导出为CSV文件中的数据
2011/10/06 PHP
windows平台中配置nginx+php环境
2015/12/06 PHP
一个简单的JavaScript数据缓存系统实现代码
2010/10/24 Javascript
jQuery scroll事件实现监控滚动条分页示例
2014/04/04 Javascript
extjs每个组件要设置唯一的ID否则会出错
2014/06/15 Javascript
jquery.validate 自定义验证方法及validate相关参数
2016/01/18 Javascript
使用jQuery处理AJAX请求的基础学习教程
2016/05/10 Javascript
判断JS对象是否拥有某属性的方法推荐
2016/05/12 Javascript
jquery日历插件e-calendar升级版
2016/11/10 Javascript
angular十大常见问题
2017/03/07 Javascript
详解vue-cli + webpack 多页面实例配置优化方法
2017/07/13 Javascript
vue结合Echarts实现点击高亮效果的示例
2018/03/17 Javascript
详解vuex数据传输的两种方式及this.$store undefined的解决办法
2019/08/26 Javascript
JavaScript 预解析的4种实现方法解析
2019/09/03 Javascript
vue+vant使用图片预览功能ImagePreview的问题解决
2020/04/10 Javascript
Vue-cli4 配置 element-ui 按需引入操作
2020/09/11 Javascript
JavaScript实现弹出窗口效果
2020/12/09 Javascript
跟老齐学Python之玩转字符串(3)
2014/09/14 Python
Python实现的堆排序算法原理与用法实例分析
2017/11/22 Python
PyQt5 窗口切换与自定义对话框的实例
2019/06/20 Python
python实现登录密码重置简易操作代码
2019/08/14 Python
python3实现从kafka获取数据,并解析为json格式,写入到mysql中
2019/12/23 Python
Python属性和内建属性实例解析
2020/01/14 Python
资生堂美国官网:Shiseido美国
2016/09/02 全球购物
大学生职业生涯规划范文
2013/12/31 职场文书
小学三年级数学教学反思
2014/01/31 职场文书
连锁酒店店长职责范本
2014/02/13 职场文书
国土资源局开展党的群众路线教育实践活动整改措施
2014/09/26 职场文书
仓库保管员岗位职责
2015/02/09 职场文书
关于成立领导小组的通知
2015/04/23 职场文书
2016党员学习《反对自由主义》心得体会
2016/01/22 职场文书
导游词之广东佛山(南风古灶)
2019/09/24 职场文书
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python
python使用pycharm安装pyqt5以及相关配置
2022/04/22 Python