@iamproperty/components 3.2.0 → 3.4.5

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.
Files changed (96) hide show
  1. package/README.md +30 -66
  2. package/assets/css/core.min.css.map +1 -1
  3. package/assets/css/style.min.css.map +1 -1
  4. package/assets/js/main.js +9 -9
  5. package/assets/js/modules/accordion.js +1 -0
  6. package/assets/js/modules/alert.js +37 -53
  7. package/assets/js/modules/carousel.js +74 -100
  8. package/assets/js/modules/chart.js +142 -209
  9. package/assets/js/modules/drawer.js +9 -15
  10. package/assets/js/modules/file-upload.js +30 -45
  11. package/assets/js/modules/form.js +111 -157
  12. package/assets/js/modules/helpers.js +64 -93
  13. package/assets/js/modules/modal.js +67 -88
  14. package/assets/js/modules/nav.js +17 -27
  15. package/assets/js/modules/orderablelist.js +84 -115
  16. package/assets/js/modules/table.js +387 -521
  17. package/assets/js/modules/testimonial.js +61 -80
  18. package/assets/js/modules/youtubevideo.js +104 -135
  19. package/assets/js/scripts.bundle.js +870 -936
  20. package/assets/js/scripts.bundle.js.map +1 -1
  21. package/assets/js/scripts.bundle.min.js +3 -3
  22. package/assets/js/scripts.bundle.min.js.map +1 -1
  23. package/assets/sass/_corefiles.scss +9 -9
  24. package/assets/sass/_forms.scss +1 -1
  25. package/assets/sass/_tests/{sass.spec.js → colours.spec.js} +2 -2
  26. package/assets/sass/_tests/func.spec.js +9 -0
  27. package/assets/sass/_tests/mixins.spec.js +9 -0
  28. package/assets/sass/_tests/typography.spec.js +9 -0
  29. package/assets/ts/main.ts +9 -9
  30. package/assets/ts/modules/accordion.ts +1 -0
  31. package/assets/ts/modules/alert.ts +58 -0
  32. package/assets/ts/modules/carousel.ts +103 -0
  33. package/assets/ts/modules/chart.ts +219 -0
  34. package/assets/ts/modules/drawer.ts +17 -0
  35. package/assets/ts/modules/file-upload.ts +49 -0
  36. package/assets/ts/modules/form.ts +169 -0
  37. package/assets/ts/modules/helpers.ts +120 -0
  38. package/assets/ts/modules/modal.ts +91 -0
  39. package/assets/ts/modules/nav.ts +29 -0
  40. package/assets/ts/modules/orderablelist.ts +123 -0
  41. package/assets/ts/modules/table.ts +586 -0
  42. package/assets/ts/modules/testimonial.ts +84 -0
  43. package/assets/ts/modules/youtubevideo.ts +146 -0
  44. package/dist/components.es.js +671 -750
  45. package/dist/components.umd.js +13 -13
  46. package/dist/style.css +1 -1
  47. package/package.json +54 -38
  48. package/src/components/Accordion/Accordion.vue +1 -1
  49. package/src/components/Alert/Alert.vue +1 -1
  50. package/src/{elements → components}/Card/Card.vue +1 -1
  51. package/src/components/CardDeck/CardDeck.spec.js +1 -1
  52. package/src/components/CardDeck/CardDeck.vue +1 -1
  53. package/src/components/Carousel/Carousel.vue +2 -2
  54. package/src/components/Chart/Chart.vue +2 -2
  55. package/src/{elements → components}/FileUploads/FileUploads.vue +1 -1
  56. package/src/components/Modal/Modal.vue +1 -1
  57. package/src/components/Nav/Nav.vue +2 -2
  58. package/src/components/NoteFeed/NoteFeed.vue +2 -2
  59. package/src/components/PropertySearchbar/PropertySearchbar.vue +1 -1
  60. package/src/{elements → components}/Table/Table.vue +1 -1
  61. package/src/components/Testimonial/Testimonial.vue +1 -1
  62. package/src/foundations/YoutubeVideo/YoutubeVideo.vue +1 -1
  63. package/src/index.js +4 -5
  64. package/assets/.DS_Store +0 -0
  65. package/assets/css/email.min.css +0 -1
  66. package/assets/css/email.min.css.map +0 -1
  67. package/assets/css/error.min.css +0 -1
  68. package/assets/css/error.min.css.map +0 -1
  69. package/assets/sass/components/drawer.scss +0 -47
  70. package/assets/ts/main.js +0 -57
  71. package/assets/ts/main.js.map +0 -1
  72. package/assets/ts/modules/accordion.js +0 -33
  73. package/assets/ts/modules/accordion.js.map +0 -1
  74. package/src/.DS_Store +0 -0
  75. package/src/components/Accordion/Accordion.screenshot.vue +0 -57
  76. package/src/components/Accordion/__screenshots__/win32/laptop/Accordion.png +0 -0
  77. package/src/components/Accordion/__screenshots__/win32/mobile/Accordion.png +0 -0
  78. package/src/components/Accordion/__screenshots__/win32/tablet/Accordion.png +0 -0
  79. package/src/components/Drawer/Drawer.vue +0 -53
  80. package/src/components/Drawer/README.md +0 -23
  81. /package/assets/sass/{elements → components}/buttons.scss +0 -0
  82. /package/assets/sass/{elements → components}/card.scss +0 -0
  83. /package/assets/sass/{elements → components}/container.scss +0 -0
  84. /package/assets/sass/{elements → components}/forms.scss +0 -0
  85. /package/assets/sass/{elements → components}/links.scss +0 -0
  86. /package/assets/sass/{elements → components}/lists.scss +0 -0
  87. /package/assets/sass/{elements → components}/panel.scss +0 -0
  88. /package/assets/sass/{elements → components}/tables.scss +0 -0
  89. /package/assets/sass/{elements → components}/tooltips.scss +0 -0
  90. /package/assets/sass/{elements → foundations}/type.scss +0 -0
  91. /package/src/{elements → components}/Card/README.md +0 -0
  92. /package/src/{elements → components}/FileUploads/README.md +0 -0
  93. /package/src/{elements → components}/Input/Input.vue +0 -0
  94. /package/src/{elements → components}/Input/README.md +0 -0
  95. /package/src/{elements → components}/Table/README.md +0 -0
  96. /package/src/{elements → components}/Table/Table.spec.js +0 -0
