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 相关文章推荐
Extjs ajax同步请求时post方式参数发送方式
Aug 05 Javascript
jquery slibings选取同级其他元素的实现代码
Nov 15 Javascript
jquery如何获取复选框的值
Dec 12 Javascript
Jquery对象和Dom对象的区别分析
Nov 20 Javascript
学习JavaScript设计模式(多态)
Nov 25 Javascript
vue-router 中router-view不能渲染的解决方法
May 23 Javascript
利用ES6实现单例模式及其应用详解
Dec 09 Javascript
Vue-Quill-Editor富文本编辑器的使用教程
Sep 21 Javascript
vue拖拽组件使用方法详解
Dec 01 Javascript
解决Vue调用springboot接口403跨域问题
Sep 02 Javascript
Vue组件模板的几种书写形式(3种)
Feb 19 Javascript
JavaScript判断数据类型有几种方法及区别介绍
Sep 02 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
PHILIPS L4X25T电路分析和打理
2021/03/02 无线电
php 获得汉字拼音首字母的函数
2009/08/01 PHP
自己写的兼容低于PHP 5.5版本的array_column()函数
2014/10/24 PHP
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
javascript中检测变量的类型的代码
2010/12/28 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
JavaScript中对象property的删除方法介绍
2014/12/30 Javascript
Bootstrap模仿起筷首页效果
2016/05/09 Javascript
原生js实现下拉框功能(支持键盘事件)
2017/01/13 Javascript
Node.js中 __dirname 的使用介绍
2017/06/19 Javascript
Three.js利用dat.GUI如何简化试验流程详解
2017/09/26 Javascript
Vue按需加载的具体实现
2017/12/02 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
axios携带cookie配置详解(axios+koa)
2018/12/28 Javascript
JS立即执行的匿名函数用法分析
2019/11/04 Javascript
JavaScript监听一个DOM元素大小变化
2020/04/26 Javascript
python计算最大优先级队列实例
2013/12/18 Python
python对字典进行排序实例
2014/09/25 Python
200行自定义python异步非阻塞Web框架
2017/03/15 Python
Python程序运行原理图文解析
2018/02/10 Python
Python 函数返回值的示例代码
2019/03/11 Python
解决Python import docx出错DLL load failed的问题
2020/02/13 Python
利用HTML5+CSS3实现3D转换效果实例详解
2017/05/02 HTML / CSS
日本航空官方网站:JAL
2019/06/19 全球购物
巴西一家专门从事家居和装饰的连锁店:Camicado
2019/08/14 全球购物
LN-CC英国:伦敦时尚生活的缩影
2019/09/01 全球购物
精致的手工皮鞋:Shoe Embassy
2019/11/08 全球购物
服装设计行业个人的自我评价
2013/12/20 职场文书
《理想》教学反思
2014/02/17 职场文书
房屋买卖协议书
2014/04/10 职场文书
《三顾茅庐》教学反思
2014/04/10 职场文书
广告宣传策划方案
2014/05/21 职场文书
单位消防安全责任书
2014/07/23 职场文书
代办出身证明书
2014/10/21 职场文书
幼儿园教师师德承诺书
2015/04/28 职场文书
openstack云计算keystone组件工作介绍
2022/04/20 Servers