@iamproperty/components 2.7.8 → 2.8.0

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