-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.cascadeSelect.js
117 lines (104 loc) · 3.29 KB
/
jquery.cascadeSelect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* global jQuery */
(function ($) {
// Data keys
const KEY_DATA_INITED = 'inited.cascadeSelect'
const KEY_DATA_OPTION = 'option.cascadeSelect'
const KEY_DATA_PREVICOUSUPPERTIER = 'previous-uppertier.cascadeSelect'
// Events
const EVENT_CHANGE = 'cascadeSelectChange';
// Override $.fn.val
// Opt for elements which has used cascadeSelect plugin.
(function (originVal) {
$.fn.val = function (value) {
// Getter
if (!arguments.length) {
return originVal.call(this)
}
// Setter
const r = originVal.call(this, value)
// Fire cascade changed
return r.each(function () {
if ($(this).data(KEY_DATA_INITED)) {
$(this).trigger(EVENT_CHANGE)
}
})
}
})($.fn.val)
// Generate list by upper-tier.
const getList = function (strUpperTier, dataSource) {
if (dataSource && strUpperTier !== undefined) {
const upperTiers = strUpperTier.split(';')
let r = []
let upperTier
for (let i = 0, len = upperTiers.length; i < len; i++) {
upperTier = upperTiers[i]
// Only for valid list.
if (dataSource[upperTier]) {
r = r.concat(dataSource[upperTier])
}
}
return r
}
return null
}
// Generate option html
const genOptionHtml = (value, text) =>
'<option value="' + value + '">' + text + '</option>'
// Update select html
const updateOptionHtml = function (select, data, upperTier) {
const list = getList(upperTier, data.dataSource)
const $select = $(select)
if (list) {
if (
$select.data(KEY_DATA_PREVICOUSUPPERTIER) !== upperTier
) {
let h = []
let allIds = []
$.each(list, function (i, itm) {
allIds.push(itm.id)
h.push(genOptionHtml(itm.id, itm.label))
})
// Generate default option
h.unshift(genOptionHtml(allIds.join(';'), data?.labels?.all ?? '全部'))
$select.html(h.join(''))
$select.data(KEY_DATA_PREVICOUSUPPERTIER, upperTier)
h = null
allIds = null
}
} else {
throw new Error('Missing data, key=' + upperTier)
}
}
/**
* $.fn.cascadeSelect Plugin
*
* @param {Object} option config data for plugin
* @param {function} option.upperTierGetter return upperTier key
* @param {Array} option.dataSource data source
* @param {?Object} option.labels label map
* @return {jQuery}
*
*/
$.fn.cascadeSelect = function (option) {
return this.each(function () {
const $this = $(this)
if (!$this.data(KEY_DATA_INITED)) {
$this.data(KEY_DATA_INITED, true)
}
updateOptionHtml(this, option, option.upperTierGetter())
$this.data(KEY_DATA_OPTION, option)
// If value changed, then call updated.
$this.bind('change', function () {
const $this = $(this)
const val = $this.val()
updateOptionHtml(this, option, option.upperTierGetter())
$this.val(val) // A trick, get the real value.
})
// For external API. Like $(elem).trigger("update");
$this.bind('update', function () {
const $this = $(this)
$this.trigger('change')
})
})
}
})(jQuery)