@iamproperty/components 5.6.1-beta9 → 5.7.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.
Files changed (92) hide show
  1. package/assets/css/components/address-lookup.css +1 -1
  2. package/assets/css/components/address-lookup.css.map +1 -1
  3. package/assets/css/components/carousel.css +1 -1
  4. package/assets/css/components/carousel.css.map +1 -1
  5. package/assets/css/components/fileupload.css +1 -1
  6. package/assets/css/components/fileupload.css.map +1 -1
  7. package/assets/css/components/pagination.css +1 -1
  8. package/assets/css/components/pagination.css.map +1 -1
  9. package/assets/css/components/tabs.css +1 -1
  10. package/assets/css/components/tabs.css.map +1 -1
  11. package/assets/css/core.min.css +1 -1
  12. package/assets/css/core.min.css.map +1 -1
  13. package/assets/css/style.min.css +1 -1
  14. package/assets/css/style.min.css.map +1 -1
  15. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  16. package/assets/js/components/actionbar/actionbar.component.min.js +3 -3
  17. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
  18. package/assets/js/components/address-lookup/address-lookup.component.js +21 -10
  19. package/assets/js/components/address-lookup/address-lookup.component.min.js +6 -5
  20. package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
  21. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  22. package/assets/js/components/card/card.component.js +39 -20
  23. package/assets/js/components/card/card.component.min.js +19 -19
  24. package/assets/js/components/card/card.component.min.js.map +1 -1
  25. package/assets/js/components/carousel/carousel.component.js +14 -1
  26. package/assets/js/components/carousel/carousel.component.min.js +5 -5
  27. package/assets/js/components/carousel/carousel.component.min.js.map +1 -1
  28. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
  29. package/assets/js/components/fileupload/fileupload.component.js +16 -0
  30. package/assets/js/components/fileupload/fileupload.component.min.js +7 -5
  31. package/assets/js/components/fileupload/fileupload.component.min.js.map +1 -1
  32. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  33. package/assets/js/components/header/header.component.min.js +1 -1
  34. package/assets/js/components/inline-edit/inline-edit.component.js +2 -2
  35. package/assets/js/components/inline-edit/inline-edit.component.min.js +3 -3
  36. package/assets/js/components/inline-edit/inline-edit.component.min.js.map +1 -1
  37. package/assets/js/components/marketing/marketing.component.min.js +1 -1
  38. package/assets/js/components/multiselect/multiselect.component.min.js +1 -1
  39. package/assets/js/components/nav/nav.component.min.js +1 -1
  40. package/assets/js/components/notification/notification.component.min.js +1 -1
  41. package/assets/js/components/pagination/pagination.component.min.js +3 -3
  42. package/assets/js/components/search/search.component.min.js +1 -1
  43. package/assets/js/components/search/search.component.min.js.map +1 -1
  44. package/assets/js/components/slider/slider.component.min.js +1 -1
  45. package/assets/js/components/table/table.component.js +16 -1
  46. package/assets/js/components/table/table.component.min.js +4 -4
  47. package/assets/js/components/table/table.component.min.js.map +1 -1
  48. package/assets/js/components/tabs/tabs.component.js +3 -1
  49. package/assets/js/components/tabs/tabs.component.min.js +8 -6
  50. package/assets/js/components/tabs/tabs.component.min.js.map +1 -1
  51. package/assets/js/dynamic.min.js +4 -4
  52. package/assets/js/dynamic.min.js.map +1 -1
  53. package/assets/js/modules/carousel.js +30 -8
  54. package/assets/js/modules/dialogs.js +6 -0
  55. package/assets/js/modules/fileupload.js +44 -12
  56. package/assets/js/modules/helpers.js +30 -0
  57. package/assets/js/modules/inputs.js +1 -1
  58. package/assets/js/modules/table.js +6 -1
  59. package/assets/js/modules/tabs.js +84 -1
  60. package/assets/js/scripts.bundle.js +34 -32
  61. package/assets/js/scripts.bundle.js.map +1 -1
  62. package/assets/js/scripts.bundle.min.js +2 -2
  63. package/assets/js/scripts.bundle.min.js.map +1 -1
  64. package/assets/sass/_components.scss +14 -0
  65. package/assets/sass/components/address-lookup.scss +4 -0
  66. package/assets/sass/components/carousel.scss +31 -7
  67. package/assets/sass/components/fileupload.scss +0 -10
  68. package/assets/sass/components/pagination.scss +11 -16
  69. package/assets/sass/components/tabs.scss +38 -3
  70. package/assets/sass/elements/admin-panel.scss +44 -6
  71. package/assets/sass/elements/dialog.scss +1 -1
  72. package/assets/sass/elements/forms.scss +3 -2
  73. package/assets/ts/components/address-lookup/address-lookup.component.ts +25 -11
  74. package/assets/ts/components/card/card.component.ts +49 -23
  75. package/assets/ts/components/carousel/carousel.component.ts +17 -1
  76. package/assets/ts/components/fileupload/fileupload.component.ts +26 -0
  77. package/assets/ts/components/inline-edit/inline-edit.component.ts +2 -2
  78. package/assets/ts/components/table/table.component.ts +24 -1
  79. package/assets/ts/components/tabs/tabs.component.ts +3 -1
  80. package/assets/ts/modules/carousel.ts +40 -9
  81. package/assets/ts/modules/dialogs.ts +8 -0
  82. package/assets/ts/modules/fileupload.ts +64 -20
  83. package/assets/ts/modules/helpers.ts +29 -0
  84. package/assets/ts/modules/inputs.ts +1 -1
  85. package/assets/ts/modules/table.ts +8 -2
  86. package/assets/ts/modules/tabs.ts +116 -1
  87. package/dist/components.es.js +199 -193
  88. package/dist/components.umd.js +78 -68
  89. package/dist/style.css +1 -1
  90. package/package.json +1 -1
  91. package/src/components/Card/Card.vue +1 -1
  92. package/src/components/Carousel/Carousel.vue +5 -1
