autocomplete实现联想输入,自动补全
jQuery.AutoComplete是一个基于jQuery的自动补全插件。借助于jQuery优秀的跨浏览器特性,可以兼容Chrome/IE/Firefox/Opera/Safari等多种浏览器。
特性一览:
- 支持补全列表的宽度设定。
- 支持补全列表的最大高度设定。
- 支持补全列表的行数限制。
- 支持补全列表的显示位置及方向的设定。
- 支持自定义匹配规则。
- 支持匹配文本的渲染。
- 支持自定义匹配文本的渲染样式。
- 支持补全列表的样式设定。
- 支持自定义补全列表项的创建。
- 支持多种数据源。
- 支持'json'和'xml'两种数据格式。
- 支持异步处理。
- 支持错误调试。
- 支持jQuery1.7.1+。
先看效果图:
上图是通过ajax请求服务器返回的数据。下面简单介绍如何使用。
一、如何使用:
二、参数说明:
$("#tt").AutoComplete({
'data': ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve']
});
data可以是数组,也可以是url,但url返回的数据必须是数组。
三、示例:
<input type="text" id="tt" value="" class="text" />
$(function(){ $("#tt").AutoComplete({
'data':['Cambodia', 'Cameroon', 'Canada', 'Cape-Verde', 'Cayman-Islands', 'Central-African-Republic', 'Chad', 'Chile', 'China', 'Colombia', 'Commonwealth', 'Comoros', 'Costa-Rica', "Cote-d'Ivoire", 'Croatia', 'Cuba', 'Cyprus', 'Czech-Republic'],
}); })
注意data是有引号的。
2、ajax请求:
<input type="text" id="company" value="" class="text" />
javascript代码:
$(function(){
$("#tt").AutoComplete({
'data':'http://localhost/test/suggestCom',
});
})
服务端返回数据格式:
["\u5317\u4eac\u73b0\u4ee3","\u5317\u4eac\u57ce\u5efa\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u5efa\u5de5\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u9996\u90fd\u65c5\u6e38\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u533b\u836f\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u4e00\u8f7b\u63a7\u80a1\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u91d1\u9685\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u71d5\u4eac\u5564\u9152\u96c6\u56e2\u516c\u53f8","\u5317\u4eac\u5e02\u71c3\u6c14\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8","\u5317\u4eac\u4f4f\u603b\u96c6\u56e2\u6709\u9650\u8d23\u4efb\u516c\u53f8"]
服务端的代码:(以ThinkPHP示例)
public function suggestCom(){
$wd = $_GET['keyword'];
$keywords = $wd; $company_model = M('Company'); $res = $company_model->where("name like '%".$keywords."%' or abbr like '%".$keywords."%' ")->limit(10)->select();
foreach($res as $v){
$suggestions[]= $v['name'];
} echo json_encode($suggestions);
}
注意默认是GET过来的数据,名称是keyword,返回数据是和本地data一致的。
附上jquery.autocomplete.js和jquery.autocomplete.css文件代码:
jquery.autocomplete.js
/*
* jQuery.autocomplete.js (v1.1.2)
* authored by nswish (nswish@gmail.com)
* jQuery 1.7.1+ support
* compatible: ie/chrome/firefox/opera/safari
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function($){
$.fn.extend({
'AutoComplete': function(option){
return this.each(function(){
if (!(this && this.tagName === 'INPUT' && this.type === 'text')) return; if(this.controller)
this.controller.setOption(option);
else {
if($.isPlainObject(option))
this.controller = new Controller(this, option);
}
});
}
}); // ------- Construct Method Here -------------
var Controller = function(input, option){
this.option = $.extend(false, {
// style
'width': 320, // number, string 'auto'
'maxHeight': null, // number
'itemHeight': null, // number
'listStyle': 'normal', // string 'normal', 'iconList', 'custom'
'listDirection': 'down', // string 'down' or 'up'
// data
'data': [], // array, string, function
'ajaxDataType': 'json', // string 'json' or 'xml'
'ajaxParams': {}, // function, string, object
'ajaxTimeout': 3000, // number
'ajaxType': 'GET', // string 'GET' or 'POST'
'maxItems': 20, // number
// event
'matchHandler': defaultMatchHandler, // function
'emphasisHandler': defaultEmphasisHandler, // function
'createItemHandler': null, // function
'beforeLoadDataHandler': null, // function
'afterSelectedHandler': null, // function
// behavior
'async': false, // bool
'emphasis': true, // bool
// debug
'onerror': null // function
}, option); _setupInputView.apply(this, [input]);
_setupSearchView.apply(this);
}; // ------- Private Method Here -------------
var _setupInputView = function(input){
var that = this; this.inputView = $(input); this.inputView
.attr('autocomplete', 'off') // disable IE's autocomplete feature
.keyup(this._keyup = function(event){
switch(event.keyCode){
case 13: // enter
case 16: // shift
case 17: // ctrl
case 37: // left
case 38: // up
case 39: // right
case 40: // down
break;
case 27: // esc
_emptySearchView.apply(that);
break;
default:
if(that.option.async){
setTimeout(function(){
_search.apply(that);
}, 0);
} else {
_search.apply(that);
}
}
})
.keydown(this._keydown = function(event){
switch(event.keyCode){
case 38: // up
_move.apply(that, ['up']);
break;
case 40: // down
_move.apply(that, ['down']);
break;
case 13: // enter
var isSearchViewVisible = that.searchView.is(':visible');
_select.apply(that);
if(isSearchViewVisible)
return false;
break;
}
})
.blur(this._blur = function(){
$(document).one('click', function(){
_emptySearchView.apply(that);
});
});
}; var _setupSearchView = function(){
var that = this; this.searchView = $("<div class='ac'><ul></ul></div>")
.appendTo(document.body)
.on('mouseenter', 'li', function(){
that.searchView.find("li.selected").removeClass("selected");
$(this).addClass('selected');
})
.on('mouseleave', 'li', function(){
$(this).removeClass('selected');
})
.on('click', 'li', function(){
_select.apply(that);
_emptySearchView.apply(that);
})
.css('font-size', this.inputView.css('font-size')); $(window).resize(function(){
_locateSearchView.apply(that);
});
}; var _createItems = function(result){
var that = this,
container = this.searchView.find('ul').empty(); if ($.inArray(this.option.listStyle, ['normal', 'iconList', 'custom']) == -1) {
throw ['遇到未知的listStyle参数!'];
}; $.each(result, function(index, data){
var item = $("<li><div></div></li>").appendTo(container).addClass(that.option.listStyle).data("data", data).find("div"); switch(that.option.listStyle){
case 'normal':
item.append("<span>"+data.label+"</span>");
break;
case 'iconList':
var img = $("<img></img>").attr('src', data.image);
item.append($("<div></div>").append(img)).append("<span>"+data.label+"</span>");
break;
case 'custom':
item.append(that.option.createItemHandler.apply(that, [index, data]));
case 'default':
break;
} if(that.option.itemHeight > 0){
item.height(that.option.itemHeight).css('max-height', that.option.itemHeight);
}
});
}; var _locateSearchView = function(){
if(this.option.listDirection === 'down'){
var top = this.inputView.offset().top + this.inputView.outerHeight();
} else if(this.option.listDirection === 'up'){
var top = this.inputView.offset().top - this.searchView.outerHeight();
} else {
throw '遇到未知的listDirection参数!';
} var left = this.inputView.offset().left;
this.searchView.css("top", top+"px").css("left", left+"px");
}; var _calcWidth = function(){
if(typeof(this.option.width) === 'string' && this.option.width.toLowerCase() === 'auto'){
return this.inputView.outerWidth() - 2;
} else if(typeof(this.option.width) === 'number'){
return this.option.width;
} else {
throw '遇到未知的width参数!';
}
} var _showSearchView = function(result){
var that = this; if(this.option.listDirection === 'up')
result = result.reverse(); try{
_createItems.apply(that, [result]);//console.log("length="+this.searchView.find('li').size()); if(this.option.maxHeight > 0){
this.searchView.css('max-height', this.option.maxHeight+"px");
if($.browser.msie){
this.searchView.css("height", this.searchView.height() > this.option.maxHeight ? this.option.maxHeight+"px" : "auto");
}
} // 定位补全列表
_locateSearchView.apply(this); // 计算并设定补全列表的宽度
this.searchView.css("width", _calcWidth.apply(this)+'px'); } catch(ex) {
_error.apply(this, [ex+'']);
return;
} this.searchView.show(); _move.apply(this, [this.option.listDirection]);
}; var _emptySearchView = function(){
this.searchView.find('ul').empty();
this.searchView.hide();
}; var _move = function(dir){
var selected = this.searchView.find('li.selected'); if (selected.size())
var nextSelected = dir === 'up' ? selected.prev() : selected.next();
else
var nextSelected = dir === 'up' ? this.searchView.find('li').last() : this.searchView.find('li').first(); if(nextSelected.size()){
this.searchView.find('li').removeClass('selected');
nextSelected.addClass("selected"); var itemHeight = nextSelected.outerHeight();
var itemTop = nextSelected.position().top;
if(itemHeight + itemTop > this.searchView.height())
this.searchView.scrollTop(this.searchView.scrollTop() + itemTop + itemHeight - this.searchView.height());
else if(itemTop < 0)
this.searchView.scrollTop(this.searchView.scrollTop() + itemTop);
}
}; var _select = function(){
var that = this,
selected = this.searchView.find('li.selected'); if (selected.size()) {
var data = selected.data('data'); this.inputView.val(data.value); if ($.isFunction(this.option.afterSelectedHandler)) {
try{
this.option.afterSelectedHandler.apply(that, [data]);
} catch(e) {
_error.apply(this, ['调用afterSelectedHandler错误:'+e]);
return;
}
} _emptySearchView.apply(this);
}
}; var _ajaxSend = function(keyword){
jQuery.support.cors = true;
var that = this,
data = [],
ajaxOption = {
'async': false,
'dataType': that.option.ajaxDataType,
'type': that.option.ajaxType,
'timeout': this.option.ajaxTimeout,
'success': function(theData, textStatus, jqXHR){
if (that.option.ajaxDataType === 'xml') {
$(theData).find('item').each(function(){
var item = {
'value': $(this).text(),
'label': $(this).text()
}; for (var i=0; i<this.attributes.length; i++) {
var key = this.attributes[i].nodeName,
value = this.attributes[i].nodeValue; item[key] = value;
}; data.push(item);
});
} else if(that.option.ajaxDataType === 'json') {
data = theData;
} else {
throw '遇到未知的ajaxDataType参数!';
}
},
'error': function(jqXHR, textStatus, errorThrown){
throw errorThrown;
}
}; if ($.isPlainObject(this.option.ajaxParams)) {
ajaxOption['data'] = $.extend(false, {'keyword': keyword}, this.option.ajaxParams);
} else if ($.isFunction(this.option.ajaxParams)) {
ajaxOption['data'] = $.extend(false, {'keyword': keyword}, this.option.ajaxParams.apply(this, [keyword]));
} else if (typeof(this.option.ajaxParams) === 'string') {
ajaxOption['data'] = "keyword=" + keyword + "&" + this.option.ajaxParams;
} else {
throw '遇到未知的ajaxParams参数!';
} $.ajax(this.option.data, ajaxOption); return data;
}; var _search = function(){
var that = this,
keyword = this.inputView.val(),
data = [],
loadDataFlag = true,
result = []; if($.trim(keyword).length == 0){
_emptySearchView.apply(that);
return;
} // invoke beforeLoadDataHandler if exists
if ($.isFunction(this.option.beforeLoadDataHandler)) {
try{
loadDataFlag = this.option.beforeLoadDataHandler.apply(this, [keyword]);
} catch(e) {
_error.apply(this, ['调用beforeLoadDataHandler错误:'+e]);
return;
}
} if (loadDataFlag){
if ($.isArray(this.option.data)) {
data = this.option.data;
} else if ($.isFunction(this.option.data)) {
try{
data = this.option.data.apply(this, [keyword]);
} catch(e) {
_error.apply(this, ['调用data错误:'+e]);
return;
}
} else if (typeof(this.option.data) === 'string') {
try{
data = _ajaxSend.apply(this, [keyword]);
} catch(e) {
_error.apply(this, ['Ajax错误:'+e]);
return;
}
} else {
_error.apply(this, ['遇到未知的data参数!']);
return;
}
} $.each(data, function(index, value){
if(that.option.maxItems > 0 && result.length >= that.option.maxItems)
return false; if($.isPlainObject(value)){
var item = $.extend(false, {}, value);
} else if(typeof(value) === 'string') {
var item = {'label': value, 'value': value, 'image': value};
} else {
_error.apply(that, ['数据源Item类型错误!']);
return false;
} if(that.option.matchHandler.apply(that, [keyword, item])){
result.push(item);
}
}); if(keyword == this.inputView.val()){
if(result.length > 0)
_showSearchView.apply(this, [result]);
else
_emptySearchView.apply(this);
}
}; var _error = function(msg){
if($.isFunction(this.option.onerror)){
this.option.onerror.apply(this, [msg]);
}
}; // ------- Public Method Here -------------
Controller.prototype.setOption = function(option){
if ($.isPlainObject(option)) {
this.option = $.extend(false, this.option, option);
} else if(typeof(option) === 'string'){
switch(option){
case 'destroy':
this.destroy();
break;
case 'show':
this.show();
break;
default:
_error.apply(this, ['未知的AutoComplete参数!']);
return;
}
} else {
_error.apply(this, ['未知的AutoComplete参数类型!']);
return;
}
}; Controller.prototype.destroy = function(){
this.searchView.remove();
this.inputView.unbind('keyup', this._keyup).unbind('keydown', this._keydown).unbind('blur', this._blur);
delete this.inputView.get(0).controller;
}; Controller.prototype.show = function(){
if(this.option.async){
setTimeout(function(){
_search.apply(this);
}, 0);
} else {
_search.apply(this);
}
}; // ------- Default Handler Function Here -------------
var defaultMatchHandler = function(keyword, data){
var regex = RegExp(keyword.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"), 'i');
if(this.option.emphasis && $.isFunction(this.option.emphasisHandler))
this.option.emphasisHandler.apply(this, [keyword, data]);
return regex.test(data.value);
}; var defaultEmphasisHandler = function(keyword, data){
var regex = RegExp("("+keyword.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1")+")", 'ig');
data.label = data.label.replace(regex, "<em>$1</em>");
}; })(jQuery);
jquery.autocomplete.css
/*
* jQuery.autocomplete.css (v1.1.0)
* authored by nswish (nswish@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
div.ac {
border-style: solid;
border-width: 1px;
border-color: gray;
position: absolute;
display: none;
overflow: auto;
} div.ac > ul {
margin: 0px;
padding: 0px;
} div.ac > ul > li {
margin: 0px;
list-style-type: none;
background-color: white;
word-break: break-all;
font-family: helvetica, arial, "Courier New", sans-serif;
} div.ac > ul > li > div {
display: table-row;
width: 100%;
} div.ac > ul > li > div em {
background-color: #B0E2FF;
font-style: normal;
} div.ac > ul > li.normal {
padding: 2px 0px 2px 2px;
} div.ac > ul > li.normal > div > span{
display: table-cell;
vertical-align: middle;
} div.ac > ul > li.iconList {
padding: 0px 0px 0px 2px;
} div.ac > ul > li.iconList > div > div {
display: table-cell;
vertical-align: middle;
padding-right: 5px;
} div.ac > ul > li.iconList > div > div > img {
display: table;
display: table-cell\9;
} div.ac > ul > li.iconList > div > span {
display: table-cell;
vertical-align: middle;
} div.ac > ul > li.selected {
background-color: #DCDCDC;
}
页面html代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jquery实现仿搜索引擎文本框自动补全插件 - autocomplete</title> <script src="__PUBLIC__/dwz/js/jquery-1.7.min.js" type="text/javascript"></script>
<script src="__PUBLIC__/autocomplete/jquery.autocomplete.js?v=2"></script>
<link rel="stylesheet" href="__PUBLIC__/autocomplete/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript">
$(function(){ $("#tt").AutoComplete({
'data':'__MODULE__/test/suggestCom2',
}); })
</script> </head>
<body> <style type="text/css">
*{margin:0;padding:0;list-style-type:none;}
a,img{border:0;}
.demo{width:720px;margin:30px auto;}
.demo h2{font-size:16px;color:#3366cc;height:30px;}
.demo li{float:left;}
.text,.button{background:url(http://su.bdimg.com/static/superpage/img/spis_031ddf34.png) no-repeat;}
.text{width:529px;height:22px;padding:4px 7px;padding:6px 7px 2px\9;font:16px arial;border:1px solid #cdcdcd;border-color:#9a9a9a #cdcdcd #cdcdcd #9a9a9a;vertical-align:top;outline:none;margin:0 5px 0 0;}
.button{width:95px;height:32px;padding:0;padding-top:2px\9;border:0;background-position:0 -35px;background-color:#ddd;cursor:pointer}
</style> <div class="demo">
<h2>autocomplete联想输入测试</h2>
<form action="" method="post" name="searchform" id="searchform" class="searchinfo">
<ul>
<li><input type="text" id="tt" value="" class="text" /></li>
<li><input type="submit" value="搜索" class="button" /></li>
</ul>
</form>
</div> </body>
</html>
autocomplete实现联想输入,自动补全的更多相关文章
- bigautocomplete实现联想输入,自动补全
bigautocomplete是一款Jquery插件.用它实现仿搜索引擎文本框自动补全插件功能很实用,使用也很简单,引入了插件之后写几行代码就可以实现,可以灵活设置. 先看效果图: 上图是通过ajax ...
- Autocomplete 自动补全(Webform实战篇)
开篇语 因为项目中需要用到一个自动补全的功能,功能描述: 需求一:新增收件人的时候,自动下拉显示出数据库中所有的收件人信息(显示的信息包括:姓名-收件地址-联系方式) 需求二:选中一个值得时候,分别赋 ...
- jQuery AutoComplete 自动补全
jQuery.AutoComplete是一个基于jQuery的自动补全插件.借助于jQuery优秀的跨浏览器特性,可以兼容Chrome/IE/Firefox/Opera/Safari等多种浏览器. 特 ...
- jquery autocomplete实现读取sql数据库自动补全TextBox
转自我本良人 原文 jquery autocomplete实现读取sql数据库自动补全TextBox 项目需要这样子一个功能,其他部门提的意见,只好去实现了哦,搞了好久才弄出来,分享一下. 1.前台页 ...
- gocode+auto-complete搭建emacs的go语言自动补全功能
上篇随笔记录了在emacs中使用go-mode和goflymake搭建了go语言的简单编程环境(推送门),今天来记录一下使用gocode+auto-complete配置emacs中go语言的自动补全功 ...
- WinForm AutoComplete 输入提示、自动补全
一.前言 又临近春节,作为屌丝的我,又要为车票发愁了.记得去年出现了各种12306的插件,最近不忙,于是也着手自己写个抢票插件,当是熟悉一下WinForm吧.小软件还在开发中,待完善后,也写篇博客与大 ...
- jquery.autocomplete自动补全功能
项目实例: 一:js //SupplierAutoComplete.js $().ready(function () { $("#txtSupplier").autocomplet ...
- [LeetCode] Design Search Autocomplete System 设计搜索自动补全系统
Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...
- jQuery搜索框自动补全功能插件实现-autocomplete.js
最近用nodeclub实现股票的输入关键字自动补全股票信息进行搜索功能,原先用jQuery-ui,结果jQuery-ui库太大,所以考虑用其他插件,最终选择使用autocomplete.js,控件简单 ...
随机推荐
- debian 8 和centos 配置java 环境变量的正确姿态
export JAVA_HOME=/usr/java/jre1.8.0_111export JAVA_BIN=/usr/java/jre1.8.0_111/binexport PATH=$PATH:$ ...
- eclipse tomcat maven热部署
1. tomcat插件 如果是Kepler的话,已经自带了tomcat插件,如果没有,到http://www.eclipsetotale.com/tomcatPlugin.html下载安装或在线安装 ...
- union all 里面的order by
例1: SELECT 1 order2 FROM dual union all SELECT 3 order2 FROM dual union all SELECT 2 order1 FROM dua ...
- 如何用Jquery实现 ,比如点击图片之后 ,该图片变成向下的箭头,再点击向下箭头的图片 又变成原始图片呢
<!DOCTYPE html><html><head><meta charset="utf-8" /><title>切换 ...
- rem 和 ::
-------siwuxie095 rem 和 :: 都是用作批处理注解(等同于各种编程语言中的注释) 注解批处理时,标准写法是写在被注解代码的上一行 REM 在批处理文件或CONFIG.SYS里 ...
- std::reverse_iterator::base
google chromium base MRU_Cache 支持反向erase iterator Erase(iterator pos) { deletor_(pos->second); ...
- 代码中修改组件的margin属性
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_ ...
- ngxtop:在命令行实时监控 Nginx 的神器
Nginx网站服务器在生产环境中运行的时候需要进行实时监控.实际上,诸如Nagios, Zabbix, Munin 的网络监控软件是支持 Nginx 监控的. 如果你不需要以上软件提供的综合性报告或者 ...
- Pair Project: Elevator Scheduler [电梯调度算法的实现和测试]
作业提交时间:10月9日上课前. Design and implement an Elevator Scheduler to aim for both correctness and performa ...
- (Python)list的内建函数 filter(), map(), 和 reduce()
这一节,我们将主要学习用于list的三个内建函数: filter(), map(), 和 reduce(). 1.filter(function, sequence) 逐个从sequence中取一个 ...