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 相关文章推荐
JS加ASP二级域名转向的代码
May 17 Javascript
Jquery中增加参数与Json转换代码
Nov 20 Javascript
为jquery.ui.dialog 增加“自动记住关闭时的位置”的功能
Nov 24 Javascript
动感效果的TAB选项卡jquery 插件
Jul 09 Javascript
js超时调用setTimeout和间歇调用setInterval实例分析
Jan 28 Javascript
jQuery实现的在线答题功能
Apr 12 Javascript
Ionic实现仿通讯录点击滑动及$ionicscrolldelegate使用分析
Jan 18 Javascript
JavaScript对象数组排序实例方法浅析
Jun 15 Javascript
详解Angular操作cookies方法
Jun 01 Javascript
js运算符的一些特殊用法
Jul 29 Javascript
使用webpack搭建vue项目及注意事项
Jun 10 Javascript
JS实现放大镜效果
Sep 21 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快递单号查询接口使用示例
2014/05/05 PHP
PHP获取MySql新增记录ID值的3种方法
2014/06/24 PHP
PHP执行Curl时报错提示CURL ERROR: Recv failure: Connection reset by peer的解决方法
2014/06/26 PHP
php转换颜色为其反色的方法
2015/04/27 PHP
PHP aes (ecb)解密后乱码问题
2015/06/22 PHP
基于jquery的lazy loader插件实现图片的延迟加载[简单使用]
2011/05/07 Javascript
JQuery鼠标移到小图显示大图效果的方法
2015/06/10 Javascript
JavaScript代码判断点击第几个按钮
2015/12/13 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
关于JavaScript和jQuery的类型判断详解
2016/10/08 Javascript
JavaScript用构造函数如何获取变量的类型名
2016/12/23 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
2018/06/28 Javascript
深入理解NodeJS 多进程和集群
2018/10/17 NodeJs
VUE 动态组件的应用案例分析
2019/12/02 Javascript
ES6中Promise的使用方法实例总结
2020/02/18 Javascript
Javascript Worker子线程代码实例
2020/02/20 Javascript
简单了解JS打开url的方法
2020/02/21 Javascript
[01:41]DOTA2超级联赛专访YYF 称一辈子难忘TI2
2013/05/28 DOTA
[40:01]OG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python通过字典dict判断指定键值是否存在的方法
2015/03/21 Python
python实现用于测试网站访问速率的方法
2015/05/26 Python
Python中datetime常用时间处理方法
2015/06/15 Python
Python基于Floyd算法求解最短路径距离问题实例详解
2018/05/16 Python
python 实现数字字符串左侧补零的方法
2018/12/04 Python
python Selenium实现付费音乐批量下载的实现方法
2019/01/24 Python
详解pytorch 0.4.0迁移指南
2019/06/16 Python
英国骑行、跑步、游泳、铁人三项运动装备专卖店:Wiggle
2016/08/23 全球购物
德国自然时尚和有机产品购物网站:Waschbär
2019/05/29 全球购物
如何转换一个字符串到enum值
2014/04/12 面试题
Internet主要有哪些网络群组成
2015/12/24 面试题
十佳教师事迹材料
2014/01/11 职场文书
法定代表人资格证明书
2014/09/11 职场文书
优秀员工事迹材料
2014/12/20 职场文书
干部个人考察材料
2014/12/24 职场文书
MySQL 数据丢失排查案例
2021/05/08 MySQL
Python+Pillow+Pytesseract实现验证码识别
2022/05/11 Python