slim-select 2.0.2 → 2.2.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/README.md +8 -0
- package/dist/index.d.ts +1 -1
- package/dist/render.d.ts +10 -3
- package/dist/select.d.ts +6 -6
- package/dist/settings.d.ts +0 -3
- package/dist/slimselect.cjs.js +202 -67
- package/dist/slimselect.css +1 -1
- package/dist/slimselect.css.map +1 -1
- package/dist/slimselect.es.js +202 -67
- package/dist/slimselect.global.js +202 -67
- package/dist/slimselect.js +202 -67
- package/dist/slimselect.min.js +1 -1
- package/dist/slimselect.umd.js +202 -67
- package/dist/slimselect.umd.min.js +1 -1
- package/dist/store.d.ts +5 -0
- package/docs/assets/data.js +7 -3
- package/docs/assets/home.css +1 -1
- package/docs/assets/home.js +1 -1
- package/docs/assets/index.css +1 -1
- package/docs/assets/index.js +7 -7
- package/docs/assets/index2.js +119 -35
- package/docs/assets/index3.js +39 -23
- package/docs/assets/index4.js +1 -1
- package/docs/assets/index5.js +147 -9
- package/docs/assets/install.js +4 -4
- package/docs/assets/selects.js +1 -1
- package/package.json +11 -3
- package/src/docs/app.vue +6 -5
- package/src/docs/{images → assets/images}/check-mark.svg +0 -0
- package/src/docs/{images → assets/images}/chrome.svg +0 -0
- package/src/docs/{images → assets/images}/firefox.svg +0 -0
- package/src/docs/{images → assets/images}/github.png +0 -0
- package/src/docs/{images → assets/images}/ie.svg +0 -0
- package/src/docs/{images → assets/images}/npm.png +0 -0
- package/src/docs/{images → assets/images}/opera.svg +0 -0
- package/src/docs/{images → assets/images}/safari.svg +0 -0
- package/src/docs/assets/scss/misc.scss +7 -0
- package/src/docs/env.d.ts +1 -0
- package/src/docs/pages/data.vue +4 -0
- package/src/docs/pages/events/addable.vue +22 -6
- package/src/docs/pages/events/before_after_change.vue +15 -1
- package/src/docs/pages/events/search.vue +31 -16
- package/src/docs/pages/frameworks/vue.vue +375 -7
- package/src/docs/pages/home.vue +104 -57
- package/src/docs/pages/methods/get_data.vue +2 -1
- package/src/docs/pages/methods/open_close.vue +1 -1
- package/src/docs/pages/settings/closable.vue +128 -0
- package/src/docs/pages/settings/index.vue +6 -3
- package/src/docs/pages/settings/select_all.vue +88 -0
- package/src/slim-select/index.ts +4 -2
- package/src/slim-select/render.ts +247 -59
- package/src/slim-select/rollup.config.mjs +5 -0
- package/src/slim-select/select.ts +48 -31
- package/src/slim-select/settings.ts +0 -4
- package/src/slim-select/slimselect.scss +112 -11
- package/src/slim-select/store.ts +19 -1
- package/src/vue/README.md +48 -0
- package/src/vue/dist/slimselectvue.es.js +1752 -0
- package/src/vue/dist/slimselectvue.global.js +1755 -0
- package/src/vue/dist/slimselectvue.ssr.js +1754 -0
- package/src/vue/hello.ts +5 -0
- package/src/vue/package.json +28 -0
- package/src/vue/rollup.config.mjs +44 -0
- package/src/vue/slimselect.vue +39 -5
- package/src/vue/tsconfig.json +14 -0
- package/src/docs/pages/settings/select_by_group.vue +0 -46
|
@@ -5,7 +5,7 @@ import Store, { DataArray, Optgroup, Option, OptionOptional } from './store'
|
|
|
5
5
|
export interface Callbacks {
|
|
6
6
|
open: () => void
|
|
7
7
|
close: () => void
|
|
8
|
-
addable?: (value: string) => OptionOptional | string
|
|
8
|
+
addable?: (value: string) => Promise<OptionOptional | string> | OptionOptional | string
|
|
9
9
|
setSelected: (value: string[]) => void
|
|
10
10
|
addOption: (option: Option) => void
|
|
11
11
|
search: (search: string) => void
|
|
@@ -89,17 +89,28 @@ export default class Render {
|
|
|
89
89
|
addable: 'ss-addable',
|
|
90
90
|
addablePath: 'M50,10 L50,90 M10,50 L90,50', // Not a class but whatever
|
|
91
91
|
|
|
92
|
-
// List options
|
|
92
|
+
// List optgroups/options
|
|
93
93
|
list: 'ss-list',
|
|
94
|
+
|
|
95
|
+
// Optgroup
|
|
94
96
|
optgroup: 'ss-optgroup',
|
|
95
97
|
optgroupLabel: 'ss-optgroup-label',
|
|
96
|
-
|
|
98
|
+
optgroupLabelText: 'ss-optgroup-label-text',
|
|
99
|
+
optgroupActions: 'ss-optgroup-actions',
|
|
100
|
+
optgroupSelectAll: 'ss-selectall', // optgroup select all
|
|
101
|
+
optgroupSelectAllBox: 'M60,10 L10,10 L10,90 L90,90 L90,50', // Not a class but whatever
|
|
102
|
+
optgroupSelectAllCheck: 'M30,45 L50,70 L90,10', // Not a class but whatever
|
|
103
|
+
optgroupClosable: 'ss-closable',
|
|
104
|
+
|
|
105
|
+
// Option
|
|
97
106
|
option: 'ss-option',
|
|
98
|
-
optionSelected: 'ss-option-selected',
|
|
99
107
|
optionDelete: 'M10,10 L90,90 M10,90 L90,10', // Not a class but whatever
|
|
100
108
|
highlighted: 'ss-highlighted',
|
|
101
109
|
|
|
102
110
|
// Misc
|
|
111
|
+
open: 'ss-open',
|
|
112
|
+
close: 'ss-close',
|
|
113
|
+
selected: 'ss-selected',
|
|
103
114
|
error: 'ss-error',
|
|
104
115
|
disabled: 'ss-disabled',
|
|
105
116
|
hide: 'ss-hide',
|
|
@@ -113,12 +124,6 @@ export default class Render {
|
|
|
113
124
|
this.main = this.mainDiv()
|
|
114
125
|
this.content = this.contentDiv()
|
|
115
126
|
|
|
116
|
-
// Render the values
|
|
117
|
-
this.renderValues()
|
|
118
|
-
|
|
119
|
-
// Render the options
|
|
120
|
-
this.renderOptions(this.store.getData())
|
|
121
|
-
|
|
122
127
|
// Add content to the content location settings
|
|
123
128
|
this.settings.contentLocation.appendChild(this.content.main)
|
|
124
129
|
}
|
|
@@ -266,6 +271,8 @@ export default class Render {
|
|
|
266
271
|
if (!this.settings.allowDeselect || this.settings.isMultiple) {
|
|
267
272
|
deselect.classList.add(this.classes.hide)
|
|
268
273
|
}
|
|
274
|
+
|
|
275
|
+
// Add deselect onclick event
|
|
269
276
|
deselect.onclick = (e: Event) => {
|
|
270
277
|
e.stopPropagation()
|
|
271
278
|
|
|
@@ -274,7 +281,29 @@ export default class Render {
|
|
|
274
281
|
return
|
|
275
282
|
}
|
|
276
283
|
|
|
277
|
-
|
|
284
|
+
// By Default we will delete
|
|
285
|
+
let shouldDelete = true
|
|
286
|
+
const before = this.store.getSelectedOptions()
|
|
287
|
+
const after = [] as Option[]
|
|
288
|
+
|
|
289
|
+
// Add beforeChange callback
|
|
290
|
+
if (this.callbacks.beforeChange) {
|
|
291
|
+
shouldDelete = this.callbacks.beforeChange(after, before) === true
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (shouldDelete) {
|
|
295
|
+
this.callbacks.setSelected([''])
|
|
296
|
+
|
|
297
|
+
// Check if we need to close the dropdown
|
|
298
|
+
if (this.settings.closeOnSelect) {
|
|
299
|
+
this.callbacks.close()
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Run afterChange callback
|
|
303
|
+
if (this.callbacks.afterChange) {
|
|
304
|
+
this.callbacks.afterChange(after)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
278
307
|
}
|
|
279
308
|
|
|
280
309
|
// Add deselect svg
|
|
@@ -466,8 +495,11 @@ export default class Render {
|
|
|
466
495
|
|
|
467
496
|
// Only add deletion if the option is not mandatory
|
|
468
497
|
if (!option.mandatory) {
|
|
498
|
+
// Create delete div element
|
|
469
499
|
const deleteDiv = document.createElement('div')
|
|
470
500
|
deleteDiv.classList.add(this.classes.valueDelete)
|
|
501
|
+
|
|
502
|
+
// Add delete onclick event
|
|
471
503
|
deleteDiv.onclick = (e: Event) => {
|
|
472
504
|
e.preventDefault()
|
|
473
505
|
e.stopPropagation()
|
|
@@ -656,13 +688,18 @@ export default class Render {
|
|
|
656
688
|
|
|
657
689
|
// If addable is enabled, add the addable div
|
|
658
690
|
if (this.callbacks.addable) {
|
|
691
|
+
// Add main class
|
|
659
692
|
addable.classList.add(this.classes.addable)
|
|
693
|
+
|
|
694
|
+
// Add svg icon
|
|
660
695
|
const plus = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
661
696
|
plus.setAttribute('viewBox', '0 0 100 100')
|
|
662
697
|
const plusPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
663
698
|
plusPath.setAttribute('d', this.classes.addablePath)
|
|
664
699
|
plus.appendChild(plusPath)
|
|
665
700
|
addable.appendChild(plus)
|
|
701
|
+
|
|
702
|
+
// Add click event to addable div
|
|
666
703
|
addable.onclick = (e: Event) => {
|
|
667
704
|
e.preventDefault()
|
|
668
705
|
e.stopPropagation()
|
|
@@ -679,35 +716,61 @@ export default class Render {
|
|
|
679
716
|
return
|
|
680
717
|
}
|
|
681
718
|
|
|
719
|
+
// Run finish will be ran at the end of the addable function.
|
|
720
|
+
// Reason its in a function is so we can run it after the
|
|
721
|
+
// addable function is done for promise based addables
|
|
722
|
+
const runFinish = (oo: OptionOptional) => {
|
|
723
|
+
let newOption = new Option(oo)
|
|
724
|
+
|
|
725
|
+
// Call addOption to add the new option
|
|
726
|
+
this.callbacks.addOption(newOption)
|
|
727
|
+
|
|
728
|
+
// set selected value for single and multiple
|
|
729
|
+
if (this.settings.isMultiple) {
|
|
730
|
+
let values = this.store.getSelected()
|
|
731
|
+
values.push(newOption.value)
|
|
732
|
+
this.callbacks.setSelected(values)
|
|
733
|
+
} else {
|
|
734
|
+
this.callbacks.setSelected([newOption.value])
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Clear search
|
|
738
|
+
this.callbacks.search('')
|
|
739
|
+
|
|
740
|
+
// Close it only if closeOnSelect = true
|
|
741
|
+
if (this.settings.closeOnSelect) {
|
|
742
|
+
setTimeout(() => {
|
|
743
|
+
// Give it a little padding for a better looking animation
|
|
744
|
+
this.callbacks.close()
|
|
745
|
+
}, 100)
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
682
749
|
// Call addable callback
|
|
683
750
|
const addableValue = this.callbacks.addable(inputValue)
|
|
684
751
|
|
|
685
|
-
// If
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
752
|
+
// If addableValue is a promise, wait for it to resolve
|
|
753
|
+
if (addableValue instanceof Promise) {
|
|
754
|
+
addableValue.then((value) => {
|
|
755
|
+
if (typeof value === 'string') {
|
|
756
|
+
runFinish({
|
|
757
|
+
text: value,
|
|
758
|
+
value: value,
|
|
759
|
+
})
|
|
760
|
+
} else {
|
|
761
|
+
runFinish(value)
|
|
762
|
+
}
|
|
763
|
+
})
|
|
764
|
+
} else if (typeof addableValue === 'string') {
|
|
765
|
+
runFinish({
|
|
766
|
+
text: addableValue,
|
|
767
|
+
value: addableValue,
|
|
768
|
+
})
|
|
694
769
|
} else {
|
|
695
|
-
|
|
770
|
+
runFinish(addableValue)
|
|
696
771
|
}
|
|
697
772
|
|
|
698
|
-
|
|
699
|
-
this.callbacks.setSelected([inputValue])
|
|
700
|
-
|
|
701
|
-
// Clear search
|
|
702
|
-
this.callbacks.search('')
|
|
703
|
-
|
|
704
|
-
// Close it only if closeOnSelect = true
|
|
705
|
-
if (this.settings.closeOnSelect) {
|
|
706
|
-
setTimeout(() => {
|
|
707
|
-
// Give it a little padding for a better looking animation
|
|
708
|
-
this.callbacks.close()
|
|
709
|
-
}, 100)
|
|
710
|
-
}
|
|
773
|
+
return
|
|
711
774
|
}
|
|
712
775
|
main.appendChild(addable)
|
|
713
776
|
|
|
@@ -768,25 +831,31 @@ export default class Render {
|
|
|
768
831
|
// Loop through options and find the highlighted one
|
|
769
832
|
for (let i = 0; i < options.length; i++) {
|
|
770
833
|
if (options[i].classList.contains(this.classes.highlighted)) {
|
|
834
|
+
const prevOption = options[i]
|
|
771
835
|
// Remove highlighted class from current one
|
|
772
|
-
|
|
836
|
+
prevOption.classList.remove(this.classes.highlighted)
|
|
837
|
+
|
|
838
|
+
// If previous option has parent classes ss-optgroup with ss-open then click it
|
|
839
|
+
const prevParent = prevOption.parentElement
|
|
840
|
+
if (prevParent && prevParent.classList.contains(this.classes.open)) {
|
|
841
|
+
const optgroupLabel = prevParent.querySelector('.' + this.classes.optgroupLabel) as HTMLDivElement
|
|
842
|
+
if (optgroupLabel) {
|
|
843
|
+
optgroupLabel.click()
|
|
844
|
+
}
|
|
845
|
+
}
|
|
773
846
|
|
|
774
847
|
// Highlight the next one
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (
|
|
785
|
-
|
|
786
|
-
this.ensureElementInView(this.content.list, options[i - 1])
|
|
787
|
-
} else {
|
|
788
|
-
options[options.length - 1].classList.add(this.classes.highlighted)
|
|
789
|
-
this.ensureElementInView(this.content.list, options[options.length - 1])
|
|
848
|
+
let selectOption =
|
|
849
|
+
options[dir === 'down' ? (i + 1 < options.length ? i + 1 : 0) : i - 1 >= 0 ? i - 1 : options.length - 1]
|
|
850
|
+
selectOption.classList.add(this.classes.highlighted)
|
|
851
|
+
this.ensureElementInView(this.content.list, selectOption)
|
|
852
|
+
|
|
853
|
+
// If selected option has parent classes ss-optgroup with ss-close then click it
|
|
854
|
+
const selectParent = selectOption.parentElement
|
|
855
|
+
if (selectParent && selectParent.classList.contains(this.classes.close)) {
|
|
856
|
+
const optgroupLabel = selectParent.querySelector('.' + this.classes.optgroupLabel) as HTMLDivElement
|
|
857
|
+
if (optgroupLabel) {
|
|
858
|
+
optgroupLabel.click()
|
|
790
859
|
}
|
|
791
860
|
}
|
|
792
861
|
|
|
@@ -857,21 +926,140 @@ export default class Render {
|
|
|
857
926
|
// Create label
|
|
858
927
|
const optgroupLabel = document.createElement('div')
|
|
859
928
|
optgroupLabel.classList.add(this.classes.optgroupLabel)
|
|
860
|
-
optgroupLabel
|
|
929
|
+
optgroupEl.appendChild(optgroupLabel)
|
|
930
|
+
|
|
931
|
+
// Create label text div element
|
|
932
|
+
const optgroupLabelText = document.createElement('div')
|
|
933
|
+
optgroupLabelText.classList.add(this.classes.optgroupLabelText)
|
|
934
|
+
optgroupLabelText.textContent = d.label
|
|
935
|
+
optgroupLabel.appendChild(optgroupLabelText)
|
|
936
|
+
|
|
937
|
+
// Create options container
|
|
938
|
+
const optgroupActions = document.createElement('div')
|
|
939
|
+
optgroupActions.classList.add(this.classes.optgroupActions)
|
|
940
|
+
optgroupLabel.appendChild(optgroupActions)
|
|
861
941
|
|
|
862
942
|
// If selectByGroup is true and isMultiple then add click event to label
|
|
863
|
-
if (this.settings.
|
|
864
|
-
|
|
943
|
+
if (this.settings.isMultiple && d.selectAll) {
|
|
944
|
+
// Create new div to hold a checkbox svg
|
|
945
|
+
const selectAll = document.createElement('div')
|
|
946
|
+
selectAll.classList.add(this.classes.optgroupSelectAll)
|
|
947
|
+
|
|
948
|
+
// Check options and if all are selected, if so add class selected
|
|
949
|
+
let allSelected = true
|
|
950
|
+
for (const o of d.options) {
|
|
951
|
+
if (!o.selected) {
|
|
952
|
+
allSelected = false
|
|
953
|
+
break
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// Add class if all selected
|
|
958
|
+
if (allSelected) {
|
|
959
|
+
selectAll.classList.add(this.classes.selected)
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// Add select all text span
|
|
963
|
+
const selectAllText = document.createElement('span')
|
|
964
|
+
selectAllText.textContent = 'Select All'
|
|
965
|
+
selectAll.appendChild(selectAllText)
|
|
966
|
+
|
|
967
|
+
// Create new svg for checkbox
|
|
968
|
+
const selectAllSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
969
|
+
selectAllSvg.setAttribute('viewBox', '0 0 100 100')
|
|
970
|
+
selectAll.appendChild(selectAllSvg)
|
|
971
|
+
|
|
972
|
+
// Create new path for box
|
|
973
|
+
const selectAllBox = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
974
|
+
selectAllBox.setAttribute('d', this.classes.optgroupSelectAllBox)
|
|
975
|
+
selectAllSvg.appendChild(selectAllBox)
|
|
976
|
+
|
|
977
|
+
// Create new path for check
|
|
978
|
+
const selectAllCheck = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
979
|
+
selectAllCheck.setAttribute('d', this.classes.optgroupSelectAllCheck)
|
|
980
|
+
selectAllSvg.appendChild(selectAllCheck)
|
|
981
|
+
|
|
982
|
+
// Add click event listener to select all
|
|
983
|
+
selectAll.addEventListener('click', (e: MouseEvent) => {
|
|
984
|
+
e.preventDefault()
|
|
985
|
+
e.stopPropagation()
|
|
986
|
+
|
|
987
|
+
// Get the store current selected values
|
|
988
|
+
const currentSelected = this.store.getSelected()
|
|
989
|
+
|
|
990
|
+
// If all selected, remove all options from selected
|
|
991
|
+
// call setSelected and return
|
|
992
|
+
if (allSelected) {
|
|
993
|
+
// Put together new list minus all options in this optgroup
|
|
994
|
+
const newSelected = currentSelected.filter((s) => {
|
|
995
|
+
for (const o of d.options) {
|
|
996
|
+
if (s === o.value) {
|
|
997
|
+
return false
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
return true
|
|
1002
|
+
})
|
|
1003
|
+
|
|
1004
|
+
this.callbacks.setSelected(newSelected)
|
|
1005
|
+
return
|
|
1006
|
+
} else {
|
|
1007
|
+
// Put together new list with all options in this optgroup
|
|
1008
|
+
const newSelected = currentSelected.concat(d.options.map((o) => o.value))
|
|
1009
|
+
|
|
1010
|
+
this.callbacks.setSelected(newSelected)
|
|
1011
|
+
}
|
|
1012
|
+
})
|
|
1013
|
+
|
|
1014
|
+
// Append select all to label
|
|
1015
|
+
optgroupActions.appendChild(selectAll)
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// If optgroup has collapsable
|
|
1019
|
+
if (d.closable !== 'off') {
|
|
1020
|
+
// Create new div to hold a checkbox svg
|
|
1021
|
+
const optgroupClosable = document.createElement('div')
|
|
1022
|
+
optgroupClosable.classList.add(this.classes.optgroupClosable)
|
|
1023
|
+
|
|
1024
|
+
// Create svg arrow
|
|
1025
|
+
const optgroupClosableSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
1026
|
+
optgroupClosableSvg.setAttribute('viewBox', '0 0 100 100')
|
|
1027
|
+
optgroupClosableSvg.classList.add(this.classes.arrow)
|
|
1028
|
+
optgroupClosable.appendChild(optgroupClosableSvg)
|
|
1029
|
+
|
|
1030
|
+
// Create new path for arrow
|
|
1031
|
+
const optgroupClosableArrow = document.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
1032
|
+
optgroupClosableArrow.setAttribute('d', this.classes.arrow)
|
|
1033
|
+
optgroupClosableSvg.appendChild(optgroupClosableArrow)
|
|
1034
|
+
|
|
1035
|
+
// Add primary open or close class to optgroupEl
|
|
1036
|
+
if (d.closable === 'open') {
|
|
1037
|
+
optgroupEl.classList.add(this.classes.open)
|
|
1038
|
+
optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)
|
|
1039
|
+
} else if (d.closable === 'close') {
|
|
1040
|
+
optgroupEl.classList.add(this.classes.close)
|
|
1041
|
+
optgroupClosableArrow.setAttribute('d', this.classes.arrowClose)
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// Add click event listener to close
|
|
865
1045
|
optgroupLabel.addEventListener('click', (e: MouseEvent) => {
|
|
866
1046
|
e.preventDefault()
|
|
867
1047
|
e.stopPropagation()
|
|
868
1048
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1049
|
+
// If optgroup is closed, open it
|
|
1050
|
+
if (optgroupEl.classList.contains(this.classes.close)) {
|
|
1051
|
+
optgroupEl.classList.remove(this.classes.close)
|
|
1052
|
+
optgroupEl.classList.add(this.classes.open)
|
|
1053
|
+
optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)
|
|
1054
|
+
} else {
|
|
1055
|
+
optgroupEl.classList.remove(this.classes.open)
|
|
1056
|
+
optgroupEl.classList.add(this.classes.close)
|
|
1057
|
+
optgroupClosableArrow.setAttribute('d', this.classes.arrowClose)
|
|
873
1058
|
}
|
|
874
1059
|
})
|
|
1060
|
+
|
|
1061
|
+
// Append close to label
|
|
1062
|
+
optgroupActions.appendChild(optgroupClosable)
|
|
875
1063
|
}
|
|
876
1064
|
|
|
877
1065
|
// Add optgroup label
|
|
@@ -948,9 +1136,9 @@ export default class Render {
|
|
|
948
1136
|
|
|
949
1137
|
// If option is selected
|
|
950
1138
|
if (option.selected) {
|
|
951
|
-
optionEl.classList.add(this.classes.
|
|
1139
|
+
optionEl.classList.add(this.classes.selected)
|
|
952
1140
|
} else {
|
|
953
|
-
optionEl.classList.remove(this.classes.
|
|
1141
|
+
optionEl.classList.remove(this.classes.selected)
|
|
954
1142
|
}
|
|
955
1143
|
|
|
956
1144
|
// Add click event listener
|
|
@@ -18,6 +18,7 @@ export default [
|
|
|
18
18
|
resolve(),
|
|
19
19
|
commonjs(),
|
|
20
20
|
babel({
|
|
21
|
+
babelHelpers: 'bundled',
|
|
21
22
|
exclude: 'node_modules/**',
|
|
22
23
|
babelrc: false,
|
|
23
24
|
presets: [
|
|
@@ -54,6 +55,7 @@ export default [
|
|
|
54
55
|
resolve(),
|
|
55
56
|
commonjs(),
|
|
56
57
|
babel({
|
|
58
|
+
babelHelpers: 'bundled',
|
|
57
59
|
exclude: 'node_modules/**',
|
|
58
60
|
}),
|
|
59
61
|
],
|
|
@@ -79,6 +81,7 @@ export default [
|
|
|
79
81
|
resolve(),
|
|
80
82
|
commonjs(),
|
|
81
83
|
babel({
|
|
84
|
+
babelHelpers: 'bundled',
|
|
82
85
|
exclude: 'node_modules/**',
|
|
83
86
|
}),
|
|
84
87
|
terser(),
|
|
@@ -97,6 +100,7 @@ export default [
|
|
|
97
100
|
resolve(),
|
|
98
101
|
commonjs(),
|
|
99
102
|
babel({
|
|
103
|
+
babelHelpers: 'bundled',
|
|
100
104
|
exclude: 'node_modules/**',
|
|
101
105
|
}),
|
|
102
106
|
],
|
|
@@ -115,6 +119,7 @@ export default [
|
|
|
115
119
|
resolve(),
|
|
116
120
|
commonjs(),
|
|
117
121
|
babel({
|
|
122
|
+
babelHelpers: 'bundled',
|
|
118
123
|
exclude: 'node_modules/**',
|
|
119
124
|
}),
|
|
120
125
|
],
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { generateID, kebabCase } from './helpers'
|
|
2
|
-
import { DataArray,
|
|
2
|
+
import { DataArray, DataArrayPartial, Optgroup, OptgroupOptional, Option } from './store'
|
|
3
3
|
|
|
4
4
|
export default class Select {
|
|
5
5
|
public select: HTMLSelectElement
|
|
6
6
|
public listen: boolean = false
|
|
7
7
|
|
|
8
8
|
// Mutation observer fields
|
|
9
|
-
public onSelectChange?: (data:
|
|
9
|
+
public onSelectChange?: (data: DataArrayPartial) => void
|
|
10
10
|
public onValueChange?: (value: string[]) => void
|
|
11
11
|
private observer: MutationObserver | null = null
|
|
12
12
|
|
|
@@ -55,7 +55,7 @@ export default class Select {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// Add change listener to original select
|
|
58
|
-
public addSelectChangeListener(func: (data:
|
|
58
|
+
public addSelectChangeListener(func: (data: DataArrayPartial) => void): void {
|
|
59
59
|
this.onSelectChange = func
|
|
60
60
|
this.addObserver()
|
|
61
61
|
this.connectObserver()
|
|
@@ -86,7 +86,11 @@ export default class Select {
|
|
|
86
86
|
|
|
87
87
|
private observeWrapper(mutations: MutationRecord[]): void {
|
|
88
88
|
if (this.onSelectChange) {
|
|
89
|
+
// Just in case this triggers a change in the select
|
|
90
|
+
// we want to stop listening to it while we run onSelectChange
|
|
91
|
+
this.changeListen(false)
|
|
89
92
|
this.onSelectChange(this.getData())
|
|
93
|
+
this.changeListen(true)
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
96
|
|
|
@@ -99,16 +103,21 @@ export default class Select {
|
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
// If anything changes in the select then update the data
|
|
102
|
-
this.observer = new MutationObserver(this.observeWrapper)
|
|
106
|
+
this.observer = new MutationObserver(this.observeWrapper.bind(this))
|
|
103
107
|
}
|
|
104
108
|
|
|
109
|
+
// Start observing the select
|
|
105
110
|
private connectObserver(): void {
|
|
106
111
|
if (this.observer) {
|
|
107
112
|
this.observer.observe(this.select, {
|
|
108
|
-
|
|
113
|
+
// For now we only care about if the children change
|
|
109
114
|
childList: true,
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
|
|
116
|
+
// We dont care about attributes for now
|
|
117
|
+
// might need to add this later
|
|
118
|
+
// attributes: true,
|
|
119
|
+
// characterData: true,
|
|
120
|
+
// subtree: true,
|
|
112
121
|
})
|
|
113
122
|
}
|
|
114
123
|
}
|
|
@@ -120,8 +129,8 @@ export default class Select {
|
|
|
120
129
|
}
|
|
121
130
|
|
|
122
131
|
// From the select element pull optgroup and options into data
|
|
123
|
-
public getData():
|
|
124
|
-
let data = []
|
|
132
|
+
public getData(): DataArrayPartial {
|
|
133
|
+
let data = [] as DataArrayPartial
|
|
125
134
|
|
|
126
135
|
// Loop through nodes and get data
|
|
127
136
|
const nodes = this.select.childNodes as any as HTMLOptGroupElement[] | HTMLOptionElement[]
|
|
@@ -140,23 +149,43 @@ export default class Select {
|
|
|
140
149
|
return data
|
|
141
150
|
}
|
|
142
151
|
|
|
143
|
-
public getDataFromOptgroup(optgroup: HTMLOptGroupElement):
|
|
152
|
+
public getDataFromOptgroup(optgroup: HTMLOptGroupElement): OptgroupOptional {
|
|
144
153
|
let data = {
|
|
145
|
-
id: '',
|
|
154
|
+
id: (optgroup.dataset ? optgroup.dataset.id : false) || '',
|
|
146
155
|
label: optgroup.label,
|
|
156
|
+
selectAll: optgroup.dataset ? optgroup.dataset.selectall === 'true' : false,
|
|
157
|
+
closable: optgroup.dataset ? optgroup.dataset.closable : 'off',
|
|
147
158
|
options: [],
|
|
148
|
-
} as
|
|
159
|
+
} as OptgroupOptional
|
|
149
160
|
|
|
150
161
|
const options = optgroup.childNodes as any as HTMLOptionElement[]
|
|
151
162
|
for (const o of options) {
|
|
152
163
|
if (o.nodeName === 'OPTION') {
|
|
153
|
-
data.options
|
|
164
|
+
data.options!.push(this.getDataFromOption(o as HTMLOptionElement))
|
|
154
165
|
}
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
return data
|
|
158
169
|
}
|
|
159
170
|
|
|
171
|
+
// From passed in option pull pieces of usable information
|
|
172
|
+
public getDataFromOption(option: HTMLOptionElement): Option {
|
|
173
|
+
return {
|
|
174
|
+
id: (option.dataset ? option.dataset.id : false) || '',
|
|
175
|
+
value: option.value,
|
|
176
|
+
text: option.text,
|
|
177
|
+
html: option.innerHTML,
|
|
178
|
+
selected: option.selected,
|
|
179
|
+
display: option.style.display === 'none' ? false : true,
|
|
180
|
+
disabled: option.disabled,
|
|
181
|
+
mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
|
|
182
|
+
placeholder: option.dataset.placeholder === 'true',
|
|
183
|
+
class: option.className,
|
|
184
|
+
style: option.style.cssText,
|
|
185
|
+
data: option.dataset,
|
|
186
|
+
} as Option
|
|
187
|
+
}
|
|
188
|
+
|
|
160
189
|
public getSelectedValues(): string[] {
|
|
161
190
|
let values = []
|
|
162
191
|
|
|
@@ -186,24 +215,6 @@ export default class Select {
|
|
|
186
215
|
return values
|
|
187
216
|
}
|
|
188
217
|
|
|
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
218
|
public setSelected(value: string[]): void {
|
|
208
219
|
// Loop through options and set selected
|
|
209
220
|
const options = this.select.childNodes as any as (HTMLOptGroupElement | HTMLOptionElement)[]
|
|
@@ -279,6 +290,12 @@ export default class Select {
|
|
|
279
290
|
const optgroupEl = document.createElement('optgroup')
|
|
280
291
|
optgroupEl.id = optgroup.id
|
|
281
292
|
optgroupEl.label = optgroup.label
|
|
293
|
+
if (optgroup.selectAll) {
|
|
294
|
+
optgroupEl.dataset.selectAll = 'true'
|
|
295
|
+
}
|
|
296
|
+
if (optgroup.closable !== 'off') {
|
|
297
|
+
optgroupEl.dataset.closable = optgroup.closable
|
|
298
|
+
}
|
|
282
299
|
if (optgroup.options) {
|
|
283
300
|
for (const o of optgroup.options) {
|
|
284
301
|
optgroupEl.appendChild(this.createOption(o))
|
|
@@ -14,8 +14,6 @@ export default class Settings {
|
|
|
14
14
|
public intervalMove: NodeJS.Timeout | null = null
|
|
15
15
|
|
|
16
16
|
// Fields set from constructor
|
|
17
|
-
public mainHeight: number = 30
|
|
18
|
-
public contentHeight: number = 0
|
|
19
17
|
public isEnabled: boolean
|
|
20
18
|
public alwaysOpen: boolean
|
|
21
19
|
public showSearch: boolean
|
|
@@ -31,7 +29,6 @@ export default class Settings {
|
|
|
31
29
|
public allowDeselect: boolean
|
|
32
30
|
public hideSelected: boolean
|
|
33
31
|
public showOptionTooltips: boolean
|
|
34
|
-
public selectByGroup: boolean
|
|
35
32
|
public minSelected: number
|
|
36
33
|
public maxSelected: number
|
|
37
34
|
public timeoutDelay: number
|
|
@@ -60,7 +57,6 @@ export default class Settings {
|
|
|
60
57
|
this.allowDeselect = settings.allowDeselect !== undefined ? settings.allowDeselect : false
|
|
61
58
|
this.hideSelected = settings.hideSelected !== undefined ? settings.hideSelected : false
|
|
62
59
|
this.showOptionTooltips = settings.showOptionTooltips !== undefined ? settings.showOptionTooltips : false
|
|
63
|
-
this.selectByGroup = settings.selectByGroup !== undefined ? settings.selectByGroup : false
|
|
64
60
|
this.minSelected = settings.minSelected || 0
|
|
65
61
|
this.maxSelected = settings.maxSelected || 1000
|
|
66
62
|
this.timeoutDelay = settings.timeoutDelay || 200
|