提交 | 用户 | 时间
|
71e81e
|
1 |
/** |
懒 |
2 |
* @ Name:selectPlus 加强版的选择框,可以多选、单选以及通过ulr导入数据 |
|
3 |
* @ Author: YWang |
|
4 |
* @ License: MIT |
|
5 |
*/ |
|
6 |
|
|
7 |
layui.define('form', function (exports) { |
|
8 |
var $ = layui.$, |
|
9 |
form = layui.form, |
|
10 |
hint = layui.hint() |
|
11 |
// 字符常量 |
|
12 |
, |
|
13 |
MOD_NAME = 'selectPlus', |
|
14 |
SELECT = 'layui-form-select', |
|
15 |
SELECTED = 'layui-form-selected' |
|
16 |
|
|
17 |
, |
|
18 |
selectPlus = { |
|
19 |
index: layui.selectPlus ? layui.selectPlus.index : 0 |
|
20 |
|
|
21 |
// 设置全局项 |
|
22 |
, |
|
23 |
set: function (options) { |
|
24 |
var that = this; |
|
25 |
that.config = $.extend({}, that.config, options); |
|
26 |
return that; |
|
27 |
} |
|
28 |
|
|
29 |
// 事件监听 |
|
30 |
, |
|
31 |
on: function (events, callback) { |
|
32 |
return layui.onevent.call(this, MOD_NAME, events, callback); |
|
33 |
} |
|
34 |
} |
|
35 |
|
|
36 |
// 操作当前实例 |
|
37 |
, |
|
38 |
thisIns = function () { |
|
39 |
var that = this, |
|
40 |
options = that.config; |
|
41 |
|
|
42 |
return { |
|
43 |
// 获取数据 |
|
44 |
getChecked: function () { |
|
45 |
return that.getChecked.call(that); |
|
46 |
}, |
|
47 |
// 配置数据 |
|
48 |
config: options |
|
49 |
} |
|
50 |
} |
|
51 |
|
|
52 |
// 构造器 |
|
53 |
, |
|
54 |
Class = function (options) { |
|
55 |
var that = this; |
|
56 |
that.index = ++selectPlus.index; |
|
57 |
that.config = $.extend({}, that.config, selectPlus.config, options); |
|
58 |
that.render(); |
|
59 |
}; |
|
60 |
|
|
61 |
//默认配置 |
|
62 |
Class.prototype.config = { |
|
63 |
type: 'checkbox', |
|
64 |
valueSeparator: '/', |
|
65 |
labelSeparator: ' --- ', |
|
66 |
|
|
67 |
data: [], |
|
68 |
valueName: 'title', |
|
69 |
label: [], |
|
70 |
values: [], |
|
71 |
|
|
72 |
url: '', |
|
73 |
method: 'get', |
|
74 |
where: '', |
|
75 |
contentType: '', |
|
76 |
headers: '', |
|
77 |
response: 'data', |
|
78 |
parseData: null, |
|
79 |
|
|
80 |
config: { |
|
81 |
checkedName: 'SELECTPLUS_CHECKED', |
|
82 |
indexName: 'SELECTPLUS_INDEX' |
|
83 |
}, |
|
84 |
|
|
85 |
error: '' |
|
86 |
|
|
87 |
}; |
|
88 |
//渲染视图 |
|
89 |
Class.prototype.render = function () { |
|
90 |
var that = this, |
|
91 |
options = that.config; |
|
92 |
|
|
93 |
typeof (options.el) === 'string' ? options.el = $(options.el): options.el; |
|
94 |
options.reElem = $('<div class="layui-unselect layui-form-select">' + |
|
95 |
'<div class="layui-select-title">' + |
|
96 |
'<input type="text" placeholder="请选择" value="" readonly="" class="layui-input layui-unselect">' + |
|
97 |
'<i class="layui-edge"></i>' + |
|
98 |
'</div>' + |
|
99 |
'<dl class="layui-anim layui-anim-upbit">' + |
|
100 |
'<dd lay-value="" class="layui-select-tips layui-hide">请选择</dd>' + |
|
101 |
'</dl>' + |
|
102 |
'</div>'); |
|
103 |
|
|
104 |
// 事件 |
|
105 |
options.reElem.find('.layui-select-title').on('click', function (e) { |
|
106 |
!$(this).parent().hasClass(SELECTED) ? $(document).find('.' + SELECT).removeClass(SELECTED) : ""; |
|
107 |
$(this).parent().toggleClass(SELECTED); |
|
108 |
}); |
|
109 |
$(document).on('click', function (e) { |
|
110 |
($(e.target).parents('.' + SELECT).length <= 0) && (options.reElem.hasClass(SELECTED)) ? options.reElem.removeClass(SELECTED): ""; |
|
111 |
|
|
112 |
}); |
|
113 |
|
|
114 |
|
|
115 |
!Array.isArray(options.values) ? options.values = [options.values] : ""; |
|
116 |
|
|
117 |
// 查找 表单的 filter |
|
118 |
options.filter = options.el.parents('.layui-form').attr('lay-filter'); |
|
119 |
|
|
120 |
options.el.append(options.reElem); |
|
121 |
|
|
122 |
|
|
123 |
if (options.url) { // 获取后端数据 |
|
124 |
this.pullData(); |
|
125 |
} else { |
|
126 |
that.renderData(); // 数据渲染 |
|
127 |
} |
|
128 |
|
|
129 |
options.el.on('click', '.layui-select-title', function () { |
|
130 |
var $title = $(this), |
|
131 |
$dd0 = $title.next().find('dd').eq(0); |
|
132 |
|
|
133 |
if (!$dd0.hasClass('layui-hide')) { |
|
134 |
$dd0.addClass('layui-hide'); |
|
135 |
} |
|
136 |
$title.find('input').val(options.values.join(options.valueSeparator)); |
|
137 |
}) |
|
138 |
|
|
139 |
} |
|
140 |
|
|
141 |
Class.prototype.pullData = function () { |
|
142 |
var that = this, |
|
143 |
options = that.config; |
|
144 |
$.ajax({ |
|
145 |
type: options.method || 'get', |
|
146 |
url: options.url, |
|
147 |
contentType: options.contentType, |
|
148 |
data: options.where || {}, |
|
149 |
dataType: 'json', |
|
150 |
headers: options.headers || {}, |
|
151 |
success: function (res) { |
|
152 |
//如果有数据解析的回调,则获得其返回的数据 |
|
153 |
if (typeof options.parseData === 'function') { |
|
154 |
res = options.parseData(res) || res[options.response]; |
|
155 |
} |
|
156 |
// 如果是数组,则覆盖options.data |
|
157 |
if (Array.isArray(res)) { |
|
158 |
options.data = that.formatData(res); |
|
159 |
options.error = ''; |
|
160 |
that.renderData(); |
|
161 |
} else { |
|
162 |
options.error = '数据格式不对'; |
|
163 |
} |
|
164 |
}, |
|
165 |
error: function (e, m) { |
|
166 |
options.error = '数据接口请求异常:' + m; |
|
167 |
} |
|
168 |
}); |
|
169 |
|
|
170 |
} |
|
171 |
|
|
172 |
// 格式化数据 |
|
173 |
Class.prototype.formatData = function (data) { |
|
174 |
var that = this, |
|
175 |
options = that.config, |
|
176 |
valueName = options.valueName, |
|
177 |
values = options.values, |
|
178 |
checkedName = options.config.checkedName, |
|
179 |
indexName = options.config.indexName; |
|
180 |
|
|
181 |
layui.each(data, function (i, item) { |
|
182 |
if (typeof item !== 'object') { |
|
183 |
data[i] = { |
|
184 |
title: item |
|
185 |
} |
|
186 |
} |
|
187 |
data[i][indexName] = i; |
|
188 |
if (!data[i][checkedName]) data[i][checkedName] = false; |
|
189 |
layui.each(values, function (index, value) { |
|
190 |
if (data[i][valueName] === value) { |
|
191 |
data[i][checkedName] = true; |
|
192 |
} |
|
193 |
}) |
|
194 |
}); |
|
195 |
values.splice(0); |
|
196 |
|
|
197 |
|
|
198 |
|
|
199 |
return data; |
|
200 |
} |
|
201 |
|
|
202 |
|
|
203 |
// 渲染数据 |
|
204 |
Class.prototype.renderData = function (data) { |
|
205 |
var that = this, |
|
206 |
options = that.config, |
|
207 |
type = options.type, |
|
208 |
id = that.index, |
|
209 |
data = data ? that.formatData(data) : that.formatData(options.data) |
|
210 |
|
|
211 |
|
|
212 |
|
|
213 |
items = { |
|
214 |
|
|
215 |
// 多选 |
|
216 |
checkbox: function (config, data, id) { |
|
217 |
var CLASSNAME = 'layui-form-checkbox', |
|
218 |
CHECKED = 'layui-form-checked', |
|
219 |
|
|
220 |
el = config.reElem.find('dl'), |
|
221 |
valueName = config.valueName, |
|
222 |
checkedName = config.config.checkedName, |
|
223 |
indexName = config.config.indexName, |
|
224 |
values = config.values, |
|
225 |
label = config.label, |
|
226 |
filter = config.filter, |
|
227 |
labelSeparator = config.labelSeparator, |
|
228 |
valueSeparator = config.valueSeparator, |
|
229 |
|
|
230 |
sum = 0; |
|
231 |
|
|
232 |
|
|
233 |
// 添加选项 |
|
234 |
el.append($('<dd lay-value="全选"></dd>')); |
|
235 |
layui.each(data, function (i, item) { |
|
236 |
el.append($('<dd lay-value="' + item[valueName] + '"></dd>')); |
|
237 |
}) |
|
238 |
|
|
239 |
|
|
240 |
var allEle = el.find('dd').eq(1); |
|
241 |
|
|
242 |
// 添加多选框 |
|
243 |
|
|
244 |
allEle.nextAll().each(function (index) { |
|
245 |
var $dd = $(this), |
|
246 |
item = data[index], |
|
247 |
layuiValue = item[valueName], |
|
248 |
title = layuiValue; |
|
249 |
if (label.length > 0) { |
|
250 |
title = ""; |
|
251 |
layui.each(label, function (i, n) { |
|
252 |
title += item[n]; |
|
253 |
i < (label.length - 1) ? title += labelSeparator : ''; |
|
254 |
}) |
|
255 |
} |
|
256 |
var checkbox = $('<input type="checkbox" name="' + MOD_NAME + 'checkbox' + id + '" yw-index="' + item[indexName] + '" lay-skin="primary" title="' + title + '" layui-value="' + layuiValue + '">'); |
|
257 |
if (item[checkedName]) { |
|
258 |
checkbox.prop('checked', true); |
|
259 |
values.push(layuiValue); |
|
260 |
sum++; |
|
261 |
} |
|
262 |
$dd.html(checkbox); |
|
263 |
}) |
|
264 |
|
|
265 |
var allcheckbox = $('<input type="checkbox" selectplus-all lay-skin="primary" title="全选" layui-value="全选">'); |
|
266 |
sum === data.length ? allcheckbox.prop('checked', true) : ""; |
|
267 |
allEle.html(allcheckbox); |
|
268 |
|
|
269 |
allEle.parent().prev().find('input').val(values.join(valueSeparator)); |
|
270 |
|
|
271 |
// 添加事件 |
|
272 |
allEle.on('click', function (event) { |
|
273 |
var $all = $(this), |
|
274 |
checked = event.target.nodeName === 'DD' ? $all.find('.' + CLASSNAME).toggleClass(CHECKED).hasClass(CHECKED) : $all.find('input').prop('checked'); |
|
275 |
|
|
276 |
// 禁止下拉框收回 |
|
277 |
$all.parents('.' + SELECT).addClass(SELECTED); |
|
278 |
|
|
279 |
// 设置选中状态 |
|
280 |
$all.find('input').prop('checked', checked); |
|
281 |
|
|
282 |
$all.nextAll().each(function () { |
|
283 |
var dd = $(this); |
|
284 |
checked ? dd.find('.' + CLASSNAME).addClass(CHECKED) : dd.find('.' + CLASSNAME).removeClass(CHECKED); |
|
285 |
dd.find('input').prop('checked', checked); |
|
286 |
}) |
|
287 |
|
|
288 |
|
|
289 |
// 显示选中数据 |
|
290 |
layui.event.call($all, MOD_NAME, 'checkbox' + '(' + MOD_NAME + ')', { |
|
291 |
type: "checkbox", |
|
292 |
ele: $all, |
|
293 |
eleChecked: checked, |
|
294 |
isAll: checked |
|
295 |
}); |
|
296 |
|
|
297 |
}) |
|
298 |
allEle.nextAll().on('click', function (e) { |
|
299 |
var $dd = $(this), |
|
300 |
checked = event.target.nodeName === 'DD' ? $dd.find('.' + CLASSNAME).toggleClass(CHECKED).hasClass(CHECKED) : $dd.find('input').prop('checked'); |
|
301 |
|
|
302 |
// 禁止下拉框收回 |
|
303 |
$dd.parents('.' + SELECT).addClass(SELECTED); |
|
304 |
|
|
305 |
// 设置选中状态 |
|
306 |
$dd.find('input').prop('checked', checked); |
|
307 |
|
|
308 |
// 判断全选 |
|
309 |
var $all = $dd.parents('dl').find('dd').eq(1), |
|
310 |
$dds = $all.nextAll(), |
|
311 |
sum = 0; |
|
312 |
$dds.each(function () { |
|
313 |
$(this).find('input').prop('checked') ? sum++ : ''; |
|
314 |
}) |
|
315 |
|
|
316 |
if (sum === $dds.length) { |
|
317 |
$all.find('input').prop('checked', true); |
|
318 |
$all.find('.' + CLASSNAME).addClass(CHECKED); |
|
319 |
} else { |
|
320 |
$all.find('input').prop('checked', false); |
|
321 |
$all.find('.' + CLASSNAME).removeClass(CHECKED); |
|
322 |
} |
|
323 |
|
|
324 |
// 显示选中数据 |
|
325 |
layui.event.call($all, MOD_NAME, 'checkbox' + '(' + MOD_NAME + ')', { |
|
326 |
type: "checkbox", |
|
327 |
ele: $dd, |
|
328 |
eleChecked: checked, |
|
329 |
isAll: (sum === $dds.length) |
|
330 |
}); |
|
331 |
|
|
332 |
// 阻断事件 |
|
333 |
event.stopPropagation(); |
|
334 |
}) |
|
335 |
|
|
336 |
// 渲染多选框 |
|
337 |
// el.next().find('dl').addClass('yw-selectPlus'); |
|
338 |
form.render('checkbox', filter); |
|
339 |
|
|
340 |
}, |
|
341 |
|
|
342 |
// 单选 |
|
343 |
radio: function (config, data, id) { |
|
344 |
var CLASSNAME = 'layui-form-radio', |
|
345 |
CHECKED = 'layui-form-radioed', |
|
346 |
ICON = ['', ''], |
|
347 |
CHECKED_ICON = 'layui-anim-scaleSpring', |
|
348 |
|
|
349 |
elID = config.el, |
|
350 |
el = config.reElem.find('dl'), |
|
351 |
valueName = config.valueName, |
|
352 |
checkedName = config.config.checkedName, |
|
353 |
indexName = config.config.indexName, |
|
354 |
checkedData = data.filter(function (item) { |
|
355 |
return item[checkedName] === true; |
|
356 |
}), |
|
357 |
values = config.values, |
|
358 |
label = config.label, |
|
359 |
filter = config.filter, |
|
360 |
labelSeparator = config.labelSeparator, |
|
361 |
valueSeparator = config.valueSeparator; |
|
362 |
|
|
363 |
|
|
364 |
// 添加选项 |
|
365 |
layui.each(data, function (i, item) { |
|
366 |
el.append('<dd lay-value="' + item[valueName] + '"></dd>'); |
|
367 |
}) |
|
368 |
form.render('select', options.filter); |
|
369 |
|
|
370 |
|
|
371 |
// 渲染单选框 |
|
372 |
el.find('dd').eq(0).nextAll().each(function (index) { |
|
373 |
var $dd = $(this), |
|
374 |
item = data[index], |
|
375 |
layuiValue = item[valueName], |
|
376 |
title = layuiValue; |
|
377 |
if (label.length > 0) { |
|
378 |
title = ""; |
|
379 |
layui.each(label, function (i, n) { |
|
380 |
title += item[n]; |
|
381 |
i < (label.length - 1) ? title += labelSeparator : ''; |
|
382 |
}) |
|
383 |
} |
|
384 |
|
|
385 |
var dd = $('<input type="radio" name="' + MOD_NAME + 'radio' + id + '" yw-index="' + item[indexName] + '" lay-skin="primary" title="' + title + '" layui-value="' + layuiValue + '">'); |
|
386 |
|
|
387 |
if (checkedData.length > 0 && checkedData[0][indexName] === item[indexName]) { |
|
388 |
dd.prop('checked', true); |
|
389 |
values.push(layuiValue); |
|
390 |
$dd.parent().prev().find('input').val(values.join(valueSeparator)) |
|
391 |
} |
|
392 |
$dd.html(dd); |
|
393 |
}) |
|
394 |
|
|
395 |
|
|
396 |
// el.next().find('dl').addClass('yw-selectPlus'); |
|
397 |
form.render('radio', filter); |
|
398 |
|
|
399 |
// 事件 |
|
400 |
el.find('dd').on('click', function (event) { |
|
401 |
var $dd = $(this); |
|
402 |
$dd.find('.' + CLASSNAME).addClass(CHECKED).find('i').addClass(CHECKED_ICON).html(ICON[0]); |
|
403 |
$dd.find('input').prop('checked', true); |
|
404 |
$dd.siblings().find('.' + CLASSNAME).removeClass(CHECKED).find('i').removeClass(CHECKED_ICON).html(ICON[1]); |
|
405 |
$dd.siblings().find('input').prop('checked', false); |
|
406 |
// 显示选中数据 |
|
407 |
layui.event.call($dd, MOD_NAME, 'radio' + '(' + MOD_NAME + ')', { |
|
408 |
type: "radio", |
|
409 |
ele: $dd, |
|
410 |
eleChecked: true, |
|
411 |
isAll: false |
|
412 |
}); |
|
413 |
}) |
|
414 |
} |
|
415 |
|
|
416 |
|
|
417 |
}; |
|
418 |
|
|
419 |
// 选择时触发的事件 |
|
420 |
layui.onevent.call(that, MOD_NAME, type + '(' + MOD_NAME + ')', that.checked.bind(that)); |
|
421 |
|
|
422 |
items[type] ? items[type](options, data, id) : hint.error('不支持的' + type + '表单渲染'); |
|
423 |
|
|
424 |
} |
|
425 |
|
|
426 |
// 选中数据处理 |
|
427 |
Class.prototype.checked = function (res) { |
|
428 |
var that = this, |
|
429 |
options = that.config, |
|
430 |
data = options.data, |
|
431 |
checkedName = options.config.checkedName, |
|
432 |
type = res.type, |
|
433 |
isAll = res.isAll, |
|
434 |
ele = res.ele, |
|
435 |
eleChecked = res.eleChecked, |
|
436 |
filter = options.el.attr('lay-filter'); |
|
437 |
|
|
438 |
if (type === 'checkbox') { |
|
439 |
options.values = []; |
|
440 |
ele.parents('dl').find('[type="checkbox"]').each(function (i) { |
|
441 |
var $dd = $(this), |
|
442 |
ywIndex = $dd.attr('yw-index'), |
|
443 |
checked = $dd.prop('checked'); |
|
444 |
ywIndex ? data[ywIndex][checkedName] = checked : ""; |
|
445 |
checked && ywIndex ? options.values.push($dd.attr('layui-value')) : ""; |
|
446 |
}) |
|
447 |
|
|
448 |
ele.parent().prev().find('input').val(options.values.join(options.valueSeparator)); |
|
449 |
|
|
450 |
layui.event.call(ele, MOD_NAME, MOD_NAME + '(' + filter + ')', { |
|
451 |
checked: eleChecked, |
|
452 |
isAll: isAll, |
|
453 |
values: options.values, |
|
454 |
checkedData: data.filter(function (item) { |
|
455 |
return item[checkedName] === true; |
|
456 |
}), |
|
457 |
ele: ele |
|
458 |
}); |
|
459 |
} else if (type === 'radio') { |
|
460 |
var index = ele.find('input').attr('yw-index'), |
|
461 |
value = ele.find('input').attr('layui-value'); |
|
462 |
|
|
463 |
options.values = [value]; |
|
464 |
ele.parent().prev().find('input').val(value); |
|
465 |
|
|
466 |
layui.each(data, function (i, item) { |
|
467 |
item[checkedName] = false; |
|
468 |
}) |
|
469 |
|
|
470 |
data[index][checkedName] = true; |
|
471 |
|
|
472 |
layui.event.call(ele, MOD_NAME, MOD_NAME + '(' + filter + ')', { |
|
473 |
value: value, |
|
474 |
checkedData: data[index], |
|
475 |
ele: ele |
|
476 |
}); |
|
477 |
} |
|
478 |
|
|
479 |
} |
|
480 |
|
|
481 |
// 获取选中数据 |
|
482 |
Class.prototype.getChecked = function () { |
|
483 |
var that = this, |
|
484 |
options = that.config, |
|
485 |
data = options.data, |
|
486 |
checkedName = options.config.checkedName; |
|
487 |
|
|
488 |
return { |
|
489 |
values: options.values, |
|
490 |
data: data.filter(function (item) { |
|
491 |
return item[checkedName] === true; |
|
492 |
}) |
|
493 |
}; |
|
494 |
} |
|
495 |
|
|
496 |
// 核心入口 |
|
497 |
selectPlus.render = function (options) { |
|
498 |
var ins = new Class(options); |
|
499 |
return thisIns.call(ins); |
|
500 |
}; |
|
501 |
exports('selectPlus', selectPlus); |
|
502 |
}) |