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 Ajax 跨域访问的解决方案
Mar 12 Javascript
Html中JS脚本执行顺序简单举例说明
Jun 19 Javascript
精选的10款用于构建良好易用性网站的jQuery插件
Jan 23 Javascript
js获取URL的参数的方法(getQueryString)示例
Sep 29 Javascript
js替代copy(示例代码)
Nov 27 Javascript
Extjs中RowExpander控件的默认展开问题示例探讨
Jan 24 Javascript
屏蔽相应键盘按钮操作
Mar 10 Javascript
jQuery实现按钮的点击 全选/反选 单选框/复选框 文本框 表单验证
Jun 25 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
Nov 25 Javascript
详解webpack-dev-server 设置反向代理解决跨域问题
Apr 18 Javascript
Vue加载json文件的方法简单示例
Jan 28 Javascript
jQuery单页面文字搜索插件jquery.fullsearch.js的使用方法
Feb 04 jQuery
同一页面多个商品倒计时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文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
2012/06/13 PHP
php读取目录所有文件信息dir示例
2014/03/18 PHP
PHP连接和操作MySQL数据库基础教程
2014/09/29 PHP
轻松掌握php设计模式之访问者模式
2016/09/23 PHP
老生常谈PHP 文件写入和读取(必看篇)
2017/05/22 PHP
php 命名空间(namespace)原理与用法实例小结
2019/11/13 PHP
通过身份证号得到出生日期和性别的js代码
2009/11/23 Javascript
JavaScript中的关键字&quot;VAR&quot;使用详解 分享
2013/07/31 Javascript
通过Jquery的Ajax方法读取将table转换为Json
2014/05/31 Javascript
在AngularJS中使用AJAX的方法
2015/06/17 Javascript
node.js cookie-parser 中间件介绍
2016/06/06 Javascript
浅谈JS使用[ ]来访问对象属性
2016/09/21 Javascript
Bootstrap基本样式学习笔记之按钮(4)
2016/12/07 Javascript
webpack配置的最佳实践分享
2017/04/21 Javascript
vue jsx 使用指南及vue.js 使用jsx语法的方法
2017/11/11 Javascript
vue.js 实现点击展开收起动画效果
2018/07/07 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
微信小程序自定义toast的实现代码
2018/11/16 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
2019/07/25 Javascript
Python正则表达式匹配ip地址实例
2014/10/09 Python
Python比较文件夹比另一同名文件夹多出的文件并复制出来的方法
2015/03/05 Python
Python数据类型详解(三)元祖:tuple
2016/05/08 Python
python getopt详解及简单实例
2016/12/30 Python
详解django三种文件下载方式
2018/04/06 Python
python简易远程控制单线程版
2018/06/20 Python
django基础学习之send_mail功能
2019/08/07 Python
python递归下载文件夹下所有文件
2019/08/31 Python
windows环境中利用celery实现简单任务队列过程解析
2019/11/29 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
python怎么删除缓存文件
2020/07/19 Python
CSS3 Backgrounds属性相关介绍
2011/05/11 HTML / CSS
html5贪吃蛇游戏使用63行代码完美实现
2013/06/25 HTML / CSS
澳大利亚天然护肤品、化妆品和健康产品一站式商店:Nourished Life
2018/12/02 全球购物
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
最美家庭活动方案
2014/08/31 职场文书
关于清明节的演讲稿
2014/09/13 职场文书