selectN.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * @version: 1.2
  3. * @Author: tomato
  4. * @Date: 2018-4-24 22:56:00
  5. * @Last Modified by: tomato
  6. * @Last Modified time: 2018-5-26 18:08:43
  7. */
  8. //无限级下拉框
  9. layui.define(['jquery', 'form'], function(exports){
  10. var MOD_NAME = 'selectN';
  11. var $ = layui.jquery;
  12. var form = layui.form;
  13. var obj = function(config){
  14. //当前选中数据值名数据
  15. this.selected =[];
  16. //当前选中的值
  17. this.values = [];
  18. //当前选中的名
  19. this.names = [];
  20. //当前选中最后一个值
  21. this.lastValue = '';
  22. //当前选中最后一个值
  23. this.lastName = '';
  24. //是否已选
  25. this.isSelected = false;
  26. //初始化配置
  27. this.config = {
  28. //选择器id或class
  29. elem: '',
  30. //无限级分类数据
  31. data: [],
  32. //默认选中值
  33. selected: [],
  34. //空值项提示,可设置为数组['请选择省','请选择市','请选择县']
  35. tips: '请选择',
  36. //是否允许搜索,可设置为数组[true,true,true]
  37. search:false,
  38. //选择项宽度,可设置为数组['80','90','100']
  39. width:null,
  40. //为真只取最后一个值
  41. last: false,
  42. //值验证,与lay-verify一致
  43. verify: '',
  44. //事件过滤器,lay-filter名
  45. filter: '',
  46. //input的name 不设置与选择器相同(去#.)
  47. name: '',
  48. //数据分隔符
  49. delimiter: ',',
  50. //数据的键名 status=0为禁用状态
  51. field:{idName:'id',titleName:'name',statusName:'status',childName:'children'},
  52. //多表单区分 form.render(type, filter); 为class="layui-form" 所在元素的 lay-filter="" 的值
  53. formFilter: null
  54. }
  55. //实例化配置
  56. this.config = $.extend(this.config,config);
  57. //“请选择”文字
  58. this.setTips = function(){
  59. var o = this,c = o.config;
  60. if(Object.prototype.toString.call(c.tips)!='[object Array]'){
  61. return c.tips;
  62. }
  63. else{
  64. var i=$(c.elem).find('select').length;
  65. return c.tips.hasOwnProperty(i) ? c.tips[i] : '请选择';
  66. }
  67. }
  68. //设置是否允许搜索
  69. this.setSearch = function(){
  70. var o = this,c = o.config;
  71. if(Object.prototype.toString.call(c.search)!='[object Array]'){
  72. return c.search===true ? 'lay-search ' : ' ';
  73. }
  74. else{
  75. var i=$(c.elem).find('select').length;
  76. if(c.search.hasOwnProperty(i)){
  77. return c.search[i]===true ? 'lay-search ' : ' ';
  78. }
  79. }
  80. return ' ';
  81. }
  82. //设置是否允许搜索
  83. this.setWidth = function(){
  84. var o = this,c = o.config;
  85. if(Object.prototype.toString.call(c.width)!='[object Array]'){
  86. return /^\d+$/.test(c.width) ? 'style="width:'+c.width+'px;" ' : ' ';
  87. }
  88. else{
  89. var i=$(c.elem).find('select').length;
  90. if(c.width.hasOwnProperty(i)){
  91. return /^\d+$/.test(c.width[i]) ? 'style="width:'+c.width[i]+'px;" ' : ' ';
  92. }
  93. }
  94. }
  95. //创建一个Select
  96. this.createSelect = function(optionData){
  97. var o = this,c = o.config,f=c.field;
  98. var html = '';
  99. html+= '<div class="layui-input-inline" '+o.setWidth()+'>';
  100. html+= ' <select '+o.setSearch()+'lay-filter="'+c.filter+'">';
  101. html+= ' <option value="">'+o.setTips()+'</option>';
  102. for(var i=0;i<optionData.length;i++){
  103. var disabled = optionData[i][f.statusName]==0 ? 'disabled="" ' : '';
  104. html+= ' <option '+disabled+'value="'+optionData[i][f.idName]+'">'+optionData[i][f.titleName]+'</option>';
  105. }
  106. html+= ' </select>';
  107. html+= '</div>';
  108. return html;
  109. };
  110. //获取当前option的数据
  111. this.getOptionData=function(catData,optionIndex){
  112. var f = this.config.field;
  113. var item = catData;
  114. for(var i=0;i<optionIndex.length;i++){
  115. if('undefined' == typeof item[optionIndex[i]]){
  116. item = null;
  117. break;
  118. }
  119. else if('undefined' == typeof item[optionIndex[i]][f.childName]){
  120. item = null;
  121. break;
  122. }
  123. else{
  124. item = item[optionIndex[i]][f.childName];
  125. }
  126. }
  127. return item;
  128. };
  129. //初始化
  130. this.set = function(selected){
  131. var o = this,c = o.config;
  132. $E = $(c.elem);
  133. //创建顶级select
  134. var verify = c.verify=='' ? '' : 'lay-verify="'+c.verify+'" ';
  135. var html = '<div style="height:0px;width:0px;overflow:hidden"><input '+verify+'name="'+c.name+'"></div>';
  136. html += o.createSelect(c.data);
  137. $E.html(html);
  138. selected = typeof selected=='undefined' ? c.selected : selected;
  139. var index=[];
  140. for(var i=0;i<selected.length;i++){
  141. //设置最后一个select的选中值
  142. $E.find('select:last').val(selected[i]);
  143. //获取该选中值的索引
  144. var lastIndex = $E.find('select:last').get(0).selectedIndex-1;
  145. index.push(lastIndex);
  146. //取出下级的选项值
  147. var childItem = o.getOptionData(c.data,index);
  148. //下级选项值存在则创建select
  149. if(childItem){
  150. var html = o.createSelect(childItem);
  151. $E.append(html);
  152. }
  153. }
  154. form.render('select',c.formFilter);
  155. o.getSelected();
  156. };
  157. //下拉事件
  158. this.change = function(elem){
  159. var o = this,c = o.config;
  160. var $thisItem = elem.parent();
  161. //移除后面的select
  162. $thisItem.nextAll('div.layui-input-inline').remove();
  163. var index=[];
  164. //获取所有select,取出选中项的值和索引
  165. $thisItem.parent().find('select').each(function(){
  166. index.push($(this).get(0).selectedIndex-1);
  167. });
  168. var childItem = o.getOptionData(c.data,index);
  169. if(childItem){
  170. var html = o.createSelect(childItem);
  171. $thisItem.after(html);
  172. form.render('select',c.formFilter);
  173. }
  174. o.getSelected();
  175. };
  176. //获取所有值-数组 每次选择后执行
  177. this.getSelected=function(){
  178. var o = this,c = o.config;
  179. var values =[];
  180. var names =[];
  181. var selected =[];
  182. $E = $(c.elem);
  183. $E.find('select').each(function(){
  184. var item = {};
  185. var v = $(this).val()
  186. var n = $(this).find('option:selected').text();
  187. item.value = v;
  188. item.name = n;
  189. values.push(v);
  190. names.push(n);
  191. selected.push(item);
  192. });
  193. o.selected =selected;
  194. o.values = values;
  195. o.names = names;
  196. o.lastValue = $E.find('select:last').val();
  197. o.lastName = $E.find('option:selected:last').text();
  198. o.isSelected = o.lastValue=='' ? false : true;
  199. var inputVal = c.last===true ? o.lastValue : o.values.join(c.delimiter);
  200. $E.find('input[name="'+c.name+'"]').val(inputVal);
  201. };
  202. //ajax方式获取候选数据
  203. this.getData = function(url){
  204. var d;
  205. $.ajax({
  206. url:url,
  207. dataType:'json',
  208. async:false,
  209. success:function(json){
  210. d=json;
  211. },
  212. error: function(){
  213. console.error(MOD_NAME+' hint:候选数据ajax请求错误 ');
  214. d = false;
  215. }
  216. });
  217. return d;
  218. }
  219. };
  220. //渲染一个实例
  221. obj.prototype.render = function(){
  222. var o=this,c=o.config;
  223. $E = $(c.elem);
  224. if($E.length==0){
  225. console.error(MOD_NAME+' hint:找不到容器 '+c.elem);
  226. return false;
  227. }
  228. if(Object.prototype.toString.call(c.data)!='[object Array]'){
  229. var data = o.getData(c.data);
  230. if(data===false){
  231. console.error(MOD_NAME+' hint:缺少分类数据');
  232. return false;
  233. }
  234. o.config.data = data;
  235. }
  236. c.filter = c.filter=='' ? c.elem.replace('#','').replace('.','') : c.filter;
  237. c.name = c.name=='' ? c.elem.replace('#','').replace('.','') : c.name;
  238. o.config = c;
  239. //初始化
  240. o.set();
  241. //监听下拉事件
  242. form.on('select('+c.filter+')',function(data){
  243. o.change($(data.elem));
  244. });
  245. //验证失败样式
  246. $E.find('input[name="'+c.name+'"]').focus(function(){
  247. var t = $(c.elem).offset().top;
  248. $('html,body').scrollTop(t-200);
  249. $(c.elem).find('select:last').addClass('layui-form-danger');
  250. setTimeout(function(){
  251. $(c.elem).find('select:last').removeClass('layui-form-danger');
  252. },3000);
  253. });
  254. }
  255. //输出模块
  256. exports(MOD_NAME, function (config) {
  257. var _this = new obj(config);
  258. _this.render();
  259. return _this;
  260. });
  261. });