/*!
* jquery cxselect
* @name jquery.cxselect.js
* @version 1.4.2
* @date 2017-09-26
* @author ciaoca
* @email ciaoca@gmail.com
* @site https://github.com/ciaoca/cxselect
* @license released under the mit license
*/
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else {
factory(window.jquery || window.zepto || window.$);
};
}(function($) {
var cxselect = function() {
var self = this;
var dom, settings, callback;
// 分配参数
for (var i = 0, l = arguments.length; i < l; i++) {
if (cxselect.isjquery(arguments[i]) || cxselect.iszepto(arguments[i])) {
dom = arguments[i];
} else if (cxselect.iselement(arguments[i])) {
dom = $(arguments[i]);
} else if (typeof arguments[i] === 'function') {
callback = arguments[i];
} else if (typeof arguments[i] === 'object') {
settings = arguments[i];
};
};
var api = new cxselect.init(dom, settings);
if (typeof callback === 'function') {
callback(api);
};
return api;
};
cxselect.iselement = function(o){
if (o && (typeof htmlelement === 'function' || typeof htmlelement === 'object') && o instanceof htmlelement) {
return true;
} else {
return (o && o.nodetype && o.nodetype === 1) ? true : false;
};
};
cxselect.isjquery = function(o){
return (o && o.length && (typeof jquery === 'function' || typeof jquery === 'object') && o instanceof jquery) ? true : false;
};
cxselect.iszepto = function(o){
return (o && o.length && (typeof zepto === 'function' || typeof zepto === 'object') && zepto.zepto.isz(o)) ? true : false;
};
cxselect.getindex = function(n, required) {
return required ? n : n - 1;
};
cxselect.getdata = function(data, space) {
if (typeof space === 'string' && space.length) {
space = space.split('.');
for (var i = 0, l = space.length; i < l; i++) {
data = data[space[i]];
};
};
return data;
};
cxselect.init = function(dom, settings) {
var self = this;
if (!cxselect.isjquery(dom) && !cxselect.iszepto(dom)) {return};
var theselect = {
dom: {
box: dom
}
};
self.attach = cxselect.attach.bind(theselect);
self.detach = cxselect.detach.bind(theselect);
self.setoptions = cxselect.setoptions.bind(theselect);
self.clear = cxselect.clear.bind(theselect);
theselect.changeevent = function() {
cxselect.selectchange.call(theselect, this.classname);
};
theselect.settings = $.extend({}, $.cxselect.defaults, settings, {
url: theselect.dom.box.data('url'),
emptystyle: theselect.dom.box.data('emptystyle'),
required: theselect.dom.box.data('required'),
firsttitle: theselect.dom.box.data('firsttitle'),
firstvalue: theselect.dom.box.data('firstvalue'),
jsonspace: theselect.dom.box.data('jsonspace'),
jsonname: theselect.dom.box.data('jsonname'),
jsonvalue: theselect.dom.box.data('jsonvalue'),
jsonsub: theselect.dom.box.data('jsonsub')
});
var _dataselects = theselect.dom.box.data('selects');
if (typeof _dataselects === 'string' && _dataselects.length) {
theselect.settings.selects = _dataselects.split(',');
};
self.setoptions();
self.attach();
// 使用独立接口获取数据
if (!theselect.settings.url && !theselect.settings.data) {
cxselect.start.apply(theselect);
// 设置自定义数据
} else if ($.isarray(theselect.settings.data)) {
cxselect.start.call(theselect, theselect.settings.data);
// 设置 url,通过 ajax 获取数据
} else if (typeof theselect.settings.url === 'string' && theselect.settings.url.length) {
$.getjson(theselect.settings.url, function(json) {
cxselect.start.call(theselect, json);
});
};
};
// 设置参数
cxselect.setoptions = function(opts) {
var self = this;
if (opts) {
$.extend(self.settings, opts);
};
// 初次或重设选择器组
if (!$.isarray(self.selectarray) || !self.selectarray.length || (opts && opts.selects)) {
self.selectarray = [];
if ($.isarray(self.settings.selects) && self.settings.selects.length) {
var _tempselect;
for (var i = 0, l = self.settings.selects.length; i < l; i++) {
_tempselect = self.dom.box.find('select.' + self.settings.selects[i]);
if (!_tempselect || !_tempselect.length) {break};
self.selectarray.push(_tempselect);
};
};
};
if (opts) {
if (!$.isarray(opts.data) && typeof opts.url === 'string' && opts.url.length) {
$.getjson(self.settings.url, function(json) {
cxselect.start.call(self, json);
});
} else {
cxselect.start.call(self, opts.data);
};
};
};
// 绑定
cxselect.attach = function() {
var self = this;
if (!self.attachstatus) {
self.dom.box.on('change', 'select', self.changeevent);
};
if (typeof self.attachstatus === 'boolean') {
cxselect.start.call(self);
};
self.attachstatus = true;
};
// 移除绑定
cxselect.detach = function() {
var self = this;
self.dom.box.off('change', 'select', self.changeevent);
self.attachstatus = false;
};
// 清空选项
cxselect.clear = function(index) {
var self = this;
var _style = {
display: '',
visibility: ''
};
index = isnan(index) ? 0 : index;
// 清空后面的 select
for (var i = index, l = self.selectarray.length; i < l; i++) {
self.selectarray[i].empty().prop('disabled', true);
if (self.settings.emptystyle === 'none') {
_style.display = 'none';
} else if (self.settings.emptystyle === 'hidden') {
_style.visibility = 'hidden';
};
self.selectarray[i].css(_style);
};
};
cxselect.start = function(data) {
var self = this;
if ($.isarray(data)) {
self.settings.data = cxselect.getdata(data, self.settings.jsonspace);
};
if (!self.selectarray.length) {return};
// 保存默认值
for (var i = 0, l = self.selectarray.length; i < l; i++) {
if (typeof self.selectarray[i].attr('data-value') !== 'string' && self.selectarray[i][0].options.length) {
self.selectarray[i].attr('data-value', self.selectarray[i].val());
};
};
if (self.settings.data || (typeof self.selectarray[0].data('url') === 'string' && self.selectarray[0].data('url').length)) {
cxselect.getoptiondata.call(self, 0);
} else if (self.selectarray[0][0].options.length && typeof self.selectarray[0].attr('data-value') === 'string' && self.selectarray[0].attr('data-value').length) {
self.selectarray[0].val(self.selectarray[0].attr('data-value'));
cxselect.getoptiondata.call(self, 1);
} else {
self.selectarray[0].prop('disabled', false).css({
'display': '',
'visibility': ''
});
};
};
// 获取选项数据
cxselect.getoptiondata = function(index) {
var self = this;
if (typeof index !== 'number' || isnan(index) || index < 0 || index >= self.selectarray.length) {return};
var _indexprev = index - 1;
var _select = self.selectarray[index];
var _selectdata;
var _valueindex;
var _dataurl = _select.data('url');
var _jsonspace = typeof _select.data('jsonspace') === 'undefined' ? self.settings.jsonspace : _select.data('jsonspace');
var _query = {};
var _queryname;
var _selectname;
var _selectvalue;
cxselect.clear.call(self, index);
// 使用独立接口
if (typeof _dataurl === 'string' && _dataurl.length) {
if (index > 0) {
for (var i = 0, j = 1; i < index; i++, j++) {
_queryname = self.selectarray[j].data('queryname');
_selectname = self.selectarray[i].attr('name');
_selectvalue = self.selectarray[i].val();
if (typeof _queryname === 'string' && _queryname.length) {
_query[_queryname] = _selectvalue;
} else if (typeof _selectname === 'string' && _selectname.length) {
_query[_selectname] = _selectvalue;
};
};
};
$.getjson(_dataurl, _query, function(json) {
_selectdata = cxselect.getdata(json, _jsonspace);
cxselect.buildoption.call(self, index, _selectdata);
});
// 使用整合数据
} else if (self.settings.data && typeof self.settings.data === 'object') {
_selectdata = self.settings.data;
for (var i = 0; i < index; i++) {
_valueindex = cxselect.getindex(self.selectarray[i][0].selectedindex, typeof self.selectarray[i].data('required') === 'boolean' ? self.selectarray[i].data('required') : self.settings.required);
if (typeof _selectdata[_valueindex] === 'object' && $.isarray(_selectdata[_valueindex][self.settings.jsonsub]) && _selectdata[_valueindex][self.settings.jsonsub].length) {
_selectdata = _selectdata[_valueindex][self.settings.jsonsub];
} else {
_selectdata = null;
break;
};
};
cxselect.buildoption.call(self, index, _selectdata);
};
};
// 构建选项列表
cxselect.buildoption = function(index, data) {
var self = this;
var _select = self.selectarray[index];
var _required = typeof _select.data('required') === 'boolean' ? _select.data('required') : self.settings.required;
var _firsttitle = typeof _select.data('firsttitle') === 'undefined' ? self.settings.firsttitle : _select.data('firsttitle');
var _firstvalue = typeof _select.data('firstvalue') === 'undefined' ? self.settings.firstvalue : _select.data('firstvalue');
var _jsonname = typeof _select.data('jsonname') === 'undefined' ? self.settings.jsonname : _select.data('jsonname');
var _jsonvalue = typeof _select.data('jsonvalue') === 'undefined' ? self.settings.jsonvalue : _select.data('jsonvalue');
if (!$.isarray(data)) {return};
var _html = !_required ? '' : '';
// 区分标题、值的数据
if (typeof _jsonname === 'string' && _jsonname.length) {
// 无值字段时使用标题作为值
if (typeof _jsonvalue !== 'string' || !_jsonvalue.length) {
_jsonvalue = _jsonname;
};
for (var i = 0, l = data.length; i < l; i++) {
_html += '';
};
// 数组即为值的数据
} else {
for (var i = 0, l = data.length; i < l; i++) {
_html += '';
};
};
_select.html(_html).prop('disabled', false).css({
'display': '',
'visibility': ''
});
// 初次加载设置默认值
if (typeof _select.attr('data-value') === 'string') {
_select.val(string(_select.attr('data-value'))).removeattr('data-value');
if (_select[0].selectedindex < 0) {
_select[0].options[0].selected = true;
};
};
if (_required || _select[0].selectedindex > 0) {
_select.trigger('change');
};
};
// 改变选择时的处理
cxselect.selectchange = function(name) {
var self = this;
if (typeof name !== 'string' || !name.length) {return};
var index;
name = name.replace(/\s+/g, ',');
name = ',' + name + ',';
// 获取当前 select 位置
for (var i = 0, l = self.selectarray.length; i < l; i++) {
if (name.indexof(',' + self.settings.selects[i] + ',') > -1) {
index = i;
break;
};
};
if (typeof index === 'number' && index > -1) {
index += 1;
cxselect.getoptiondata.call(self, index);
};
};
$.cxselect = function() {
return cxselect.apply(this, arguments);
};
// 默认值
$.cxselect.defaults = {
selects: [], // 下拉选框组
url: null, // 列表数据文件路径(url)或数组数据
data: null, // 自定义数据
emptystyle: null, // 无数据状态显示方式
required: false, // 是否为必选
firsttitle: '请选择', // 第一个选项的标题
firstvalue: '', // 第一个选项的值
jsonspace: '', // 数据命名空间
jsonname: 'n', // 数据标题字段名称
jsonvalue: '', // 数据值字段名称
jsonsub: 's' // 子集数据字段名称
};
$.fn.cxselect = function(settings, callback) {
this.each(function(i) {
$.cxselect(this, settings, callback);
});
return this;
};
}));