@internetstiftelsen/styleguide 4.0.11 → 4.0.12-beta.0.1

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.
@@ -14,10 +14,10 @@ function toggleTextOnClick(e) {
14
14
  target.innerText = options[nextIteration];
15
15
  }
16
16
 
17
- var toggleTextButtons = document.querySelectorAll('[data-toggle-text]');
18
-
19
- if (toggleTextButtons) {
20
- [].forEach.call(toggleTextButtons, function (toggleTextButton) {
21
- toggleTextButton.addEventListener('click', toggleTextOnClick);
22
- });
23
- }
17
+ /* eslint-disable */
18
+ document.addEventListener('click', function (e) {
19
+ if (e.target.closest('[data-toggle-text]')) {
20
+ toggleTextOnClick(e);
21
+ return false;
22
+ }
23
+ });
@@ -1,80 +1,83 @@
1
1
  'use strict';
2
2
 
3
3
  /* eslint-disable */
4
- // Get references to the search input and suggestions box elements
5
4
  var className = 'm-multi-select';
6
- var multiSelectElement = document.querySelector('.js-' + className);
7
- var multiSelectInput = document.querySelector('.js-' + className + '__input');
8
- var suggestionsBox = document.querySelector('.js-' + className + '-suggestions-box');
9
-
10
- if (multiSelectInput && suggestionsBox) {
11
-
12
- // Function to highlight the active (focused) suggestion
13
- var setActive = 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');
19
-
20
- return items;
21
- };
22
-
23
- // Function to remove highlighting from all suggestions
24
-
25
-
26
- var removeActive = function removeActive(items) {
27
- for (var i = 0; i < items.length; i++) {
28
- items[i].classList.remove('autocomplete-active');
29
- }
30
- };
31
-
32
- // Function to add a selected item to the list of selected items
33
-
34
-
35
- var addSelectedItem = function addSelectedItem(item) {
36
- var container = document.getElementById('selectedItemsContainer');
37
- var newItem = document.createElement('li');
38
- newItem.textContent = item + ' ';
39
- var removeBtn = document.createElement('button');
40
- var buttonTextContainer = document.createElement('span');
41
- //removeBtn.textContent = 'x';
42
- buttonTextContainer.classList.add('visually-hidden');
43
- removeBtn.appendChild(buttonTextContainer);
44
- buttonTextContainer.textContent = 'Remove ' + item; // Accessibility label for screen readers
45
- // Event listener for removing the selected item
46
- removeBtn.addEventListener('click', function () {
47
- removeItem(newItem, Array.from(container.children).indexOf(newItem));
48
- });
49
- newItem.appendChild(removeBtn);
50
- container.appendChild(newItem);
51
- };
52
-
53
- // Function to remove an item and manage focus appropriately
54
-
55
-
56
- var removeItem = function removeItem(item, index) {
57
- var container = document.getElementById('selectedItemsContainer');
58
- container.removeChild(item);
59
-
60
- var remainingItems = container.getElementsByTagName('div');
61
- // Focus management: set focus to the next item, or the search input if no items left
62
- if (remainingItems.length > 0) {
63
- if (index < remainingItems.length) {
64
- remainingItems[index].getElementsByTagName('button')[0].focus();
65
- } else {
66
- remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
67
- }
5
+ var multiSelectElements = document.querySelectorAll('.js-' + className);
6
+ var namespace = void 0;
7
+
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');
29
+ }
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();
68
66
  } else {
69
- multiSelectInput.focus();
67
+ remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
70
68
  }
71
- };
72
-
73
- // Event listener for input changes in the search field
69
+ } else {
70
+ multiSelectInput.focus();
71
+ }
72
+ }
74
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');
75
78
 
