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 相关文章推荐
动态表格Table类的实现
Aug 26 Javascript
JS实现匀速运动的代码实例
Nov 29 Javascript
javascript 处理null及null值示例
Jun 09 Javascript
jQuery实现根据滚动条位置加载相应内容功能
Jul 18 Javascript
JS使用正则表达式过滤多个词语并替换为相同长度星号的方法
Aug 03 Javascript
基于bootstrap的文件上传控件bootstrap fileinput
Dec 23 Javascript
原生JS实现自定义滚动条效果
Oct 27 Javascript
javascript+jQuery实现360开机时间显示效果
Nov 03 jQuery
vue 移动端注入骨架屏的配置方法
Jun 25 Javascript
jquery树形插件zTree高级使用详解
Aug 16 jQuery
vue中input的v-model清空操作
Sep 06 Javascript
JS获取当前时间戳方法解析
Aug 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
重置版战役片段
2020/04/09 魔兽争霸
php自动识别文件编码并转换为UTF-8的方法
2014/06/12 PHP
php之header的不同用法总结(实例讲解)
2017/11/28 PHP
PHP两个n位的二进制整数相加问题的解决
2018/08/26 PHP
PHP字符串和十六进制如何实现互相转换
2020/07/16 PHP
Alliance vs Liquid BO3 第一场2.13
2021/03/10 DOTA
Javascript的闭包
2009/12/31 Javascript
jQuery Validation插件remote验证方式的Bug解决
2010/07/01 Javascript
23个Javascript弹出窗口特效整理
2011/02/25 Javascript
javascript阻止scroll事件多次执行的思路及实现
2013/11/08 Javascript
javascript实现根据身份证号读取相关信息
2014/12/17 Javascript
js动态切换图片的方法
2015/01/20 Javascript
JavaScript动态改变表格单元格内容的方法
2015/03/30 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
2015/09/12 Javascript
javascript实现很浪漫的气泡冒出特效
2020/09/05 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
详解webpack+gulp实现自动构建部署
2017/06/29 Javascript
微信小程序实现banner图轮播效果
2020/06/28 Javascript
python Django连接MySQL数据库做增删改查
2013/11/07 Python
python实现代理服务功能实例
2013/11/15 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
Python爬虫爬取新浪微博内容示例【基于代理IP】
2018/08/03 Python
python3.5 cv2 获取视频特定帧生成jpg图片
2019/08/28 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
opencv-python 读取图像并转换颜色空间实例
2019/12/09 Python
python实现滑雪者小游戏
2020/02/22 Python
django 获取字段最大值,最新的记录操作
2020/08/09 Python
接口自动化多层嵌套json数据处理代码实例
2020/11/20 Python
CSS3的常见transformation图形变化用法小结
2016/05/13 HTML / CSS
css3实现画半圆弧线的示例代码
2017/11/06 HTML / CSS
Canvas多边形绘制的实现方法
2019/08/05 HTML / CSS
英国HYPE双肩包官网:英国本土时尚潮牌
2018/09/26 全球购物
美国帽子俱乐部商店:Hat Club
2019/07/05 全球购物
最新会计专业求职信范文
2014/01/28 职场文书
中国好声音广告词
2014/03/18 职场文书
社区学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书