slim-select 1.27.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/.prettierrc +6 -0
- package/.vscode/extensions.json +3 -0
- package/.vscode/settings.json +15 -5
- package/README.md +2 -1
- package/dist/helper.d.ts +1 -4
- package/dist/index.d.ts +38 -58
- package/dist/render.d.ts +109 -0
- package/dist/select.d.ts +31 -20
- package/dist/settings.d.ts +33 -0
- package/dist/slimselect.cjs.js +2 -0
- package/dist/slimselect.cjs.js.map +1 -0
- package/dist/slimselect.css +1 -2
- package/dist/slimselect.css.map +1 -0
- package/dist/slimselect.es.js +2 -0
- package/dist/slimselect.es.js.map +1 -0
- package/dist/slimselect.global.js +2 -0
- package/dist/slimselect.global.js.map +1 -0
- package/dist/slimselect.js +2 -1970
- package/dist/slimselect.js.map +1 -0
- package/dist/slimselect.umd.js +2 -0
- package/dist/slimselect.umd.js.map +1 -0
- package/dist/store.d.ts +71 -0
- package/docs/assets/check-mark.svg +6 -0
- package/docs/assets/data.js +59 -0
- package/docs/assets/home.css +1 -0
- package/docs/assets/home.js +1 -0
- package/docs/assets/index.css +1 -0
- package/docs/assets/index.js +16 -0
- package/docs/assets/index2.js +274 -0
- package/docs/assets/index3.js +126 -0
- package/docs/assets/index4.js +60 -0
- package/docs/assets/install.js +34 -0
- package/docs/assets/selects.js +55 -0
- package/docs/index.html +18 -5
- package/docs.go +3 -1
- package/index.html +16 -0
- package/jest.config.js +7 -0
- package/package.json +39 -35
- package/src/docs/app.vue +185 -76
- package/src/docs/assets/scss/_variables.scss +26 -10
- package/src/docs/assets/scss/alert.scss +12 -0
- package/src/docs/assets/scss/animations.scss +5 -3
- package/src/docs/assets/scss/button.scss +21 -0
- package/src/docs/assets/scss/index.scss +8 -6
- package/src/docs/assets/scss/input.scss +2 -2
- package/src/docs/assets/scss/layout.scss +195 -65
- package/src/docs/assets/scss/misc.scss +144 -34
- package/src/docs/assets/scss/prism.scss +155 -153
- package/src/docs/env.d.ts +12 -0
- package/src/docs/images/check-mark.svg +6 -0
- package/src/docs/images/chrome.svg +22 -0
- package/src/docs/images/firefox.svg +58 -0
- package/src/docs/images/github.png +0 -0
- package/src/docs/images/ie.svg +11 -0
- package/src/docs/images/npm.png +0 -0
- package/src/docs/images/opera.svg +15 -0
- package/src/docs/images/safari.svg +22 -0
- package/src/docs/main.ts +27 -0
- package/src/docs/pages/data.vue +130 -0
- package/src/docs/pages/events/addable.vue +79 -0
- package/src/docs/pages/events/before_after_change.vue +140 -0
- package/src/docs/pages/events/before_after_open_close.vue +122 -0
- package/src/docs/pages/events/error.vue +59 -0
- package/src/docs/pages/events/index.vue +33 -0
- package/src/docs/pages/events/search.vue +154 -0
- package/src/docs/pages/events/search_filter.vue +45 -0
- package/src/docs/pages/home.vue +96 -116
- package/src/docs/pages/install.vue +47 -74
- package/src/docs/pages/methods/destroy.vue +66 -0
- package/src/docs/pages/methods/enable_disable.vue +70 -0
- package/src/docs/pages/methods/get_data.vue +81 -0
- package/src/docs/pages/methods/get_selected.vue +78 -0
- package/src/docs/pages/methods/index.vue +36 -0
- package/src/docs/pages/methods/open_close.vue +63 -0
- package/src/docs/pages/methods/search.vue +62 -0
- package/src/docs/pages/methods/set_data.vue +106 -0
- package/src/docs/pages/methods/set_selected.vue +70 -0
- package/src/docs/pages/selects.vue +108 -114
- package/src/docs/pages/settings/always_open.vue +88 -0
- package/src/docs/pages/settings/close_on_select.vue +69 -0
- package/src/docs/pages/settings/content_location.vue +64 -0
- package/src/docs/pages/settings/content_position.vue +86 -0
- package/src/docs/pages/settings/css.vue +73 -0
- package/src/docs/pages/settings/data_attributes.vue +39 -0
- package/src/docs/pages/settings/deselect.vue +69 -0
- package/src/docs/pages/settings/display.vue +88 -0
- package/src/docs/pages/settings/hide_selected.vue +73 -0
- package/src/docs/pages/settings/html.vue +86 -0
- package/src/docs/pages/settings/index.vue +73 -0
- package/src/docs/pages/settings/mandatory.vue +91 -0
- package/src/docs/pages/settings/min_max.vue +61 -0
- package/src/docs/pages/settings/open_position.vue +60 -0
- package/src/docs/pages/settings/placeholder.vue +72 -0
- package/src/docs/pages/settings/search.vue +140 -0
- package/src/docs/pages/settings/select.vue +32 -0
- package/src/docs/pages/settings/select_by_group.vue +46 -0
- package/src/docs/pages/settings/show_tooltip.vue +44 -0
- package/src/docs/pages/settings/styles.vue +51 -0
- package/src/docs/router.ts +41 -13
- package/src/slim-select/helper.ts +25 -86
- package/src/slim-select/index.ts +317 -420
- package/src/slim-select/render.test.ts +39 -0
- package/src/slim-select/render.ts +1129 -0
- package/src/slim-select/rollup.config.mjs +39 -0
- package/src/slim-select/select.test.ts +155 -0
- package/src/slim-select/select.ts +280 -108
- package/src/slim-select/settings.ts +68 -0
- package/src/slim-select/slimselect.scss +263 -278
- package/src/slim-select/store.test.ts +220 -0
- package/src/slim-select/store.ts +320 -0
- package/src/slim-select/tsconfig.json +11 -5
- package/src/vue/slimselect.vue +61 -0
- package/tsconfig.json +10 -29
- package/vite.config.ts +18 -0
- package/.browserslistrc +0 -4
- package/.postcssrc.js +0 -5
- package/.travis.yml +0 -22
- package/babel.config.js +0 -5
- package/dist/config.d.ts +0 -83
- package/dist/data.d.ts +0 -50
- package/dist/slim.d.ts +0 -50
- package/dist/slimselect.min.css +0 -1
- package/dist/slimselect.min.js +0 -1
- package/dist/slimselect.min.mjs +0 -1
- package/docs/css/app.d5840d21.css +0 -1
- package/docs/css/chunk-vendors.fa8199af.css +0 -1
- package/docs/css/home.57020178.css +0 -1
- package/docs/css/install.baa5d3fb.css +0 -1
- package/docs/css/methods.728c742a.css +0 -1
- package/docs/css/options.b28a32ef.css +0 -1
- package/docs/css/selects.1a7e1e6a.css +0 -1
- package/docs/js/app.238ee382.js +0 -2
- package/docs/js/app.238ee382.js.map +0 -1
- package/docs/js/chunk-vendors.5125e3d8.js +0 -21
- package/docs/js/chunk-vendors.5125e3d8.js.map +0 -1
- package/docs/js/home.e7b28581.js +0 -2
- package/docs/js/home.e7b28581.js.map +0 -1
- package/docs/js/install.d4300783.js +0 -2
- package/docs/js/install.d4300783.js.map +0 -1
- package/docs/js/methods.fa1608f1.js +0 -11
- package/docs/js/methods.fa1608f1.js.map +0 -1
- package/docs/js/options.2c4ceb87.js +0 -2
- package/docs/js/options.2c4ceb87.js.map +0 -1
- package/docs/js/selects.1eeba693.js +0 -2
- package/docs/js/selects.1eeba693.js.map +0 -1
- package/src/docs/pages/methods.vue +0 -427
- package/src/docs/pages/options.vue +0 -1480
- package/src/main.ts +0 -29
- package/src/shims-vue.d.ts +0 -8
- package/src/slim-select/config.ts +0 -118
- package/src/slim-select/data.ts +0 -377
- package/src/slim-select/slim.ts +0 -775
- package/tslint.json +0 -26
- package/vue.config.js +0 -23
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import typescript from '@rollup/plugin-typescript'
|
|
2
|
+
import { terser } from 'rollup-plugin-terser'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
input: './index.ts',
|
|
6
|
+
output: [
|
|
7
|
+
{
|
|
8
|
+
name: 'SlimSelect',
|
|
9
|
+
file: '../../dist/slimselect.js',
|
|
10
|
+
format: 'es',
|
|
11
|
+
sourcemap: true,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'SlimSelect',
|
|
15
|
+
file: '../../dist/slimselect.es.js',
|
|
16
|
+
format: 'es',
|
|
17
|
+
sourcemap: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'SlimSelect',
|
|
21
|
+
file: '../../dist/slimselect.cjs.js',
|
|
22
|
+
format: 'cjs',
|
|
23
|
+
sourcemap: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'SlimSelect',
|
|
27
|
+
file: '../../dist/slimselect.global.js',
|
|
28
|
+
format: 'iife',
|
|
29
|
+
sourcemap: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'SlimSelect',
|
|
33
|
+
file: '../../dist/slimselect.umd.js',
|
|
34
|
+
format: 'umd',
|
|
35
|
+
sourcemap: true,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
plugins: [typescript(), terser()],
|
|
39
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict'
|
|
6
|
+
|
|
7
|
+
import { describe, expect, test } from '@jest/globals'
|
|
8
|
+
import Select from './select'
|
|
9
|
+
import Store, { Optgroup, Option } from './store'
|
|
10
|
+
|
|
11
|
+
describe('select module', () => {
|
|
12
|
+
test('constructor', () => {
|
|
13
|
+
document.body.innerHTML = '<select id="test"></select>'
|
|
14
|
+
|
|
15
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
16
|
+
let select = new Select(selectElement)
|
|
17
|
+
expect(select).toBeInstanceOf(Select)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('get data from select options', () => {
|
|
21
|
+
document.body.innerHTML = `<select id="test">
|
|
22
|
+
<option value="1">One</option>
|
|
23
|
+
<option value="2">Two</option>
|
|
24
|
+
</select>`
|
|
25
|
+
|
|
26
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
27
|
+
let select = new Select(selectElement)
|
|
28
|
+
let data = select.getData() as Option[]
|
|
29
|
+
expect(data.length).toBe(2)
|
|
30
|
+
expect(data[0].value).toBe('1')
|
|
31
|
+
expect(data[0].text).toBe('One')
|
|
32
|
+
expect(data[1].value).toBe('2')
|
|
33
|
+
expect(data[1].text).toBe('Two')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('get data from select optgroups', () => {
|
|
37
|
+
document.body.innerHTML = `<select id="test">
|
|
38
|
+
<optgroup label="test1">
|
|
39
|
+
<option value="1">One</option>
|
|
40
|
+
<option value="2">Two</option>
|
|
41
|
+
</optgroup>
|
|
42
|
+
<optgroup label="test2">
|
|
43
|
+
<option value="3">Three</option>
|
|
44
|
+
<option value="4">Four</option>
|
|
45
|
+
<option value="5">Five</option>
|
|
46
|
+
</optgroup>
|
|
47
|
+
</select>`
|
|
48
|
+
|
|
49
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
50
|
+
let select = new Select(selectElement)
|
|
51
|
+
let data = select.getData() as Optgroup[]
|
|
52
|
+
expect(data.length).toBe(2)
|
|
53
|
+
expect(data[0].label).toBe('test1')
|
|
54
|
+
expect(data[0].options.length).toBe(2)
|
|
55
|
+
expect(data[0].options[0].value).toBe('1')
|
|
56
|
+
expect(data[0].options[0].text).toBe('One')
|
|
57
|
+
expect(data[0].options[1].value).toBe('2')
|
|
58
|
+
expect(data[0].options[1].text).toBe('Two')
|
|
59
|
+
expect(data[1].label).toBe('test2')
|
|
60
|
+
expect(data[1].options.length).toBe(3)
|
|
61
|
+
expect(data[1].options[0].value).toBe('3')
|
|
62
|
+
expect(data[1].options[0].text).toBe('Three')
|
|
63
|
+
expect(data[1].options[1].value).toBe('4')
|
|
64
|
+
expect(data[1].options[1].text).toBe('Four')
|
|
65
|
+
expect(data[1].options[2].value).toBe('5')
|
|
66
|
+
expect(data[1].options[2].text).toBe('Five')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('update select from data', () => {
|
|
70
|
+
document.body.innerHTML = '<select id="test"></select>'
|
|
71
|
+
|
|
72
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
73
|
+
let select = new Select(selectElement)
|
|
74
|
+
let store = new Store('single', [
|
|
75
|
+
{
|
|
76
|
+
id: '1',
|
|
77
|
+
value: '1',
|
|
78
|
+
text: 'One',
|
|
79
|
+
selected: false,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: '2',
|
|
83
|
+
value: '2',
|
|
84
|
+
text: 'Two',
|
|
85
|
+
selected: false,
|
|
86
|
+
},
|
|
87
|
+
])
|
|
88
|
+
let data = store.getData()
|
|
89
|
+
select.updateOptions(data)
|
|
90
|
+
|
|
91
|
+
expect(selectElement.innerHTML).toBe('<option value="1">One</option><option value="2">Two</option>')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('event change value listener', () => {
|
|
95
|
+
document.body.innerHTML = `<select id="test">
|
|
96
|
+
<option value="1">One</option>
|
|
97
|
+
<option value="2">Two</option>
|
|
98
|
+
<option value="3">Three</option>
|
|
99
|
+
</select>`
|
|
100
|
+
|
|
101
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
102
|
+
let select = new Select(selectElement)
|
|
103
|
+
|
|
104
|
+
let data = select.getData() as Option[]
|
|
105
|
+
|
|
106
|
+
expect(data[0].selected).toBe(true)
|
|
107
|
+
|
|
108
|
+
let didChange = false
|
|
109
|
+
select.addValueChangeListener(() => {
|
|
110
|
+
didChange = true
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
selectElement.value = '2'
|
|
114
|
+
|
|
115
|
+
data = select.getData() as Option[]
|
|
116
|
+
|
|
117
|
+
expect(data[1].selected).toBe(true)
|
|
118
|
+
|
|
119
|
+
// Give the mutation observer time to run
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
expect(didChange).toBe(true)
|
|
122
|
+
}, 100)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('mutation observer listener', () => {
|
|
126
|
+
document.body.innerHTML = `<select id="test">
|
|
127
|
+
<option value="1">One</option>
|
|
128
|
+
<option value="2">Two</option>
|
|
129
|
+
<option value="3">Three</option>
|
|
130
|
+
</select>`
|
|
131
|
+
|
|
132
|
+
let selectElement = document.getElementById('test') as HTMLSelectElement
|
|
133
|
+
let select = new Select(selectElement)
|
|
134
|
+
|
|
135
|
+
let data = select.getData() as Option[]
|
|
136
|
+
|
|
137
|
+
expect(data.length).toBe(3)
|
|
138
|
+
|
|
139
|
+
let didChange = false
|
|
140
|
+
select.addSelectChangeListener(() => {
|
|
141
|
+
didChange = true
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
selectElement.innerHTML = '<option value="1">One</option><option value="2">Two</option>'
|
|
145
|
+
|
|
146
|
+
data = select.getData() as Option[]
|
|
147
|
+
|
|
148
|
+
expect(data.length).toBe(2)
|
|
149
|
+
|
|
150
|
+
// Give the mutation observer time to run
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
expect(didChange).toBe(true)
|
|
153
|
+
}, 100)
|
|
154
|
+
})
|
|
155
|
+
})
|
|
@@ -1,149 +1,311 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { kebabCase } from './helper'
|
|
1
|
+
import { generateID, kebabCase } from './helper'
|
|
2
|
+
import { DataArray, DataObject, Optgroup, Option } from './store'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
select: HTMLSelectElement
|
|
7
|
-
|
|
8
|
-
}
|
|
4
|
+
export default class Select {
|
|
5
|
+
public select: HTMLSelectElement
|
|
6
|
+
public listen: boolean = false
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
public
|
|
12
|
-
public
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
constructor(
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
8
|
+
// Mutation observer fields
|
|
9
|
+
public onSelectChange?: (data: DataArray) => void
|
|
10
|
+
public onValueChange?: (value: string[]) => void
|
|
11
|
+
private observer: MutationObserver | null = null
|
|
12
|
+
|
|
13
|
+
constructor(select: HTMLSelectElement) {
|
|
14
|
+
this.select = select
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Set to enabled
|
|
18
|
+
public enable(): void {
|
|
19
|
+
// Disable original select but dont trigger observer
|
|
20
|
+
this.disconnectObserver()
|
|
21
|
+
this.select.disabled = false
|
|
22
|
+
this.connectObserver()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Set to disabled
|
|
26
|
+
public disable(): void {
|
|
27
|
+
// Enable original select but dont trigger observer
|
|
28
|
+
this.disconnectObserver()
|
|
29
|
+
this.select.disabled = true
|
|
30
|
+
this.connectObserver()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Set misc attributes on the main select element
|
|
34
|
+
public hideUI(): void {
|
|
35
|
+
this.select.tabIndex = -1
|
|
36
|
+
this.select.style.display = 'none'
|
|
37
|
+
this.select.setAttribute('aria-hidden', 'true')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public showUI(): void {
|
|
41
|
+
this.select.removeAttribute('tabindex')
|
|
42
|
+
this.select.style.display = ''
|
|
43
|
+
this.select.removeAttribute('aria-hidden')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public changeListen(on: boolean) {
|
|
47
|
+
this.listen = on
|
|
48
|
+
|
|
49
|
+
// Deal with some observer situations
|
|
50
|
+
if (this.listen) {
|
|
51
|
+
this.connectObserver()
|
|
47
52
|
} else {
|
|
48
|
-
|
|
49
|
-
const selected = this.main.data.getSelected() as any
|
|
50
|
-
this.element.value = (selected ? selected.value : '')
|
|
53
|
+
this.disconnectObserver()
|
|
51
54
|
}
|
|
55
|
+
}
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
57
|
+
// Add change listener to original select
|
|
58
|
+
public addSelectChangeListener(func: (data: DataArray) => void): void {
|
|
59
|
+
this.onSelectChange = func
|
|
60
|
+
this.addObserver()
|
|
61
|
+
this.connectObserver()
|
|
62
|
+
this.changeListen(true) // Last start listening
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.
|
|
65
|
+
// remove change listener from original select
|
|
66
|
+
public removeSelectChangeListener(): void {
|
|
67
|
+
this.changeListen(false) // First stop listening
|
|
68
|
+
this.onSelectChange = undefined
|
|
69
|
+
}
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
71
|
+
public addValueChangeListener(func: (value: string[]) => void): void {
|
|
72
|
+
this.onValueChange = func
|
|
73
|
+
this.select.addEventListener('change', this.valueChange.bind(this))
|
|
66
74
|
}
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
public removeValueChangeListener(): void {
|
|
77
|
+
this.onValueChange = undefined
|
|
78
|
+
this.select.removeEventListener('change', this.valueChange.bind(this))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public valueChange(ev: Event): any {
|
|
82
|
+
if (this.onValueChange) {
|
|
83
|
+
this.onValueChange(this.getSelectedValues())
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private observeWrapper(mutations: MutationRecord[]): void {
|
|
88
|
+
if (this.onSelectChange) {
|
|
89
|
+
this.onSelectChange(this.getData())
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
// Add MutationObserver to select
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
if (this.
|
|
94
|
+
private addObserver(): void {
|
|
95
|
+
// If mutation observer already exists then disconnect and
|
|
96
|
+
if (this.observer) {
|
|
97
|
+
this.disconnectObserver()
|
|
98
|
+
this.observer = null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// If anything changes in the select then update the data
|
|
102
|
+
this.observer = new MutationObserver(this.observeWrapper)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private connectObserver(): void {
|
|
106
|
+
if (this.observer) {
|
|
107
|
+
this.observer.observe(this.select, {
|
|
108
|
+
attributes: true,
|
|
109
|
+
childList: true,
|
|
110
|
+
characterData: true,
|
|
111
|
+
subtree: true,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private disconnectObserver(): void {
|
|
117
|
+
if (this.observer) {
|
|
118
|
+
this.observer.disconnect()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// From the select element pull optgroup and options into data
|
|
123
|
+
public getData(): DataArray {
|
|
124
|
+
let data = []
|
|
125
|
+
|
|
126
|
+
// Loop through nodes and get data
|
|
127
|
+
const nodes = this.select.childNodes as any as HTMLOptGroupElement[] | HTMLOptionElement[]
|
|
128
|
+
for (const n of nodes) {
|
|
129
|
+
// Optgroup
|
|
130
|
+
if (n.nodeName === 'OPTGROUP') {
|
|
131
|
+
data.push(this.getDataFromOptgroup(n as HTMLOptGroupElement))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Option
|
|
135
|
+
if (n.nodeName === 'OPTION') {
|
|
136
|
+
data.push(this.getDataFromOption(n as HTMLOptionElement))
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return data
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public getDataFromOptgroup(optgroup: HTMLOptGroupElement): Optgroup {
|
|
144
|
+
let data = {
|
|
145
|
+
id: '',
|
|
146
|
+
label: optgroup.label,
|
|
147
|
+
options: [],
|
|
148
|
+
} as Optgroup
|
|
80
149
|
|
|
81
|
-
|
|
82
|
-
|
|
150
|
+
const options = optgroup.childNodes as any as HTMLOptionElement[]
|
|
151
|
+
for (const o of options) {
|
|
152
|
+
if (o.nodeName === 'OPTION') {
|
|
153
|
+
data.options.push(this.getDataFromOption(o as HTMLOptionElement))
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return data
|
|
158
|
+
}
|
|
83
159
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.main.render()
|
|
160
|
+
public getSelectedValues(): string[] {
|
|
161
|
+
let values = []
|
|
87
162
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
163
|
+
// Loop through options and set selected
|
|
164
|
+
const options = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]
|
|
165
|
+
for (const o of options) {
|
|
166
|
+
if (o.nodeName === 'OPTGROUP') {
|
|
167
|
+
const optgroupOptions = o.childNodes as any as HTMLOptionElement[]
|
|
168
|
+
for (const oo of optgroupOptions) {
|
|
169
|
+
if (oo.nodeName === 'OPTION') {
|
|
170
|
+
const option = oo as HTMLOptionElement
|
|
171
|
+
if (option.selected) {
|
|
172
|
+
values.push(option.value)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
91
175
|
}
|
|
92
|
-
}
|
|
93
|
-
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (o.nodeName === 'OPTION') {
|
|
179
|
+
const option = o as HTMLOptionElement
|
|
180
|
+
if (option.selected) {
|
|
181
|
+
values.push(option.value)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
94
185
|
|
|
95
|
-
|
|
186
|
+
return values
|
|
96
187
|
}
|
|
97
188
|
|
|
98
|
-
|
|
99
|
-
|
|
189
|
+
// From passed in option pull pieces of usable information
|
|
190
|
+
public getDataFromOption(option: HTMLOptionElement): Option {
|
|
191
|
+
return {
|
|
192
|
+
id: (option.dataset ? option.dataset.id : false) || generateID(),
|
|
193
|
+
value: option.value,
|
|
194
|
+
text: option.text,
|
|
195
|
+
html: option.innerHTML,
|
|
196
|
+
selected: option.selected,
|
|
197
|
+
display: option.style.display === 'none' ? false : true,
|
|
198
|
+
disabled: option.disabled,
|
|
199
|
+
mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
|
|
200
|
+
placeholder: option.dataset.placeholder === 'true',
|
|
201
|
+
class: option.className,
|
|
202
|
+
style: option.style.cssText,
|
|
203
|
+
data: option.dataset,
|
|
204
|
+
} as Option
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public setSelected(value: string[]): void {
|
|
208
|
+
// Loop through options and set selected
|
|
209
|
+
const options = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]
|
|
210
|
+
for (const o of options) {
|
|
211
|
+
if (o.nodeName === 'OPTGROUP') {
|
|
212
|
+
const optgroup = o as HTMLOptGroupElement
|
|
213
|
+
const optgroupOptions = optgroup.childNodes as any as HTMLOptionElement[]
|
|
214
|
+
for (const oo of optgroupOptions) {
|
|
215
|
+
if (oo.nodeName === 'OPTION') {
|
|
216
|
+
const option = oo as HTMLOptionElement
|
|
217
|
+
option.selected = value.includes(option.value)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
100
221
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
222
|
+
if (o.nodeName === 'OPTION') {
|
|
223
|
+
const option = o as HTMLOptionElement
|
|
224
|
+
option.selected = value.includes(option.value)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
106
227
|
}
|
|
107
228
|
|
|
108
|
-
public
|
|
109
|
-
|
|
110
|
-
|
|
229
|
+
public updateSelect(id?: string, style?: string, classes?: string[]): void {
|
|
230
|
+
// Stop listening to changes
|
|
231
|
+
this.changeListen(false)
|
|
232
|
+
|
|
233
|
+
// Update id
|
|
234
|
+
if (id) {
|
|
235
|
+
this.select.id = id
|
|
111
236
|
}
|
|
237
|
+
|
|
238
|
+
// Update style
|
|
239
|
+
if (style) {
|
|
240
|
+
this.select.style.cssText = style
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Update classes
|
|
244
|
+
if (classes) {
|
|
245
|
+
this.select.className = ''
|
|
246
|
+
classes.forEach((c) => {
|
|
247
|
+
if (c.trim() !== '') {
|
|
248
|
+
this.select.classList.add(c.trim())
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Start listening to changes
|
|
254
|
+
this.changeListen(true)
|
|
112
255
|
}
|
|
113
256
|
|
|
114
|
-
|
|
115
|
-
|
|
257
|
+
public updateOptions(data: DataArray): void {
|
|
258
|
+
// Stop listening to changes
|
|
259
|
+
this.changeListen(false)
|
|
260
|
+
|
|
116
261
|
// Clear out select
|
|
117
|
-
this.
|
|
262
|
+
this.select.innerHTML = ''
|
|
118
263
|
|
|
119
264
|
for (const d of data) {
|
|
120
|
-
if (d
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
optgroupEl.appendChild(this.createOption(oo))
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
this.element.appendChild(optgroupEl)
|
|
130
|
-
} else {
|
|
131
|
-
this.element.appendChild(this.createOption(d))
|
|
265
|
+
if (d instanceof Optgroup) {
|
|
266
|
+
this.select.appendChild(this.createOptgroup(d))
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (d instanceof Option) {
|
|
270
|
+
this.select.appendChild(this.createOption(d))
|
|
132
271
|
}
|
|
133
272
|
}
|
|
273
|
+
|
|
274
|
+
// Start listening to changes
|
|
275
|
+
this.changeListen(true)
|
|
134
276
|
}
|
|
135
277
|
|
|
136
|
-
public
|
|
278
|
+
public createOptgroup(optgroup: Optgroup): HTMLOptGroupElement {
|
|
279
|
+
const optgroupEl = document.createElement('optgroup')
|
|
280
|
+
optgroupEl.id = optgroup.id
|
|
281
|
+
optgroupEl.label = optgroup.label
|
|
282
|
+
if (optgroup.options) {
|
|
283
|
+
for (const o of optgroup.options) {
|
|
284
|
+
optgroupEl.appendChild(this.createOption(o))
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return optgroupEl
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
public createOption(info: Option): HTMLOptionElement {
|
|
137
291
|
const optionEl = document.createElement('option')
|
|
138
292
|
optionEl.value = info.value !== '' ? info.value : info.text
|
|
139
|
-
optionEl.innerHTML = info.
|
|
140
|
-
if (info.selected) {
|
|
293
|
+
optionEl.innerHTML = info.html || info.text
|
|
294
|
+
if (info.selected) {
|
|
295
|
+
optionEl.selected = info.selected
|
|
296
|
+
}
|
|
297
|
+
if (info.disabled) {
|
|
298
|
+
optionEl.disabled = true
|
|
299
|
+
}
|
|
141
300
|
if (info.display === false) {
|
|
142
301
|
optionEl.style.display = 'none'
|
|
143
302
|
}
|
|
144
|
-
if (info.
|
|
145
|
-
|
|
146
|
-
|
|
303
|
+
if (info.placeholder) {
|
|
304
|
+
optionEl.setAttribute('data-placeholder', 'true')
|
|
305
|
+
}
|
|
306
|
+
if (info.mandatory) {
|
|
307
|
+
optionEl.setAttribute('data-mandatory', 'true')
|
|
308
|
+
}
|
|
147
309
|
if (info.class) {
|
|
148
310
|
info.class.split(' ').forEach((optionClass: string) => {
|
|
149
311
|
optionEl.classList.add(optionClass)
|
|
@@ -157,4 +319,14 @@ export class Select {
|
|
|
157
319
|
|
|
158
320
|
return optionEl
|
|
159
321
|
}
|
|
322
|
+
|
|
323
|
+
public destroy() {
|
|
324
|
+
this.changeListen(false)
|
|
325
|
+
this.disconnectObserver()
|
|
326
|
+
this.removeSelectChangeListener()
|
|
327
|
+
this.removeValueChangeListener()
|
|
328
|
+
|
|
329
|
+
// show the original select
|
|
330
|
+
this.showUI()
|
|
331
|
+
}
|
|
160
332
|
}
|