PluginProbe
seQura / 3.2.2
seQura v3.2.2
4.3.4 4.3.3 4.3.2 4.3.1 trunk 2.0.0 2.0.10 2.0.11 2.0.12 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0.0 3.0.2 3.0.5 3.0.6 3.0.7 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 4.0.0 All 30 releases
sequra / assets / js / src / core / MultiItemSelectorComponent.js

MultiItemSelectorComponent.js in seQura 3.2.2, at assets/js/src/core/MultiItemSelectorComponent.js

126 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 if (!window.SequraFE) {
2 window.SequraFE = {};
3 }
4
5 if (!window.SequraFE.components) {
6 window.SequraFE.components = {};
7 }
8
9 (function () {
10 /**
11 * @typedef MultiItemSelectorComponentModel
12 *
13 * @property {Option[]} options
14 * @property {string?} name
15 * @property {string?} value
16 * @property {string?} placeholder
17 * @property {(value: string[]) => void?} onChange
18 * @property {boolean?} searchable
19 */
20
21 /**
22 * Multi-select dropdown component.
23 *
24 * @param {MultiItemSelectorComponentModel} props
25 *
26 * @constructor
27 */
28 const MultiItemSelectorComponent = ({ options = [], name, onChange, value = '', searchable = true }) => {
29 const { elementGenerator: generator } = SequraFE;
30 const selectedItems = value ? value.split(',').map((item) => item.trim()) : [];
31 const wrapper = generator.createElement('div', 'sq-multi-item-selector');
32 const hiddenInput = generator.createElement('input', 'sqp-hidden-input', '', {
33 type: 'hidden',
34 name,
35 value: selectedItems.join(',')
36 });
37 const removeItem = (item) => {
38 selectedItems.splice(selectedItems.indexOf(item), 1);
39 render(true);
40 };
41
42 const render = (focused = false) => {
43 hiddenInput.value = selectedItems.join(',');
44 SequraFE.templateService.clearComponent(wrapper);
45 const availableOptions = options.filter((option) => !selectedItems.includes(option.value));
46 const renderSelectedItem = (item) => {
47 return generator.createElement(
48 'span',
49 'sqp-selected-item',
50 searchable ? options.find((o) => o.value === item).label : item,
51 null,
52 [
53 generator.createButton({
54 className: 'sqp-remove-button',
55 onClick: () => {
56 removeItem(item);
57 onChange && onChange(selectedItems);
58 }
59 })
60 ]
61 );
62 };
63
64 let inputElement = SequraFE.components.Dropdown.create({
65 searchable: true,
66 options: availableOptions,
67 onChange: (value) => {
68 selectedItems.push(value);
69 render(true);
70 onChange && onChange(selectedItems);
71 },
72 onOpenStateChange: (opened) => {
73 opened ? wrapper.classList.add('sqs--active') : wrapper.classList.remove('sqs--active');
74 }
75 });
76
77 if (!searchable) {
78 inputElement = generator.createElement('input', 'sq-multi-input', '', { type: 'text' });
79 inputElement.addEventListener('blur', (event) => addItemToSelected(event.currentTarget.value.trim()))
80 inputElement.addEventListener('keydown', (event) => {
81 if (event.keyCode === 13) {
82 event.preventDefault();
83 addItemToSelected(event.currentTarget.value.trim());
84 }
85 });
86 }
87
88 const addItemToSelected = (inputValue) => {
89 if (inputValue.length !== 0 && !selectedItems.includes(inputValue)) {
90 selectedItems.push(inputValue);
91 render(true);
92 onChange && onChange(selectedItems);
93 }
94 }
95
96 wrapper.append(...selectedItems.map(renderSelectedItem), hiddenInput, inputElement);
97 wrapper.addEventListener('click', () => {
98 wrapper.classList.add('sqs--active');
99 if (searchable) {
100 setTimeout(() => {
101 inputElement.querySelector('button').click();
102 }, 10);
103 }
104 });
105
106 if (focused) {
107 setTimeout(() => {
108 searchable ? inputElement.querySelector('button').click() : inputElement.focus();
109 }, 10);
110 }
111 };
112
113 render();
114
115 return wrapper;
116 };
117
118 SequraFE.components.MultiItemSelector = {
119 /**
120 * @param {MultiItemSelectorComponentModel} config
121 * @returns {HTMLElement}
122 */
123 create: (config) => MultiItemSelectorComponent(config)
124 };
125 })();
126