input输入框的自动匹配(原生代码)


Posted in Javascript onMarch 19, 2013

今天看群里有人发起了人人网以前一些面试题,我以前也转载过一些,恰好闲着,挑选一题来做做,练个手。

本题有以下要求
1. 使用原生代码实现,不可使用任何框架;
2. 对 input框中输入的字符进行匹配,将匹配到的内容以菜单的形式展现在 input框的下方;
3. 只针对英文字符进行匹配,并且匹配到的内容在菜单中加粗;
4. 通过键盘上的上下箭头可以对菜单进行选择,按下回车后将选中的内容写入到 input框中;
思 路
捕捉输入变化,用用户输入的值(下称输入值)去匹配列表项,这里假设列表项是查询返回的一个数组(下称列表),匹配方式为用输入值作为开始值匹配每个列表值,将符合筛选条件的项输出到页面。
分 析
第三点要求中关键字是加粗,这里用正则替换就好了。
第四点要求的关键字就比较多了,一句话暗藏许多杀机,这一部分主要是针对键盘,首先是上下按键,然后是回车,还有一个写入到input框。

到这,如果你认为完了那就操之过急了,至少还有4个隐性的需求。
•第一项默认高亮显示,上下按键的同时当前项高亮。
•按下Enter默认第一项被选中。
•鼠标经过时当前项高亮。
•支持点击选中项。
也许还有所遗漏,这里就不纠结了。
实 践
这虽然是一道JS题,但这之前,页面结构还是要先写好。

<div id="wrap"> 
<input type="text" id="put" /> 
</div> 
<div id="menu"> 
<div> 
<ul id="output"> 
<li>占位</li> 
<li>占坑</li> 
</ul> 
</div> 
</div>

由于不允许用框架,这里对一些可能要到的方法作一个简单的封装。
首先创建一个封装对象,暂且取名 dom,接下来的原生方法都放进这个对象以作复用。
var dom = { 
$ : function( id ){ 
return document.getElementById(id); 
}, 
tag : function( tagName,root ){ 
root = root ? root : document; 
return this.makeArray( root.getElementsByTagName(tagName) ); 
}, 
bind : function( element,type,handler ){ 
if( document.addEventListener ){ 
element.addEventListener( type,handler,false ); 
}else if( document.attachEvent ){ 
element.attachEvent( 'on' + type,handler ); 
}; 
}, 
removeClass : function( list,name ){ 
var el = list[i], 
r = new RegExp('\\s*\\b' + name + '\\b\\s*','g'); 
for( var i = 0 , len = list.length ; i < len ; i++ ){ 
var cur = list[i]; 
if( r.test( cur.className ) ){ 
cur.className = cur.className.replace(r,''); 
}; 
}; 
}, 
height : function( element ){ 
return element.offsetHeight; 
}, 
getBound : function( element ){ 
return element.getBoundingClientRect(); 
}, 
getText : function( element ){ 
return element.textContent ? element.textContent : element.innerText; 
}, 
trim : function( string ){ 
return string.replace( /^\s*(.*)\s*$/,'$1' ); 
}, 
makeArray : function( tagList ){ 
for( var i = 0 , arr = [] , len = tagList.length ; i < len ; i++ ){ 
arr.push( tagList[i] ); 
}; 
return arr; 
}, 
isVisible : function( element ){ 
return element.style.display == 'block'; 
} 
};

接着再创建一个对象,用于存放具体的处理逻辑,作者英文比较狗血,就叫autoMatch吧。
这个对象要做的事情可多了:
•确定好菜单的位置;
•实时处理用户输入;
•处理鼠标和键盘按键动作;
确定菜单的位置 用封装对象dom的getBound方法,返回一个边界对象,此对象有两个属性left和top。眼熟吧,它类似jQuery里的offset()方法。
处理用户输入这里值得一提,由于是实时处理,开始考虑用onchange事件,但是它只会在失去焦点时才触发,所以是不合理的。
这时我的目光转向了oninput,它完全能够胜任工作。
dom.bind( obj.input,'input' , this.inputProcess );

可是,IE又做了一回不走寻常路的事儿。它并不支持oninput。
空欢喜一场,白瞎了!
凡事总是有转机的。角落里的onpropertychange向我们缓缓走来…,它和oninput非常相似,有着一样的特性,至少在捕捉input输入方面,正是我想要的,对付IE,我们都用它,用了都说好。
再绑定一次:
dom.bind( obj.input,'propertychange' , this.inputProcess );

