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 xml为数据源的下拉框控件
Jul 07 Javascript
jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
May 08 Javascript
基于javascript实现漂亮的页面过渡动画效果附源码下载
Oct 26 Javascript
jquery特效 点击展示与隐藏全文
Dec 09 Javascript
JavaScript+html5 canvas绘制缤纷多彩的三角形效果完整实例
Jan 26 Javascript
基于BootStrap Metronic开发框架经验小结【二】列表分页处理和插件JSTree的使用
May 12 Javascript
discuz表情的JS提取方法分析
Mar 22 Javascript
JS实现非首屏图片延迟加载的示例
Jan 06 Javascript
mpvue项目中使用第三方UI组件库的方法
Sep 30 Javascript
微信小程序事件对象中e.target和e.currentTarget的区别详解
May 08 Javascript
JavaScript实现的开关灯泡点击切换特效示例
Jul 08 Javascript
使用uni-app开发微信小程序的实现
Dec 13 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无限极分类实现的两种解决方法
2013/04/28 PHP
php自定义加密与解密程序实例
2014/12/31 PHP
最新制作ThinkPHP3.2.3完全开发手册
2015/11/23 PHP
php上传图片生成缩略图(GD库)
2016/01/06 PHP
PHP面向对象继承用法详解(优化与减少代码重复)
2016/12/02 PHP
Javascript 调试利器 Firebug使用详解六
2009/07/05 Javascript
改变文件域的样式实现思路同时兼容ie、firefox
2013/10/23 Javascript
js与jQuery 获取父窗、子窗的iframe
2013/12/20 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
2015/04/06 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
2020/08/27 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
javascript如何定义对象数组
2016/06/07 Javascript
详解基于javascript实现的苹果系统底部菜单
2016/12/02 Javascript
详谈JavaScript的闭包及应用
2017/01/17 Javascript
jQuery插件zTree实现清空选中第一个节点所有子节点的方法
2017/03/08 Javascript
微信小程序 获取javascript 里的数据
2017/08/17 Javascript
解决Linux无法正常安装与卸载Node.js的方法
2018/01/19 Javascript
jQuery中ajax请求后台返回json数据并渲染HTML的方法
2018/08/08 jQuery
react用Redux中央仓库实现一个todolist
2019/09/29 Javascript
JavaScript利用键盘码控制div移动
2020/03/19 Javascript
[04:26]2014DOTA2西雅图国际邀请赛 总决赛TOPPLAY
2014/07/22 DOTA
pygame实现俄罗斯方块游戏
2018/06/26 Python
Pyinstaller打包.py生成.exe的方法和报错总结
2019/04/02 Python
解决Keras TensorFlow 混编中 trainable=False设置无效问题
2020/06/28 Python
Under Armour安德玛法国官网:美国高端运动科技品牌
2018/06/29 全球购物
Fabletics官网:美国运动服饰品牌,由好莱坞女演员凯特·哈德森创立
2019/10/19 全球购物
世界上最大的皮肤科医生拥有和经营的美容网站:LovelySkin
2021/01/03 全球购物
Ibatis如何使用动态表名
2015/07/12 面试题
安全检查验收制度
2014/01/12 职场文书
试用期转正鉴定评语
2014/01/27 职场文书
求职面试个人自我评价
2014/02/28 职场文书
应届生求职信范文
2014/06/30 职场文书
销售人才自我评价范文
2014/09/27 职场文书
2016年春季运动会通讯稿
2015/11/25 职场文书
Angular CLI发布路径的配置项浅析
2021/03/29 Javascript
详解Go语言中配置文件使用与日志配置
2022/06/01 Golang