/*! * 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; }; }));