前言:
最近有个输入框自动补全的需求,例如百度搜索功能:前端
在输入框输入信息后,自动提示补全。我选择用typeahead.js,后来发现,原来这个库的相关学习资料不多,搞的稍微有点久,才弄明白点...
本文实属原创,若有错误,敬请指教!jquery
简介:git
官网:http://twitter.github.io/typeahead.js
github: https://github.com/twitter/typeahead.js
使用文档:https://www.awesomes.cn/repo/twitter/typeahead-jsgithub
在查资料的过程当中,不难发现,typeahead.js一直会跟boostrap扯上关系。实际上在bootstrap 2.x时,自带了补全控件typeahead;可是到了,bootstrap 3.x时,舍弃了这个插件,这是出现了单独插件,名叫bootstrap-3-typeahead,再后面bootstrap-3-typeahead 更名 typeahead.js.ajax
实践:正则表达式
由于typeahead的更新变更老是很大,因此每一个版本的改动也很大,而typeahead因此依赖的库也出现了稍微的变化。下面介绍两种方法:
第一个bower安装,也是比较能保证依赖文件的准确性:json
在项目里面
$ bower install typeahead.js
bootstrap
第二种手动引用:
先下载最新版的typeahead.js,以及全部相关依赖。点我点我下载~
下载后,会是下面这几个文件:数组
详解:缓存
bloodhound.js(独立建议引擎)
typeahead.jquery.js(独立的typeahead库)
typeahead.bundle.js(bloodhound+typeahead.jquery的组合体)
注:bloodhound.js和typeahead.jquery.js对jQuery 1.9+依赖。
Examples:
一、基础示例
Html代码:
<div class="example"> <h2>基本示例</h2> <div id="basic-example"> <input class="typeahead" type="text" placeholder="请输入省份"> </div> </div>
js代码:
jQuery(function () { /*** 1.基本示例 ***/ var provinces = ["广东省", "海南省", "山西省", "山东省","湖北省", "湖南省", "陕西省", "上海市", "北京市", "广西省"]; var substringMatcher = function (strs) { return function findMatches(q, cb) { var matches, substrRegex; matches = [];//定义字符串数组 substrRegex = new RegExp(q, 'i'); //用正则表达式来肯定哪些字符串包含子串的'q' $.each(strs, function (i, str) { //遍历字符串池中的任何字符串 if (substrRegex.test(str)) { matches.push({ value: str }); } //包含子串的'q',将它添加到'match' }); cb(matches); }; }; $('#basic-example .typeahead').typeahead({ highlight: true, minLength: 1 }, { name: 'provinces', displayKey: 'value', source: substringMatcher(provinces) }); });
效果图下(请忽略丑丑的UI):
数据为:
var provinces = ["广东省", "海南省", "山西省", "山东省","湖北省", "湖南省", "陕西省", "上海市", "北京市", "广西省"];
---------- 华丽丽的分割线 ----------
下面为要介绍两种用ajax获取远程数据的模式:
第一种是prefetch,是对数据请求一次,把全部数据拿下来。
第二种是remote,只有当触发输入框的时候,数据才从服务端获取。
二、ajax数据预读示例(prefetch)
Html代码为:
<div class="example"> <h2>Ajax数据预读示例</h2> <div id="ajax-prefetch-example"> <input class="typeahead" type="text" placeholder="请输入省份"> </div> </div>
JS代码为:
/*** 2.Ajax数据预读示例 ***/ // 远程数据源 var prefetch_provinces = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), queryTokenizer: Bloodhound.tokenizers.whitespace, // 预获取并缓存 prefetch: '././data/provinces.json' }); prefetch_provinces.initialize(); $('#ajax-prefetch-example .typeahead').typeahead({ hint: true, highlight: true, minLength: 1 } , { name: 'provinces', displayKey: 'value', source: prefetch_provinces.ttAdapter() });
数据为:
[ { "Id":1, "value": "广东省" }, { "Id":2, "value": "海南省" }, { "Id":3, "value": "山西省" }, { "Id":4, "value": "山东省" }, { "Id":5, "value": "湖北省" }, { "Id":6, "value": "湖南省" }, { "Id":7, "value": "陕西省" }, { "Id":8, "value": "上海市" }, { "Id":9, "value": "北京市" }, { "Id":10, "value": "广西省" } ]
文件结构为:
效果以下:
这时候咱们发现了一个问题,当你输入一个“海”字,是否还能跟示例1同样,出现“海南省”和“上海市”呢?答案看图:
结果是不能!!
为何呢??哈哈~由于相比示例1,示例2没有严谨的正则表达式再作筛选,改进方法是本身再添加多一个正则判断!
3.Ajax及时获取数据示例(remote)
Html代码:
<div class="example"> <h2>Ajax及时获取数据示例</h2> <div id="ajax-remote-example"> <input class="typeahead" type="text" placeholder="请输入城市"> </div> </div>
JS代码为:
/*** 3.Ajax及时获取数据示例 ***/ //远程数据源 var remote_cities = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('CityName'), queryTokenizer: Bloodhound.tokenizers.whitespace, // 在文本框输入字符时才发起请求 remote: '././ajax/GetCities?q=%QUERY' }); remote_cities.initialize(); $('#ajax-remote-example .typeahead').typeahead({ hint: true, highlight: true, minLength: 1 }, { name: 'cities', displayKey: 'CityName', source: remote_cities.ttAdapter(), });
数据为:
[{"Id":1,"ProvinceName":"广东省","CityName":"广州市"},{"Id":2,"ProvinceName":"山东省","CityName":"济南市"},{"Id":3,"ProvinceName":"陕西省","CityName":"西安市"},{"Id":4,"ProvinceName":"北京市","CityName":"北京市"},{"Id":5,"ProvinceName":"广西自治区","CityName":"南宁市"},{"Id":6,"ProvinceName":"江苏省","CityName":"南京市"}]
文件结构为:
效果图为:
看到这里应该有很多人有疑问吧?为何输入“南”字,虽然与“南”相关的数据都有匹配到,可是全部数据都出来了?这是为何呢?
答案有点绕,首先,咱们要清楚一点,remote的方法是当你触发事件后,才想远程及时获取数据的,可是示例3所有用到的是前端的东西,只是模拟从远程拿取数据,并无从真正的服务器上面获取,因此结果就是显示全部数据(个人错!哈哈哈),解决方法就是:在服务端加多一个正则加以过滤,只有匹配到的才拿下来。虽说前端也是能够作过滤的,可是尽可能不要把没必要要的数据下载下来。
有些同窗可能会问了,示例2和示例3的数据匹配方式好像不一样耶?为何同一个库示例2匹配只从头开始,而示例3则是任意文字匹配呢?
答案:由于在typeahead里面prefetch和remote封装的方法不一样。详情能够查看typeahead里面的源码。
接口:
name —— 数据集的名字。
source —— 规定包含查询时要显示的值的数据源。值的类型是 array,默认值是 [ ]。
items —— 规定查询时要显示的条目的最大值。数据类型是 number,默认值是 8。
highlighter —— 用于自动高亮突出显示结果。带有一个单一的参数,即具备 typeahead 实例范围的条目。数据类型是 function。默认状况下是高亮突出显示全部默认的匹配项。
minLength —— 推荐引擎开始渲染所须要的最小字符。默认为 1 。
hint —— 默认为 true,会自动补全第一个匹配的元素,设置为 false 时,typeahead 将不会补全 .
display - 对于推荐对象,决定用何种字符串表示,并将会在某个输入控件选择后使用。其值能够是关键字符串,或者是将推荐对象转换为string的函数。默认为 value.
$('.typeahead').typeahead('destroy');移除typeahead功能,并将 input 元素的状态重置为原始状态。
$('.typeahead').typeahead('open');打开typeahead下拉菜单。
$('.typeahead').typeahead('close');关闭typeahead的下拉菜单。
var myVal = $('.typeahead').typeahead('val'); 返回typeahead的当前值,该值为用户输入到 input 元素中的文本
$('.typeahead').typeahead('val', myVal);设置typeahead的值,要来替代 jQuery#val 函数。
实属原创,若有错误,烦请指教!