@@ -1,1054 +1,988 @@
1
1
  /*!
2
- * Bootstrap v3.2.0
3
- * Copyright 2011-2022 [object Object]
2
+ * Bootstrap [object Object] v3.4.5
3
+ * Copyright 2011-2023 [object Object]
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  */
6
6
  (function (factory) {
7
- typeof define === 'function' && define.amd ? define(factory) :
8
- factory();
7
+ typeof define === 'function' && define.amd ? define(factory) :
8
+ factory();
9
9
  })((function () { 'use strict';
10
10
 
11
- /**
12
- * Global helper functions to help maintain and enhance framework elements.
13
- * @module Helpers
14
- */
15
-
16
- /**
17
- * Add global classes used by the CSS and later JavaScript.
18
- * @param {HTMLElement} body Dom element, this doesn't have to be the body but it is recommended.
19
- */
20
- var addBodyClasses = body => {
21
- body.classList.add("js-enabled");
22
- if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) {
23
- body.classList.add("ie");
24
- }
25
- return null;
26
- };
27
-
28
- /**
29
- * Add global events.
30
- * @param {HTMLElement} body Dom element, this doesn't have to be the body but it is recommended.
31
- */
32
- var addGlobalEvents = body => {
33
- window.addEventListener('hashchange', function () {
34
- var hash = location.hash.replace('#', '');
35
- var label = document.querySelector("label[for=\"".concat(hash, "\"]"));
36
- var detail = document.querySelector("details[id=\"".concat(hash, "\"]:not([open])"));
37
- if (label) label.click();else if (detail) detail.setAttribute('open', 'open');
38
- }, false);
39
- return null;
40
- };
41
-
42
- /**
43
- * Check if an element contains certain elements that needs enhancing with the JavaScript helpers, it is recommended to do this on the page body after the dom is loaded. Elements that are loaded via ajax should also run this function.
44
- * @param {HTMLElement} element Dom element, this doesn't have to be the body but it is recommended.
45
- */
46
- var checkElements = element => {
47
- // Tables
48
- Array.from(element.querySelectorAll('table')).forEach((table, index) => {
49
- tableStacked(table);
50
- tableWrap(table);
51
- });
52
- };
53
-
54
- /**
55
- * Wrap tables with a table wrapper div to help maintain its responsive design.
56
- * @param {HTMLElement} table Dom table element
57
- */
58
- var tableWrap = table => {
59
- if (!table.parentNode.classList.contains('table__wrapper')) {
60
- var tableHTML = table.outerHTML;
61
- table.outerHTML = "<div class=\"table__wrapper\">".concat(tableHTML, "</div>");
62
- }
63
- };
64
-
65
- /**
66
- * Creates data attributes to be used by the CSS for mobile views.
67
- * @param {HTMLElement} table Dom table element
68
- */
69
- var tableStacked = table => {
70
- var colHeadings = Array.from(table.querySelectorAll('thead th'));
71
- var colRows = Array.from(table.querySelectorAll('tbody tr'));
72
- colRows.forEach((row, index) => {
73
- var cells = Array.from(row.querySelectorAll('th, td'));
74
- cells.forEach((cell, cellIndex) => {
75
- var heading = colHeadings[cellIndex];
76
- if (typeof heading != "undefined") {
77
- var tempDiv = document.createElement("div");
78
- tempDiv.innerHTML = heading.innerHTML;
79
- var headingText = tempDiv.textContent || tempDiv.innerText || "";
80
- cell.setAttribute('data-label', headingText);
81
- }
82
- });
83
- });
84
- };
85
- var isNumeric = function isNumeric(str) {
86
- if (typeof str != "string") return false; // we only process strings!
87
- return !isNaN(str) &&
88
- // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
89
- !isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail
90
- };
91
-
92
- var zeroPad = (num, places) => String(num).padStart(places, '0');
93
-
94
- var navbar = element => {
95
- Array.from(element.querySelectorAll('details')).forEach((detail, index) => {
96
- detail.addEventListener('mouseenter', function (e) {
97
- if (window.matchMedia('(min-width: 62em)').matches) detail.setAttribute('open', 'true');
98
- }, false);
99
- detail.addEventListener('mouseleave', function (e) {
100
- if (window.matchMedia('(min-width: 62em)').matches) detail.removeAttribute('open');
11
+ // @ts-nocheck
12
+ /**
13
+ * Global helper functions to help maintain and enhance framework elements.
14
+ * @module Helpers
15
+ */
16
+ /**
17
+ * Add global classes used by the CSS and later JavaScript.
18
+ * @param {HTMLElement} body Dom element, this doesn't have to be the body but it is recommended.
19
+ */
20
+ var addBodyClasses = body => {
21
+ body.classList.add("js-enabled");
22
+ if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) {
23
+ body.classList.add("ie");
24
+ }
25
+ return null;
26
+ };
27
+ /**
28
+ * Add global events.
29
+ * @param {HTMLElement} body Dom element, this doesn't have to be the body but it is recommended.
30
+ */
31
+ var addGlobalEvents = body => {
32
+ window.addEventListener('hashchange', function () {
33
+ var hash = location.hash.replace('#', '');
34
+ var label = document.querySelector("label[for=\"".concat(hash, "\"]"));
35
+ var detail = document.querySelector("details[id=\"".concat(hash, "\"]:not([open])"));
36
+ if (label) label.click();else if (detail) detail.setAttribute('open', 'open');
101
37
  }, false);
102
- });
103
- if ('IntersectionObserver' in window) {
104
- var observer = new IntersectionObserver(_ref => {
105
- var [e] = _ref;
106
- return e.target.classList.toggle("is-stuck", e.intersectionRatio < 1);
107
- }, {
108
- threshold: [1]
109
- });
110
- observer.observe(element);
111
- }
112
- };
113
-
114
- function table(tableElement) {
115
- if (typeof tableElement != "object") return false;
116
- var thead = tableElement.querySelector('thead');
117
- var tbody = tableElement.querySelector('tbody');
118
- var storedData = tbody.cloneNode(true);
119
- var sortedEvent = new Event('sorted');
120
- var filteredEvent = new Event('filtered');
121
- var reorderedEvent = new Event('reordered');
122
- var randID = 'table_' + Math.random().toString(36).substr(2, 9); // Random to make sure IDs created are unique
123
- var draggedRow;
124
- tableElement.setAttribute('id', randID);
125
-
126
- // #region Sortable
127
- var sortTable = function sortTable(sortBy, sort) {
128
- // Create an array from the table rows, the index created is then used to sort the array
129
- var tableArr = [];
130
- Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
131
- var rowIndex = tableRow.querySelector('td[data-label="' + sortBy + '"], th[data-label="' + sortBy + '"]').textContent;
132
- if (isNumeric(rowIndex)) rowIndex = zeroPad(rowIndex, 10);
133
- var dataRow = {
134
- index: rowIndex,
135
- row: tableRow
136
- };
137
- tableArr.push(dataRow);
138
- });
139
-
140
- // Sort array
141
- tableArr.sort((a, b) => a.index > b.index ? 1 : -1);
142
-
143
- // Reverse if descending
144
- if (sort == "descending") tableArr = tableArr.reverse();
145
-
146
- // Create a string to return and populate the tbody
147
- var strTbody = '';
148
- tableArr.forEach((tableRow, index) => {
149
- strTbody += tableRow.row.outerHTML;
38
+ return null;
39
+ };
40
+ /**
41
+ * Check if an element contains certain elements that needs enhancing with the JavaScript helpers, it is recommended to do this on the page body after the dom is loaded. Elements that are loaded via ajax should also run this function.
42
+ * @param {HTMLElement} element Dom element, this doesn't have to be the body but it is recommended.
43
+ */
44
+ var checkElements = element => {
45
+ // Tables
46
+ Array.from(element.querySelectorAll('table')).forEach((table, index) => {
47
+ tableStacked(table);
48
+ tableWrap(table);
150
49
  });
151
- tbody.innerHTML = strTbody;
152
-
153
- // Dispatch the sortable event
154
- tableElement.dispatchEvent(sortedEvent);
155
50
  };
156
-
157
- // Declare event handlers
158
- tableElement.addEventListener('click', function (e) {
159
- for (var target = e.target; target && target != this; target = target.parentNode) {
160
- if (target.matches('[data-sortable]')) {
161
- // Get current sort order
162
- var sort = target.getAttribute('aria-sort') == "ascending" ? "descending" : "ascending";
163
-
164
- // unset sort attributes
165
- Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
166
- col.setAttribute('aria-sort', 'none');
167
- });
168
-
169
- // Set the sort order attribute
170
- target.setAttribute('aria-sort', sort);
171
-
172
- // Save the sort options on the table element so that it can be re-sorted later
173
- tableElement.setAttribute('data-sort', sort);
174
- tableElement.setAttribute('data-sortBy', target.textContent);
175
-
176
- // Sort the table
177
- sortTable(target.textContent, sort);
178
- Array.from(tableElement.querySelectorAll('tr[draggable]')).forEach((tableRow, index) => {
179
- tableRow.removeAttribute('draggable');
180
- });
181
- break;
182
- }
51
+ /**
52
+ * Wrap tables with a table wrapper div to help maintain its responsive design.
53
+ * @param {HTMLElement} table Dom table element
54
+ */
55
+ var tableWrap = table => {
56
+ if (!table.parentNode.classList.contains('table__wrapper')) {
57
+ var tableHTML = table.outerHTML;
58
+ table.outerHTML = "<div class=\"table__wrapper\">".concat(tableHTML, "</div>");
183
59
  }
184
- }, false);
185
-
186
- // On page load check if the table should be pre-sorted, if so trigger a click
187
- if (tableElement.getAttribute('data-sortBy')) {
188
- var sort = tableElement.getAttribute('data-sort') == "ascending" ? "descending" : "ascending";
189
- Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
190
- if (col.textContent == tableElement.getAttribute('data-sortBy')) {
191
- col.setAttribute('aria-sort', sort);
192
- col.click();
193
- }
194
- });
195
- }
196
-
197
- // #endregion Sortable
198
-
199
- // #region Filters
200
- var createFilterForm = function createFilterForm(count) {
201
- // Create wrapper div
202
- var form = document.createElement("div");
203
- form.classList.add('table__filters');
204
- form.classList.add('row');
205
- form.classList.add('pt-1');
206
- form.classList.add('pb-3');
207
-
208
- // Create the filter options array
209
- var filterColumns = Array.from(tableElement.querySelectorAll('th[data-filterable]'));
210
-
211
- // Populate a list of searchable terms from the cells of the columns that could be used as a filter
212
- var searchableTerms = {};
213
- filterColumns.forEach((columnHeading, index) => {
214
- Array.from(tableElement.querySelectorAll('td[data-label="' + columnHeading.textContent + '"]')).forEach((label, index) => {
215
- searchableTerms[label.textContent] = label.textContent;
60
+ };
61
+ /**
62
+ * Creates data attributes to be used by the CSS for mobile views.
63
+ * @param {HTMLElement} table Dom table element
64
+ */
65
+ var tableStacked = table => {
66
+ var colHeadings = Array.from(table.querySelectorAll('thead th'));
67
+ var colRows = Array.from(table.querySelectorAll('tbody tr'));
68
+ colRows.forEach((row, index) => {
69
+ var cells = Array.from(row.querySelectorAll('th, td'));
70
+ cells.forEach((cell, cellIndex) => {
71
+ var heading = colHeadings[cellIndex];
72
+ if (typeof heading != "undefined") {
73
+ var tempDiv = document.createElement("div");
74
+ tempDiv.innerHTML = heading.innerHTML;
75
+ var headingText = tempDiv.textContent || tempDiv.innerText || "";
76
+ cell.setAttribute('data-label', headingText);
77
+ }
216
78
  });
217
79
  });
80
+ };
81
+ var isNumeric = function isNumeric(str) {
82
+ if (typeof str != "string") return false; // we only process strings!
83
+ return !isNaN(str) &&
84
+ // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
85
+ !isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail
86
+ };
218
87
 
219
- // Create the form
220
- var filterTitle = filterColumns.length == 1 ? "Filter by " + filterColumns[0].textContent : "Filter"; // Update title if only one filter is chosen
221
- var checkboxClass = filterColumns.length == 1 ? "d-none" : "d-sm-flex"; // Hide controls when only one filter is chosen
222
-
223
- form.innerHTML = "<div class=\"col-sm-6 col-md-4 pb-3\">\n <div class=\"form-control__wrapper form-control-inline mb-0\">\n <label for=\"".concat(randID, "_filter\" class=\"form-label\">").concat(filterTitle, ":</label>\n <input type=\"search\" name=\"").concat(randID, "_filter\" id=\"").concat(randID, "_filter\" class=\"form-control form-control-sm\" placeholder=\"\" list=\"").concat(randID, "_list\" />\n </div>\n <datalist id=\"").concat(randID, "_list\">\n ").concat(Object.keys(searchableTerms).map(term => "<option value=\"".concat(term, "\"></option>")).join(""), "\n </datalist>\n</div>\n<div class=\"col-md-8 align-items-center pb-3 ").concat(checkboxClass, "\">\n ").concat("<span class=\"pe-3 text-nowrap h5 mb-0\">Filter by: </span>" + filterColumns.map(column => "<div class=\"form-check pe-3 mt-0 mb-0\"><input class=\"form-check-input\" type=\"checkbox\" id=\"".concat(randID, "_").concat(column.textContent.replace(' ', '_').toLowerCase(), "\" checked=\"checked\" /><label class=\"form-check-label text-nowrap\" for=\"").concat(randID, "_").concat(column.textContent.replace(' ', '_').toLowerCase(), "\">").concat(column.textContent, "</label></div>")).join(""), "\n</div>");
88
+ var zeroPad = (num, places) => String(num).padStart(places, '0');
224
89
 
225
- // Add before the actual table
226
- tableElement.prepend(form);
227
- };
228
- var filterTable = function filterTable(searchTerm) {
229
- // Create an array of rows that match the search term
230
- var tableArr = [];
231
- Array.from(storedData.querySelectorAll('tr')).forEach((tableRow, index) => {
232
- // We want one long search string per row including each filterable table cell
233
- var rowSearchString = '';
234
- Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
235
- rowSearchString += tableRow.querySelector('td[data-label="' + label.textContent + '"]').textContent + ' | ';
90
+ // @ts-nocheck
91
+ var navbar = element => {
92
+ Array.from(element.querySelectorAll('details')).forEach((detail, index) => {
93
+ detail.addEventListener('mouseenter', function (e) {
94
+ if (window.matchMedia('(min-width: 62em)').matches) detail.setAttribute('open', 'true');
95
+ }, false);
96
+ detail.addEventListener('mouseleave', function (e) {
97
+ if (window.matchMedia('(min-width: 62em)').matches) detail.removeAttribute('open');
98
+ }, false);
99
+ });
100
+ if ('IntersectionObserver' in window) {
101
+ var observer = new IntersectionObserver(_ref => {
102
+ var [e] = _ref;
103
+ return e.target.classList.toggle("is-stuck", e.intersectionRatio < 1);
104
+ }, {
105
+ threshold: [1]
236
106
  });
107
+ observer.observe(element);
108
+ }
109
+ };
237
110
 
238
- // Check if the table row search string contains the search term
239
- if (rowSearchString.indexOf(searchTerm) >= 0) {
111
+ // @ts-nocheck
112
+ function table(tableElement) {
113
+ if (typeof tableElement != "object") return false;
114
+ var thead = tableElement.querySelector('thead');
115
+ var tbody = tableElement.querySelector('tbody');
116
+ var storedData = tbody.cloneNode(true);
117
+ var sortedEvent = new Event('sorted');
118
+ var filteredEvent = new Event('filtered');
119
+ var reorderedEvent = new Event('reordered');
120
+ var randID = 'table_' + Math.random().toString(36).substr(2, 9); // Random to make sure IDs created are unique
121
+ var draggedRow;
122
+ tableElement.setAttribute('id', randID);
123
+ // #region Sortable
124
+ var sortTable = function sortTable(sortBy, sort) {
125
+ // Create an array from the table rows, the index created is then used to sort the array
126
+ var tableArr = [];
127
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
128
+ var rowIndex = tableRow.querySelector('td[data-label="' + sortBy + '"], th[data-label="' + sortBy + '"]').textContent;
129
+ if (isNumeric(rowIndex)) rowIndex = zeroPad(rowIndex, 10);
240
130
  var dataRow = {
131
+ index: rowIndex,
241
132
  row: tableRow
242
133
  };
243
134
  tableArr.push(dataRow);
244
- }
245
- });
246
-
247
- // Create a string to return and populate the tbody
248
- var strTbody = '';
249
- tableArr.forEach((tableRow, index) => {
250
- strTbody += tableRow.row.outerHTML;
251
- });
252
- tbody.innerHTML = strTbody;
253
-
254
- // Dispatch the filter event.
255
- tableElement.dispatchEvent(filteredEvent);
256
- };
257
- var createFilterList = function createFilterList() {
258
- // Check which options are checked
259
- var filterOptions = [];
260
- Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
261
- filterOptions.push(label.textContent);
262
- });
263
-
264
- // Build up the list of searchable terms
265
- var searchableTerms = [];
266
- filterOptions.forEach((option, index) => {
267
- Array.from(tableElement.querySelectorAll('td[data-label="' + option + '"]')).forEach((label, index) => {
268
- searchableTerms[label.textContent] = label.textContent;
269
135
  });
270
- });
271
-
272
- // Rebuild the list
273
- var dataList = tableElement.querySelector('datalist');
274
- dataList.innerHTML = Object.keys(searchableTerms).map(term => "<option value=\"".concat(term, "\"></option>")).join("");
275
- };
276
-
277
- // On page load check if filters are needed
278
- if (Array.from(tableElement.querySelectorAll('[data-filterable]')).length) {
279
- // Create the filter options
280
- createFilterForm(tableElement, Array.from(tableElement.querySelectorAll('[data-filterable]')).length);
281
-
282
- // Add event handlers for the filter options
283
- tableElement.addEventListener('keyup', function (e) {
284
- for (var target = e.target; target && target != this; target = target.parentNode) {
285
- if (target.matches('input[type="search"]')) {
286
- var searchTerm = target.value;
287
- filterTable(searchTerm);
288
- }
289
- }
290
- });
291
- tableElement.addEventListener('change', function (e) {
136
+ // Sort array
137
+ tableArr.sort((a, b) => a.index > b.index ? 1 : -1);
138
+ // Reverse if descending
139
+ if (sort == "descending") tableArr = tableArr.reverse();
140
+ // Create a string to return and populate the tbody
141
+ var strTbody = '';
142
+ tableArr.forEach((tableRow, index) => {
143
+ strTbody += tableRow.row.outerHTML;
144
+ });
145
+ tbody.innerHTML = strTbody;
146
+ // Dispatch the sortable event
147
+ tableElement.dispatchEvent(sortedEvent);
148
+ };
149
+ // Declare event handlers
150
+ tableElement.addEventListener('click', function (e) {
292
151
  for (var target = e.target; target && target != this; target = target.parentNode) {
293
- if (target.matches('input[type="search"]')) {
294
- var searchTerm = target.value;
295
- filterTable(searchTerm);
152
+ if (target.matches('[data-sortable]')) {
153
+ // Get current sort order
154
+ var sort = target.getAttribute('aria-sort') == "ascending" ? "descending" : "ascending";
155
+ // unset sort attributes
156
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
157
+ col.setAttribute('aria-sort', 'none');
158
+ });
159
+ // Set the sort order attribute
160
+ target.setAttribute('aria-sort', sort);
161
+ // Save the sort options on the table element so that it can be re-sorted later
162
+ tableElement.setAttribute('data-sort', sort);
163
+ tableElement.setAttribute('data-sortBy', target.textContent);
164
+ // Sort the table
165
+ sortTable(target.textContent, sort);
166
+ Array.from(tableElement.querySelectorAll('tr[draggable]')).forEach((tableRow, index) => {
167
+ tableRow.removeAttribute('draggable');
168
+ });
169
+ break;
296
170
  }
297
171
  }
298
- });
299
- tableElement.addEventListener('change', function (e) {
300
- for (var target = e.target; target && target != this; target = target.parentNode) {
301
- if (target.matches('input[type="checkbox"]')) {
302
- var searchTerm = tableElement.querySelector('input[type="search"]').value;
303
- filterTable(searchTerm);
304
- createFilterList();
172
+ }, false);
173
+ // On page load check if the table should be pre-sorted, if so trigger a click
174
+ if (tableElement.getAttribute('data-sortBy')) {
175
+ var sort = tableElement.getAttribute('data-sort') == "ascending" ? "descending" : "ascending";
176
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
177
+ if (col.textContent == tableElement.getAttribute('data-sortBy')) {
178
+ col.setAttribute('aria-sort', sort);
179
+ col.click();
305
180
  }
306
- }
307
- });
308
- }
309
- // #endregion Filters
310
-
311
- // #region Pagination
312
- var paginateRows = function paginateRows(show, page) {
313
- // Create some inline CSS to control what is viewed on the table, unline the filters we are just hiding the rable rows not removing them from the DOM.
314
- var style = document.getElementById(randID + '_style');
315
- if (style == null) {
316
- style = document.createElement("style");
317
- style.setAttribute('id', randID + '_style');
181
+ });
318
182
  }
319
- var startShowing = show * (page - 1) + 1;
320
- var stopShowing = show * page;
321
- style.innerHTML = "\n #".concat(randID, " tbody tr {\n display: none;\n }\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, "),\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, ") ~ tr{\n display: block;\n }\n @media screen and (min-width: 36em) {\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, "),\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, ") ~ tr{\n display: table-row;\n }\n }\n #").concat(randID, " tbody tr:nth-child(").concat(stopShowing, ") ~ tr{\n display: none;\n }\n ");
322
- tableElement.append(style);
323
- };
324
-
325
- // On page load check if the table should be paginated
326
- if (tableElement.getAttribute('data-show')) {
327
- var show = parseInt(tableElement.getAttribute('data-show'));
328
- var page = parseInt(tableElement.getAttribute('data-page')) ? parseInt(tableElement.getAttribute('data-page')) : 1;
329
- var totalRows = tableElement.querySelectorAll('tbody tr').length;
330
- if (show < totalRows) {
331
- paginateRows(show, page);
332
- createPaginationForm(randID, tableElement, show, page, totalRows);
333
- createPaginationButttons(randID, tableElement, show, page, totalRows);
334
- tableElement.addEventListener('change', function (e) {
183
+ // #endregion Sortable
184
+ // #region Filters
185
+ var createFilterForm = function createFilterForm(count) {
186
+ // Create wrapper div
187
+ var form = document.createElement("div");
188
+ form.classList.add('table__filters');
189
+ form.classList.add('row');
190
+ form.classList.add('pt-1');
191
+ form.classList.add('pb-3');
192
+ // Create the filter options array
193
+ var filterColumns = Array.from(tableElement.querySelectorAll('th[data-filterable]'));
194
+ // Populate a list of searchable terms from the cells of the columns that could be used as a filter
195
+ var searchableTerms = {};
196
+ filterColumns.forEach((columnHeading, index) => {
197
+ Array.from(tableElement.querySelectorAll('td[data-label="' + columnHeading.textContent + '"]')).forEach((label, index) => {
198
+ searchableTerms[label.textContent] = label.textContent;
199
+ });
200
+ });
201
+ // Create the form
202
+ var filterTitle = filterColumns.length == 1 ? "Filter by " + filterColumns[0].textContent : "Filter"; // Update title if only one filter is chosen
203
+ var checkboxClass = filterColumns.length == 1 ? "d-none" : "d-sm-flex"; // Hide controls when only one filter is chosen
204
+ form.innerHTML = "<div class=\"col-sm-6 col-md-4 pb-3\">\n <div class=\"form-control__wrapper form-control-inline mb-0\">\n <label for=\"".concat(randID, "_filter\" class=\"form-label\">").concat(filterTitle, ":</label>\n <input type=\"search\" name=\"").concat(randID, "_filter\" id=\"").concat(randID, "_filter\" class=\"form-control form-control-sm\" placeholder=\"\" list=\"").concat(randID, "_list\" />\n </div>\n <datalist id=\"").concat(randID, "_list\">\n ").concat(Object.keys(searchableTerms).map(term => "<option value=\"".concat(term, "\"></option>")).join(""), "\n </datalist>\n</div>\n<div class=\"col-md-8 align-items-center pb-3 ").concat(checkboxClass, "\">\n ").concat("<span class=\"pe-3 text-nowrap h5 mb-0\">Filter by: </span>" + filterColumns.map(column => "<div class=\"form-check pe-3 mt-0 mb-0\"><input class=\"form-check-input\" type=\"checkbox\" id=\"".concat(randID, "_").concat(column.textContent.replace(' ', '_').toLowerCase(), "\" checked=\"checked\" /><label class=\"form-check-label text-nowrap\" for=\"").concat(randID, "_").concat(column.textContent.replace(' ', '_').toLowerCase(), "\">").concat(column.textContent, "</label></div>")).join(""), "\n</div>");
205
+ // Add before the actual table
206
+ tableElement.prepend(form);
207
+ };
208
+ var filterTable = function filterTable(searchTerm) {
209
+ // Create an array of rows that match the search term
210
+ var tableArr = [];
211
+ Array.from(storedData.querySelectorAll('tr')).forEach((tableRow, index) => {
212
+ // We want one long search string per row including each filterable table cell
213
+ var rowSearchString = '';
214
+ Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
215
+ rowSearchString += tableRow.querySelector('td[data-label="' + label.textContent + '"]').textContent + ' | ';
216
+ });
217
+ // Check if the table row search string contains the search term
218
+ if (rowSearchString.indexOf(searchTerm) >= 0) {
219
+ var dataRow = {
220
+ row: tableRow
221
+ };
222
+ tableArr.push(dataRow);
223
+ }
224
+ });
225
+ // Create a string to return and populate the tbody
226
+ var strTbody = '';
227
+ tableArr.forEach((tableRow, index) => {
228
+ strTbody += tableRow.row.outerHTML;
229
+ });
230
+ tbody.innerHTML = strTbody;
231
+ // Dispatch the filter event.
232
+ tableElement.dispatchEvent(filteredEvent);
233
+ };
234
+ var createFilterList = function createFilterList() {
235
+ // Check which options are checked
236
+ var filterOptions = [];
237
+ Array.from(tableElement.querySelectorAll('[type="checkbox"]:checked + label')).forEach((label, index) => {
238
+ filterOptions.push(label.textContent);
239
+ });
240
+ // Build up the list of searchable terms
241
+ var searchableTerms = [];
242
+ filterOptions.forEach((option, index) => {
243
+ Array.from(tableElement.querySelectorAll('td[data-label="' + option + '"]')).forEach((label, index) => {
244
+ searchableTerms[label.textContent] = label.textContent;
245
+ });
246
+ });
247
+ // Rebuild the list
248
+ var dataList = tableElement.querySelector('datalist');
249
+ dataList.innerHTML = Object.keys(searchableTerms).map(term => "<option value=\"".concat(term, "\"></option>")).join("");
250
+ };
251
+ // On page load check if filters are needed
252
+ if (Array.from(tableElement.querySelectorAll('[data-filterable]')).length) {
253
+ // Create the filter options
254
+ createFilterForm(tableElement, Array.from(tableElement.querySelectorAll('[data-filterable]')).length);
255
+ // Add event handlers for the filter options
256
+ tableElement.addEventListener('keyup', function (e) {
335
257
  for (var target = e.target; target && target != this; target = target.parentNode) {
336
- if (target.matches('.table__pagination input[type="number"]')) {
337
- paginateRows(target.value, page);
338
- createPaginationButttons(randID, tableElement, target.value, page, totalRows);
339
- tableElement.setAttribute('data-show', target.value);
258
+ if (target.matches('input[type="search"]')) {
259
+ var searchTerm = target.value;
260
+ filterTable(searchTerm);
340
261
  }
341
262
  }
342
263
  });
343
- tableElement.addEventListener('click', function (e) {
264
+ tableElement.addEventListener('change', function (e) {
344
265
  for (var target = e.target; target && target != this; target = target.parentNode) {
345
- if (target.matches('.page-item:not(.active):not(.disabled) .page-link')) {
346
- paginateRows(tableElement.getAttribute('data-show'), target.getAttribute('data-page'));
347
- createPaginationButttons(randID, tableElement, tableElement.getAttribute('data-show'), target.getAttribute('data-page'), totalRows);
266
+ if (target.matches('input[type="search"]')) {
267
+ var searchTerm = target.value;
268
+ filterTable(searchTerm);
348
269
  }
349
270
  }
350
- }, false);
271
+ });
351
272
  tableElement.addEventListener('change', function (e) {
352
273
  for (var target = e.target; target && target != this; target = target.parentNode) {
353
- if (target.matches('.table__pagination select')) {
354
- paginateRows(tableElement.getAttribute('data-show'), target.value);
355
- createPaginationButttons(randID, tableElement, tableElement.getAttribute('data-show'), target.value, totalRows);
274
+ if (target.matches('input[type="checkbox"]')) {
275
+ var searchTerm = tableElement.querySelector('input[type="search"]').value;
276
+ filterTable(searchTerm);
277
+ createFilterList();
356
278
  }
357
279
  }
358
280
  });
359
281
  }
360
- }
361
- // #endregion Pagination
362
-
363
- // #region Reorderable
364
- // Set the row thats being dragged and copy the row
365
- function setDraggedRow(e) {
366
- e.dataTransfer.setData("text/plain", e.target.id);
367
- draggedRow = e.target;
368
- e.target.classList.add('tr--dragging');
369
- }
370
-
371
- // Create the order column and event handler for rows
372
- var setReorderRows = function setReorderRows() {
373
- Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
374
- // Create column if not already created
375
- if (tableRow.querySelector('[data-label="Order"]') == null) {
376
- var orderColumn = document.createElement('th');
377
- orderColumn.innerHTML = index + 1;
378
- orderColumn.setAttribute('data-label', 'Order');
379
- tableRow.prepend(orderColumn);
282
+ // #endregion Filters
283
+ // #region Pagination
284
+ var paginateRows = function paginateRows(show, page) {
285
+ // Create some inline CSS to control what is viewed on the table, unline the filters we are just hiding the rable rows not removing them from the DOM.
286
+ var style = document.getElementById(randID + '_style');
287
+ if (style == null) {
288
+ style = document.createElement("style");
289
+ style.setAttribute('id', randID + '_style');
380
290
  }
381
-
382
- // Make draggable
383
- tableRow.setAttribute('id', randID + '_row_' + (index + 1));
384
- tableRow.setAttribute('data-order', index + 1);
385
- tableRow.setAttribute('draggable', 'true');
386
- tableRow.addEventListener("dragstart", setDraggedRow);
387
- });
388
- };
389
- if (tableElement.getAttribute('data-reorder') && tableElement.getAttribute('data-reorder') != "false") {
390
- // Add column heading
391
- var orderHeading = document.createElement('th');
392
- orderHeading.innerHTML = 'Order';
393
- orderHeading.title = 'Click here to enable re-ordering via drag and drop';
394
- orderHeading.classList.add('table-order-reset');
395
- thead.querySelector('tr').prepend(orderHeading);
396
- setReorderRows();
397
-
398
- // Reset order button
399
- tableElement.addEventListener('click', function (e) {
400
- for (var target = e.target; target && target != this; target = target.parentNode) {
401
- if (target.matches('.table-order-reset')) {
402
- // unset sort attributes
403
- Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
404
- col.setAttribute('aria-sort', 'none');
405
- });
406
-
407
- // Save the sort options on the table element so that it can be re-sorted later
408
- tableElement.removeAttribute('data-sort');
409
- tableElement.removeAttribute('data-sortBy');
410
-
411
- // Sort the table
412
- sortTable('Order', 'ascending');
413
- Array.from(tableElement.querySelectorAll('tbody tr')).forEach((tableRow, index) => {
414
- tableRow.setAttribute('draggable', 'true');
415
- });
416
- break;
417
- }
418
- }
419
- }, false);
420
- document.addEventListener("dragover", function (e) {
421
- // prevent default to allow drop
422
- e.preventDefault();
423
- }, false);
424
- document.addEventListener("dragenter", function (e) {
425
- // prevent default to allow drop
426
- e.preventDefault();
427
- e.dataTransfer.dropEffect = "move";
428
- for (var target = e.target; target && target != this; target = target.parentNode) {
429
- if (target.matches('[data-reorder] tbody tr')) {
430
- target.classList.add('tr--dropable');
431
- }
291
+ var startShowing = show * (page - 1) + 1;
292
+ var stopShowing = show * page;
293
+ style.innerHTML = "\n #".concat(randID, " tbody tr {\n display: none;\n }\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, "),\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, ") ~ tr{\n display: block;\n }\n @media screen and (min-width: 36em) {\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, "),\n #").concat(randID, " tbody tr:nth-child(").concat(startShowing, ") ~ tr{\n display: table-row;\n }\n }\n #").concat(randID, " tbody tr:nth-child(").concat(stopShowing, ") ~ tr{\n display: none;\n }\n ");
294
+ tableElement.append(style);
295
+ };
296
+ // On page load check if the table should be paginated
297
+ if (tableElement.getAttribute('data-show')) {
298
+ var show = parseInt(tableElement.getAttribute('data-show'));
299
+ var page = parseInt(tableElement.getAttribute('data-page')) ? parseInt(tableElement.getAttribute('data-page')) : 1;
300
+ var totalRows = tableElement.querySelectorAll('tbody tr').length;
301
+ if (show < totalRows) {
302
+ paginateRows(show, page);
303
+ createPaginationForm(randID, tableElement, show, page, totalRows);
304
+ createPaginationButttons(randID, tableElement, show, page, totalRows);
305
+ tableElement.addEventListener('change', function (e) {
306
+ for (var target = e.target; target && target != this; target = target.parentNode) {
307
+ if (target.matches('.table__pagination input[type="number"]')) {
308
+ paginateRows(target.value, page);
309
+ createPaginationButttons(randID, tableElement, target.value, page, totalRows);
310
+ tableElement.setAttribute('data-show', target.value);
311
+ }
312
+ }
313
+ });
314
+ tableElement.addEventListener('click', function (e) {
315
+ for (var target = e.target; target && target != this; target = target.parentNode) {
316
+ if (target.matches('.page-item:not(.active):not(.disabled) .page-link')) {
317
+ paginateRows(tableElement.getAttribute('data-show'), target.getAttribute('data-page'));
318
+ createPaginationButttons(randID, tableElement, tableElement.getAttribute('data-show'), target.getAttribute('data-page'), totalRows);
319
+ }
320
+ }
321
+ }, false);
322
+ tableElement.addEventListener('change', function (e) {
323
+ for (var target = e.target; target && target != this; target = target.parentNode) {
324
+ if (target.matches('.table__pagination select')) {
325
+ paginateRows(tableElement.getAttribute('data-show'), target.value);
326
+ createPaginationButttons(randID, tableElement, tableElement.getAttribute('data-show'), target.value, totalRows);
327
+ }
328
+ }
329
+ });
432
330
  }
433
- }, false);
434
- document.addEventListener("dragleave", function (e) {
435
- // prevent default to allow drop
436
- e.preventDefault();
437
- for (var target = e.target; target && target != this; target = target.parentNode) {
438
- if (target.matches('[data-reorder] tbody tr')) {
439
- target.classList.remove('tr--dropable');
331
+ }
332
+ // #endregion Pagination
333
+ // #region Reorderable
334
+ // Set the row thats being dragged and copy the row
335
+ function setDraggedRow(e) {
336
+ e.dataTransfer.setData("text/plain", e.target.id);
337
+ draggedRow = e.target;
338
+ e.target.classList.add('tr--dragging');
339
+ }
340
+ // Create the order column and event handler for rows
341
+ var setReorderRows = function setReorderRows() {
342
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRow, index) => {
343
+ // Create column if not already created
344
+ if (tableRow.querySelector('[data-label="Order"]') == null) {
345
+ var orderColumn = document.createElement('th');
346
+ orderColumn.innerHTML = index + 1;
347
+ orderColumn.setAttribute('data-label', 'Order');
348
+ tableRow.prepend(orderColumn);
440
349
  }
441
- }
442
- }, false);
443
- document.addEventListener("drop", function (e) {
444
- e.preventDefault();
445
- for (var target = e.target; target && target != this; target = target.parentNode) {
446
- if (target.matches('[data-reorder] tbody tr')) {
447
- if (target.parentNode != null && draggedRow.parentNode != null && target != draggedRow) {
448
- draggedRow.parentNode.removeChild(draggedRow);
449
- if (draggedRow.getAttribute('data-order') > target.getAttribute('data-order')) target.parentNode.insertBefore(draggedRow, target);else target.parentNode.insertBefore(draggedRow, target.nextElementSibling);
450
-
451
- // Re label the rows
452
- Array.from(tbody.querySelectorAll('tr')).forEach((tableRowOrder, index) => {
453
- tableRowOrder.classList.remove('tr--dragging');
454
- tableRowOrder.classList.remove('tr--dropable');
455
- tableRowOrder.querySelector('th').innerHTML = index + 1;
456
- tableRowOrder.setAttribute('data-order', index + 1);
350
+ // Make draggable
351
+ tableRow.setAttribute('id', randID + '_row_' + (index + 1));
352
+ tableRow.setAttribute('data-order', index + 1);
353
+ tableRow.setAttribute('draggable', 'true');
354
+ tableRow.addEventListener("dragstart", setDraggedRow);
355
+ });
356
+ };
357
+ if (tableElement.getAttribute('data-reorder') && tableElement.getAttribute('data-reorder') != "false") {
358
+ // Add column heading
359
+ var orderHeading = document.createElement('th');
360
+ orderHeading.innerHTML = 'Order';
361
+ orderHeading.title = 'Click here to enable re-ordering via drag and drop';
362
+ orderHeading.classList.add('table-order-reset');
363
+ thead.querySelector('tr').prepend(orderHeading);
364
+ setReorderRows();
365
+ // Reset order button
366
+ tableElement.addEventListener('click', function (e) {
367
+ for (var target = e.target; target && target != this; target = target.parentNode) {
368
+ if (target.matches('.table-order-reset')) {
369
+ // unset sort attributes
370
+ Array.from(tableElement.querySelectorAll('[data-sortable]')).forEach((col, index) => {
371
+ col.setAttribute('aria-sort', 'none');
372
+ });
373
+ // Save the sort options on the table element so that it can be re-sorted later
374
+ tableElement.removeAttribute('data-sort');
375
+ tableElement.removeAttribute('data-sortBy');
376
+ // Sort the table
377
+ sortTable('Order', 'ascending');
378
+ Array.from(tableElement.querySelectorAll('tbody tr')).forEach((tableRow, index) => {
379
+ tableRow.setAttribute('draggable', 'true');
457
380
  });
458
- tableElement.dispatchEvent(reorderedEvent);
381
+ break;
382
+ }
383
+ }
384
+ }, false);
385
+ document.addEventListener("dragover", function (e) {
386
+ // prevent default to allow drop
387
+ e.preventDefault();
388
+ }, false);
389
+ document.addEventListener("dragenter", function (e) {
390
+ // prevent default to allow drop
391
+ e.preventDefault();
392
+ e.dataTransfer.dropEffect = "move";
393
+ for (var target = e.target; target && target != this; target = target.parentNode) {
394
+ if (target.matches('[data-reorder] tbody tr')) {
395
+ target.classList.add('tr--dropable');
459
396
  }
460
- break;
461
397
  }
398
+ }, false);
399
+ document.addEventListener("dragleave", function (e) {
400
+ // prevent default to allow drop
401
+ e.preventDefault();
402
+ for (var target = e.target; target && target != this; target = target.parentNode) {
403
+ if (target.matches('[data-reorder] tbody tr')) {
404
+ target.classList.remove('tr--dropable');
405
+ }
406
+ }
407
+ }, false);
408
+ document.addEventListener("drop", function (e) {
409
+ e.preventDefault();
410
+ for (var target = e.target; target && target != this; target = target.parentNode) {
411
+ if (target.matches('[data-reorder] tbody tr')) {
412
+ if (target.parentNode != null && draggedRow.parentNode != null && target != draggedRow) {
413
+ draggedRow.parentNode.removeChild(draggedRow);
414
+ if (draggedRow.getAttribute('data-order') > target.getAttribute('data-order')) target.parentNode.insertBefore(draggedRow, target);else target.parentNode.insertBefore(draggedRow, target.nextElementSibling);
415
+ // Re label the rows
416
+ Array.from(tbody.querySelectorAll('tr')).forEach((tableRowOrder, index) => {
417
+ tableRowOrder.classList.remove('tr--dragging');
418
+ tableRowOrder.classList.remove('tr--dropable');
419
+ tableRowOrder.querySelector('th').innerHTML = index + 1;
420
+ tableRowOrder.setAttribute('data-order', index + 1);
421
+ });
422
+ tableElement.dispatchEvent(reorderedEvent);
423
+ }
424
+ break;
425
+ }
426
+ }
427
+ }, false);
428
+ }
429
+ // #endregion Reorderable
430
+ // Watch for the filterable event and re-sort the tbody
431
+ tableElement.addEventListener('filtered', function (e) {
432
+ if (tableElement.getAttribute('data-sortBy') && tableElement.getAttribute('data-sort')) sortTable(tableElement.getAttribute('data-sortBy'), tableElement.getAttribute('data-sort'));
433
+ if (tableElement.getAttribute('data-show')) {
434
+ var _show = parseInt(tableElement.getAttribute('data-show'));
435
+ var _totalRows = tableElement.querySelectorAll('tbody tr').length;
436
+ var tablePagination = tableElement.querySelector('.table__pagination');
437
+ if (tablePagination != null) tablePagination.remove();
438
+ if (_show < _totalRows) {
439
+ paginateRows(_show, 1);
440
+ createPaginationForm(randID, tableElement, _show, 1, _totalRows);
441
+ createPaginationButttons(randID, tableElement, _show, 1, _totalRows);
442
+ }
443
+ }
444
+ if (tableElement.getAttribute('data-reorder')) {
445
+ setReorderRows();
462
446
  }
463
447
  }, false);
464
- }
465
- // #endregion Reorderable
466
-
467
- // Watch for the filterable event and re-sort the tbody
468
- tableElement.addEventListener('filtered', function (e) {
469
- if (tableElement.getAttribute('data-sortBy') && tableElement.getAttribute('data-sort')) sortTable(tableElement.getAttribute('data-sortBy'), tableElement.getAttribute('data-sort'));
470
- if (tableElement.getAttribute('data-show')) {
471
- var _show = parseInt(tableElement.getAttribute('data-show'));
472
- var _totalRows = tableElement.querySelectorAll('tbody tr').length;
448
+ tableElement.addEventListener('sorted', function (e) {
449
+ if (tableElement.getAttribute('data-reorder')) {
450
+ setReorderRows();
451
+ }
452
+ }, false);
453
+ tableElement.addEventListener('populated', function (e) {
454
+ var tableFilter = tableElement.querySelector('.table__filters');
455
+ tableFilter.remove();
473
456
  var tablePagination = tableElement.querySelector('.table__pagination');
474
- if (tablePagination != null) tablePagination.remove();
475
- if (_show < _totalRows) {
476
- paginateRows(_show, 1);
477
- createPaginationForm(randID, tableElement, _show, 1, _totalRows);
478
- createPaginationButttons(randID, tableElement, _show, 1, _totalRows);
457
+ tablePagination.remove();
458
+ var newTable = tableElement.cloneNode(true);
459
+ tableElement.parentNode.replaceChild(newTable, tableElement);
460
+ table(newTable);
461
+ }, false);
462
+ }
463
+ var createPaginationForm = function createPaginationForm(randID, tableElement, show, page, totalRows) {
464
+ var form = document.createElement("div");
465
+ form.classList.add('table__pagination');
466
+ form.classList.add('row');
467
+ form.classList.add('pt-3');
468
+ form.classList.add('pb-3');
469
+ // Create the form and create a container div to hold the pagination buttons
470
+ form.innerHTML = "<div class=\"col mw-fit-content mb-3\">\n<div class=\"form-control__wrapper form-control-inline mb-0\">\n <label for=\"".concat(randID, "_showing\" class=\"form-label\">Showing:</label>\n <input type=\"number\" name=\"").concat(randID, "_showing\" id=\"").concat(randID, "_showing\" class=\"form-control form-control-sm showing-input-field\" placeholder=\"\" list=\"").concat(randID, "_pagination\" value=\"").concat(show, "\" min=\"1\" max=\"").concat(totalRows, "\" />\n</div>\n<datalist id=\"").concat(randID, "_pagination\">\n<option value=\"5\">5</option>\n").concat(totalRows > 10 ? "<option value=\"10\">10</option>" : '', "\n").concat(totalRows > 20 ? "<option value=\"20\">20</option>" : '', "\n<option value=\"").concat(totalRows, "\">").concat(totalRows, "</option>\n</datalist>\n</div>\n<div class=\"col mw-fit-content me-auto d-flex align-items-center mb-3\"><span class=\"label\">per page</span></div>\n<div class=\"col mw-fit-content d-sm-flex justify-content-end align-items-center\" id=\"").concat(randID, "_paginationBtns\"></div>");
471
+ // Add after the actual table
472
+ tableElement.append(form);
473
+ };
474
+ var createPaginationButttons = function createPaginationButttons(randID, tableElement, show, page, totalRows) {
475
+ var paginationButtonsWrapper = document.getElementById(randID + '_paginationBtns');
476
+ if (paginationButtonsWrapper == null) return false;
477
+ var numberPages = Math.ceil(totalRows / show);
478
+ if (numberPages == 1) {
479
+ // Remore the buttons or dont display any if we dont need them
480
+ paginationButtonsWrapper.innerHTML = '';
481
+ } else if (numberPages < 5) {
482
+ // If less than 5 pages (which fits comfortably on mobile) we display buttons
483
+ var strButtons = '';
484
+ for (var i = 1; i <= numberPages; i++) {
485
+ if (i == page) strButtons += "<li class=\"page-item active\" aria-current=\"page\"><span class=\"page-link\">".concat(i, "</span></li>");else strButtons += "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(i, "\">").concat(i, "</button></li>");
479
486
  }
487
+ paginationButtonsWrapper.innerHTML = "<span class=\"pe-2 mb-3\">Page: </span><ul class=\"pagination mb-3\">\n ".concat(page == 1 ? "<li class=\"page-item disabled\"><span class=\"page-link\">Previous</span></li>" : "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(parseInt(page) - 1, "\">Previous</button></li>"), "\n ").concat(strButtons, "\n ").concat(page == numberPages ? "<li class=\"page-item disabled\"><span class=\"page-link\">Next</span></li>" : "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(parseInt(page) + 1, "\">Next</button></li>"), "\n </ul>");
488
+ } else {
489
+ // If more than 5 lets show a select field instead so that we dont have loads and loads of buttons
490
+ var strOptions = '';
491
+ for (var _i = 1; _i <= numberPages; _i++) {
492
+ if (_i == page) strOptions += "<option value=\"".concat(_i, "\" selected>Page ").concat(_i, "</option>");else strOptions += "<option value=\"".concat(_i, "\">Page ").concat(_i, "</option>");
493
+ }
494
+ paginationButtonsWrapper.innerHTML = "\n<div class=\"form-control__wrapper page-number mb-2\">\n<select class=\"form-select\">\n".concat(strOptions, "\n</select>\n</div>\n ");
480
495
  }
481
- if (tableElement.getAttribute('data-reorder')) {
482
- setReorderRows();
483
- }
484
- }, false);
485
- tableElement.addEventListener('sorted', function (e) {
486
- if (tableElement.getAttribute('data-reorder')) {
487
- setReorderRows();
488
- }
489
- }, false);
490
- tableElement.addEventListener('populated', function (e) {
491
- var tableFilter = tableElement.querySelector('.table__filters');
492
- tableFilter.remove();
493
- var tablePagination = tableElement.querySelector('.table__pagination');
494
- tablePagination.remove();
495
- var newTable = tableElement.cloneNode(true);
496
- tableElement.parentNode.replaceChild(newTable, tableElement);
497
- table(newTable);
498
- }, false);
499
- }
500
- var createPaginationForm = function createPaginationForm(randID, tableElement, show, page, totalRows) {
501
- var form = document.createElement("div");
502
- form.classList.add('table__pagination');
503
- form.classList.add('row');
504
- form.classList.add('pt-3');
505
- form.classList.add('pb-3');
506
-
507
- // Create the form and create a container div to hold the pagination buttons
508
- form.innerHTML = "<div class=\"col mw-fit-content mb-3\">\n<div class=\"form-control__wrapper form-control-inline mb-0\">\n <label for=\"".concat(randID, "_showing\" class=\"form-label\">Showing:</label>\n <input type=\"number\" name=\"").concat(randID, "_showing\" id=\"").concat(randID, "_showing\" class=\"form-control form-control-sm showing-input-field\" placeholder=\"\" list=\"").concat(randID, "_pagination\" value=\"").concat(show, "\" min=\"1\" max=\"").concat(totalRows, "\" />\n</div>\n<datalist id=\"").concat(randID, "_pagination\">\n<option value=\"5\">5</option>\n").concat(totalRows > 10 ? "<option value=\"10\">10</option>" : '', "\n").concat(totalRows > 20 ? "<option value=\"20\">20</option>" : '', "\n<option value=\"").concat(totalRows, "\">").concat(totalRows, "</option>\n</datalist>\n</div>\n<div class=\"col mw-fit-content me-auto d-flex align-items-center mb-3\"><span class=\"label\">per page</span></div>\n<div class=\"col mw-fit-content d-sm-flex justify-content-end align-items-center\" id=\"").concat(randID, "_paginationBtns\"></div>");
509
-
510
- // Add after the actual table
511
- tableElement.append(form);
512
- };
513
- var createPaginationButttons = function createPaginationButttons(randID, tableElement, show, page, totalRows) {
514
- var paginationButtonsWrapper = document.getElementById(randID + '_paginationBtns');
515
- if (paginationButtonsWrapper == null) return false;
516
- var numberPages = Math.ceil(totalRows / show);
517
- if (numberPages == 1) {
518
- // Remore the buttons or dont display any if we dont need them
519
- paginationButtonsWrapper.innerHTML = '';
520
- } else if (numberPages < 5) {
521
- // If less than 5 pages (which fits comfortably on mobile) we display buttons
522
-
523
- var strButtons = '';
524
- for (var i = 1; i <= numberPages; i++) {
525
- if (i == page) strButtons += "<li class=\"page-item active\" aria-current=\"page\"><span class=\"page-link\">".concat(i, "</span></li>");else strButtons += "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(i, "\">").concat(i, "</button></li>");
526
- }
527
- paginationButtonsWrapper.innerHTML = "<span class=\"pe-2 mb-3\">Page: </span><ul class=\"pagination mb-3\">\n ".concat(page == 1 ? "<li class=\"page-item disabled\"><span class=\"page-link\">Previous</span></li>" : "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(parseInt(page) - 1, "\">Previous</button></li>"), "\n ").concat(strButtons, "\n ").concat(page == numberPages ? "<li class=\"page-item disabled\"><span class=\"page-link\">Next</span></li>" : "<li class=\"page-item\"><button class=\"page-link\" data-page=\"".concat(parseInt(page) + 1, "\">Next</button></li>"), "\n </ul>");
528
- } else {
529
- // If more than 5 lets show a select field instead so that we dont have loads and loads of buttons
530
-
531
- var strOptions = '';
532
- for (var _i = 1; _i <= numberPages; _i++) {
533
- if (_i == page) strOptions += "<option value=\"".concat(_i, "\" selected>Page ").concat(_i, "</option>");else strOptions += "<option value=\"".concat(_i, "\">Page ").concat(_i, "</option>");
534
- }
535
- paginationButtonsWrapper.innerHTML = "\n<div class=\"form-control__wrapper page-number mb-2\">\n<select class=\"form-select\">\n".concat(strOptions, "\n</select>\n</div>\n ");
536
- }
537
- };
496
+ };
538
497
 
539
- function accordion(accordionElement) {
540
- // Fetch all the details element.
541
- if (!accordionElement.classList.contains('accordion--keep-open')) {
542
- var details = accordionElement.querySelectorAll(":scope > details");
543
- // Add the onclick listeners.
544
- details.forEach(targetDetail => {
545
- targetDetail.addEventListener("click", () => {
546
- // Close all the details that are not targetDetail.
547
- details.forEach(detail => {
548
- if (detail !== targetDetail) {
549
- detail.removeAttribute("open");
550
- }
498
+ // @ts-nocheck
499
+ function accordion(accordionElement) {
500
+ // Fetch all the details element.
501
+ if (!accordionElement.classList.contains('accordion--keep-open')) {
502
+ var details = accordionElement.querySelectorAll(":scope > details");
503
+ // Add the onclick listeners.
504
+ details.forEach(targetDetail => {
505
+ targetDetail.addEventListener("click", () => {
506
+ // Close all the details that are not targetDetail.
507
+ details.forEach(detail => {
508
+ if (detail !== targetDetail) {
509
+ detail.removeAttribute("open");
510
+ }
511
+ });
551
512
  });
552
513
  });
553
- });
554
- }
555
- if (window.location.hash && document.querySelector(window.location.hash + ':not([open]) summary')) {
556
- var detail = document.querySelector(window.location.hash + ' summary');
557
- if (detail instanceof HTMLElement) {
558
- detail.click();
559
514
  }
560
- }
561
- window.addEventListener('hashchange', function () {
562
- if (window.location.hash && document.querySelector(window.location.hash + ' summary')) {
563
- var _detail = document.querySelector(window.location.hash + ' summary');
564
- if (_detail instanceof HTMLElement) {
565
- _detail.click();
515
+ if (window.location.hash && document.querySelector(window.location.hash + ':not([open]) summary')) {
516
+ var detail = document.querySelector(window.location.hash + ' summary');
517
+ if (detail instanceof HTMLElement) {
518
+ detail.click();
566
519
  }
567
520
  }
568
- });
569
- }
570
-
571
- function testimonial(testimonialElement) {
572
- var scrollTimeout;
573
- var imagesCarousel = testimonialElement.querySelector('.testimonial__images');
574
- var itemCount = imagesCarousel.querySelectorAll('img').length;
575
-
576
- // If we only have 1 item lets not bother doing anything else
577
- if (itemCount == 1) {
578
- return false;
521
+ window.addEventListener('hashchange', function () {
522
+ if (window.location.hash && document.querySelector(window.location.hash + ' summary')) {
523
+ var _detail = document.querySelector(window.location.hash + ' summary');
524
+ if (_detail instanceof HTMLElement) {
525
+ _detail.click();
526
+ }
527
+ }
528
+ });
579
529
  }
580
- testimonialElement.classList.add('testimonial--multi');
581
-
582
- // Set where the buttons go to
583
- var setButtons = function setButtons(scrollTo) {
584
- var nextButton = testimonialElement.querySelector('.btn-next');
585
- var prevButton = testimonialElement.querySelector('.btn-prev');
586
- nextButton.setAttribute('data-go', scrollTo + 1);
587
- prevButton.setAttribute('data-go', scrollTo - 1);
588
- nextButton.removeAttribute('disabled');
589
- prevButton.removeAttribute('disabled');
590
- if (scrollTo == 1) prevButton.setAttribute('disabled', true);else if (scrollTo == itemCount) nextButton.setAttribute('disabled', true);
591
- };
592
530
 
593
- // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
594
- imagesCarousel.addEventListener('scroll', function (e) {
595
- clearTimeout(scrollTimeout);
596
- scrollTimeout = setTimeout(function () {
597
- var scrollWidth = imagesCarousel.scrollWidth;
598
- var scrollHeight = imagesCarousel.scrollHeight;
599
- var scrollLeft = imagesCarousel.scrollLeft;
600
- var scrollDown = imagesCarousel.scrollTop;
601
- var scrollTo = Math.round(scrollLeft / scrollWidth * itemCount) + 1;
602
-
603
- // Change in scroll direction
604
- if (scrollLeft == 0 && scrollDown != 0) scrollTo = Math.round(scrollDown / scrollHeight * itemCount) + 1;
605
- testimonialElement.setAttribute('data-show', scrollTo);
606
- setButtons(scrollTo);
607
- }, 300);
608
- }, false);
609
-
610
- // when the buttons are used we need to make sure the carousel scrolls to the correct place
611
- testimonialElement.addEventListener('click', function (e) {
612
- for (var target = e.target; target && target != this; target = target.parentNode) {
613
- if (target.matches('[data-go]')) {
614
- var scrollTo = parseInt(target.getAttribute('data-go'));
615
- var scrollDown = 0;
616
- var scrollLeft = 0;
531
+ // @ts-nocheck
532
+ function testimonial(testimonialElement) {
533
+ var scrollTimeout;
534
+ var imagesCarousel = testimonialElement.querySelector('.testimonial__images');
535
+ var itemCount = imagesCarousel.querySelectorAll('img').length;
536
+ // If we only have 1 item lets not bother doing anything else
537
+ if (itemCount == 1) {
538
+ return false;
539
+ }
540
+ testimonialElement.classList.add('testimonial--multi');
541
+ // Set where the buttons go to
542
+ var setButtons = function setButtons(scrollTo) {
543
+ var nextButton = testimonialElement.querySelector('.btn-next');
544
+ var prevButton = testimonialElement.querySelector('.btn-prev');
545
+ nextButton.setAttribute('data-go', scrollTo + 1);
546
+ prevButton.setAttribute('data-go', scrollTo - 1);
547
+ nextButton.removeAttribute('disabled');
548
+ prevButton.removeAttribute('disabled');
549
+ if (scrollTo == 1) prevButton.setAttribute('disabled', true);else if (scrollTo == itemCount) nextButton.setAttribute('disabled', true);
550
+ };
551
+ // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
552
+ imagesCarousel.addEventListener('scroll', function (e) {
553
+ clearTimeout(scrollTimeout);
554
+ scrollTimeout = setTimeout(function () {
617
555
  var scrollWidth = imagesCarousel.scrollWidth;
618
556
  var scrollHeight = imagesCarousel.scrollHeight;
619
- if (scrollWidth > scrollHeight) scrollLeft = Math.floor(scrollWidth * ((scrollTo - 1) / itemCount));else scrollDown = Math.floor(scrollHeight * ((scrollTo - 1) / itemCount));
620
-
621
- // Trigger the scroll
622
- imagesCarousel.scroll({
623
- top: scrollDown,
624
- left: scrollLeft,
625
- behavior: 'smooth'
626
- });
627
- break;
557
+ var scrollLeft = imagesCarousel.scrollLeft;
558
+ var scrollDown = imagesCarousel.scrollTop;
559
+ var scrollTo = Math.round(scrollLeft / scrollWidth * itemCount) + 1;
560
+ // Change in scroll direction
561
+ if (scrollLeft == 0 && scrollDown != 0) scrollTo = Math.round(scrollDown / scrollHeight * itemCount) + 1;
562
+ testimonialElement.setAttribute('data-show', scrollTo);
563
+ setButtons(scrollTo);
564
+ }, 300);
565
+ }, false);
566
+ // when the buttons are used we need to make sure the carousel scrolls to the correct place
567
+ testimonialElement.addEventListener('click', function (e) {
568
+ for (var target = e.target; target && target != this; target = target.parentNode) {
569
+ if (target.matches('[data-go]')) {
570
+ var scrollTo = parseInt(target.getAttribute('data-go'));
571
+ var scrollDown = 0;
572
+ var scrollLeft = 0;
573
+ var scrollWidth = imagesCarousel.scrollWidth;
574
+ var scrollHeight = imagesCarousel.scrollHeight;
575
+ if (scrollWidth > scrollHeight) scrollLeft = Math.floor(scrollWidth * ((scrollTo - 1) / itemCount));else scrollDown = Math.floor(scrollHeight * ((scrollTo - 1) / itemCount));
576
+ // Trigger the scroll
577
+ imagesCarousel.scroll({
578
+ top: scrollDown,
579
+ left: scrollLeft,
580
+ behavior: 'smooth'
581
+ });
582
+ break;
583
+ }
628
584
  }
629
- }
630
- }, false);
631
- }
632
-
633
- function carousel(carouselElement) {
634
- var scrollTimeout;
635
- var carouselInner = carouselElement.querySelector('.carousel__inner');
636
- var itemCount = carouselElement.querySelectorAll('.carousel__item').length;
637
- carouselElement.getAttribute('data-cols');
638
- var smCols = carouselElement.getAttribute('data-sm-cols');
639
- var mdCols = carouselElement.getAttribute('data-md-cols');
640
- carouselElement.querySelector('.carousel__controls a').classList.add('active');
641
-
642
- // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
643
- carouselInner.addEventListener('scroll', function (e) {
644
- clearTimeout(scrollTimeout);
645
- scrollTimeout = setTimeout(function () {
646
- var scrollArea = carouselInner.clientWidth;
647
- var scrollWidth = carouselInner.scrollWidth;
648
- var scrollLeft = carouselInner.scrollLeft;
649
- var targetSlide = Math.round(scrollLeft / scrollWidth * itemCount) + 1;
650
- var lastItemOffset = carouselElement.querySelector('.carousel__item:last-child').offsetLeft;
651
- Array.from(carouselElement.querySelectorAll('.carousel__controls a')).forEach((link, index) => {
652
- link.classList.remove('active');
653
- });
654
- carouselElement.querySelector('.control-' + targetSlide).classList.add('active');
655
-
656
- // Disable the previous button
657
- if (targetSlide == 1) carouselElement.querySelector('.btn-prev').setAttribute('disabled', 'disabled');else carouselElement.querySelector('.btn-prev').removeAttribute('disabled');
658
-
659
- // Disable the next button if the last item is in view
660
- if (carouselInner.scrollLeft + scrollArea > lastItemOffset) carouselElement.querySelector('.btn-next').setAttribute('disabled', 'disabled');else carouselElement.querySelector('.btn-next').removeAttribute('disabled');
661
- }, 100);
662
- }, false);
585
+ }, false);
586
+ }
663
587
 
664
- // when the buttons are used we need to make sure the carousel scrolls to the correct place
665
- carouselElement.addEventListener('click', function (e) {
666
- for (var target = e.target; target && target != this; target = target.parentNode) {
667
- if (target.matches('.carousel__controls a')) {
668
- e.preventDefault();
588
+ // @ts-nocheck
589
+ function carousel(carouselElement) {
590
+ var scrollTimeout;
591
+ var carouselInner = carouselElement.querySelector('.carousel__inner');
592
+ var itemCount = carouselElement.querySelectorAll('.carousel__item').length;
593
+ carouselElement.getAttribute('data-cols');
594
+ var smCols = carouselElement.getAttribute('data-sm-cols');
595
+ var mdCols = carouselElement.getAttribute('data-md-cols');
596
+ carouselElement.querySelector('.carousel__controls a').classList.add('active');
597
+ // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
598
+ carouselInner.addEventListener('scroll', function (e) {
599
+ clearTimeout(scrollTimeout);
600
+ scrollTimeout = setTimeout(function () {
601
+ var scrollArea = carouselInner.clientWidth;
602
+ var scrollWidth = carouselInner.scrollWidth;
603
+ var scrollLeft = carouselInner.scrollLeft;
604
+ var targetSlide = Math.round(scrollLeft / scrollWidth * itemCount) + 1;
605
+ var lastItemOffset = carouselElement.querySelector('.carousel__item:last-child').offsetLeft;
669
606
  Array.from(carouselElement.querySelectorAll('.carousel__controls a')).forEach((link, index) => {
670
607
  link.classList.remove('active');
671
608
  });
672
- target.classList.add('active');
673
- var el = document.querySelector(target.getAttribute('href'));
674
- carouselInner.scroll({
675
- top: 0,
676
- left: el.offsetLeft,
677
- behavior: 'smooth'
678
- });
679
- break;
680
- }
681
- }
682
- }, false);
683
- carouselElement.addEventListener('click', function (e) {
684
- for (var target = e.target; target && target != this; target = target.parentNode) {
685
- if (target.matches('.btn-next, .btn-prev')) {
686
- e.preventDefault();
687
- var scrollTo = target.classList.contains('btn-prev') ? carouselInner.scrollLeft - carouselInner.clientWidth : carouselInner.scrollLeft + carouselInner.clientWidth;
688
- carouselInner.scroll({
689
- top: 0,
690
- left: scrollTo,
691
- behavior: 'smooth'
692
- });
693
- break;
694
- }
695
- }
696
- }, false);
697
-
698
- // Add responsive hide button classes
699
- if (itemCount == 1) carouselElement.classList.add('hide-btns');
700
- if (smCols >= itemCount) carouselElement.classList.add('hide-sm-btns');
701
- if (mdCols >= itemCount) carouselElement.classList.add('hide-md-btns');
702
- }
703
-
704
- // Create a link between two input/selects with one acting as setting a minimum value and the second a maximum
705
- // The link between the two will prevent the max input field form setting a lower value than the min and vice versa
706
- function inputRange(inputWrapper) {
707
- inputWrapper.addEventListener('change', function (e) {
708
- var min = parseInt(inputWrapper.querySelector('[data-min] select,[data-min] input').value);
709
- var max = parseInt(inputWrapper.querySelector('[data-max] select,[data-max] input').value);
710
-
711
- // Set attributes for input fields
712
- Array.from(inputWrapper.querySelectorAll('[data-min] input')).forEach((input, index) => {
713
- input.setAttribute('max', max);
714
- });
715
- Array.from(inputWrapper.querySelectorAll('[data-max] input')).forEach((input, index) => {
716
- input.setAttribute('min', min);
717
- });
718
-
719
- // Hide select options if they are higher or lower than the min and max values
720
- Array.from(inputWrapper.querySelectorAll('[data-min] select option')).forEach((option, index) => {
721
- if (parseInt(option.getAttribute('value')) > max) option.classList.add('d-none');else option.classList.remove('d-none');
722
- });
723
- Array.from(inputWrapper.querySelectorAll('[data-max] select option')).forEach((option, index) => {
724
- if (parseInt(option.getAttribute('value')) < min) option.classList.add('d-none');else option.classList.remove('d-none');
725
- });
726
- }, false);
727
- }
728
- function inputRedirect(inputWrapper) {
729
- inputWrapper.addEventListener('change', function (e) {
730
- if (inputWrapper.matches('[data-value-if]')) {
731
- var url = inputWrapper.getAttribute('data-redirect');
732
- var desiredValue = inputWrapper.getAttribute('data-value-if');
733
- if (inputWrapper.value == desiredValue) document.location.href = url;
734
- } else {
735
- if (typeof inputWrapper.value != "undefined") document.location.href = inputWrapper.value;
736
- }
737
- }, false);
738
- }
739
-
740
- //
741
- function multipleFileUploads(wrapper) {
742
- var fileTenplate = wrapper.querySelector('.row');
743
- var clone = fileTenplate.cloneNode(true);
744
- var addButton = wrapper.querySelector('[data-add]');
745
- wrapper.addEventListener('click', function (e) {
746
- for (var target = e.target; target && target != this; target = target.parentNode) {
747
- if (target.matches('[data-add]')) {
748
- // Add a new row upload file input fields
749
-
750
- var tempClone = clone.cloneNode(true);
751
- wrapper.insertBefore(tempClone, target);
752
- if (addButton.matches('[data-maxfiles]') && Array.from(wrapper.querySelectorAll(':scope > .row')).length >= addButton.dataset.maxfiles) addButton.setAttribute('disabled', 'disabled');
753
- break;
754
- }
755
- if (target.matches('[data-delete]')) {
756
- // Delete the current row
757
-
758
- var row = target.closest('.row');
759
- row.remove();
760
- if (addButton.matches('[data-maxfiles]') && Array.from(wrapper.querySelectorAll(':scope > .row')).length < addButton.dataset.maxfiles) addButton.removeAttribute('disabled');
761
- break;
609
+ carouselElement.querySelector('.control-' + targetSlide).classList.add('active');
610
+ // Disable the previous button
611
+ if (targetSlide == 1) carouselElement.querySelector('.btn-prev').setAttribute('disabled', 'disabled');else carouselElement.querySelector('.btn-prev').removeAttribute('disabled');
612
+ // Disable the next button if the last item is in view
613
+ if (carouselInner.scrollLeft + scrollArea > lastItemOffset) carouselElement.querySelector('.btn-next').setAttribute('disabled', 'disabled');else carouselElement.querySelector('.btn-next').removeAttribute('disabled');
614
+ }, 100);
615
+ }, false);
616
+ // when the buttons are used we need to make sure the carousel scrolls to the correct place
617
+ carouselElement.addEventListener('click', function (e) {
618
+ for (var target = e.target; target && target != this; target = target.parentNode) {
619
+ if (target.matches('.carousel__controls a')) {
620
+ e.preventDefault();
621
+ Array.from(carouselElement.querySelectorAll('.carousel__controls a')).forEach((link, index) => {
622
+ link.classList.remove('active');
623
+ });
624
+ target.classList.add('active');
625
+ var el = document.querySelector(target.getAttribute('href'));
626
+ carouselInner.scroll({
627
+ top: 0,
628
+ left: el.offsetLeft,
629
+ behavior: 'smooth'
630
+ });
631
+ break;
632
+ }
762
633
  }
763
- }
764
- }, false);
765
- }
766
-
767
- // Acts as an overall initialise function to trigger other functions.
768
- function form(formElement) {
769
- // Check for input range groups
770
- Array.from(formElement.querySelectorAll('[data-input-range]')).forEach((arrayElement, index) => {
771
- inputRange(arrayElement);
772
- });
773
- Array.from(formElement.querySelectorAll('[data-redirect]')).forEach((arrayElement, index) => {
774
- inputRedirect(arrayElement);
775
- });
776
- Array.from(formElement.querySelectorAll('.multiple-file-uploads')).forEach((arrayElement, index) => {
777
- multipleFileUploads(arrayElement);
778
- });
779
-
780
- // Check the file size of a file when uploaded in case it exceeds the max file size set
781
- formElement.addEventListener('change', function (e) {
782
- for (var target = e.target; target && target != this; target = target.parentNode) {
783
- if (target.matches('[type="file"][data-filesize]') && target.files && target.files[0]) {
784
- var maxAllowedSize = target.dataset.filesize;
785
- if (target.files[0].size > maxAllowedSize) {
786
- target.value = '';
787
- alert('File too large');
634
+ }, false);
635
+ carouselElement.addEventListener('click', function (e) {
636
+ for (var target = e.target; target && target != this; target = target.parentNode) {
637
+ if (target.matches('.btn-next, .btn-prev')) {
638
+ e.preventDefault();
639
+ var scrollTo = target.classList.contains('btn-prev') ? carouselInner.scrollLeft - carouselInner.clientWidth : carouselInner.scrollLeft + carouselInner.clientWidth;
640
+ carouselInner.scroll({
641
+ top: 0,
642
+ left: scrollTo,
643
+ behavior: 'smooth'
644
+ });
645
+ break;
788
646
  }
789
- break;
790
647
  }
791
- }
792
- }, false);
648
+ }, false);
649
+ // Add responsive hide button classes
650
+ if (itemCount == 1) carouselElement.classList.add('hide-btns');
651
+ if (smCols >= itemCount) carouselElement.classList.add('hide-sm-btns');
652
+ if (mdCols >= itemCount) carouselElement.classList.add('hide-md-btns');
653
+ }
793
654
 
794
- // When a form is updated we may want to update some of the existing input fields; setting active fields when some data is selected.
795
- formElement.addEventListener('change', function (e) {
796
- // Remove disabled attribute when a pre-selected input field equals a certain value
797
- Array.from(formElement.querySelectorAll('select[data-activeif][data-equals],input[data-activeif][data-equals]')).forEach((arrayElement, index) => {
798
- var group = arrayElement.closest('[data-group]') ? arrayElement.closest('[data-group]') : formElement;
799
- var selector = arrayElement.dataset.activeif;
800
- var value = arrayElement.dataset.equals;
801
- var testElement = group.querySelector("select[data-id=\"".concat(selector, "\"],input[data-id=\"").concat(selector, "\"]"));
802
- if (testElement.value == value) {
803
- arrayElement.removeAttribute('disabled');
655
+ // @ts-nocheck
656
+ // Create a link between two input/selects with one acting as setting a minimum value and the second a maximum
657
+ // The link between the two will prevent the max input field form setting a lower value than the min and vice versa
658
+ function inputRange(inputWrapper) {
659
+ inputWrapper.addEventListener('change', function (e) {
660
+ var min = parseInt(inputWrapper.querySelector('[data-min] select,[data-min] input').value);
661
+ var max = parseInt(inputWrapper.querySelector('[data-max] select,[data-max] input').value);
662
+ // Set attributes for input fields
663
+ Array.from(inputWrapper.querySelectorAll('[data-min] input')).forEach((input, index) => {
664
+ input.setAttribute('max', max);
665
+ });
666
+ Array.from(inputWrapper.querySelectorAll('[data-max] input')).forEach((input, index) => {
667
+ input.setAttribute('min', min);
668
+ });
669
+ // Hide select options if they are higher or lower than the min and max values
670
+ Array.from(inputWrapper.querySelectorAll('[data-min] select option')).forEach((option, index) => {
671
+ if (parseInt(option.getAttribute('value')) > max) option.classList.add('d-none');else option.classList.remove('d-none');
672
+ });
673
+ Array.from(inputWrapper.querySelectorAll('[data-max] select option')).forEach((option, index) => {
674
+ if (parseInt(option.getAttribute('value')) < min) option.classList.add('d-none');else option.classList.remove('d-none');
675
+ });
676
+ }, false);
677
+ }
678
+ function inputRedirect(inputWrapper) {
679
+ inputWrapper.addEventListener('change', function (e) {
680
+ if (inputWrapper.matches('[data-value-if]')) {
681
+ var url = inputWrapper.getAttribute('data-redirect');
682
+ var desiredValue = inputWrapper.getAttribute('data-value-if');
683
+ if (inputWrapper.value == desiredValue) document.location.href = url;
804
684
  } else {
805
- arrayElement.setAttribute('disabled', 'disabled');
806
- arrayElement.value = '';
685
+ if (typeof inputWrapper.value != "undefined") document.location.href = inputWrapper.value;
686
+ }
687
+ }, false);
688
+ }
689
+ //
690
+ function multipleFileUploads(wrapper) {
691
+ var fileTenplate = wrapper.querySelector('.row');
692
+ var clone = fileTenplate.cloneNode(true);
693
+ var addButton = wrapper.querySelector('[data-add]');
694
+ wrapper.addEventListener('click', function (e) {
695
+ for (var target = e.target; target && target != this; target = target.parentNode) {
696
+ if (target.matches('[data-add]')) {
697
+ // Add a new row upload file input fields
698
+ var tempClone = clone.cloneNode(true);
699
+ wrapper.insertBefore(tempClone, target);
700
+ if (addButton.matches('[data-maxfiles]') && Array.from(wrapper.querySelectorAll(':scope > .row')).length >= addButton.dataset.maxfiles) addButton.setAttribute('disabled', 'disabled');
701
+ break;
702
+ }
703
+ if (target.matches('[data-delete]')) {
704
+ // Delete the current row
705
+ var row = target.closest('.row');
706
+ row.remove();
707
+ if (addButton.matches('[data-maxfiles]') && Array.from(wrapper.querySelectorAll(':scope > .row')).length < addButton.dataset.maxfiles) addButton.removeAttribute('disabled');
708
+ break;
709
+ }
807
710
  }
711
+ }, false);
712
+ }
713
+ // Acts as an overall initialise function to trigger other functions.
714
+ function form(formElement) {
715
+ // Check for input range groups
716
+ Array.from(formElement.querySelectorAll('[data-input-range]')).forEach((arrayElement, index) => {
717
+ inputRange(arrayElement);
808
718
  });
809
-
810
- // Show this input wrapper when a pre-selected input field equals a certain value
811
- Array.from(formElement.querySelectorAll('.form-control__wrapper[data-displayif][data-equals]')).forEach((arrayElement, index) => {
812
- var group = arrayElement.closest('[data-group]') ? arrayElement.closest('[data-group]') : formElement;
813
- var selector = arrayElement.dataset.activeif;
814
- var value = arrayElement.dataset.equals;
815
- var testElement = group.querySelector("select[data-id=\"".concat(selector, "\"],input[data-id=\"").concat(selector, "\"]"));
816
- if (testElement.value == value) arrayElement.classList.remove('d-none');else arrayElement.classList.add('d-none');
719
+ Array.from(formElement.querySelectorAll('[data-redirect]')).forEach((arrayElement, index) => {
720
+ inputRedirect(arrayElement);
817
721
  });
818
- }, false);
819
- }
820
-
821
- /**
822
- * Integrate YouTube videos as a way of hosting videos without the overhead and worry surrounding hosting vides. i.e. file sizes, performance and accessibility.
823
- */
824
- class youtubeVideo {
825
- /** @param {Element} embed dom element */
826
- constructor(embed) {
827
- var createEmbed = this.createEmbed;
828
-
829
- // If the scripts is already loaded then lets just create the embed
830
- if (document.body.classList.contains('youtubeLoaded')) {
831
- embed.addEventListener('click', function (e) {
832
- // loop parent nodes from the target to the delegation node
833
- for (var target = e.target; target && target != this; target = target.parentNode) {
834
- if (target.matches('a:not([data-modal-youtube]')) {
835
- e.preventDefault();
836
- createEmbed(embed, target);
837
- break;
722
+ Array.from(formElement.querySelectorAll('.multiple-file-uploads')).forEach((arrayElement, index) => {
723
+ multipleFileUploads(arrayElement);
724
+ });
725
+ // Check the file size of a file when uploaded in case it exceeds the max file size set
726
+ formElement.addEventListener('change', function (e) {
727
+ for (var target = e.target; target && target != this; target = target.parentNode) {
728
+ if (target.matches('[type="file"][data-filesize]') && target.files && target.files[0]) {
729
+ var maxAllowedSize = target.dataset.filesize;
730
+ if (target.files[0].size > maxAllowedSize) {
731
+ target.value = '';
732
+ alert('File too large');
838
733
  }
734
+ break;
839
735
  }
840
- }, false);
841
- } else {
842
- this.loadScripts(embed, this.createEmbed);
843
- }
736
+ }
737
+ }, false);
738
+ // When a form is updated we may want to update some of the existing input fields; setting active fields when some data is selected.
739
+ formElement.addEventListener('change', function (e) {
740
+ // Remove disabled attribute when a pre-selected input field equals a certain value
741
+ Array.from(formElement.querySelectorAll('select[data-activeif][data-equals],input[data-activeif][data-equals]')).forEach((arrayElement, index) => {
742
+ var group = arrayElement.closest('[data-group]') ? arrayElement.closest('[data-group]') : formElement;
743
+ var selector = arrayElement.dataset.activeif;
744
+ var value = arrayElement.dataset.equals;
745
+ var testElement = group.querySelector("select[data-id=\"".concat(selector, "\"],input[data-id=\"").concat(selector, "\"]"));
746
+ if (testElement.value == value) {
747
+ arrayElement.removeAttribute('disabled');
748
+ } else {
749
+ arrayElement.setAttribute('disabled', 'disabled');
750
+ arrayElement.value = '';
751
+ }
752
+ });
753
+ // Show this input wrapper when a pre-selected input field equals a certain value
754
+ Array.from(formElement.querySelectorAll('.form-control__wrapper[data-displayif][data-equals]')).forEach((arrayElement, index) => {
755
+ var group = arrayElement.closest('[data-group]') ? arrayElement.closest('[data-group]') : formElement;
756
+ var selector = arrayElement.dataset.activeif;
757
+ var value = arrayElement.dataset.equals;
758
+ var testElement = group.querySelector("select[data-id=\"".concat(selector, "\"],input[data-id=\"").concat(selector, "\"]"));
759
+ if (testElement.value == value) arrayElement.classList.remove('d-none');else arrayElement.classList.add('d-none');
760
+ });
761
+ }, false);
844
762
  }
845
763
 
764
+ // @ts-nocheck
846
765
  /**
847
- * Load the YouTube scripts before trying to create the embed
848
- * @param {HTMLElement} embed dom element
849
- * @param {Function} createEmbed function to create the embed after script loaded.
766
+ * Integrate YouTube videos as a way of hosting videos without the overhead and worry surrounding hosting vides. i.e. file sizes, performance and accessibility.
850
767
  */
851
- loadScripts(embed, createEmbed) {
852
- return new Promise((resolve, reject) => {
853
- var image = new Image();
854
- image.onload = function () {
855
- // This code loads the IFrame Player API code asynchronously.
856
- var tag = document.createElement('script');
857
- tag.src = "https://www.youtube.com/iframe_api";
858
- var firstScriptTag = document.getElementsByTagName('script')[0];
859
- firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
860
- document.body.classList.add('youtubeLoaded');
861
- resolve(true);
862
-
863
- // script has loaded, you can now use it safely
864
- tag.onload = () => {
865
- embed.addEventListener('click', function (e) {
866
- // loop parent nodes from the target to the delegation node
867
- for (var target = e.target; target && target != this; target = target.parentNode) {
868
- if (target.matches('a:not([data-modal-youtube]')) {
869
- e.preventDefault();
870
- createEmbed(embed, target);
871
- break;
872
- }
768
+ class youtubeVideo {
769
+ /** @param {Element} embed dom element */
770
+ constructor(embed) {
771
+ var createEmbed = this.createEmbed;
772
+ // If the scripts is already loaded then lets just create the embed
773
+ if (document.body.classList.contains('youtubeLoaded')) {
774
+ embed.addEventListener('click', function (e) {
775
+ // loop parent nodes from the target to the delegation node
776
+ for (var target = e.target; target && target != this; target = target.parentNode) {
777
+ if (target.matches('a:not([data-modal-youtube]')) {
778
+ e.preventDefault();
779
+ createEmbed(embed, target);
780
+ break;
873
781
  }
874
- }, false);
875
- };
876
- };
877
- image.onerror = function () {
878
- reject(false);
879
- };
880
- image.src = "https://youtube.com/favicon.ico";
881
- });
882
- }
883
-
884
- /**
885
- * Create the YouTube embed after the user has clicked on it.
886
- * @param {HTMLElement} embed dom element
887
- */
888
- createEmbed(embed, target) {
889
- // If there is more than one video lets make sure there is only one playing at a time.
890
- if (typeof window.player != "undefined" && typeof window.player.pauseVideo == "function") window.player.pauseVideo();
891
- var video_id = target.getAttribute('data-id');
892
- var link_id = target.getAttribute('id');
893
-
894
- // create an id to pass t the script if one isn't present
895
- if (typeof link_id == 'undefined' || link_id == null) {
896
- var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
897
- link_id = randLetter + Date.now();
898
- target.setAttribute('id', link_id);
782
+ }
783
+ }, false);
784
+ } else {
785
+ this.loadScripts(embed, this.createEmbed);
786
+ }
899
787
  }
900
-
901
- // This function creates an <iframe> (and YouTube player) after the API code downloads.
902
- function onYouTubeIframeAPIReady() {
903
- window.player = new YT.Player(link_id, {
904
- height: '100%',
905
- width: '100%',
906
- videoId: video_id,
907
- playerVars: {
908
- 'modestbranding': 1,
909
- 'playsinline': 1,
910
- 'rel': 0,
911
- 'showinfo': 0
912
- },
913
- events: {
914
- 'onReady': onPlayerReady,
915
- 'onStateChange': onPlayerStateChange
916
- }
788
+ /**
789
+ * Load the YouTube scripts before trying to create the embed
790
+ * @param {HTMLElement} embed dom element
791
+ * @param {Function} createEmbed function to create the embed after script loaded.
792
+ */
793
+ loadScripts(embed, createEmbed) {
794
+ return new Promise((resolve, reject) => {
795
+ var image = new Image();
796
+ image.onload = function () {
797
+ // This code loads the IFrame Player API code asynchronously.
798
+ var tag = document.createElement('script');
799
+ tag.src = "https://www.youtube.com/iframe_api";
800
+ var firstScriptTag = document.getElementsByTagName('script')[0];
801
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
802
+ document.body.classList.add('youtubeLoaded');
803
+ resolve(true);
804
+ // script has loaded, you can now use it safely
805
+ tag.onload = () => {
806
+ embed.addEventListener('click', function (e) {
807
+ // loop parent nodes from the target to the delegation node
808
+ for (var target = e.target; target && target != this; target = target.parentNode) {
809
+ if (target.matches('a:not([data-modal-youtube]')) {
810
+ e.preventDefault();
811
+ createEmbed(embed, target);
812
+ break;
813
+ }
814
+ }
815
+ }, false);
816
+ };
817
+ };
818
+ image.onerror = function () {
819
+ reject(false);
820
+ };
821
+ image.src = "https://youtube.com/favicon.ico";
917
822
  });
918
823
  }
919
- onYouTubeIframeAPIReady();
920
-
921
- // The API will call this function when the video player is ready.
922
- function onPlayerReady(event) {
923
- // Play the video straight away
924
- event.target.playVideo();
925
- }
926
-
927
- // The API calls this function when the player's state changes.
928
- // The function indicates that when playing a video (state=1)
929
- var done = false;
930
- function onPlayerStateChange(event) {
931
- if (event.data == YT.PlayerState.PLAYING && !done) {
932
- var link = document.getElementById(link_id);
933
- link.classList.add('player-ready');
934
- done = true;
824
+ /**
825
+ * Create the YouTube embed after the user has clicked on it.
826
+ * @param {HTMLElement} embed dom element
827
+ */
828
+ createEmbed(embed, target) {
829
+ // If there is more than one video lets make sure there is only one playing at a time.
830
+ if (typeof window.player != "undefined" && typeof window.player.pauseVideo == "function") window.player.pauseVideo();
831
+ var video_id = target.getAttribute('data-id');
832
+ var link_id = target.getAttribute('id');
833
+ // create an id to pass t the script if one isn't present
834
+ if (typeof link_id == 'undefined' || link_id == null) {
835
+ var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
836
+ link_id = randLetter + Date.now();
837
+ target.setAttribute('id', link_id);
838
+ }
839
+ // This function creates an <iframe> (and YouTube player) after the API code downloads.
840
+ function onYouTubeIframeAPIReady() {
841
+ window.player = new YT.Player(link_id, {
842
+ height: '100%',
843
+ width: '100%',
844
+ videoId: video_id,
845
+ playerVars: {
846
+ 'modestbranding': 1,
847
+ 'playsinline': 1,
848
+ 'rel': 0,
849
+ 'showinfo': 0
850
+ },
851
+ events: {
852
+ 'onReady': onPlayerReady,
853
+ 'onStateChange': onPlayerStateChange
854
+ }
855
+ });
856
+ }
857
+ onYouTubeIframeAPIReady();
858
+ // The API will call this function when the video player is ready.
859
+ function onPlayerReady(event) {
860
+ // Play the video straight away
861
+ event.target.playVideo();
862
+ }
863
+ // The API calls this function when the player's state changes.
864
+ // The function indicates that when playing a video (state=1)
865
+ var done = false;
866
+ function onPlayerStateChange(event) {
867
+ if (event.data == YT.PlayerState.PLAYING && !done) {
868
+ var link = document.getElementById(link_id);
869
+ link.classList.add('player-ready');
870
+ done = true;
871
+ }
935
872
  }
936
873
  }
937
874
  }
938
- }
939
-
940
- var modal = element => {
941
- var links = element.querySelectorAll('.modal__outer a, .modal__outer button');
942
- var firstLink = links[0];
943
- var lastLink = links[links.length - 1];
944
- var modalID = element.getAttribute('id');
945
- var closeModal = function closeModal() {
946
- var button = document.querySelector('[href="' + window.location.hash + '"]');
947
- button.focus();
948
- window.location.hash = "close";
949
- history.replaceState("", document.title, window.location.pathname + window.location.search);
950
875
 
951
- // If there is more than one video lets make sure there is only one playing at a time.
952
- if (typeof window.player != "undefined" && typeof window.player.pauseVideo == "function") window.player.pauseVideo();
953
- };
954
-
955
- // Trap the tab focus inside
956
- element.addEventListener('keydown', function (e) {
957
- if (e.key === "Tab" && e.shiftKey && document.activeElement == firstLink) {
958
- e.preventDefault();
959
- lastLink.focus();
960
- } else if (e.key === "Tab" && !e.shiftKey && document.activeElement == lastLink) {
961
- e.preventDefault();
962
- firstLink.focus();
963
- }
964
- });
965
-
966
- // ESC will close the open modal
967
- document.addEventListener("keydown", function (e) {
968
- if (e.key === "Escape" && document.querySelector('.modal:target')) closeModal();
969
- });
970
- element.addEventListener('click', function (e) {
971
- for (var target = e.target; target && target != this; target = target.parentNode) {
972
- // Close links will close the model by default but we want to remove the hash link also
973
- if (target.matches('[href="#close"]')) {
876
+ // @ts-nocheck
877
+ var modal = element => {
878
+ var links = element.querySelectorAll('.modal__outer a, .modal__outer button');
879
+ var firstLink = links[0];
880
+ var lastLink = links[links.length - 1];
881
+ var modalID = element.getAttribute('id');
882
+ var closeModal = function closeModal() {
883
+ var button = document.querySelector('[href="' + window.location.hash + '"]');
884
+ button.focus();
885
+ window.location.hash = "close";
886
+ history.replaceState("", document.title, window.location.pathname + window.location.search);
887
+ // If there is more than one video lets make sure there is only one playing at a time.
888
+ if (typeof window.player != "undefined" && typeof window.player.pauseVideo == "function") window.player.pauseVideo();
889
+ };
890
+ // Trap the tab focus inside
891
+ element.addEventListener('keydown', function (e) {
892
+ if (e.key === "Tab" && e.shiftKey && document.activeElement == firstLink) {
974
893
  e.preventDefault();
975
- closeModal();
976
- break;
977
- }
978
- // Dock the modal to the right or left to make the content behind readable
979
- else if (target.matches('.modal__dock--right')) {
980
- e.preventDefault();
981
- if (!element.classList.contains('modal--left')) element.classList.add('modal--right');
982
- element.classList.remove('modal--left');
983
- break;
984
- } else if (target.matches('.modal__dock--left')) {
894
+ lastLink.focus();
895
+ } else if (e.key === "Tab" && !e.shiftKey && document.activeElement == lastLink) {
985
896
  e.preventDefault();
986
- if (!element.classList.contains('modal--right')) element.classList.add('modal--left');
987
- element.classList.remove('modal--right');
988
- break;
897
+ firstLink.focus();
989
898
  }
990
- }
991
- });
992
- function locationHashChanged() {
993
- if (location.hash === '#' + modalID) {
994
- console.log("Modal is now open");
995
- var videoButton = document.querySelector('.modal:target .modal__inner > .youtube-embed:first-child:last-child a');
996
- console.log(videoButton);
997
- if (videoButton) {
998
- videoButton.click();
899
+ });
900
+ // ESC will close the open modal
901
+ document.addEventListener("keydown", function (e) {
902
+ if (e.key === "Escape" && document.querySelector('.modal:target')) closeModal();
903
+ });
904
+ element.addEventListener('click', function (e) {
905
+ for (var target = e.target; target && target != this; target = target.parentNode) {
906
+ // Close links will close the model by default but we want to remove the hash link also
907
+ if (target.matches('[href="#close"]')) {
908
+ e.preventDefault();
909
+ closeModal();
910
+ break;
911
+ }
912
+ // Dock the modal to the right or left to make the content behind readable
913
+ else if (target.matches('.modal__dock--right')) {
914
+ e.preventDefault();
915
+ if (!element.classList.contains('modal--left')) element.classList.add('modal--right');
916
+ element.classList.remove('modal--left');
917
+ break;
918
+ } else if (target.matches('.modal__dock--left')) {
919
+ e.preventDefault();
920
+ if (!element.classList.contains('modal--right')) element.classList.add('modal--left');
921
+ element.classList.remove('modal--right');
922
+ break;
923
+ }
924
+ }
925
+ });
926
+ function locationHashChanged() {
927
+ if (location.hash === '#' + modalID) {
928
+ console.log("Modal is now open");
929
+ var videoButton = document.querySelector('.modal:target .modal__inner > .youtube-embed:first-child:last-child a');
930
+ console.log(videoButton);
931
+ if (videoButton) {
932
+ videoButton.click();
933
+ }
999
934
  }
1000
935
  }
1001
- }
1002
- window.onhashchange = locationHashChanged;
1003
- };
936
+ window.onhashchange = locationHashChanged;
937
+ };
1004
938
 
1005
- // @ts-nocheck
1006
- // Attach classes to dom elements
1007
- document.addEventListener("DOMContentLoaded", function () {
939
+ // @ts-nocheck
940
+ // Attach classes to dom elements
941
+ document.addEventListener("DOMContentLoaded", function () {
1008
942
  addBodyClasses(document.body);
1009
943
  addGlobalEvents();
1010
944
  checkElements(document.body);
1011
945
  console.log('test.js');
1012
946
  // ANav
1013
- Array.from(document.querySelectorAll('.nav')).forEach(function (arrayElement) {
1014
- navbar(arrayElement);
947
+ Array.from(document.querySelectorAll('.nav')).forEach(arrayElement => {
948
+ navbar(arrayElement);
1015
949
  });
1016
950
  // Advanced tables
1017
- Array.from(document.querySelectorAll('.table__wrapper')).forEach(function (arrayElement) {
1018
- table(arrayElement);
951
+ Array.from(document.querySelectorAll('.table__wrapper')).forEach(arrayElement => {
952
+ table(arrayElement);
1019
953
  });
1020
954
  // Accordions
1021
- Array.from(document.querySelectorAll('.accordion')).forEach(function (arrayElement) {
1022
- accordion(arrayElement);
955
+ Array.from(document.querySelectorAll('.accordion')).forEach(arrayElement => {
956
+ accordion(arrayElement);
1023
957
  });
1024
958
  // Testimonial
1025
- Array.from(document.querySelectorAll('.testimonial')).forEach(function (arrayElement) {
1026
- testimonial(arrayElement);
959
+ Array.from(document.querySelectorAll('.testimonial')).forEach(arrayElement => {
960
+ testimonial(arrayElement);
1027
961
  });
1028
962
  // Carousel
1029
- Array.from(document.querySelectorAll('.carousel')).forEach(function (arrayElement) {
1030
- carousel(arrayElement);
963
+ Array.from(document.querySelectorAll('.carousel')).forEach(arrayElement => {
964
+ carousel(arrayElement);
1031
965
  });
1032
966
  // Form
1033
- Array.from(document.querySelectorAll('form')).forEach(function (arrayElement) {
1034
- form(arrayElement);
967
+ Array.from(document.querySelectorAll('form')).forEach(arrayElement => {
968
+ form(arrayElement);
1035
969
  });
1036
970
  // Modal
1037
- Array.from(document.querySelectorAll('.modal')).forEach(function (arrayElement) {
1038
- modal(arrayElement);
971
+ Array.from(document.querySelectorAll('.modal')).forEach(arrayElement => {
972
+ modal(arrayElement);
1039
973
  });
1040
974
  // YouTube videos
1041
- Array.from(document.querySelectorAll('.youtube-embed')).forEach(function (arrayElement) {
1042
- new youtubeVideo(arrayElement);
975
+ Array.from(document.querySelectorAll('.youtube-embed')).forEach(arrayElement => {
976
+ new youtubeVideo(arrayElement);
1043
977
  });
1044
978
  window.addEventListener('hashchange', function () {
1045
- var hash = location.hash.replace('#', '');
1046
- var label = document.querySelector("label[for=\"".concat(hash, "\"]"));
1047
- if (label instanceof HTMLElement) {
1048
- label.click();
1049
- }
979
+ var hash = location.hash.replace('#', '');
980
+ var label = document.querySelector("label[for=\"".concat(hash, "\"]"));
981
+ if (label instanceof HTMLElement) {
982
+ label.click();
983
+ }
1050
984
  }, false);
1051
- });
985
+ });
1052
986
 
1053
987
  }));
1054
988
  //# sourceMappingURL=scripts.bundle.js.map