@internetstiftelsen/styleguide 4.0.12-beta.0.4 → 4.0.12

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.
@@ -72,4 +72,6 @@ require('./assets/js/utmGenerator');
72
72
 
73
73
  require('./assets/js/textToggle');
74
74
 
75
- require('./assets/js/iconToggle');
75
+ require('./assets/js/iconToggle');
76
+
77
+ require('./molecules/multi-select/multi-select');
@@ -1,140 +1,224 @@
1
1
  'use strict';
2
2
 
3
- /* eslint-disable */
4
- var className = 'm-multi-select';
5
- var multiSelectElements = document.querySelectorAll('.js-' + className);
6
- var namespace = void 0;
3
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
7
4
 
8
- if (multiSelectElements) {
9
- namespace = getComputedStyle(multiSelectElements[0], ':before').content.replace(/["']/g, '');
10
- }
11
-
12
- var currentFocus = -1; // Tracks the currently focused item in the suggestions
13
-
14
- // Highlight the active (focused) suggestion
15
- function setActive(items) {
16
- if (!items.length) return false;
17
- removeActive(items);
18
- if (currentFocus >= items.length) currentFocus = 0;
19
- if (currentFocus < 0) currentFocus = items.length - 1;
20
- items[currentFocus].classList.add('autocomplete-active');
21
-
22
- return items;
23
- }
24
-
25
- // Remove highlighting from all suggestions
26
- function removeActive(items) {
27
- for (var i = 0; i < items.length; i += 1) {
28
- items[i].classList.remove('autocomplete-active');
5
+ var _className = require('../../assets/js/className');
6
+
7
+ var _className2 = _interopRequireDefault(_className);
8
+
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+
11
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12
+
13
+ var MultiSelect = function () {
14
+ function MultiSelect(el) {
15
+ var _this = this;
16
+
17
+ _classCallCheck(this, MultiSelect);
18
+
19
+ this.onInput = function () {
20
+ var value = _this.input.value;
21
+
22
+ // Clear suggestions if less than 2 characters are typed
23
+
24
+ if (value.length < 2) {
25
+ _this.clearSuggestions();
26
+
27
+ return;
28
+ }
29
+
30
+ var suggestions = _this.filterData(value);
31
+
32
+ _this.populateSuggestions(suggestions);
33
+ _this.resetFocus();
34
+ };
35
+
36
+ this.onKeyDown = function (e) {
37
+ if (e.keyCode === 40) {
38
+ _this.highlight('down');
39
+ } else if (e.keyCode === 38) {
40
+ _this.highlight('up');
41
+ } else if (e.keyCode === 13) {
42
+ e.preventDefault();
43
+
44
+ _this.selectHighlighted();
45
+ }
46
+ };
47
+
48
+ this.onClick = function (e) {
49
+ if (e.target.classList.contains((0, _className2.default)(_this.baseClassName + '__suggestion-btn'))) {
50
+ _this.addItem(e.target.textContent);
51
+ _this.clearSuggestions();
52
+ _this.input.value = '';
53
+ }
54
+ };
55
+
56
+ this.element = el;
57
+ this.baseClassName = 'm-multi-select';
58
+ this.currentFocus = -1;
59
+ this.input = this.element.querySelector('.js-' + this.baseClassName + '__input');
60
+ this.suggestionsBox = this.element.querySelector('.js-' + this.baseClassName + '-suggestions-box');
61
+ this.selectedItemsList = this.element.querySelector('.js-m-multi-select-selected-items');
62
+ this.selectedItems = [];
63
+ this.data = [];
64
+
65
+ this.getData();
66
+ this.attach();
29
67
  }
30
- }
31
-
32
- // Add a selected item to the list of selected items
33
- function addSelectedItem(item) {
34
- var selectedItemsList = document.querySelector('.js-m-multi-select-selected-items');
35
- var newItem = document.createElement('li');
36
- newItem.textContent = item + ' ';
37
- newItem.classList.add(namespace + 'a-tag');
38
- newItem.classList.add(namespace + 'm-multi-select__tag');
39
-
40
- var removeBtn = document.createElement('button');
41
- removeBtn.classList.add(namespace + 'm-multi-select-selected-items__remove-btn');
42
-
43
- var buttonTextContainer = document.createElement('span');
44
- buttonTextContainer.classList.add('u-visuallyhidden');
45
- removeBtn.appendChild(buttonTextContainer);
46
- buttonTextContainer.textContent = 'Ta bort ' + item; // Accessibility label for screen readers
47
-
48
- // Event listener for removing the selected item
49
- removeBtn.addEventListener('click', function () {
50
- removeItem(newItem, Array.from(selectedItemsList.children).indexOf(newItem));
51
- });
52
- newItem.appendChild(removeBtn);
53
- selectedItemsList.appendChild(newItem);
54
- }
55
-
56
- // Remove an item and manage focus appropriately
57
- function removeItem(item, index) {
58
- var selectedItemsList = document.querySelector('.js-m-multi-select-selected-items');
59
- selectedItemsList.removeChild(item);
60
-
61
- var remainingItems = selectedItemsList.getElementsByTagName('div');
62
- // Focus management: set focus to the next item, or the search input if no items left
63
- if (remainingItems.length > 0) {
64
- if (index < remainingItems.length) {
65
- remainingItems[index].getElementsByTagName('button')[0].focus();
66
- } else {
67
- remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
68
+
69
+ _createClass(MultiSelect, [{
70
+ key: 'getData',
71
+ value: function getData() {
72
+ var id = this.input.getAttribute('data-multi-select-suggestions');
73
+ var el = document.getElementById(id);
74
+
75
+ if (!el) {
76
+ this.data = [];
77
+ return;
78
+ }
79
+
80
+ this.data = JSON.parse(el.textContent);
68
81
  }
69
- } else {
70
- multiSelectInput.focus();
71
- }
72
- }
73
-
74
- function setup(multiSelectElement) {
75
- var multiSelectInput = multiSelectElement.querySelector('.js-' + className + '__input');
76
- var suggestionsBox = multiSelectElement.querySelector('.js-' + className + '-suggestions-box');
77
- var suggestionsData = multiSelectInput.getAttribute('data-multi-select-suggestions');
78
-
79
- // Event listener for input changes in the search field
80
- multiSelectInput.addEventListener('input', function () {
81
- var value = this.value;
82
- // Clear suggestions if less than 2 characters are typed
83
- if (value.length < 2) {
84
- suggestionsBox.innerHTML = '';
85
- return;
82
+ }, {
83
+ key: 'attach',
84
+ value: function attach() {
85
+ this.input.addEventListener('input', this.onInput);
86
+ this.input.addEventListener('keydown', this.onKeyDown);
87
+ this.suggestionsBox.addEventListener('click', this.onClick);
86
88
  }
89
+ }, {
90
+ key: 'setFocus',
91
+ value: function setFocus(index) {
92
+ this.currentFocus = index;
93
+ }
94
+ }, {
95
+ key: 'resetFocus',
96
+ value: function resetFocus() {
97
+ this.setFocus(-1);
98
+ }
99
+ }, {
100
+ key: 'clearSuggestions',
101
+ value: function clearSuggestions() {
102
+ this.suggestionsBox.innerHTML = '';
103
+ }
104
+ }, {
105
+ key: 'filterData',
106
+ value: function filterData(query) {
107
+ var _this2 = this;
108
+
109
+ return this.data.filter(function (item) {
110
+ return item.name.toLowerCase().startsWith(query.toLowerCase());
111
+ }).filter(function (item) {
112
+ return !_this2.selectedItems.includes(item.name);
113
+ });
114
+ }
115
+ }, {
116
+ key: 'populateSuggestions',
117
+ value: function populateSuggestions(suggestions) {
118
+ var cls = (0, _className2.default)(this.baseClassName + '__suggestion-btn');
119
+ this.suggestionsBox.innerHTML = suggestions.map(function (item) {
120
+ return '<button class=\'' + cls + '\' tabindex=\'0\'>' + item.name + '</button>';
121
+ }).join('');
122
+ }
123
+ }, {
124
+ key: 'removeItem',
125
+ value: function removeItem(item, index) {
126
+ var selectedItemsList = this.element.querySelector('.js-m-multi-select-selected-items');
127
+ selectedItemsList.removeChild(item);
128
+
129
+ var remainingItems = selectedItemsList.getElementsByTagName('div');
130
+
131
+ // Focus management: set focus to the next item, or the search input if no items left
132
+ if (remainingItems.length > 0) {
133
+ if (index < remainingItems.length) {
134
+ remainingItems[index].getElementsByTagName('button')[0].focus();
135
+ } else {
136
+ remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
137
+ }
138
+ } else {
139
+ this.input.focus();
140
+ }
87
141
 
88
- // Define JSON
89
- var suggestions = document.getElementById(suggestionsData).textContent;
90
- suggestions = JSON.parse(suggestions);
91
-
92
- // Filter suggestions based on the input value
93
- var filtered = suggestions.filter(function (item) {
94
- return item.name.toLowerCase().startsWith(value.toLowerCase());
95
- });
96
- // Populate the suggestions box with the filtered results
97
- suggestionsBox.innerHTML = filtered.map(function (item) {
98
- return '<button class=\'' + namespace + 'm-multi-select__suggestion-btn\' tabindex=\'0\'>' + item.name + '</button>';
99
- }).join('');
100
- // Reset the current focus
101
- currentFocus = -1;
102
- });
142
+ this.selectedItems = this.selectedItems.filter(function (name) {
143
+ return name !== item.firstChild.textContent.trim();
144
+ });
145
+ }
146
+ }, {
147
+ key: 'addItem',
148
+ value: function addItem(item) {
149
+ var _this3 = this;
103
150
 
104
- // Event listener for keydown events for navigation and selection in the suggestions box
105
- multiSelectInput.addEventListener('keydown', function (e) {
106
- var items = suggestionsBox.getElementsByClassName(namespace + 'm-multi-select__suggestion-btn');
107
- // Navigate down in the suggestions list
108
- if (e.keyCode == 40) {
109
- currentFocus = (currentFocus + 1) % items.length;
110
- setActive(items);
111
- // Navigate up in the suggestions list
112
- } else if (e.keyCode == 38) {
113
- currentFocus = (currentFocus - 1 + items.length) % items.length;
114
- setActive(items);
115
- // Handle Enter key to select a focused item
116
- } else if (e.keyCode == 13) {
117
- e.preventDefault();
118
- if (currentFocus > -1 && items[currentFocus]) {
119
- addSelectedItem(items[currentFocus].textContent);
120
- suggestionsBox.innerHTML = '';
121
- multiSelectInput.value = '';
122
- currentFocus = -1;
123
- }
151
+ var newItem = document.createElement('li');
152
+ newItem.textContent = item + ' ';
153
+ newItem.classList.add((0, _className2.default)('a-tag'));
154
+ newItem.classList.add((0, _className2.default)(this.baseClassName + '__tag'));
155
+
156
+ var removeBtn = document.createElement('button');
157
+ removeBtn.classList.add((0, _className2.default)(this.baseClassName + '-selected-items__remove-btn'));
158
+
159
+ var buttonTextContainer = document.createElement('span');
160
+ buttonTextContainer.classList.add('u-visuallyhidden');
161
+ removeBtn.appendChild(buttonTextContainer);
162
+ buttonTextContainer.textContent = 'Ta bort ' + item; // Accessibility label for screen readers
163
+
164
+ // Event listener for removing the selected item
165
+ removeBtn.addEventListener('click', function () {
166
+ _this3.removeItem(newItem, Array.from(_this3.selectedItemsList.children).indexOf(newItem));
167
+ });
168
+
169
+ newItem.appendChild(removeBtn);
170
+
171
+ this.selectedItemsList.appendChild(newItem);
172
+ this.selectedItems.push(item);
124
173
  }
125
- });
174
+ }, {
175
+ key: 'removeHighlight',
176
+ value: function removeHighlight() {
177
+ var items = this.suggestionsBox.getElementsByClassName(this.baseClassName + '__suggestion-btn');
178
+
179
+ [].forEach.call(items, function (item) {
180
+ item.classList.remove('autocomplete-active');
181
+ });
182
+ }
183
+ }, {
184
+ key: 'highlight',
185
+ value: function highlight(direction) {
186
+ var items = this.suggestionsBox.getElementsByClassName(this.baseClassName + '__suggestion-btn');
187
+ var focus = this.currentFocus;
188
+
189
+ if (direction === 'down') {
190
+ focus = focus >= items.length - 1 ? 0 : focus + 1;
191
+ } else {
192
+ focus = focus <= 0 ? items.length - 1 : focus - 1;
193
+ }
194
+
195
+ this.setFocus(focus);
196
+ this.removeHighlight();
126
197
 
127
- // Event listener for the suggestions box
128
- suggestionsBox.addEventListener('click', function (e) {
129
- // Add the clicked suggestion to the selected items list
130
- if (e.target && e.target.classList.contains('suggestion-btn')) {
131
- addSelectedItem(e.target.textContent);
132
- suggestionsBox.innerHTML = '';
133
- multiSelectInput.value = '';
198
+ items[this.currentFocus].classList.add('autocomplete-active');
199
+ items[this.currentFocus].scrollIntoView({ block: 'nearest' });
134
200
  }
135
- });
136
- }
201
+ }, {
202
+ key: 'selectHighlighted',
203
+ value: function selectHighlighted() {
204
+ var items = this.suggestionsBox.getElementsByClassName(this.baseClassName + '__suggestion-btn');
205
+
206
+ if (this.currentFocus > -1 && items[this.currentFocus]) {
207
+ this.addItem(items[this.currentFocus].textContent);
208
+ this.clearSuggestions();
209
+ this.input.value = '';
210
+ this.resetFocus();
211
+ }
212
+ }
213
+ }]);
214
+
215
+ return MultiSelect;
216
+ }();
217
+
218
+ var multiSelectElements = document.querySelectorAll('.js-m-multi-select');
137
219
 
138
220
  if (multiSelectElements) {
139
- [].forEach.call(multiSelectElements, setup);
221
+ [].forEach.call(multiSelectElements, function (el) {
222
+ return new MultiSelect(el);
223
+ });
140
224
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetstiftelsen/styleguide",
3
- "version": "4.0.12-beta.0.4",
3
+ "version": "4.0.12",
4
4
  "main": "dist/components.js",
5
5
  "ports": {
6
6
  "fractal": "3000"
Binary file
@@ -1 +1,4 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" version="1.1" viewBox="0 0 32 32"><path d="M7.8 16H16v2.7H7.8V16Zm0 5.5H16v2.7H7.8v-2.7Z" class="cls-1"/><path d="M10.5 2.3v8.2H2.3v19.3h19.3v-8.2h8.2V2.3H10.5ZM13.3 5H27v13.7h-5.4v-8.3h-8.3V5ZM5 27V13.3h13.7V27H5Z" class="cls-1"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" version="1.1" viewBox="0 0 32 32" width="32" height="32"><defs><style>.cls-1{fill:#000;stroke-width:0}</style></defs>
2
+ <path d="M7 16h9v3H7v-3Zm0 6h9v3H7v-3Z" class="cls-1"/>
3
+ <path d="M10 1v8.9H1V31h21.1v-9H31V1H10Zm3 3h15v15h-5.9V9.9H13V4ZM4 28V13h15v15H4Z" class="cls-1"/>
4
+ </svg>
@@ -186,8 +186,8 @@
186
186
  <path d="M17.07 6.69l1.414-1.414 6.293 6.293-1.414 1.415z"/>
187
187
  </symbol>
188
188
  <symbol id="icon-copy" viewbox="0 0 32 32">
189
- <path d="M7.8 16H16v2.7H7.8V16Zm0 5.5H16v2.7H7.8v-2.7Z" class="cls-1"/>
190
- <path d="M10.5 2.3v8.2H2.3v19.3h19.3v-8.2h8.2V2.3H10.5ZM13.3 5H27v13.7h-5.4v-8.3h-8.3V5ZM5 27V13.3h13.7V27H5Z" class="cls-1"/>
189
+ <path d="M7 16h9v3H7v-3Zm0 6h9v3H7v-3Z" class="cls-1"/>
190
+ <path d="M10 1v8.9H1V31h21.1v-9H31V1H10Zm3 3h15v15h-5.9V9.9H13V4ZM4 28V13h15v15H4Z" class="cls-1"/>
191
191
  </symbol>
192
192
  <symbol id="icon-speaker" viewbox="0 0 32 32">
193
193
  <path d="M18 29a1 1 0 0 1-.57-.18l-10-7A1 1 0 0 1 7 21V11a1 1 0 0 1 .43-.82l10-7a1 1 0 0 1 1-.07A1 1 0 0 1 19 4v24a1 1 0 0 1-.54.89A1 1 0 0 1 18 29zm-9-8.52l8 5.6V5.92l-8 5.6z"/><path class="cls-1" d="M8 22H4a3 3 0 0 1-3-3v-6a3 3 0 0 1 3-3h4a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zM4 12a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h3v-8zM18 21v-2a3 3 0 0 0 2.12-5.12l1.42-1.42A5 5 0 0 1 18 21z"/><path class="cls-1" d="M23.65 22.65a1 1 0 0 1-.7-.29A1 1 0 0 1 23 21a7 7 0 0 0 0-9.9 1 1 0 0 1 1.41-1.41 9 9 0 0 1 0 12.72 1 1 0 0 1-.76.24z"/>
package/src/components.js CHANGED
@@ -35,4 +35,4 @@ import './atoms/range/range';
35
35
  import './assets/js/utmGenerator';
36
36
  import './assets/js/textToggle';
37
37
  import './assets/js/iconToggle';
38
- // import './molecules/multi-select/multi-select';
38
+ import './molecules/multi-select/multi-select';
@@ -1,134 +1,182 @@
1
- /* eslint-disable */
2
- const className = 'm-multi-select';
3
- const multiSelectElements = document.querySelectorAll(`.js-${className}`);
4
- let namespace;
1
+ import className from '../../assets/js/className';
2
+
3
+ class MultiSelect {
4
+ constructor(el) {
5
+ this.element = el;
6
+ this.baseClassName = 'm-multi-select';
7
+ this.currentFocus = -1;
8
+ this.input = this.element.querySelector(`.js-${this.baseClassName}__input`);
9
+ this.suggestionsBox = this.element.querySelector(`.js-${this.baseClassName}-suggestions-box`);
10
+ this.selectedItemsList = this.element.querySelector('.js-m-multi-select-selected-items');
11
+ this.selectedItems = [];
12
+ this.data = [];
13
+
14
+ this.getData();
15
+ this.attach();
16
+ }
5
17
 
6
- if( multiSelectElements ) {
7
- namespace = getComputedStyle(multiSelectElements[0], ':before').content.replace(/["']/g, '');
8
- }
18
+ getData() {
19
+ const id = this.input.getAttribute('data-multi-select-suggestions');
20
+ const el = document.getElementById(id);
9
21
 
10
- let currentFocus = -1; // Tracks the currently focused item in the suggestions
22
+ if (!el) {
23
+ this.data = [];
24
+ return;
25
+ }
11
26
 
12
- // Highlight the active (focused) suggestion
13
- function setActive(items) {
14
- if (!items.length) return false;
15
- removeActive(items);
16
- if (currentFocus >= items.length) currentFocus = 0;
17
- if (currentFocus < 0) currentFocus = items.length - 1;
18
- items[currentFocus].classList.add('autocomplete-active');
27
+ this.data = JSON.parse(el.textContent);
28
+ }
19
29
 
20
- return items;
21
- }
30
+ attach() {
31
+ this.input.addEventListener('input', this.onInput);
32
+ this.input.addEventListener('keydown', this.onKeyDown);
33
+ this.suggestionsBox.addEventListener('click', this.onClick);
34
+ }
22
35
 
23
- // Remove highlighting from all suggestions
24
- function removeActive(items) {
25
- for (let i = 0; i < items.length; i+=1) {
26
- items[i].classList.remove('autocomplete-active');
36
+ setFocus(index) {
37
+ this.currentFocus = index;
27
38
  }
28
- }
29
39
 
30
- // Add a selected item to the list of selected items
31
- function addSelectedItem(item) {
32
- const selectedItemsList = document.querySelector('.js-m-multi-select-selected-items');
33
- const newItem = document.createElement('li');
34
- newItem.textContent = item + ' ';
35
- newItem.classList.add(`${namespace}a-tag`);
36
- newItem.classList.add(`${namespace}m-multi-select__tag`);
37
-
38
- const removeBtn = document.createElement('button');
39
- removeBtn.classList.add(`${namespace}m-multi-select-selected-items__remove-btn`);
40
-
41
- const buttonTextContainer = document.createElement('span');
42
- buttonTextContainer.classList.add('u-visuallyhidden');
43
- removeBtn.appendChild(buttonTextContainer);
44
- buttonTextContainer.textContent ='Ta bort ' + item; // Accessibility label for screen readers
45
-
46
- // Event listener for removing the selected item
47
- removeBtn.addEventListener('click', function () {
48
- removeItem(newItem, Array.from(selectedItemsList.children).indexOf(newItem));
49
- });
50
- newItem.appendChild(removeBtn);
51
- selectedItemsList.appendChild(newItem);
52
- }
40
+ resetFocus() {
41
+ this.setFocus(-1);
42
+ }
53
43
 
54
- // Remove an item and manage focus appropriately
55
- function removeItem(item, index) {
56
- const selectedItemsList = document.querySelector('.js-m-multi-select-selected-items');
57
- selectedItemsList.removeChild(item);
44
+ clearSuggestions() {
45
+ this.suggestionsBox.innerHTML = '';
46
+ }
58
47
 
59
- let remainingItems = selectedItemsList.getElementsByTagName('div');
60
- // Focus management: set focus to the next item, or the search input if no items left
61
- if (remainingItems.length > 0) {
62
- if (index < remainingItems.length) {
63
- remainingItems[index].getElementsByTagName('button')[0].focus();
64
- } else {
65
- remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
66
- }
67
- } else {
68
- multiSelectInput.focus();
48
+ filterData(query) {
49
+ return this.data
50
+ .filter((item) => item.name.toLowerCase().startsWith(query.toLowerCase()))
51
+ .filter((item) => !this.selectedItems.includes(item.name));
69
52
  }
70
- }
71
53
 
72
- function setup(multiSelectElement) {
73
- const multiSelectInput = multiSelectElement.querySelector(`.js-${className}__input`);
74
- const suggestionsBox = multiSelectElement.querySelector(`.js-${className}-suggestions-box`);
75
- const suggestionsData = multiSelectInput.getAttribute('data-multi-select-suggestions');
54
+ populateSuggestions(suggestions) {
55
+ const cls = className(`${this.baseClassName}__suggestion-btn`);
56
+ this.suggestionsBox.innerHTML = suggestions.map((item) => `<button class='${cls}' tabindex='0'>${item.name}</button>`).join('');
57
+ }
58
+
59
+ onInput = () => {
60
+ const { value } = this.input;
76
61
 
77
- // Event listener for input changes in the search field
78
- multiSelectInput.addEventListener('input', function () {
79
- const value = this.value;
80
62
  // Clear suggestions if less than 2 characters are typed
81
63
  if (value.length < 2) {
82
- suggestionsBox.innerHTML = '';
64
+ this.clearSuggestions();
65
+
83
66
  return;
84
67
  }
85
68
 
86
- // Define JSON
87
- let suggestions = document.getElementById(suggestionsData).textContent;
88
- suggestions = JSON.parse(suggestions);
89
-
90
- // Filter suggestions based on the input value
91
- const filtered = suggestions.filter(item => item.name.toLowerCase().startsWith(value.toLowerCase()));
92
- // Populate the suggestions box with the filtered results
93
- suggestionsBox.innerHTML = filtered.map(item => `<button class='${namespace}m-multi-select__suggestion-btn' tabindex='0'>${item.name}</button>`).join('');
94
- // Reset the current focus
95
- currentFocus = -1;
96
- });
97
-
98
- // Event listener for keydown events for navigation and selection in the suggestions box
99
- multiSelectInput.addEventListener('keydown', function (e) {
100
- let items = suggestionsBox.getElementsByClassName(`${namespace}m-multi-select__suggestion-btn`);
101
- // Navigate down in the suggestions list
102
- if (e.keyCode == 40) {
103
- currentFocus = (currentFocus + 1) % items.length;
104
- setActive(items);
105
- // Navigate up in the suggestions list
106
- } else if (e.keyCode == 38) {
107
- currentFocus = (currentFocus - 1 + items.length) % items.length;
108
- setActive(items);
109
- // Handle Enter key to select a focused item
110
- } else if (e.keyCode == 13) {
111
- e.preventDefault();
112
- if (currentFocus > -1 && items[currentFocus]) {
113
- addSelectedItem(items[currentFocus].textContent);
114
- suggestionsBox.innerHTML = '';
115
- multiSelectInput.value = '';
116
- currentFocus = -1;
69
+ const suggestions = this.filterData(value);
70
+
71
+ this.populateSuggestions(suggestions);
72
+ this.resetFocus();
73
+ }
74
+
75
+ removeItem(item, index) {
76
+ const selectedItemsList = this.element.querySelector('.js-m-multi-select-selected-items');
77
+ selectedItemsList.removeChild(item);
78
+
79
+ const remainingItems = selectedItemsList.getElementsByTagName('div');
80
+
81
+ // Focus management: set focus to the next item, or the search input if no items left
82
+ if (remainingItems.length > 0) {
83
+ if (index < remainingItems.length) {
84
+ remainingItems[index].getElementsByTagName('button')[0].focus();
85
+ } else {
86
+ remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
117
87
  }
88
+ } else {
89
+ this.input.focus();
118
90
  }
119
- });
120
-
121
- // Event listener for the suggestions box
122
- suggestionsBox.addEventListener('click', function (e) {
123
- // Add the clicked suggestion to the selected items list
124
- if (e.target && e.target.classList.contains('suggestion-btn')) {
125
- addSelectedItem(e.target.textContent);
126
- suggestionsBox.innerHTML = '';
127
- multiSelectInput.value = '';
91
+
92
+ this.selectedItems = this.selectedItems
93
+ .filter((name) => name !== item.firstChild.textContent.trim());
94
+ }
95
+
96
+ addItem(item) {
97
+ const newItem = document.createElement('li');
98
+ newItem.textContent = `${item} `;
99
+ newItem.classList.add(className('a-tag'));
100
+ newItem.classList.add(className(`${this.baseClassName}__tag`));
101
+
102
+ const removeBtn = document.createElement('button');
103
+ removeBtn.classList.add(className(`${this.baseClassName}-selected-items__remove-btn`));
104
+
105
+ const buttonTextContainer = document.createElement('span');
106
+ buttonTextContainer.classList.add('u-visuallyhidden');
107
+ removeBtn.appendChild(buttonTextContainer);
108
+ buttonTextContainer.textContent = `Ta bort ${item}`; // Accessibility label for screen readers
109
+
110
+ // Event listener for removing the selected item
111
+ removeBtn.addEventListener('click', () => {
112
+ this.removeItem(newItem, Array.from(this.selectedItemsList.children).indexOf(newItem));
113
+ });
114
+
115
+ newItem.appendChild(removeBtn);
116
+
117
+ this.selectedItemsList.appendChild(newItem);
118
+ this.selectedItems.push(item);
119
+ }
120
+
121
+ removeHighlight() {
122
+ const items = this.suggestionsBox.getElementsByClassName(`${this.baseClassName}__suggestion-btn`);
123
+
124
+ [].forEach.call(items, (item) => {
125
+ item.classList.remove('autocomplete-active');
126
+ });
127
+ }
128
+
129
+ highlight(direction) {
130
+ const items = this.suggestionsBox.getElementsByClassName(`${this.baseClassName}__suggestion-btn`);
131
+ let focus = this.currentFocus;
132
+
133
+ if (direction === 'down') {
134
+ focus = (focus >= items.length - 1) ? 0 : focus + 1;
135
+ } else {
136
+ focus = (focus <= 0) ? items.length - 1 : focus - 1;
128
137
  }
129
- });
138
+
139
+ this.setFocus(focus);
140
+ this.removeHighlight();
141
+
142
+ items[this.currentFocus].classList.add('autocomplete-active');
143
+ items[this.currentFocus].scrollIntoView({ block: 'nearest' });
144
+ }
145
+
146
+ selectHighlighted() {
147
+ const items = this.suggestionsBox.getElementsByClassName(`${this.baseClassName}__suggestion-btn`);
148
+
149
+ if (this.currentFocus > -1 && items[this.currentFocus]) {
150
+ this.addItem(items[this.currentFocus].textContent);
151
+ this.clearSuggestions();
152
+ this.input.value = '';
153
+ this.resetFocus();
154
+ }
155
+ }
156
+
157
+ onKeyDown = (e) => {
158
+ if (e.keyCode === 40) {
159
+ this.highlight('down');
160
+ } else if (e.keyCode === 38) {
161
+ this.highlight('up');
162
+ } else if (e.keyCode === 13) {
163
+ e.preventDefault();
164
+
165
+ this.selectHighlighted();
166
+ }
167
+ }
168
+
169
+ onClick = (e) => {
170
+ if (e.target.classList.contains(className(`${this.baseClassName}__suggestion-btn`))) {
171
+ this.addItem(e.target.textContent);
172
+ this.clearSuggestions();
173
+ this.input.value = '';
174
+ }
175
+ }
130
176
  }
131
177
 
178
+ const multiSelectElements = document.querySelectorAll('.js-m-multi-select');
179
+
132
180
  if (multiSelectElements) {
133
- [].forEach.call(multiSelectElements, setup);
181
+ [].forEach.call(multiSelectElements, (el) => new MultiSelect(el));
134
182
  }