@@ -30,11 +30,13 @@ class iamTabs extends HTMLElement {
30
30
 
31
31
  ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
32
32
  </style>
33
- <div class="tabs">
33
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
34
+ <div class="tabs" part="tabs">
34
35
  <div class="tabs__links__wrapper">
35
36
  <div class="tabs__links"></div>
36
37
  </div>
37
38
  <slot></slot>
39
+ <button part="next-button" class="btn btn-secondary btn-sm btn-compact fa-regular fa-chevron-right tabs__next">Next</button>
38
40
  </div>
39
41
  `;
40
42
  this.shadowRoot.appendChild(template.content.cloneNode(true));
@@ -5,8 +5,8 @@ function carousel(carouselElement, row) {
5
5
 
6
6
  let carouselInner = carouselElement.querySelector('.carousel__inner');
7
7
  let carouselControls = carouselElement.querySelector('.carousel__controls');
8
- let itemCount = row.querySelectorAll('.col').length;
9
-
8
+ let itemCount = row.querySelectorAll(':scope > .col').length;
9
+
10
10
  // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
11
11
  carouselInner.addEventListener('scroll', function(e){
12
12
  clearTimeout(scrollTimeout);
@@ -16,11 +16,21 @@ function carousel(carouselElement, row) {
16
16
  let scrollWidth = carouselInner.scrollWidth;
17
17
  let scrollLeft = carouselInner.scrollLeft;
18
18
  let targetSlide = Math.round((scrollLeft / scrollWidth) * itemCount) + 1;
19
- let lastItemOffset = row.querySelector('.col:last-child').offsetLeft + 50;
19
+
20
+ let itemWidth = row.querySelector(':scope > .col').scrollWidth;
21
+ let lastItemOffset = row.querySelector(':scope > .col:last-child').offsetLeft;
22
+ //+60px here is to account for when the next offscreen slide is visible beneath the next arrow
23
+ let lastItemInView = carouselInner.scrollLeft + scrollArea + carouselInner.getBoundingClientRect().left >= (lastItemOffset + 60);
24
+
25
+ let visibleItems = Math.round(scrollArea / itemWidth);
20
26
 
21
- if(carouselInner.scrollLeft + scrollArea >= lastItemOffset)
22
- targetSlide = itemCount;
27
+ //Check if theres room for more slides than we have
28
+ let leftOverSpace = (Math.ceil(itemCount / visibleItems) * visibleItems) - itemCount;
23
29
 
30
+ if(leftOverSpace > 0 && lastItemInView){
31
+ targetSlide = (Math.floor(itemCount / visibleItems) * visibleItems) + 1;
32
+ }
33
+
24
34
  Array.from(carouselElement.querySelectorAll('.carousel__controls button')).forEach((button, index) => {
25
35
  button.removeAttribute('aria-current');
26
36
  });
@@ -34,7 +44,7 @@ function carousel(carouselElement, row) {
34
44
  carouselElement.querySelector('.btn-prev').removeAttribute('disabled');
35
45
 
36
46
  // Disable the next button if the last item is in view
37
- if(targetSlide == itemCount)
47
+ if(targetSlide > (itemCount - visibleItems))
38
48
  carouselElement.querySelector('.btn-next').setAttribute('disabled','disabled');
39
49
  else
40
50
  carouselElement.querySelector('.btn-next').removeAttribute('disabled');
@@ -56,11 +66,11 @@ function carousel(carouselElement, row) {
56
66
  });
57
67
  target.setAttribute('aria-current', true);
58
68
 
59
- const el = row.querySelector(`*:nth-child(${target.getAttribute('data-slide')})`);
69
+ const el = row.querySelector(`:scope > *:nth-child(${target.getAttribute('data-slide')})`);
60
70
 
61
71
  carouselInner.scroll({
62
72
  top: 0,
63
- left: el.offsetLeft,
73
+ left: el.offsetLeft - carouselInner.getBoundingClientRect().left,
64
74
  behavior: 'smooth'
65
75
  });
66
76
 
@@ -71,11 +81,32 @@ function carousel(carouselElement, row) {
71
81
 
72
82
  carouselElement.addEventListener('click', function(e){
73
83
 
84
+ let scrollArea = carouselInner.clientWidth;
85
+ let scrollWidth = carouselInner.scrollWidth;
86
+ let itemWidth = row.querySelector(':scope > .col').scrollWidth;
87
+
88
+ let visibleItems = Math.round(scrollArea / itemWidth);
89
+
90
+ let lastItemOffset = row.querySelector(':scope > .col:last-child').offsetLeft;
91
+ let lastItemInView = carouselInner.scrollLeft + scrollArea + carouselInner.getBoundingClientRect().left >= (lastItemOffset + 60);
92
+
93
+ //Check if theres room for more slides than we have
94
+ let leftOverSpace = (Math.ceil(itemCount / visibleItems) * visibleItems) - itemCount;
95
+
96
+ /*
97
+ When the last slide isn't filled with items, we only want to move back the number of items on the slide,
98
+ rather than the total number of possible visible items
99
+ */
100
+ let spacesToMove = visibleItems - leftOverSpace;
101
+
102
+ //Only want to change the amount of movement if the last item is visible
103
+ let movement = lastItemInView && leftOverSpace > 0 ? spacesToMove * itemWidth : carouselInner.clientWidth;
104
+
74
105
  for (var target = e.target; target && target != this; target = target.parentNode) {
75
106
  if (typeof target.matches == "function" && target.matches('.btn-next, .btn-prev')) {
76
107
 
77
108
  e.preventDefault();
78
- let scrollTo = target.classList.contains('btn-prev') ? carouselInner.scrollLeft - carouselInner.clientWidth : carouselInner.scrollLeft + carouselInner.clientWidth;
109
+ let scrollTo = target.classList.contains('btn-prev') ? carouselInner.scrollLeft - movement : carouselInner.scrollLeft + carouselInner.clientWidth;
79
110
 
80
111
  carouselInner.scroll({
81
112
  top: 0,
@@ -72,6 +72,14 @@ const extendDialogs = (body) => {
72
72
  btnElement.classList.remove('active');
73
73
  });
74
74
 
75
+ let closeEvent = new CustomEvent('dialog-closed', {
76
+ bubbles: true,
77
+ cancelable: true,
78
+ detail: { modalId: dialog.id }
79
+ });
80
+
81
+ event.target.dispatchEvent(closeEvent);
82
+
75
83
  window.dataLayer = window.dataLayer || [];
76
84
  window.dataLayer.push({
77
85
  "event": "closeModal",
@@ -5,11 +5,27 @@ function fileupload(fileupload: Element, wrapper: Element) {
5
5
  const dropArea = wrapper.querySelector('.drop-area');
6
6
  const input = fileupload.querySelector('input');
7
7
  const maxSize = fileupload.hasAttribute('data-maxsize') ? fileupload.getAttribute('data-maxsize') : 0;
8
+ const errorMsgSize = wrapper.querySelector('.invalid-feedback.size');
9
+ const errorMsgExt = wrapper.querySelector('.invalid-feedback.ext');
8
10
 
9
11
  // We clone the input field to work as a buffer input field, this allows us to add new files without losing the old ones
10
12
  const cloneInput = input.cloneNode();
11
13
  dropArea.append(cloneInput);
12
14
 
15
+ let checkFileExt = function(filename){
16
+
17
+ if(!input.hasAttribute('accept'))
18
+ return true;
19
+
20
+ const nameExtension = filename.split('.').pop();
21
+ const acceptedTypes = input.getAttribute('accept');
22
+
23
+ if(acceptedTypes.includes(nameExtension))
24
+ return true;
25
+
26
+ return false;
27
+ }
28
+
13
29
  wrapper.addEventListener('click', (event) => {
14
30
 
15
31
  if (event && event.target instanceof HTMLElement && event.target.closest('.btn-primary')){
@@ -17,6 +33,9 @@ function fileupload(fileupload: Element, wrapper: Element) {
17
33
  const button = event.target.closest('.btn-primary');
18
34
 
19
35
  // If the input allows multiples then use the buffer clone input
36
+
37
+ errorMsgExt.classList.remove('d-block');
38
+ errorMsgSize.classList.remove('d-block');
20
39
  const inputTrigger = input.hasAttribute('multiple') ? cloneInput : input;
21
40
 
22
41
  inputTrigger.click();
@@ -27,7 +46,6 @@ function fileupload(fileupload: Element, wrapper: Element) {
27
46
 
28
47
  if (event && event.target instanceof HTMLElement && event.target.closest('.files button')){
29
48
 
30
-
31
49
  const dt = new DataTransfer();
32
50
  const { files } = input;
33
51
  const button = event.target.closest('.files button');
@@ -42,17 +60,8 @@ function fileupload(fileupload: Element, wrapper: Element) {
42
60
 
43
61
  input.files = dt.files // Assign the updates list
44
62
 
45
-
46
- if(input.files.length == 0){
47
- const emptyEvent = new Event('empty');
48
- fileupload.dispatchEvent(emptyEvent);
49
- }
50
-
51
63
  const changeEvent = new Event('change');
52
64
  input.dispatchEvent(changeEvent);
53
-
54
- const elementChangeEvent = new Event('elementChange');
55
- fileupload.dispatchEvent(elementChangeEvent);
56
65
  }
57
66
  });
58
67
 
@@ -60,6 +69,7 @@ function fileupload(fileupload: Element, wrapper: Element) {
60
69
  cloneInput.addEventListener('change', (event) => {
61
70
 
62
71
  if(input.hasAttribute('multiple')){
72
+
63
73
  const filesArray = [...input.files, ...cloneInput.files];
64
74
 
65
75
  let fileNames = [];
@@ -71,8 +81,17 @@ function fileupload(fileupload: Element, wrapper: Element) {
71
81
 
72
82
  const size = file.size/1000;
73
83
 
74
- if(!fileNames.includes(file.name) && (maxSize == 0 || size < maxSize))
84
+ if(!fileNames.includes(file.name) && (maxSize == 0 || size < maxSize) && checkFileExt(file.name))
75
85
  dt.items.add(file) // here you exclude the file. thus removing it.
86
+
87
+
88
+ if(!checkFileExt(file.name)){
89
+ errorMsgExt.classList.add('d-block');
90
+ }
91
+
92
+ if(size > maxSize){
93
+ errorMsgSize.classList.add('d-block');
94
+ }
76
95
 
77
96
  fileNames.push(file.name);
78
97
  }
@@ -83,12 +102,9 @@ function fileupload(fileupload: Element, wrapper: Element) {
83
102
 
84
103
  input.files = cloneInput.files;
85
104
  }
86
-
105
+
87
106
  const changeEvent = new Event('change');
88
107
  input.dispatchEvent(changeEvent);
89
-
90
- const elementChangeEvent = new Event('elementChange');
91
- fileupload.dispatchEvent(elementChangeEvent);
92
108
  });
93
109
 
94
110
 
@@ -109,11 +125,40 @@ function fileupload(fileupload: Element, wrapper: Element) {
109
125
 
110
126
  input.addEventListener('change', (event) => {
111
127
 
128
+ if(input.files.length == 1) {
129
+
130
+ let file = input.files[0];
131
+
132
+ const size = file.size/1000;
133
+
134
+ if(!checkFileExt(file.name)){
135
+ errorMsgExt.classList.add('d-block');
136
+
137
+ const dt = new DataTransfer();
138
+ input.files = dt.files;
139
+ }
140
+ if(size > maxSize){
141
+ errorMsgSize.classList.add('d-block');
142
+
143
+ const dt = new DataTransfer();
144
+ input.files = dt.files;
145
+ }
146
+ }
147
+
112
148
  // Reset
113
149
  filesWrapper.innerHTML = '';
114
150
 
115
- for (const file of input.files)
116
- filesWrapper.innerHTML += `<span class="file">${file.name} <button data-file="${file.name}">Remove</button></span>`;
151
+ for (const file of input.files){
152
+ filesWrapper.innerHTML += `<span class="file" part="file">${file.name} <button data-file="${file.name}">Remove</button></span>`;
153
+ }
154
+
155
+ const elementChangeEvent = new CustomEvent('elementchange', {detail: {"files": input.files}});
156
+ fileupload.dispatchEvent(elementChangeEvent);
157
+
158
+ if(input.files.length == 0){
159
+ const emptyEvent = new CustomEvent('empty');
160
+ fileupload.dispatchEvent(emptyEvent);
161
+ }
117
162
  });
118
163
 
119
164
  if(fileupload.hasAttribute('data-filename')){
@@ -121,9 +166,8 @@ function fileupload(fileupload: Element, wrapper: Element) {
121
166
  let filename = fileupload.getAttribute('data-filename');
122
167
 
123
168
  if(filename)
124
- filesWrapper.innerHTML += `<span class="file">${filename} <button data-file="${filename}">Remove</button></span>`;
169
+ filesWrapper.innerHTML = `<span class="file">${filename} <button data-file="${filename}">Remove</button></span>`;
125
170
  }
126
-
127
171
  }
128
172
 
129
- export default fileupload;
173
+ export default fileupload;
@@ -157,3 +157,32 @@ export const resolvePath = (object, path, defaultValue) => path.split(/[\.\[\]\'
157
157
 
158
158
 
159
159
  export const isTraversable = o => Array.isArray(o) || o !== null && ['function', 'object'].includes(typeof o);
160
+
161
+ export const getSwipeDirection = (touchstartX,touchstartY,touchendX,touchendY) => {
162
+
163
+ const limit = Math.tan(45 * 1.5 / 180 * Math.PI);
164
+ let pageWidth = window.innerWidth || document.body.clientWidth;
165
+ let treshold = Math.max(1,Math.floor(0.01 * (pageWidth)));
166
+ let x = touchendX - touchstartX;
167
+ let y = touchendY - touchstartY;
168
+ let xy = Math.abs(x / y);
169
+ let yx = Math.abs(y / x);
170
+ if (Math.abs(x) > treshold || Math.abs(y) > treshold) {
171
+ if (yx <= limit) {
172
+ if (x < 0) {
173
+ return "left";
174
+ } else {
175
+ return "right";
176
+ }
177
+ }
178
+ if (xy <= limit) {
179
+ if (y < 0) {
180
+ return "top";
181
+ } else {
182
+ return "bottom";
183
+ }
184
+ }
185
+ } else {
186
+ return "tap";
187
+ }
188
+ }
@@ -5,7 +5,7 @@ const extendInputs = (body) => {
5
5
 
6
6
  function loadInput(){
7
7
  // maxlength counter init
8
- Array.from(document.querySelectorAll('input[maxlength]')).forEach((input,index) => {
8
+ Array.from(document.querySelectorAll('input[maxlength],textarea[maxlength]')).forEach((input,index) => {
9
9
  let wrapper = input.parentElement;
10
10
  setMaxlengthVars(input,wrapper);
11
11
  });
@@ -149,7 +149,9 @@ export const addFilterEventListeners = (table, form, pagination, wrapper, savedT
149
149
  // Check what conditions are set on the table to see what the form actions are
150
150
  let formSubmit = function(event, paginate = false){
151
151
 
152
- console.log('submit');
152
+ if(wrapper.hasAttribute('data-no-submit')){
153
+ return false;
154
+ }
153
155
 
154
156
  if(form.classList.contains('processing'))
155
157
  return false;
@@ -848,6 +850,10 @@ export const populateDataQueries = (table,form,wrapper) => {
848
850
  // Pagination
849
851
  export const addPaginationEventListeners = function(table, form, pagination, wrapper){
850
852
 
853
+ if(wrapper.hasAttribute('data-no-submit')){
854
+ return false;
855
+ }
856
+
851
857
  pagination.addEventListener('update-page', (event) => {
852
858
 
853
859
  let paginationInput = form.querySelector('[data-pagination]');
@@ -1007,7 +1013,7 @@ const filterFilters = function(form){
1007
1013
  }
1008
1014
 
1009
1015
  export const loadAjaxTable = async function (table, form, pagination, wrapper){
1010
-
1016
+
1011
1017
  let formData = new FormData(form);
1012
1018
  let queryString = new URLSearchParams(formData).toString();
1013
1019
  let columns = table.querySelectorAll('thead tr th:not(.expand-button-heading)');
@@ -1,4 +1,6 @@
1
1
  // @ts-nocheck
2
+ import { getSwipeDirection } from './helpers'
3
+
2
4
  export const createTabsLinks = function(tabsElement: Element) {
3
5
 
4
6
  const details = tabsElement.querySelectorAll(':scope > details');
@@ -65,10 +67,51 @@ export const setTabsEventHandlers = function(tabsElement: Element){
65
67
 
66
68
  let details = tabsElement.querySelectorAll(':scope > details');
67
69
  let summaries = tabsElement.querySelectorAll(':scope > details > summary');
70
+ let buttonWrapper = tabsElement.querySelector(':scope .tabs__links');
68
71
  let buttons = tabsElement.querySelectorAll(':scope .tabs__links > button');
69
72
 
70
- if(tabsElement.shadowRoot)
73
+ let nextButton = tabsElement.querySelector(':scope .tabs__next');
74
+
75
+ var scrollTimeout;
76
+ let isScrolled = false;
77
+ let isClicked = false;
78
+
79
+ if(tabsElement.shadowRoot){
71
80
  buttons = tabsElement.shadowRoot.querySelectorAll('.tabs__links > button');
81
+ buttonWrapper = tabsElement.shadowRoot.querySelector('.tabs__links');
82
+ nextButton = tabsElement.shadowRoot.querySelector(':scope .tabs__next');
83
+ }
84
+
85
+ buttonWrapper.addEventListener('scroll', function(e){
86
+
87
+ if(isClicked){
88
+ isClicked = false;
89
+ return false;
90
+ }
91
+
92
+ clearTimeout(scrollTimeout);
93
+ let buttonToClick = buttons[0];
94
+
95
+ scrollTimeout = setTimeout(function(){
96
+
97
+ let closestOffset = Math.abs(buttonToClick.getBoundingClientRect().left);
98
+
99
+ buttons.forEach((button) => {
100
+
101
+ if(Math.abs(button.getBoundingClientRect().left) < closestOffset){
102
+ closestOffset = Math.abs(button.getBoundingClientRect().left);
103
+ buttonToClick = button;
104
+ }
105
+ });
106
+
107
+ isScrolled = true;
108
+ buttonToClick.click();
109
+ buttonToClick.focus();
110
+
111
+ }, 100);
112
+
113
+ }, false);
114
+
72
115
 
73
116
  // Set the on click for the tab buttons, these will open the details box it matches too
74
117
  buttons.forEach((button) => {
@@ -76,6 +119,8 @@ export const setTabsEventHandlers = function(tabsElement: Element){
76
119
  button.addEventListener("click", (e) => {
77
120
  e.preventDefault();
78
121
 
122
+ isClicked = true;
123
+
79
124
  if (button.classList.contains('disabled'))
80
125
  return false
81
126
 
@@ -84,6 +129,16 @@ export const setTabsEventHandlers = function(tabsElement: Element){
84
129
  buttonLoopItem.setAttribute('aria-pressed', buttonPressed);
85
130
  });
86
131
 
132
+ if(!isScrolled){
133
+
134
+ buttonWrapper.scroll({
135
+ top: 0,
136
+ left: button.offsetLeft,
137
+ behavior: 'smooth'
138
+ });
139
+ }
140
+ isScrolled = false;
141
+
87
142
  details.forEach((detail, detailsIndex) => {
88
143
  let detailsOpen = button.getAttribute('data-index') == detailsIndex ? true : false;
89
144
 
@@ -93,6 +148,13 @@ export const setTabsEventHandlers = function(tabsElement: Element){
93
148
  detail.removeAttribute('open')
94
149
  });
95
150
 
151
+ if(button.matches(':last-child')){
152
+ nextButton.setAttribute('disabled','disabled');
153
+ }
154
+ else {
155
+ nextButton.removeAttribute('disabled');
156
+ }
157
+
96
158
  // Data layer Open Event
97
159
  window.dataLayer = window.dataLayer || [];
98
160
  window.dataLayer.push({
@@ -112,6 +174,59 @@ export const setTabsEventHandlers = function(tabsElement: Element){
112
174
  });
113
175
  });
114
176
 
177
+ nextButton.addEventListener("click", (e) => {
178
+ e.preventDefault();
179
+
180
+ let currentTab = buttonWrapper.querySelector('[aria-pressed="true"]');
181
+ let nextTab = currentTab.nextSibling;
182
+ if(nextTab)
183
+ nextTab.click();
184
+ });
185
+
186
+
187
+ if(tabsElement.classList.contains('tabs--guided')){
188
+
189
+ var touchstartX = 0;
190
+ var touchstartY = 0;
191
+ var touchendX = 0;
192
+ var touchendY = 0;
193
+
194
+ details.forEach((detail) => {
195
+
196
+ detail.addEventListener("touchstart", (event) => {
197
+ event.stopPropagation();
198
+
199
+ touchstartX = event.changedTouches[0].screenX;
200
+ touchstartY = event.changedTouches[0].screenY;
201
+ });
202
+
203
+ detail.addEventListener("touchend", (event) => {
204
+
205
+ event.stopPropagation();
206
+ touchendX = event.changedTouches[0].screenX;
207
+ touchendY = event.changedTouches[0].screenY;
208
+ let direction = getSwipeDirection(touchstartX,touchstartY,touchendX,touchendY);
209
+ let currentTab = buttonWrapper.querySelector('[aria-pressed="true"]');
210
+
211
+ switch (direction) {
212
+ case 'left':
213
+
214
+ let nextTab = currentTab.nextSibling;
215
+ if(nextTab)
216
+ nextTab.click();
217
+
218
+ break;
219
+ case 'right':
220
+
221
+ let prevTab = currentTab.previousSibling;
222
+ if(prevTab)
223
+ prevTab.click();
224
+
225
+ break;
226
+ }
227
+ });
228
+ });
229
+ }
115
230
  }
116
231
 
117
232
  export const openFirstTab = function(tabsElement: Element){