76
- var currentFocus = -1; // Tracks the currently focused item in the suggestions
77
- var namespace = getComputedStyle(multiSelectElement, ':before').content.replace(/["']/g, '');multiSelectInput.addEventListener('input', function () {
79
+ // Event listener for input changes in the search field
80
+ multiSelectInput.addEventListener('input', function () {
78
81
  var value = this.value;
79
82
  // Clear suggestions if less than 2 characters are typed
80
83
  if (value.length < 2) {
@@ -82,8 +85,9 @@ if (multiSelectInput && suggestionsBox) {
82
85
  return;
83
86
  }
84
87
 
85
- // Define a JSON array of 100 real cities
86
- var suggestions = [{ name: 'New York' }, { name: 'Los Angeles' }, { name: 'Chicago' }, { name: 'Houston' }, { name: 'Phoenix' }, { name: 'Philadelphia' }, { name: 'San Antonio' }, { name: 'San Diego' }, { name: 'Dallas' }, { name: 'San Jose' }, { name: 'Austin' }, { name: 'Jacksonville' }, { name: 'Fort Worth' }, { name: 'Columbus' }, { name: 'San Francisco' }, { name: 'Tokyo' }, { name: 'Delhi' }, { name: 'Shanghai' }, { name: 'Sao Paulo' }, { name: 'Mumbai' }, { name: 'Beijing' }, { name: 'Cairo' }, { name: 'Dhaka' }, { name: 'Mexico City' }, { name: 'Osaka' }, { name: 'Karachi' }, { name: 'Chongqing' }, { name: 'Istanbul' }, { name: 'Buenos Aires' }, { name: 'Kolkata' }, { name: 'Kinshasa' }, { name: 'Lagos' }, { name: 'Manila' }, { name: 'Tianjin' }, { name: 'Rio de Janeiro' }, { name: 'Guangzhou' }, { name: 'Lahore' }, { name: 'Moscow' }, { name: 'Shenzhen' }, { name: 'Bangalore' }, { name: 'Paris' }, { name: 'Bogota' }, { name: 'Jakarta' }, { name: 'Chennai' }, { name: 'Lima' }, { name: 'Bangkok' }, { name: 'Seoul' }, { name: 'Nagoya' }, { name: 'Hyderabad' }, { name: 'London' }, { name: 'Tehran' }, { name: 'Chengdu' }, { name: 'Nanjing' }, { name: 'Wuhan' }, { name: 'Ho Chi Minh City' }, { name: 'Luanda' }, { name: 'Ahmedabad' }, { name: 'Kuala Lumpur' }, { name: 'Xi’an' }, { name: 'Hong Kong' }, { name: 'Dongguan' }, { name: 'Hangzhou' }, { name: 'Foshan' }, { name: 'Shenyang' }, { name: 'Riyadh' }, { name: 'Baghdad' }, { name: 'Santiago' }, { name: 'Surat' }, { name: 'Madrid' }, { name: 'Suzhou' }, { name: 'Pune' }, { name: 'Harbin' }, { name: 'Houston' }, { name: 'Toronto' }, { name: 'Dar es Salaam' }, { name: 'Miami' }, { name: 'Belo Horizonte' }, { name: 'Singapore' }, { name: 'Atlanta' }, { name: 'Fukuoka' }, { name: 'Khartoum' }, { name: 'Barcelona' }, { name: 'Johannesburg' }, { name: 'Saint Petersburg' }, { name: 'Qingdao' }, { name: 'Dalian' }, { name: 'Washington, D.C.' }, { name: 'Yangon' }, { name: 'Alexandria' }, { name: 'Jinan' }, { name: 'Guadalajara' }, { name: 'Sydney' }, { name: 'Melbourne' }, { name: 'Montreal' }, { name: 'Ankara' }, { name: 'Recife' }, { name: 'Durban' }, { name: 'Porto Alegre' }, { name: 'Dusseldorf' }, { name: 'Hamburg' }, { name: 'Cape Town' }];
88
+ // Define JSON
89
+ var suggestions = document.getElementById(suggestionsData).textContent;
90
+ suggestions = JSON.parse(suggestions);
87
91
 
88
92
  // Filter suggestions based on the input value
89
93
  var filtered = suggestions.filter(function (item) {
@@ -120,7 +124,7 @@ if (multiSelectInput && suggestionsBox) {
120
124
  }
121
125
  });
122
126
 
123
- // Click event listener for the suggestions box
127
+ // Event listener for the suggestions box
124
128
  suggestionsBox.addEventListener('click', function (e) {
125
129
  // Add the clicked suggestion to the selected items list
126
130
  if (e.target && e.target.classList.contains('suggestion-btn')) {
@@ -129,4 +133,8 @@ if (multiSelectInput && suggestionsBox) {
129
133
  multiSelectInput.value = '';
130
134
  }
131
135
  });
136
+ }
137
+
138
+ if (multiSelectElements) {
139
+ [].forEach.call(multiSelectElements, setup);
132
140
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetstiftelsen/styleguide",
3
- "version": "4.0.11",
3
+ "version": "4.0.12-beta.0.1",
4
4
  "main": "dist/components.js",
5
5
  "ports": {
6
6
  "fractal": "3000"
@@ -12,10 +12,10 @@ function toggleTextOnClick(e) {
12
12
  target.innerText = options[nextIteration];
13
13
  }
14
14
 
15
- const toggleTextButtons = document.querySelectorAll('[data-toggle-text]');
16
-
17
- if (toggleTextButtons) {
18
- [].forEach.call(toggleTextButtons, (toggleTextButton) => {
19
- toggleTextButton.addEventListener('click', toggleTextOnClick);
20
- });
21
- }
15
+ /* eslint-disable */
16
+ document.addEventListener('click', (e) => {
17
+ if (e.target.closest('[data-toggle-text]')) {
18
+ toggleTextOnClick(e);
19
+ return false;
20
+ }
21
+ });
@@ -26,91 +26,83 @@
26
26
  }
27
27
 
28
28
  @include e(suggestion-btn) {
29
- padding: 10px;
29
+ padding: rhythm(1);
30
30
  cursor: pointer;
31
- background-color: #fff;
31
+ background-color: $color-snow;
32
32
  border: none;
33
- border-bottom: 1px solid #d4d4d4;
33
+ border-bottom: 1px solid $color-concrete;
34
34
  width: 100%;
35
35
  text-align: left;
36
36
 
37
37
  &:hover,
38
38
  &.autocomplete-active {
39
- background-color: $color-ocean;
39
+ background-color: $color-ocean-dark;
40
40
  color: $color-snow;
41
41
  }
42
42
  }
43
+
44
+ @include e(tag){
45
+ margin-bottom: rhythm(1);
46
+ background-color: $color-ash;
47
+ text-transform: none;
48
+ font-size: $size-medium;
49
+
50
+ &:hover,
51
+ &:focus {
52
+ background-color: $color-ash;
53
+ color: $color-cyberspace;
54
+ }
55
+ }
43
56
  }
44
57
 
45
58
  /* Selected items container */
46
- .selected-items-container {
59
+ @include molecule(multi-select-selected-items) {
47
60
  margin-top: -#{rhythm(1)};
48
- padding: rhythm(2) rhythm(1) rhythm(1) rhythm(1);
61
+ padding: rhythm(2) rhythm(1) 0 rhythm(1);
49
62
  border: 1px solid #d4d4d4;
50
63
  background-color: $color-concrete;
51
- border-bottom-left: $border-radius;
64
+ border-bottom-left-radius: $border-radius;
52
65
  border-bottom-right-radius: $border-radius;
53
- }
54
-
55
- .selected-items-container:empty {
56
- display: none;
57
- }
58
-
59
- /* Style for selected items */
60
- .selected-items-container li {
61
- margin-right: 5px;
62
- padding: 5px;
63
- border: 1px solid #ccc;
64
- background-color: #e4e4e4;
65
- border-radius: 4px;
66
- display: inline-flex;
67
- align-items: center;
68
- margin-bottom: 0;
69
- font-size: 90%;
70
- }
71
66
 
72
- /* Remove button for selected items */
73
- .selected-items-container button {
74
- margin-left: 5px;
75
- border: none;
76
- background-color: #d80000;
77
- color: white;
78
- border-radius: 50%;
79
- cursor: pointer;
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
- line-height: 1;
84
- width: 16px;
85
- height: 16px;
86
- position: relative;
87
- }
67
+ &:empty {
68
+ display: none;
69
+ }
88
70
 
89
- .selected-items-container button::after {
90
- content: '';
91
- display: block;
92
- width: 16px;
93
- height: 16px;
94
- position: absolute;
95
- top: 0;
96
- left: 0;
97
- background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI4LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSI4LDEwIDIsMTYgMCwxNCA2LDggMCwyIDIsMCA4LDYgMTQsMCAxNiwyIDEwLDggMTYsMTQgMTQsMTYgIi8+Cjwvc3ZnPgo=);
98
- background-repeat: no-repeat;
99
- background-position: center center;
100
- background-size: 8px 8px;
101
- }
71
+ @include e(remove-btn) {
72
+ margin-left: 5px;
73
+ border: none;
74
+ background-color: #d80000;
75
+ color: white;
76
+ border-radius: 50%;
77
+ cursor: pointer;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ line-height: 1;
82
+ width: $icon-size-small;
83
+ height: $icon-size-small;
84
+ position: relative;
85
+ transform: translateX(rhythm(0.5));
102
86
 
103
- .selected-items-container button:hover {
104
- background-color: darkred;
105
- }
87
+ &::after {
88
+ content: '';
89
+ display: block;
90
+ width: 100%;
91
+ height: 100%;
92
+ position: absolute;
93
+ top: 0;
94
+ right: 0;
95
+ bottom: 0;
96
+ left: 0;
97
+ background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI4LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSI4LDEwIDIsMTYgMCwxNCA2LDggMCwyIDIsMCA4LDYgMTQsMCAxNiwyIDEwLDggMTYsMTQgMTQsMTYgIi8+Cjwvc3ZnPgo=);
98
+ background-repeat: no-repeat;
99
+ background-position: center center;
100
+ background-size: calc($icon-size-small / 2) calc($icon-size-small / 2);
101
+ }
106
102
 
107
- .visually-hidden {
108
- position: absolute;
109
- width: 1px;
110
- height: 1px;
111
- margin: -1px;
112
- padding: 0;
113
- overflow: hidden;
114
- clip: rect(0 0 0 0);
115
- clip: rect(0, 0, 0, 0);
103
+ &:hover,
104
+ &:focus {
105
+ background-color: $color-cyberspace;
106
+ }
107
+ }
116
108
  }
@@ -1,70 +1,80 @@
1
1
  /* eslint-disable */
2
- // Get references to the search input and suggestions box elements
3
2
  const className = 'm-multi-select';
4
- const multiSelectElement = document.querySelector(`.js-${className}`);
5
- const multiSelectInput = document.querySelector(`.js-${className}__input`);
6
- const suggestionsBox = document.querySelector(`.js-${className}-suggestions-box`);
7
-
8
- if (multiSelectInput && suggestionsBox) {
9
- let currentFocus = -1; // Tracks the currently focused item in the suggestions
10
- const namespace = getComputedStyle(multiSelectElement, ':before').content.replace(/["']/g, '');
11
-
12
- // Function to 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');
19
-
20
- return items;
21
- }
3
+ const multiSelectElements = document.querySelectorAll(`.js-${className}`);
4
+ let namespace;
22
5
 
23
- // Function to remove highlighting from all suggestions
24
- function removeActive(items) {
25
- for (let i = 0; i < items.length; i++) {
26
- items[i].classList.remove('autocomplete-active');
27
- }
28
- }
6
+ if( multiSelectElements ) {
7
+ namespace = getComputedStyle(multiSelectElements[0], ':before').content.replace(/["']/g, '');
8
+ }
9
+
10
+ let currentFocus = -1; // Tracks the currently focused item in the suggestions
29
11
 
30
- // Function to add a selected item to the list of selected items
31
- function addSelectedItem(item) {
32
- const container = document.getElementById('selectedItemsContainer');
33
- const newItem = document.createElement('li');
34
- newItem.textContent = item + ' ';
35
- const removeBtn = document.createElement('button');
36
- const buttonTextContainer = document.createElement('span');
37
- //removeBtn.textContent = 'x';
38
- buttonTextContainer.classList.add('visually-hidden');
39
- removeBtn.appendChild(buttonTextContainer);
40
- buttonTextContainer.textContent ='Remove ' + item; // Accessibility label for screen readers
41
- // Event listener for removing the selected item
42
- removeBtn.addEventListener('click', function () {
43
- removeItem(newItem, Array.from(container.children).indexOf(newItem));
44
- });
45
- newItem.appendChild(removeBtn);
46
- container.appendChild(newItem);
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');
19
+
20
+ return items;
21
+ }
22
+
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');
47
27
  }
28
+ }
48
29
 
49
- // Function to remove an item and manage focus appropriately
50
- function removeItem(item, index) {
51
- const container = document.getElementById('selectedItemsContainer');
52
- container.removeChild(item);
53
-
54
- let remainingItems = container.getElementsByTagName('div');
55
- // Focus management: set focus to the next item, or the search input if no items left
56
- if (remainingItems.length > 0) {
57
- if (index < remainingItems.length) {
58
- remainingItems[index].getElementsByTagName('button')[0].focus();
59
- } else {
60
- remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
61
- }
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
+ }
53
+
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);
58
+
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();
62
64
  } else {
63
- multiSelectInput.focus();
65
+ remainingItems[remainingItems.length - 1].getElementsByTagName('button')[0].focus();
64
66
  }
67
+ } else {
68
+ multiSelectInput.focus();
65
69
  }
70
+ }
66
71
 
67
- // Event listener for input changes in the search field
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');
76
+
77
+ // Event listener for input changes in the search field
68
78
  multiSelectInput.addEventListener('input', function () {
69
79
  const value = this.value;
70
80
  // Clear suggestions if less than 2 characters are typed
@@ -73,44 +83,9 @@ if (multiSelectInput && suggestionsBox) {
73
83
  return;
74
84
  }
75
85
 
76
- // Define a JSON array of 100 real cities
77
- let suggestions = [
78
- { name: 'New York' }, { name: 'Los Angeles' }, { name: 'Chicago' },
79
- { name: 'Houston' }, { name: 'Phoenix' }, { name: 'Philadelphia' },
80
- { name: 'San Antonio' }, { name: 'San Diego' }, { name: 'Dallas' },
81
- { name: 'San Jose' }, { name: 'Austin' }, { name: 'Jacksonville' },
82
- { name: 'Fort Worth' }, { name: 'Columbus' }, { name: 'San Francisco' },
83
- { name: 'Tokyo' }, { name: 'Delhi' }, { name: 'Shanghai' },
84
- { name: 'Sao Paulo' }, { name: 'Mumbai' }, { name: 'Beijing' },
85
- { name: 'Cairo' }, { name: 'Dhaka' }, { name: 'Mexico City' },
86
- { name: 'Osaka' }, { name: 'Karachi' }, { name: 'Chongqing' },
87
- { name: 'Istanbul' }, { name: 'Buenos Aires' }, { name: 'Kolkata' },
88
- { name: 'Kinshasa' }, { name: 'Lagos' }, { name: 'Manila' },
89
- { name: 'Tianjin' }, { name: 'Rio de Janeiro' }, { name: 'Guangzhou' },
90
- { name: 'Lahore' }, { name: 'Moscow' }, { name: 'Shenzhen' },
91
- { name: 'Bangalore' }, { name: 'Paris' }, { name: 'Bogota' },
92
- { name: 'Jakarta' }, { name: 'Chennai' }, { name: 'Lima' },
93
- { name: 'Bangkok' }, { name: 'Seoul' }, { name: 'Nagoya' },
94
- { name: 'Hyderabad' }, { name: 'London' }, { name: 'Tehran' },
95
- { name: 'Chengdu' }, { name: 'Nanjing' },
96
- { name: 'Wuhan' }, { name: 'Ho Chi Minh City' }, { name: 'Luanda' },
97
- { name: 'Ahmedabad' }, { name: 'Kuala Lumpur' }, { name: 'Xi’an' },
98
- { name: 'Hong Kong' }, { name: 'Dongguan' }, { name: 'Hangzhou' },
99
- { name: 'Foshan' }, { name: 'Shenyang' }, { name: 'Riyadh' },
100
- { name: 'Baghdad' }, { name: 'Santiago' }, { name: 'Surat' },
101
- { name: 'Madrid' }, { name: 'Suzhou' }, { name: 'Pune' },
102
- { name: 'Harbin' }, { name: 'Houston' },
103
- { name: 'Toronto' }, { name: 'Dar es Salaam' }, { name: 'Miami' },
104
- { name: 'Belo Horizonte' }, { name: 'Singapore' },
105
- { name: 'Atlanta' }, { name: 'Fukuoka' }, { name: 'Khartoum' },
106
- { name: 'Barcelona' }, { name: 'Johannesburg' }, { name: 'Saint Petersburg' },
107
- { name: 'Qingdao' }, { name: 'Dalian' }, { name: 'Washington, D.C.' },
108
- { name: 'Yangon' }, { name: 'Alexandria' }, { name: 'Jinan' },
109
- { name: 'Guadalajara' }, { name: 'Sydney' }, { name: 'Melbourne' },
110
- { name: 'Montreal' }, { name: 'Ankara' }, { name: 'Recife' },
111
- { name: 'Durban' }, { name: 'Porto Alegre' },
112
- { name: 'Dusseldorf' }, { name: 'Hamburg' }, { name: 'Cape Town' },
113
- ];
86
+ // Define JSON
87
+ let suggestions = document.getElementById(suggestionsData).textContent;
88
+ suggestions = JSON.parse(suggestions);
114
89
 
115
90
  // Filter suggestions based on the input value
116
91
  const filtered = suggestions.filter(item => item.name.toLowerCase().startsWith(value.toLowerCase()));
@@ -120,7 +95,7 @@ if (multiSelectInput && suggestionsBox) {
120
95
  currentFocus = -1;
121
96
  });
122
97
 
123
- // Event listener for keydown events for navigation and selection in the suggestions box
98
+ // Event listener for keydown events for navigation and selection in the suggestions box
124
99
  multiSelectInput.addEventListener('keydown', function (e) {
125
100
  let items = suggestionsBox.getElementsByClassName(`${namespace}m-multi-select__suggestion-btn`);
126
101
  // Navigate down in the suggestions list
@@ -143,7 +118,7 @@ if (multiSelectInput && suggestionsBox) {
143
118
  }
144
119
  });
145
120
 
146
- // Click event listener for the suggestions box
121
+ // Event listener for the suggestions box
147
122
  suggestionsBox.addEventListener('click', function (e) {
148
123
  // Add the clicked suggestion to the selected items list
149
124
  if (e.target && e.target.classList.contains('suggestion-btn')) {
@@ -152,8 +127,8 @@ if (multiSelectInput && suggestionsBox) {
152
127
  multiSelectInput.value = '';
153
128
  }
154
129
  });
130
+ }
155
131
 
156
-
157
-
158
-
132
+ if (multiSelectElements) {
133
+ [].forEach.call(multiSelectElements, setup);
159
134
  }