/**
* ui-select美化插件
* 基于jQuery
*/
; + function($) {
"use strict";
// 默认实例化配置
var defaults = {
width: null, //select的宽度,默认为null将自动获取select的宽度;
wrapClass: '', //加载在最外层.ui-select-wrap有class,在自定义样式时有用处;
dataKey: 'ui-select', //实例化后对象存在select的data键值,方便后续通过data('ui-select')取出;
onChange: null, //select值改变时的回调;
onClick: null //select元素点击时的回调,diabled时不发生。
};
/**
* ui-select插件
*/
$.fn.ui_select = function(options) {
var _this = $(this),
_num = _this.length;
// 当要实例的对象只有一个时,直接实例化返回对象;
if (_num === 1) {
return new UI_select(_this, options);
};
// 当要实例的对象有多个时,循环实例化,不返回对象;
if (_num > 1) {
_this.each(function(index, el) {
new UI_select($(el), options);
})
}
// 当元素个数为0时,不执行实例化。
};
/**
* UI_select对象
* @param {[jQuery]} el [jQuery选择后的对象,此处传入的为单个元素]
* @param {[object]} opt [设置的参数]
*/
function UI_select(el, opt) {
this.el = el;
this.items = this.el.find('option');
this._opt = $.extend({}, defaults, opt);
this._doc = $(document);
this._win = $(window);
return this._init();
}
// UI_select 原型链扩展。
UI_select.prototype = {
// 判断是否为IE (6-11);
_isIE: !!window.ActiveXObject || "ActiveXObject" in window,
// init初始化;
_init: function() {
var _data = this.el.data(this._opt.dataKey);
// 如果已经实例化了,则直接返回
if (_data)
return _data;
else
this.el.data(this._opt.dataKey, this);
this._setHtml(); // 组建元素
this._bindEvent(); // 绑定事件
},
// 组建并获取相关的dom元素;
_setHtml: function() {
this.el.addClass('ui-select');
var _isHide = (this.el.css('display') == 'none');
if (_isHide) {
this.el.show().css('visibility', 'hidden');
}
var _w = this._opt.width ? this._opt.width - 17 : this.el.outerWidth() - 17;
this.el.wrap('
')
.after('');
this._wrap = this.el.parent('.ui-select-wrap').css('width', _w);
this._input = this.el.next('.ui-select-input');
this._list = this._wrap.children('.ui-select-list');
this.el.prop('disabled') ? this.disable() : null;
if (_isHide) {
this.el.add(this._wrap).hide();
this.el.css('visibility', null);
}
var _ohtml = '';
this.el.find('option').each(function(index, el) {
var _this = $(el),
_text = _this.text(),
_value = _this.prop('value'),
_selected = _this.prop('selected') ? 'selected' : '',
_disabled = _this.prop('disabled') ? ' disabled' : '';
_ohtml += '' + _text + ' ';
});
this._list.html(_ohtml);
this._items = this._list.children('li');
this.val(this.el.val());
var _txt = this._list.children('li.selected').text();
this._input.text(_txt).attr('title', _txt);
},
// 绑定事件;
_bindEvent: function() {
var _this = this;
// 模拟后的select点击事件;
_this._wrap.on({
// 点击事件
'click': function(e) {
// 列表元素点击事件;
if (_this._disabled)
return;
if (e.target.tagName == 'LI') {
var _self = $(e.target),
_val = _self.attr('data-value');
if (_self.hasClass('disabled'))
return _this._isIE ? e.stopPropagation() : null;
_this.val(_val);
_this._triggerClick(_val, _this.items.eq(_self.index()));
}
// IE下点击select时其他select无法收起的bug
if (_this._isIE) {
e.stopPropagation();
_this._allWrap = _this._allWrap || $('.ui-select-wrap');
_this._allWrap.not(_this._wrap).removeClass('focus');
_this._doc.one('click', function() {
_this._allWrap.removeClass('focus');
});
}
_this._wrap.toggleClass('focus');
_this._setListCss();
},
// 失去焦点事件
'blur': function(e) {
_this._wrap.removeClass('focus');
},
// 键盘事件
'keydown': function(e) {
var code = e.keyCode;
if (code == 40 || code == 38) {
var _els = code == 40 ? _this._list.find('li.selected').nextAll('li') : _this._list.find('li.selected').prevAll('li');
var _val = _els.not('.disabled').eq(0).attr('data-value');
if (_val !== undefined) {
_this.val(_val);
}
return false;
}
}
});
return _this;
},
// 根据select所处的位置设置下拉列表显示方向up / down
_setListCss: function() {
var _toWinTop = this._wrap.offset().top - this._win.scrollTop();
var _toWinBottom = this._win.height() - _toWinTop - this._wrap.outerHeight();
var _listH = this._list.outerHeight();
if (_listH > _toWinBottom && _toWinTop > _toWinBottom) {
this._wrap.addClass('up');
if (_listH > _toWinTop)
this._list.css('maxHeight', _toWinTop - 1 + 'px');
else
this._list.removeAttr('style');
} else if (_listH > _toWinBottom && _toWinTop < _toWinBottom) {
this._wrap.removeClass('up');
this._list.css('maxHeight', _toWinBottom - 1 + 'px');
} else {
this._list.removeAttr('style');
this._wrap.removeClass('up');
}
},
// change 触发;value:值 ;item:选中的option;
_triggerChange: function(value, item) {
this.el.change();
this.onChange(value, item);
if (typeof this._opt.onChange == 'function')
this._opt.onChange.call(this, value, item);
},
// click 触发;value:值 ;item:选中的option;
_triggerClick: function(value, item) {
this.onClick(value, item);
if (typeof this._opt.onClick == 'function')
this._opt.onClick.call(this, value, item);
},
// 获取或设置值;
val: function(value) {
var _val = this.el.val();
if (value === undefined)
return _val;
this.el.val(value);
var _selectedLi = this._list.children('li[data-value="' + value + '"]');
_selectedLi.addClass('selected').siblings('li').removeClass('selected');
this._input.html(_selectedLi.text()).attr('title', _selectedLi.text());
if (_val != value) {
return this._triggerChange(value, this.items.eq(_selectedLi.index()));
}
},
// 值改变事件;
onChange: function(value, item) {},
// 点击事件;
onClick: function(value, item) {},
// 禁用select;
disable: function() {
this._disabled = true;
this.el.prop('disabled', true);
this._wrap.addClass('disabled').removeAttr('tabindex');
return this;
},
// 启用select;
enable: function() {
this._disabled = false;
this.el.prop('disabled', false);
this._wrap.removeClass('disabled').attr('tabindex', '0');
return this;
},
// 隐藏
hide: function() {
this._wrap.hide();
return this;
},
// 显示
show: function() {
this._wrap.show();
return this;
},
// 显示 或 隐藏
toggle: function() {
this._wrap.toggle();
return this;
},
// visible
visible: function(visible) {
visible = !visible ? 'hidden' : 'visible';
this._wrap.css('visibility', visible);
return this;
}
};
}(jQuery);