接下来是按键,上,下,回车。对应的键编码分别是38、40、13,唯一需要注意的是FF和IE的属性名称不一样。
详细的实现细节见Demo:
猛击我查看Demo
真实业务场景中,可能要对用户的输入作实时Ajax查询,这代表着每敲一个字母都会有一次查询。
然而如此频繁发送Ajax请求实在太不划算,响应速度上也不容许这样的实现。
我的思路是当用户敲第一个字母时,发送一次请求(请求数据一般有数量限制,一般是10条),并将返回值储存起来(下称缓存)。
在第一个字母之后的用户输入,都在缓存里面筛选,到这里就如同本地查询一样了,每输入一个字母,精确度越来越高,缓存越来越小。
当用户清空,重新输入时重复以上的步骤。
当然,不排除会有一些更加复杂的业务场景,比如,在匹配充足的情况下,要保证用户每次输入都有10条数据可选,这就需要更多的判断以及请求。
所以,具体实现取决于真实的业务场景。
至此,本文结束。感谢阅读,欢迎有血有肉的置评。
Javascript 相关文章推荐
用javascript实现自定义标签
May 08 Javascript
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
Jul 11 Javascript
jQuery中:image选择器用法实例
Jan 03 Javascript
深入理解JavaScript程序中内存泄漏
Mar 17 Javascript
BootStrap和jQuery相结合实现可编辑表格
Apr 21 Javascript
JavaScript编写页面半透明遮罩效果的简单示例
May 09 Javascript
JavaScript每天必学之基础知识
Sep 17 Javascript
jquery 动态增加,减少input表单的简单方法(必看)
Oct 12 Javascript
浅谈Angular中ngModel的$render
Oct 24 Javascript
详解VUE 定义全局变量的几种实现方式
Jun 01 Javascript
[js高手之路]HTML标签解释成DOM节点的实现方法
Aug 31 Javascript
浅析JavaScript中的特殊数据类型
Dec 15 Javascript
javascript实现tabs选项卡切换效果(扩展版)
Mar 19 #Javascript
javascript实现tabs选项卡切换效果(自写原生js)
Mar 19 #Javascript
jquery写个checkbox——类似邮箱全选功能
Mar 19 #Javascript
借助script进行Http跨域请求:JSONP实现原理及代码
Mar 19 #Javascript
DIV+CSS+JS不间断横向滚动实现代码
Mar 19 #Javascript
下载文件个别浏览器文件名乱码解决办法
Mar 19 #Javascript
jQuery点击tr实现checkbox选中的方法
Mar 19 #Javascript
You might like
PHP网站提速三大“软”招
2006/10/09 PHP
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
jQuery中对未来的元素绑定事件用bind、live or on
2014/04/17 Javascript
使用JS+plupload直接批量上传图片到又拍云
2014/12/01 Javascript
js判断是否按下了Shift键的方法
2015/01/27 Javascript
jQuery EasyUI实现右键菜单变灰不可用效果
2015/09/24 Javascript
AngularJS使用ngOption实现下拉列表的实例代码
2016/01/23 Javascript
echarts3 使用总结(绘制各种图表,地图)
2017/01/05 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
2017/06/30 Javascript
在小程序中使用Echart图表的示例代码
2018/08/02 Javascript
详解Vue SSR( Vue2 + Koa2 + Webpack4)配置指南
2018/11/13 Javascript
jQuery删除/清空指定元素的所有子节点实例代码
2019/07/04 jQuery
JS代码屏蔽F12,右键,粘贴,复制,剪切,选中,操作实例
2019/09/17 Javascript
CKEditor扩展插件:自动排版功能autoformat插件实现方法详解
2020/02/06 Javascript
使用vue编写h5公众号跳转小程序的实现代码
2020/11/27 Vue.js
[49:56]VG vs Optic 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python 正则表达式操作指南
2009/05/04 Python
Python实现的KMeans聚类算法实例分析
2018/12/29 Python
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
用python画一只可爱的皮卡丘实例
2019/11/21 Python
手把手教你进行Python虚拟环境配置教程
2020/02/03 Python
Python tkinter 下拉日历控件代码
2020/03/04 Python
python爬虫开发之urllib模块详细使用方法与实例全解
2020/03/09 Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
2020/05/15 Python
Python之Matplotlib文字与注释的使用方法
2020/06/18 Python
在 Windows 下搭建高效的 django 开发环境的详细教程
2020/07/27 Python
Django框架安装及项目创建过程解析
2020/09/14 Python
python基于openpyxl生成excel文件
2020/12/23 Python
HTML5中meta属性的使用方法
2016/02/29 HTML / CSS
Zalando Lounge瑞士:时尚与生活方式购物俱乐部
2020/03/12 全球购物
工艺员岗位职责
2014/02/11 职场文书
法制宣传日活动总结
2014/04/29 职场文书
社区平安建设方案
2014/05/25 职场文书
2014年监理个人工作总结
2014/12/11 职场文书
信仰纪录片观后感
2015/06/08 职场文书
Python函数中apply、map、applymap的区别
2021/11/27 Python