以下是 下拉查询筛选插件Combo Select js代码 的示例演示效果:
部分效果截图1:
部分效果截图2:
部分效果截图3:
部分效果截图4:
HTML代码(index.html):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>下拉查询筛选插件Combo Select - 默认</title>
<link rel="stylesheet" href="css/combo.select.css">
<style>
.zzsc { width: 400px; margin: 100px auto;}
</style>
</head>
<body>
<h1>默认</h1>
<div class="zzsc">
<select>
<option value="">月份</option>
<option value="一月">一月</option>
<option value="二月">二月</option>
<option value="三月">三月</option>
<option value="四月">四月</option>
<option value="五月">五月</option>
<option value="六月">六月</option>
<option value="七月">七月</option>
<option value="八月">八月</option>
<option value="九月">九月</option>
<option value="十月">十月</option>
<option value="十一月">十一月</option>
<option value="十二月">十二月</option>
</select>
</div>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jquery.combo.select.js"></script>
<script>
$(function() {
$('select').comboSelect();
});
</script>
<!-- 以下信息与演示无关,可不必理会 -->
<style>
body { margin: 0; border-left: 200px solid #ccc;}
h1 { width: 1000px; margin: 40px auto; font: 32px "Microsoft Yahei"; text-align: center;}
.menu { position: absolute; left: 0; top: 0; bottom: 0; width: 200px; padding-top: 100px; font-family: Consolas,arial,"宋体"; background-color: #ccc;}
.menu a { display: block; height: 40px; margin: 0 0 1px 2px; padding-left: 10px; line-height: 40px; font-size: 14px; color: #333; text-decoration: none;}
.menu a:hover { background-color: #eee;}
.menu .cur { color: #000; background-color: #fff !important;}
.vad { margin: 320px 0 10px; font-family: Consolas,arial,宋体,sans-serif; text-align:center;}
.vad a { display: inline-block; height: 36px; line-height: 36px; margin: 0 5px; padding: 0 50px; font-size: 14px; text-align:center; color:#eee; text-decoration: none; background-color: #222;}
.vad a:hover { color: #fff; background-color: #000;}
.thead { width: 728px; height: 90px; margin: 0 auto; border-bottom: 40px solid transparent;}
</style>
<div class="menu">
<a class="cur" href="index.html">1、默认</a>
<a href="index2.html">2、分组</a>
<a href="index3.html">3、默认选中/禁用</a>
<a href="index4.html">4、回调函数</a>
<a href="index5.html">5、展开/收起</a>
</div>
</body>
</html>
HTML代码(index2.html):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>下拉查询筛选插件Combo Select - 分组</title>
<link rel="stylesheet" href="css/combo.select.css">
<style>
.zzsc { width: 400px; margin: 100px auto;}
</style>
</head>
<body>
<h1>分组</h1>
<div class="zzsc">
<select>
<option value="">城市</option>
<optgroup label="广东省">
<option value="深圳">深圳</option>
<option value="广州">广州</option>
<option value="珠海">珠海</option>
<option value="惠州">惠州</option>
</optgroup>
<optgroup label="湖南省">
<option value="长沙">长沙</option>
<option value="株洲">株洲</option>
<option value="岳阳">岳阳</option>
<option value="张家界">张家界</option>
</optgroup>
<optgroup label="江西省">
<option value="南昌">南昌</option>
<option value="赣州">赣州</option>
<option value="宜春">宜春</option>
<option value="九江">九江</option>
</optgroup>
</select>
</div>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/jquery.combo.select.js"></script>
<script>
$(function() {
$('select').comboSelect()
});
</script>
<!-- 以下信息与演示无关,可不必理会 -->
<style>
body { margin: 0; border-left: 200px solid #ccc;}
h1 { width: 1000px; margin: 40px auto; font: 32px "Microsoft Yahei"; text-align: center;}
.menu { position: absolute; left: 0; top: 0; bottom: 0; width: 200px; padding-top: 100px; font-family: Consolas,arial,"宋体"; background-color: #ccc;}
.menu a { display: block; height: 40px; margin: 0 0 1px 2px; padding-left: 10px; line-height: 40px; font-size: 14px; color: #333; text-decoration: none;}
.menu a:hover { background-color: #eee;}
.menu .cur { color: #000; background-color: #fff !important;}
.vad { margin: 320px 0 10px; font-family: Consolas,arial,宋体,sans-serif; text-align:center;}
.vad a { display: inline-block; height: 36px; line-height: 36px; margin: 0 5px; padding: 0 50px; font-size: 14px; text-align:center; color:#eee; text-decoration: none; background-color: #222;}
.vad a:hover { color: #fff; background-color: #000;}
.thead { width: 728px; height: 90px; margin: 0 auto; border-bottom: 40px solid transparent;}
</style>
<div class="menu">
<a href="index.html">1、默认</a>
<a class="cur" href="index2.html">2、分组</a>
<a href="index3.html">3、默认选中/禁用</a>
<a href="index4.html">4、回调函数</a>
<a href="index5.html">5、展开/收起</a>
</div>
</body>
</html>
JS代码(jquery.combo.select.js):
/*jshint asi:true,expr:true */
/** * Plugin Name:Combo Select * Author:Vinay@Pebbleroad * Date:23/11/2014 * Description:* Converts a select box into a searchable and keyboard friendly interface. Fallbacks to native select on mobile and tablets */
// Expose plugin as an AMD module if AMD loader is present:(function (factory){
'use strict';
if (typeof define === 'function' && define.amd){
// AMD. Register as an anonymous module.define(['jquery'],factory);
}
else if (typeof exports === 'object' && typeof require === 'function'){
// Browserifyfactory(require('jquery'));
}
else{
// Browser globalsfactory(jQuery);
}
}
(function ( $,undefined ){
var pluginName = "comboSelect",dataKey = 'comboselect';
var defaults ={
comboClass:'combo-select',comboArrowClass:'combo-arrow',comboDropDownClass:'combo-dropdown',inputClass:'combo-input text-input',disabledClass:'option-disabled',hoverClass:'option-hover',selectedClass:'option-selected',markerClass:'combo-marker',themeClass:'',maxHeight:200,extendStyle:true,focusInput:true}
;
/** * Utility functions */
var keys ={
ESC:27,TAB:9,RETURN:13,LEFT:37,UP:38,RIGHT:39,DOWN:40,ENTER:13,SHIFT:16}
,isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
/** * Constructor * @param{
[Node]}
element [Select element] * @param{
[Object]}
options [Option object] */
function Plugin ( element,options ){
/* Name of the plugin */
this._name = pluginName;
/* Reverse lookup */
this.el = element/* Element */
this.$el = $(element)/* If multiple select:stop */
if(this.$el.prop('multiple')) return;
/* Settings */
this.settings = $.extend({
}
,defaults,options,this.$el.data() );
/* Defaults */
this._defaults = defaults;
/* Options */
this.$options = this.$el.find('option,optgroup')/* Initialize */
this.init();
/* Instances */
$.fn[ pluginName ].instances.push(this);
}
$.extend(Plugin.prototype,{
init:function (){
/* Construct the comboselect */
this._construct();
/* Add event bindings */
this._events();
}
,_construct:function(){
var self = this/** * Add negative TabIndex to `select` * Preserves previous tabindex */
this.$el.data('plugin_'+ dataKey + '_tabindex',this.$el.prop('tabindex'))/* Add a tab index for desktop browsers */
!isMobile && this.$el.prop("tabIndex",-1)/** * Wrap the Select */
this.$container = this.$el.wrapAll('<div class="' + this.settings.comboClass + ' '+ this.settings.themeClass + '" />').parent();
/** * Check if select has a width attribute */
if(this.settings.extendStyle && this.$el.attr('style')){
this.$container.attr('style',this.$el.attr("style"))}
/** * Append dropdown arrow */
this.$arrow = $('<div class="'+ this.settings.comboArrowClass+ '" />').appendTo(this.$container)/** * Append dropdown */
this.$dropdown = $('<ul class="'+this.settings.comboDropDownClass+'" />').appendTo(this.$container)/** * Create dropdown options */
var o = '',k = 0,p = '';
this.selectedIndex = this.$el.prop('selectedIndex')this.$options.each(function(i,e){
if(e.nodeName.toLowerCase() == 'optgroup'){
return o+='<li class="option-group">'+this.label+'</li>'}
if(!e.value) p = e.innerHTMLo+='<li class="'+(this.disabled? self.settings.disabledClass:"option-item") + ' ' +(k == self.selectedIndex? self.settings.selectedClass:'')+ '" data-index="'+(k)+'" data-value="'+this.value+'">'+ (this.innerHTML) + '</li>'k++;
}
)this.$dropdown.html(o)/** * Items */
this.$items = this.$dropdown.children();
/** * Append Input */
this.$input = $('<input type="text"' + (isMobile? 'tabindex="-1"':'') + ' placeholder="'+p+'" class="'+ this.settings.inputClass + '">').appendTo(this.$container)/* Update input text */
this._updateInput()}
,_events:function(){
/* Input:focus */
this.$container.on('focus.input','input',$.proxy(this._focus,this))/** * Input:mouseup * For input select() event to function correctly */
this.$container.on('mouseup.input','input',function(e){
e.preventDefault()}
)/* Input:blur */
this.$container.on('blur.input','input',$.proxy(this._blur,this))/* Select:change */
this.$el.on('change.select',$.proxy(this._change,this))/* Select:focus */
this.$el.on('focus.select',$.proxy(this._focus,this))/* Select:blur */
this.$el.on('blur.select',$.proxy(this._blurSelect,this))/* Dropdown Arrow:click */
this.$container.on('click.arrow','.'+this.settings.comboArrowClass,$.proxy(this._toggle,this))/* Dropdown:close */
this.$container.on('comboselect:close',$.proxy(this._close,this))/* Dropdown:open */
this.$container.on('comboselect:open',$.proxy(this._open,this))/* HTML Click */
$('html').off('click.comboselect').on('click.comboselect',function(){
$.each($.fn[ pluginName ].instances,function(i,plugin){
plugin.$container.trigger('comboselect:close')}
)}
);
/* Stop `event:click` bubbling */
this.$container.on('click.comboselect',function(e){
e.stopPropagation();
}
)/* Input:keydown */
this.$container.on('keydown','input',$.proxy(this._keydown,this))/* Input:keyup */
this.$container.on('keyup','input',$.proxy(this._keyup,this))/* Dropdown item:click */
this.$container.on('click.item','.option-item',$.proxy(this._select,this))}
,_keydown:function(event){
switch(event.which){
case keys.UP:this._move('up',event)break;
case keys.DOWN:this._move('down',event)break;
case keys.TAB:this._enter(event)break;
case keys.RIGHT:this._autofill(event);
break;
case keys.ENTER:this._enter(event);
break;
default:break;
}
}
,_keyup:function(event){
switch(event.which){
case keys.ESC:this.$container.trigger('comboselect:close')break;
case keys.ENTER:case keys.UP:case keys.DOWN:case keys.LEFT:case keys.RIGHT:case keys.TAB:case keys.SHIFT:break;
default:this._filter(event.target.value)break;
}
}
,_enter:function(event){
var item = this._getHovered()item.length && this._select(item);
/* Check if it enter key */
if(event && event.which == keys.ENTER){
if(!item.length){
/* Check if its illegal value */
this._blur();
return true;
}
event.preventDefault();
}
}
,_move:function(dir){
var items = this._getVisible(),current = this._getHovered(),index = current.prevAll('.option-item').filter(':visible').length,total = items.lengthswitch(dir){
case 'up':index--;
(index < 0) && (index = (total - 1));
break;
case 'down':index++;
(index >= total) && (index = 0);
break;
}
items.removeClass(this.settings.hoverClass).eq(index).addClass(this.settings.hoverClass)if(!this.opened) this.$container.trigger('comboselect:open');
this._fixScroll()}
,_select:function(event){
var item = event.currentTarget? $(event.currentTarget):$(event);
if(!item.length) return;
/** * 1. get Index */
var index = item.data('index');
this._selectByIndex(index);
this.$container.trigger('comboselect:close')}
,_selectByIndex:function(index){
/** * Set selected index and trigger change * @type{
[type]}
*/
if(typeof index == 'undefined'){
index = 0}
if(this.$el.prop('selectedIndex') != index){
this.$el.prop('selectedIndex',index).trigger('change');
}
}
,_autofill:function(){
var item = this._getHovered();
if(item.length){
var index = item.data('index')this._selectByIndex(index)}
}
,_filter:function(search){
var self = this,items = this._getAll();
needle = $.trim(search).toLowerCase(),reEscape = new RegExp('(\\' + ['/','.','*','+','?','|','(',')','[',']','{
','}
','\\'].join('|\\') + ')','g'),pattern = '(' + search.replace(reEscape,'\\$1') + ')';
/** * Unwrap all markers */
$('.'+self.settings.markerClass,items).contents().unwrap();
/* Search */
if(needle){
/* Hide Disabled and optgroups */
this.$items.filter('.option-group,.option-disabled').hide();
items.hide().filter(function(){
var $this = $(this),text = $.trim($this.text()).toLowerCase();
/* Found */
if(text.toString().indexOf(needle) != -1){
/** * Wrap the selection */
$this.html(function(index,oldhtml){
return oldhtml.replace(new RegExp(pattern,'gi'),'<span class="'+self.settings.markerClass+'">$1</span>')}
)return true}
}
).show()}
else{
this.$items.show();
}
/* Open the comboselect */
this.$container.trigger('comboselect:open')}
,_highlight:function(){
/*1. Check if there is a selected item2. Add hover class to it3. If not add hover class to first item*/
var visible = this._getVisible().removeClass(this.settings.hoverClass),$selected = visible.filter('.'+this.settings.selectedClass)if($selected.length){
$selected.addClass(this.settings.hoverClass);
}
else{
visible.removeClass(this.settings.hoverClass).first().addClass(this.settings.hoverClass)}
}
,_updateInput:function(){
var selected = this.$el.prop('selectedIndex')if(this.$el.val()){
text = this.$el.find('option').eq(selected).text()this.$input.val(text)}
else{
this.$input.val('')}
return this._getAll().removeClass(this.settings.selectedClass).filter(function(){
return $(this).data('index') == selected}
).addClass(this.settings.selectedClass)}
,_blurSelect:function(){
this.$container.removeClass('combo-focus');
}
,_focus:function(event){
/* Toggle focus class */
this.$container.toggleClass('combo-focus',!this.opened);
/* If mobile:stop */
if(isMobile) return;
/* Open combo */
if(!this.opened) this.$container.trigger('comboselect:open');
/* Select the input */
this.settings.focusInput && event && event.currentTarget && event.currentTarget.nodeName == 'INPUT' && event.currentTarget.select()}
,_blur:function(){
/** * 1. Get hovered item * 2. If not check if input value == select option * 3. If none */
var val = $.trim(this.$input.val().toLowerCase()),isNumber = !isNaN(val);
var index = this.$options.filter(function(){
if(isNumber){
return parseInt($.trim(this.innerHTML).toLowerCase()) == val}
return $.trim(this.innerHTML).toLowerCase() == val}
).prop('index')/* Select by Index */
this._selectByIndex(index)}
,_change:function(){
this._updateInput();
}
,_getAll:function(){
return this.$items.filter('.option-item')}
,_getVisible:function(){
return this.$items.filter('.option-item').filter(':visible')}
,_getHovered:function(){
return this._getVisible().filter('.' + this.settings.hoverClass);
}
,_open:function(){
var self = thisthis.$container.addClass('combo-open')this.opened = true/* Focus input field */
this.settings.focusInput && setTimeout(function(){
!self.$input.is(':focus') && self.$input.focus();
}
);
/* Highligh the items */
this._highlight()/* Fix scroll */
this._fixScroll()/* Close all others */
$.each($.fn[ pluginName ].instances,function(i,plugin){
if(plugin != self && plugin.opened) plugin.$container.trigger('comboselect:close')}
)}
,_toggle:function(){
this.opened? this._close.call(this):this._open.call(this)}
,_close:function(){
this.$container.removeClass('combo-open combo-focus')this.$container.trigger('comboselect:closed')this.opened = false/* Show all items */
this.$items.show();
}
,_fixScroll:function(){
/** * If dropdown is hidden */
if(this.$dropdown.is(':hidden')) return;
/** * Else */
var item = this._getHovered();
if(!item.length) return;
/** * Scroll */
var offsetTop,upperBound,lowerBound,heightDelta = item.outerHeight()offsetTop = item[0].offsetTop;
upperBound = this.$dropdown.scrollTop();
lowerBound = upperBound + this.settings.maxHeight - heightDelta;
if (offsetTop < upperBound){
this.$dropdown.scrollTop(offsetTop);
}
else if (offsetTop > lowerBound){
this.$dropdown.scrollTop(offsetTop - this.settings.maxHeight + heightDelta);
}
}
,/** * Destroy API */
dispose:function(){
/* Remove combo arrow,input,dropdown */
this.$arrow.remove()this.$input.remove()this.$dropdown.remove()/* Remove tabindex property */
this.$el.removeAttr("tabindex")/* Check if there is a tabindex set before */
if(!!this.$el.data('plugin_'+ dataKey + '_tabindex')){
this.$el.prop('tabindex',this.$el.data('plugin_'+ dataKey + '_tabindex'))}
/* Unwrap */
this.$el.unwrap()/* Remove data */
this.$el.removeData('plugin_'+dataKey)/* Remove tabindex data */
this.$el.removeData('plugin_'+dataKey + '_tabindex')/* Remove change event on select */
this.$el.off('change.select focus.select blur.select');
}
}
);
// A really lightweight plugin wrapper around the constructor,// preventing against multiple instantiations$.fn[ pluginName ] = function ( options,args ){
this.each(function(){
var $e = $(this),instance = $e.data('plugin_'+dataKey)if (typeof options === 'string'){
if (instance && typeof instance[options] === 'function'){
instance[options](args);
}
}
else{
if (instance && instance.dispose){
instance.dispose();
}
$.data( this,"plugin_" + dataKey,new Plugin( this,options ) );
}
}
);
// chain jQuery functionsreturn this;
}
;
$.fn[ pluginName ].instances = [];
}
));
CSS代码(combo.select.css):
/** * Variables */
/** * Wrapper */
.combo-select{position:relative;max-width:400px;margin-bottom:15px;font:100% Helvetica,Arial,Sans-serif;border:1px #ccc solid;border-radius:3px;}
.combo-select .combo-input{margin-bottom:0;}
/** * Input field */
.combo-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;text-overflow:ellipsis;white-space:nowrap;border:none;width:100%;box-sizing:border-box;padding:12px;padding-right:60px;border-radius:3px;}
.combo-input:focus{outline:none;}
/** * Arrow */
.combo-arrow{position:absolute;right:0;top:0;height:100%;cursor:pointer;text-align:center;font-size:14px;width:40px;font-size:12px;color:#999999;}
.combo-arrow:before{content:" ";border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #cccccc;display:block;width:0;height:0;top:0;right:15px;bottom:0;position:absolute;margin:auto 0;}
/** * When opened */
.combo-open .combo-arrow{border-color:#51A7E8;}
.combo-open .combo-arrow:before{border-top:none;border-bottom:5px solid #cccccc;}
/** * When focused */
.combo-focus{box-shadow:0 2px 5px 0 rgba(0,0,0,0.26);border-color:#51A7E8;}
.combo-focus input{border-color:#51A7E8;}
/** * Hide native select */
.combo-select select{position:absolute;z-index:1;left:0;top:0;width:100%;height:100%;-webkit-appearance:none;opacity:0;}
@media only screen and (min-width:960px){.combo-select select{left:-1px;top:-1px;width:0;height:0;margin:0;}
}
/** * Selected option */
.option-selected{background-color:#eee;}
/** * Hovered option */
.option-hover{background-color:#006eab;color:#fff;}
/** * Option item */
.option-item{cursor:pointer;border-bottom:1px #e3e3e3 solid;}
.option-item:hover{background-color:#006eab;color:#fff;}
.option-item:last-child{border-bottom:none;}
/** * Disabled and optgroups */
.option-group{cursor:text;font-weight:600;background:#e1e1e1;border:1px #ccc solid;border-width:1px 0;}
/** * Disabled */
.option-disabled{opacity:0.5;}
/** * Dropdown */
.combo-dropdown{position:absolute;z-index:1;top:100%;left:0;min-width:100%;max-width:300px;max-height:300px;margin:0;padding:0;display:none;overflow-y:auto;background:#fff;border:1px solid #999999;border-radius:0;box-shadow:0 2px 5px 0 rgba(0,0,0,0.26);box-sizing:border-box;}
.combo-dropdown li{list-style:none;padding:8px 1em;margin:0;}
/** * On Active */
.combo-open .combo-dropdown{display:block;}
/** * Search marker */
.combo-marker{text-decoration:underline;}