@iamproperty/components 7.6.3--beta3 → 7.6.3

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 (137) hide show
  1. package/assets/css/components/actionbar.component.css +1 -1
  2. package/assets/css/components/actionbar.component.css.map +1 -1
  3. package/assets/css/components/address-lookup.component.css +1 -1
  4. package/assets/css/components/address-lookup.component.css.map +1 -1
  5. package/assets/css/components/barchart.component.css +1 -1
  6. package/assets/css/components/barchart.component.css.map +1 -1
  7. package/assets/css/components/calendar.component.css +1 -1
  8. package/assets/css/components/calendar.component.css.map +1 -1
  9. package/assets/css/components/card.component.css +1 -1
  10. package/assets/css/components/card.component.css.map +1 -1
  11. package/assets/css/components/carousel.component.css +1 -1
  12. package/assets/css/components/carousel.component.css.map +1 -1
  13. package/assets/css/components/collapsible-side.css +1 -1
  14. package/assets/css/components/collapsible-side.css.map +1 -1
  15. package/assets/css/components/content.component.css +1 -1
  16. package/assets/css/components/content.component.css.map +1 -1
  17. package/assets/css/components/doughnutchart.component.css +1 -1
  18. package/assets/css/components/doughnutchart.component.css.map +1 -1
  19. package/assets/css/components/fileupload.css +1 -1
  20. package/assets/css/components/fileupload.css.map +1 -1
  21. package/assets/css/components/modal.component.css +1 -1
  22. package/assets/css/components/modal.component.css.map +1 -1
  23. package/assets/css/components/multi-step-modal.component.css +1 -1
  24. package/assets/css/components/multi-step-modal.component.css.map +1 -1
  25. package/assets/css/components/multiselect.css +1 -1
  26. package/assets/css/components/multiselect.css.map +1 -1
  27. package/assets/css/components/nav.component.css +1 -1
  28. package/assets/css/components/nav.component.css.map +1 -1
  29. package/assets/css/components/pagination.css +1 -1
  30. package/assets/css/components/pagination.css.map +1 -1
  31. package/assets/css/components/rating.component.css +1 -0
  32. package/assets/css/components/rating.component.css.map +1 -0
  33. package/assets/css/components/slider.css +1 -1
  34. package/assets/css/components/slider.css.map +1 -1
  35. package/assets/css/components/split-button.component.css +1 -1
  36. package/assets/css/components/split-button.component.css.map +1 -1
  37. package/assets/css/components/tabs.component.css +1 -1
  38. package/assets/css/components/tabs.component.css.map +1 -1
  39. package/assets/css/components/tag.component.css +1 -1
  40. package/assets/css/components/tag.component.css.map +1 -1
  41. package/assets/css/components/video-modal.component.css +1 -1
  42. package/assets/css/components/video-modal.component.css.map +1 -1
  43. package/assets/css/core.min.css +1 -1
  44. package/assets/css/core.min.css.map +1 -1
  45. package/assets/css/style.min.css +1 -1
  46. package/assets/css/style.min.css.map +1 -1
  47. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  48. package/assets/js/components/actionbar/actionbar.component.min.js +2 -2
  49. package/assets/js/components/address-lookup/address-lookup.component.js +91 -66
  50. package/assets/js/components/address-lookup/address-lookup.component.min.js +5 -6
  51. package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
  52. package/assets/js/components/advanced-select/advanced-select.component.min.js +3 -3
  53. package/assets/js/components/advanced-select/advanced-select.component.min.js.map +1 -1
  54. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  55. package/assets/js/components/barchart/barchart.component.min.js +4 -4
  56. package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
  57. package/assets/js/components/calendar/calendar.component.min.js +4 -4
  58. package/assets/js/components/card/card.component.min.js +2 -2
  59. package/assets/js/components/carousel/carousel.component.min.js +3 -3
  60. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +2 -2
  61. package/assets/js/components/content/content.component.min.js +2 -2
  62. package/assets/js/components/darkmode/darkmode.component.min.js +1 -1
  63. package/assets/js/components/doughnutchart/doughnutchart.component.min.js +3 -3
  64. package/assets/js/components/fileupload/fileupload.component.min.js +2 -2
  65. package/assets/js/components/filter-card/filter-card.component.min.js +1 -1
  66. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  67. package/assets/js/components/header/header.component.min.js +1 -1
  68. package/assets/js/components/inline-edit/inline-edit.component.min.js +1 -1
  69. package/assets/js/components/input/input.component.min.js +1 -1
  70. package/assets/js/components/input-range/input-range.component.min.js +1 -1
  71. package/assets/js/components/marketing/marketing.component.min.js +1 -1
  72. package/assets/js/components/menu/menu.component.min.js +1 -1
  73. package/assets/js/components/milestone/milestone.component.min.js +1 -1
  74. package/assets/js/components/milestone-group/milestone-group.component.min.js +1 -1
  75. package/assets/js/components/modal/modal.component.js +47 -24
  76. package/assets/js/components/modal/modal.component.min.js +10 -11
  77. package/assets/js/components/modal/modal.component.min.js.map +1 -1
  78. package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
  79. package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js +3 -3
  80. package/assets/js/components/multiselect/multiselect.component.min.js +2 -2
  81. package/assets/js/components/nav/nav.component.min.js +2 -2
  82. package/assets/js/components/notification/notification.component.min.js +1 -1
  83. package/assets/js/components/pagination/pagination.component.min.js +3 -3
  84. package/assets/js/components/password/password.component.min.js +1 -1
  85. package/assets/js/components/popover/popover.component.min.js +1 -1
  86. package/assets/js/components/rank/rank.component.min.js +1 -1
  87. package/assets/js/components/rankings/rankings.component.min.js +1 -1
  88. package/assets/js/components/rating/rating.component.js +66 -0
  89. package/assets/js/components/rating/rating.component.min.js +15 -0
  90. package/assets/js/components/rating/rating.component.min.js.map +1 -0
  91. package/assets/js/components/record-card/record-card.component.min.js +1 -1
  92. package/assets/js/components/search/search.component.min.js +5 -5
  93. package/assets/js/components/search/search.component.min.js.map +1 -1
  94. package/assets/js/components/slider/slider.component.min.js +2 -2
  95. package/assets/js/components/split-button/split-button.component.min.js +2 -2
  96. package/assets/js/components/std-address-lookup/std-address-lookup.component.js +383 -383
  97. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js +18 -19
  98. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js.map +1 -1
  99. package/assets/js/components/table/table.component.min.js +1 -1
  100. package/assets/js/components/table-ajax/table-ajax.component.min.js +1 -1
  101. package/assets/js/components/table-basic/table-basic.component.min.js +1 -1
  102. package/assets/js/components/table-no-submit/table-no-submit.component.min.js +1 -1
  103. package/assets/js/components/table-submit/table-submit.component.min.js +1 -1
  104. package/assets/js/components/tabs/tabs.component.min.js +3 -3
  105. package/assets/js/components/tag/tag.component.min.js +2 -2
  106. package/assets/js/components/tooltip/tooltip.component.min.js +1 -1
  107. package/assets/js/components/video-card/video-card.component.min.js +1 -1
  108. package/assets/js/components/video-modal/video-modal.component.min.js +2 -2
  109. package/assets/js/components/word-count/word-count.component.min.js +1 -1
  110. package/assets/js/modules/advanced-select.js +11 -9
  111. package/assets/js/scripts.bundle.js +2 -2
  112. package/assets/js/scripts.bundle.js.map +1 -1
  113. package/assets/js/scripts.bundle.min.js +2 -2
  114. package/assets/js/scripts.bundle.min.js.map +1 -1
  115. package/assets/js/scripts.js +2 -4
  116. package/assets/sass/components/modal.component.scss +179 -198
  117. package/assets/sass/components/rating.component.css +212 -0
  118. package/assets/sass/elements/button__group.css +25 -4
  119. package/assets/sass/elements/buttons--compact.scss +12 -3
  120. package/assets/sass/elements/buttons--special.scss +2 -1
  121. package/assets/sass/elements/forms.scss +33 -21
  122. package/assets/sass/elements/highlight.css +7 -0
  123. package/assets/sass/elements/label.scss +17 -0
  124. package/assets/sass/foundations/colours.scss +10 -0
  125. package/assets/sass/utilities/colours.scss +4 -3
  126. package/assets/sass/utilities/font-awesome-iso-fallbacks.scss +6 -0
  127. package/assets/sass/utilities/wider-colours.scss +1 -0
  128. package/assets/ts/components/address-lookup/address-lookup.component.ts +154 -190
  129. package/assets/ts/components/modal/modal.component.ts +63 -26
  130. package/assets/ts/components/rating/rating.component.ts +86 -0
  131. package/assets/ts/components/std-address-lookup/std-address-lookup.component.ts +383 -383
  132. package/assets/ts/modules/advanced-select.ts +13 -9
  133. package/assets/ts/scripts.ts +2 -2
  134. package/dist/components.es.js +88 -88
  135. package/dist/components.umd.js +214 -204
  136. package/package.json +1 -1
  137. package/src/components/Rating/Rating.vue +22 -0
@@ -1,6 +1,6 @@
1
1
  import Cookies from 'js-cookie';
2
2
  import advancedSelect from '../../modules/advanced-select';
3
- import {isValidPostcode} from '../../modules/helpers';
3
+ import { isValidPostcode } from '../../modules/helpers';
4
4
 
5
5
  // Data layer Web component created
6
6
  declare global {
@@ -22,14 +22,14 @@ class iamAddressLookup extends HTMLElement {
22
22
  const assetLocation = document.body.hasAttribute('data-assets-location')
23
23
  ? document.body.getAttribute('data-assets-location')
24
24
  : '/assets';
25
-
25
+
26
26
  const loadCSS = `@import "${assetLocation}/css/components/address-lookup.component.css";`;
27
27
 
28
28
  const template = document.createElement('template');
29
29
  template.innerHTML = `
30
30
  <style>
31
31
  ${loadCSS}
32
-
32
+
33
33
  </style>
34
34
  <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous" />
35
35
  <div class="wrapper">
@@ -46,11 +46,10 @@ class iamAddressLookup extends HTMLElement {
46
46
  <div>
47
47
  <label class="mb-1"><span class="title text-lowercase"></span>
48
48
  <span>
49
- <input type="text" name="postcode" class="${this.hasAttribute('data-input-class') ? this.getAttribute('data-input-class') : ''}" list="address-lookup__addressess" autocomplete="one-time-code" aria-autocomplete="none" placeholder="${this?.hasAttribute('data-placeholder') ? this?.getAttribute('data-placeholder') : 'Postcode'}" value="${this.hasAttribute('data-postcode-value')? this.getAttribute('data-postcode-value') : ''}" part="input" />
49
+ <input type="text" name="postcode" class="${this.hasAttribute('data-input-class') ? this.getAttribute('data-input-class') : ''}" list="address-lookup__addressess" autocomplete="one-time-code" aria-autocomplete="none" placeholder="${this?.hasAttribute('data-placeholder') ? this?.getAttribute('data-placeholder') : 'Postcode'}" value="${this.hasAttribute('data-postcode-value') ? this.getAttribute('data-postcode-value') : ''}" part="input" />
50
50
  <button id="postcode__submit" class="suffix fa-regular fa-search" part="suffix"></button>
51
51
  </span>
52
52
  </label>
53
-
54
53
  <span class="invalid-feedback mb-2" id="invalid-feedback-address-lookup">${this.hasAttribute('data-error-msg') ? this.getAttribute('data-error-msg') : 'Required address fields'}</span>
55
54
 
56
55
  <div class="datalist__wrapper ${this.hasAttribute('data-list-class') ? this.getAttribute('data-list-class') : ''}" tabindex="0" part="list-wrapper">
@@ -70,7 +69,7 @@ class iamAddressLookup extends HTMLElement {
70
69
 
71
70
  <div class="manual-address pb-2 js-hide">
72
71
  <slot part="contents"></slot>
73
- <button class="btn btn-tertiary switch-to-lookup-btn" type="button" part="button">${this.hasAttribute('data-postcode-lookup-label')? this.getAttribute('data-postcode-lookup-label') : 'Use postcode lookup'}</button>
72
+ <button class="btn btn-tertiary switch-to-lookup-btn" type="button" part="button">${this.hasAttribute('data-postcode-lookup-label') ? this.getAttribute('data-postcode-lookup-label') : 'Use postcode lookup'}</button>
74
73
  <slot name="after"></slot>
75
74
  </div>
76
75
  <div class="pre-filled p-2 js-hide">
@@ -94,7 +93,9 @@ class iamAddressLookup extends HTMLElement {
94
93
  const lookupWrapper = this.shadowRoot.querySelector('.postcode-lookup');
95
94
  const manualWrapper = this.shadowRoot.querySelector('.manual-address');
96
95
  const preFilledWrapper = this.shadowRoot.querySelector('.pre-filled');
97
- const list = this.querySelector('datalist[slot="preloadedList"]') ? this.querySelector('datalist[slot="preloadedList"]') : this.shadowRoot.querySelector('.datalist__wrapper datalist');
96
+ const list = this.querySelector('datalist[slot="preloadedList"]')
97
+ ? this.querySelector('datalist[slot="preloadedList"]')
98
+ : this.shadowRoot.querySelector('.datalist__wrapper datalist');
98
99
  const listWrapper = this.shadowRoot.querySelector('.datalist__wrapper');
99
100
  const switchManualBtn = this.shadowRoot.querySelector('.switch-to-manual-btn');
100
101
  const switchLookupBtn = this.shadowRoot.querySelector('.switch-to-lookup-btn');
@@ -114,55 +115,47 @@ class iamAddressLookup extends HTMLElement {
114
115
  const matchedAddressUse = this.shadowRoot.querySelector('.matched .use-matched');
115
116
  const matchedAddressEntered = this.shadowRoot.querySelector('.matched .use-entered');
116
117
 
118
+ let cacheSearchQuery = '';
119
+
117
120
  Array.from(this.shadowRoot.querySelectorAll('.title')).forEach((titleElement) => {
118
121
  titleElement.innerHTML = title;
119
122
  });
120
123
 
121
124
  // #region functions
122
125
  function checkFilled(component): void {
123
-
124
126
  const preFilledAddress = component.shadowRoot.querySelector('.pre-filled-address');
125
127
  let preFilled = true;
126
128
  preFilledAddress.innerHTML = '';
127
129
 
128
-
129
130
  Array.from(
130
131
  component.querySelectorAll('input[required],input[data-required],select[required],select[data-required]')
131
132
  ).forEach((input) => {
132
133
  let value = input.hasAttribute('data-value') ? input.getAttribute('data-value') : input.value;
133
134
 
134
- if(input.tagName == "SELECT" && component.querySelector(`[value="${input.value}"][data-value]`))
135
+ if (input.tagName == 'SELECT' && component.querySelector(`[value="${input.value}"][data-value]`))
135
136
  value = component.querySelector(`[value="${input.value}"][data-value]`).getAttribute('data-value');
136
137
 
137
- if (!value){
138
-
139
- if(input.closest('.atleastone')){
140
-
141
- if(!atleastone.querySelector('input:valid, input.is-valid')){
138
+ if (!value) {
139
+ if (input.closest('.atleastone')) {
140
+ if (!atleastone.querySelector('input:valid, input.is-valid')) {
142
141
  preFilled = false;
143
142
  }
144
- }
145
- else {
143
+ } else {
146
144
  preFilled = false;
147
145
  }
148
-
149
- }
150
- else {
146
+ } else {
151
147
  preFilledAddress.innerHTML += value + (/^-?\d+$/.test(value) ? ' ' : ', ');
152
148
  }
153
149
  });
154
150
 
155
151
  preFilledAddress.innerHTML = preFilledAddress.innerHTML.slice(0, -2);
156
152
 
157
-
158
153
  // If has label then use that
159
154
 
160
155
  if (preFilled) {
161
-
162
- if(component.querySelector('[name="label"]'))
156
+ if (component.querySelector('[name="label"]'))
163
157
  preFilledAddress.innerHTML = component.querySelector('[name="label"]').value;
164
158
 
165
-
166
159
  // If has label then use that
167
160
 
168
161
  preFilledWrapper.classList.remove('js-hide');
@@ -172,13 +165,10 @@ class iamAddressLookup extends HTMLElement {
172
165
  }
173
166
 
174
167
  function openManualWrapper(): void {
175
-
176
-
177
168
  lookupWrapper.classList.add('js-hide');
178
169
  manualWrapper.classList.remove('js-hide');
179
170
 
180
171
  Array.from(manualWrapper.querySelectorAll('[data-required]')).forEach((input) => {
181
-
182
172
  input.setAttribute('required', 'true');
183
173
  });
184
174
 
@@ -186,50 +176,42 @@ class iamAddressLookup extends HTMLElement {
186
176
  }
187
177
 
188
178
  const atleastoneValidate = (): void => {
189
-
190
- if(atleastone.querySelector('input:valid, input.is-valid')){
191
- Array.from(atleastone.querySelectorAll('input')).forEach(element => {
179
+ if (atleastone.querySelector('input:valid, input.is-valid')) {
180
+ Array.from(atleastone.querySelectorAll('input')).forEach((element) => {
192
181
  element.removeAttribute('required');
193
182
  });
194
- }
195
- else {
183
+ } else {
196
184
  Array.from(atleastone.querySelectorAll('input')).forEach((input) => {
197
185
  input.setAttribute('required', 'true');
198
186
  });
199
187
  }
200
- }
201
-
188
+ };
202
189
 
203
190
  const fillInputs = (values): void => {
204
-
205
191
  lookupWrapper.classList.add('js-hide');
206
192
  manualWrapper.classList.remove('js-hide');
207
193
 
208
194
  Object.keys(values).forEach((key) => {
209
195
  const value = values[key];
210
196
  let input = false;
211
- if (this.querySelector(`[data-name="${key}"]`))
212
- input = this.querySelector(`[data-name="${key}"]`);
213
- else if (this.querySelector(`[data-name-alt="${key}"]`))
214
- input = this.querySelector(`[data-name-alt="${key}"]`);
215
- else if (this.querySelector(`[name="${key}"]`))
216
- input = this.querySelector(`[name="${key}"]`);
217
-
218
- if(input && input.tagName == "SELECT" && value.id){
197
+ if (this.querySelector(`[data-name="${key}"]`)) input = this.querySelector(`[data-name="${key}"]`);
198
+ else if (this.querySelector(`[data-name-alt="${key}"]`)) input = this.querySelector(`[data-name-alt="${key}"]`);
199
+ else if (this.querySelector(`[name="${key}"]`)) input = this.querySelector(`[name="${key}"]`);
200
+
201
+ if (input && input.tagName == 'SELECT' && value.id) {
219
202
  input.value = value.id;
220
-
221
- }
222
- else if(input && value != ''){
223
-
203
+ } else if (input && value != '') {
224
204
  input.value = value;
225
205
 
226
- if(input.hasAttribute('data-readonly')){
206
+ if (input.hasAttribute('data-readonly')) {
227
207
  input.setAttribute('readonly', true);
228
208
  input.classList.add('is-valid');
229
209
  }
230
- }
231
- else if(value != ""){
232
- this.insertAdjacentHTML('beforeend',`<input type="hidden" class="inserted" data-hidden name="${key}" value="${value}" />`);
210
+ } else if (value != '') {
211
+ this.insertAdjacentHTML(
212
+ 'beforeend',
213
+ `<input type="hidden" class="inserted" data-hidden name="${key}" value="${value}" />`
214
+ );
233
215
  }
234
216
 
235
217
  if (this.querySelector(`[data-name-2="${key}"]`))
@@ -241,46 +223,48 @@ class iamAddressLookup extends HTMLElement {
241
223
  });
242
224
  lookup.removeAttribute('required');
243
225
 
244
- if(atleastone){
245
-
226
+ if (atleastone) {
246
227
  atleastoneValidate();
247
228
  }
248
229
 
249
- if(!this.hasAttribute('data-force-manual'))
250
- checkFilled(this);
251
- }
230
+ if (!this.hasAttribute('data-force-manual')) checkFilled(this);
231
+ };
252
232
 
253
233
  const search = async (searchValue, paginate = false): any => {
234
+ if (!paginate && searchValue === cacheSearchQuery) {
235
+ if (list?.children?.length) {
236
+ list?.classList.remove('loading');
237
+ list?.classList.remove('noresults');
238
+ listWrapper?.focus();
239
+ list?.querySelector('option')?.focus();
240
+ return true;
241
+ }
242
+ }
254
243
 
255
244
  // check if postcode is valid
256
245
  const limit = this.hasAttribute('data-limit') ? parseInt(this.getAttribute('data-limit')) : 100;
257
-
258
- if(paginate)
259
- pageNumber++;
260
- else
261
- pageNumber = 1;
246
+
247
+ if (paginate) pageNumber++;
248
+ else pageNumber = 1;
262
249
 
263
250
  let ajaxURL = this.getAttribute('data-url');
264
251
  ajaxURL += `${encodeURI(searchValue)}&page[number]=${pageNumber}&page[size]=${limit}`;
265
-
266
- if(this.hasAttribute('data-url-2')){
252
+
253
+ if (this.hasAttribute('data-url-2')) {
267
254
  ajaxURL += this.getAttribute('data-url-2');
268
255
  }
269
256
 
270
257
  const postcode = searchValue; // TODO: remove when postcode comes from response
271
258
 
272
- if(this.hasAttribute('data-postcode')){
273
-
274
- if (!isValidPostcode(searchValue)){
275
- return "Invalid postcode, please enter a valid postcode";
276
- }
277
- else {
278
- if(!paginate)
279
- list.innerHTML = "";
259
+ if (this.hasAttribute('data-postcode')) {
260
+ if (!isValidPostcode(searchValue)) {
261
+ return 'Invalid postcode, please enter a valid postcode';
262
+ } else {
263
+ if (!paginate) list.innerHTML = '';
280
264
  list?.classList.add('loading');
281
265
  list?.classList.remove('noresults');
282
266
  lookup?.classList.remove('is-invalid');
283
- errorMsg?.innerHTML = "";
267
+ errorMsg?.innerHTML = '';
284
268
  list?.classList.remove('show-welsh-banner');
285
269
 
286
270
  Array.from(this.querySelectorAll('[data-required]')).forEach((input) => {
@@ -307,7 +291,7 @@ class iamAddressLookup extends HTMLElement {
307
291
 
308
292
  // Create a new controller so it can be aborted if new fetch made
309
293
  window.controller[ajaxURL] = new AbortController();
310
- const { signal } = controller[ajaxURL];
294
+ const { signal } = window.controller[ajaxURL];
311
295
 
312
296
  try {
313
297
  return await fetch(ajaxURL, {
@@ -329,13 +313,21 @@ class iamAddressLookup extends HTMLElement {
329
313
  const addresses = response['data'] ? response['data'] : response;
330
314
 
331
315
  addresses.forEach((address) => {
332
-
333
316
  // Deal with agent platform response
334
317
  if (typeof address.attributes == 'object' && address.attributes.label) {
318
+ if (address.id) address.attributes.id = address.id;
319
+
320
+ if (address.relationships)
321
+ address.attributes = Object.assign(address.attributes, address.relationships);
322
+
335
323
  const values = JSON.stringify(address.attributes);
336
324
  listString += `<option data-values='${values}' >${address.attributes.label}</option>`;
337
- }
338
- else if (typeof address.value == 'object') {
325
+ } else if (typeof address.value == 'object') {
326
+ if (address.id) address.attributes.id = address.id;
327
+
328
+ if (address.relationships)
329
+ address.attributes = Object.assign(address.attributes, address.relationships);
330
+
339
331
  const values = JSON.stringify(address.value);
340
332
  listString += `<option data-values='${values}'>${address['label']}, ${postcode}</option>`;
341
333
  } else {
@@ -354,37 +346,35 @@ class iamAddressLookup extends HTMLElement {
354
346
  listString += `<option data-values='${values}'>${itemString}, ${postcode}</option>`; // TODO postcode should come from the response
355
347
  }
356
348
  }
357
-
358
-
359
349
  });
360
350
 
361
- if(paginate)
362
- list.innerHTML += listString;
363
- else
364
- list.innerHTML = listString;
351
+ if (paginate) list.innerHTML += listString;
352
+ else list.innerHTML = listString;
353
+
354
+ // Cache the search value to prevent further calls
355
+ cacheSearchQuery = searchValue;
365
356
 
366
- if(addresses.length){
357
+ if (addresses.length) {
367
358
  list?.classList.remove('loading');
368
-
369
- }
370
- else {
371
-
359
+ } else {
372
360
  list?.classList.remove('loading');
373
361
  list?.classList.add('noresults');
374
362
  }
375
363
 
376
364
  // pagination
377
- if(response.meta && response.meta.current_page && response.meta.total_pages && response.meta.total_pages > response.meta.current_page){
378
-
379
- paginationWrapper?.innerHTML = `<div class="bg-light text-center p-2"><p class="m-0">Showing 1-${response.meta.current_page * limit} of ${response.meta.total_results} addresses <br /><button type="button" data-next="${response.meta.current_page+1}" class="mt-1 mb-0 btn btn-action"><i class="fa-regular fa-eye me-1"></i>Show more addresses</button></p></div>`;
380
- }
381
- else {
365
+ if (
366
+ response.meta &&
367
+ response.meta.current_page &&
368
+ response.meta.total_pages &&
369
+ response.meta.total_pages > response.meta.current_page
370
+ ) {
371
+ paginationWrapper?.innerHTML = `<div class="bg-light text-center p-2"><p class="m-0">Showing 1-${response.meta.current_page * limit} of ${response.meta.total_results} addresses <br /><button type="button" data-next="${response.meta.current_page + 1}" class="mt-1 mb-0 btn btn-action"><i class="fa-regular fa-eye me-1"></i>Show more addresses</button></p></div>`;
372
+ } else {
382
373
  paginationWrapper?.innerHTML = '';
383
374
  }
384
375
 
385
- if(response.meta && response.meta.welsh_language){
386
-
387
- list?.classList.add('show-welsh-banner');
376
+ if (response.meta && response.meta.welsh_language) {
377
+ list?.classList.add('show-welsh-banner');
388
378
  }
389
379
  listWrapper?.focus();
390
380
  list?.querySelector('option')?.focus();
@@ -392,22 +382,42 @@ class iamAddressLookup extends HTMLElement {
392
382
  return true;
393
383
  });
394
384
  } catch (error) {
395
- console.log(error)
396
- return "There has been a problem. Please try again in a few moments.";
385
+ if (error?.name === 'AbortError') {
386
+ return true;
387
+ }
388
+ console.log(error);
389
+ return 'There has been a problem. Please try again in a few moments.';
390
+ }
391
+ };
392
+
393
+ let searchTimer: number | undefined;
394
+
395
+ const triggerSearch = (raw: string, paginate = false, immediate = false) => {
396
+ const value = (raw ?? '').trim();
397
+
398
+ if (value.length < minChars) return;
399
+
400
+ if (immediate) {
401
+ if (searchTimer) window.clearTimeout(searchTimer);
402
+ void search(value, paginate);
403
+ return;
397
404
  }
405
+
406
+ if (searchTimer) window.clearTimeout(searchTimer);
407
+ searchTimer = window.setTimeout(() => {
408
+ void search(value, paginate);
409
+ }, 200);
398
410
  };
399
411
 
400
412
  // #endregion
401
413
 
402
- // #region check attributes and trigger functions
403
- if(!this.hasAttribute('data-force-manual'))
404
- checkFilled(this);
414
+ // #region check attributes and trigger functions
415
+ if (!this.hasAttribute('data-force-manual')) checkFilled(this);
405
416
 
406
417
  this.addEventListener('filled', () => {
407
- if(!this.hasAttribute('data-force-manual'))
408
- checkFilled(this);
418
+ if (!this.hasAttribute('data-force-manual')) checkFilled(this);
409
419
  });
410
-
420
+
411
421
  if (this.hasAttribute('data-use')) {
412
422
  const useLabel = this.hasAttribute('data-use-label') ? this.getAttribute('data-use-label') : 'Use saved address';
413
423
  const useCheckbox = `<div><input type="checkbox" name="use" id="use" value="yes"><label for="use">${useLabel}</label></div>`;
@@ -423,7 +433,7 @@ class iamAddressLookup extends HTMLElement {
423
433
  manualWrapper.classList.remove('js-hide');
424
434
 
425
435
  const values = JSON.parse(this.getAttribute('data-use'));
426
-
436
+
427
437
  Object.keys(values).forEach((key) => {
428
438
  const value = values[key];
429
439
  if (this.querySelector(`[data-name="${key}"]`)) this.querySelector(`[data-name="${key}"]`).value = value;
@@ -433,8 +443,7 @@ class iamAddressLookup extends HTMLElement {
433
443
  }
434
444
  });
435
445
 
436
-
437
- if(this.hasAttribute('data-use-default')){
446
+ if (this.hasAttribute('data-use-default')) {
438
447
  lookupWrapper.querySelector('[name="use"]').checked = true;
439
448
 
440
449
  const values = JSON.parse(this.getAttribute('data-use'));
@@ -446,13 +455,12 @@ class iamAddressLookup extends HTMLElement {
446
455
  fillInputs({});
447
456
  }
448
457
 
449
- if(this.classList.contains('show-pagination'))
458
+ if (this.classList.contains('show-pagination'))
450
459
  paginationWrapper?.innerHTML = `<div class="bg-light text-center p-2"><p class="m-0">Showing 1-500 of 585 addresses <br /><button type="button" data-next="2" class="mt-1 mb-0 btn btn-action"><i class="fa-regular fa-eye me-1"></i>Show more addresses</button></p></div>`;
451
-
452
- if(this.classList.contains('scroll-to-bottom-results'))
453
- paginationWrapper.scrollIntoView({container: 'nearest'});
460
+
461
+ if (this.classList.contains('scroll-to-bottom-results')) paginationWrapper.scrollIntoView({ container: 'nearest' });
454
462
  // #endregion
455
-
463
+
456
464
  // #region event listeners
457
465
  preFilledAddressBtn.addEventListener('click', () => {
458
466
  preFilledWrapper.classList.add('js-hide');
@@ -464,18 +472,18 @@ class iamAddressLookup extends HTMLElement {
464
472
  lookupWrapper.classList.remove('js-hide');
465
473
  manualWrapper.classList.add('js-hide');
466
474
 
467
- list.innerHTML = "";
475
+ list.innerHTML = '';
468
476
  list?.classList.remove('loading');
469
477
  list?.classList.remove('noresults');
470
478
  lookup?.classList.remove('is-invalid');
471
- errorMsg?.innerHTML = "";
479
+ errorMsg?.innerHTML = '';
472
480
  list?.classList.remove('show-welsh-banner');
473
481
 
474
482
  lookup.focus();
475
- lookup.value = "";
483
+ lookup.value = '';
476
484
 
477
- if(lookup?.hasAttribute('data-placeholder'))
478
- lookup.setAttribute('placeholder',lookup?.getAttribute('data-placeholder'));
485
+ if (lookup?.hasAttribute('data-placeholder'))
486
+ lookup.setAttribute('placeholder', lookup?.getAttribute('data-placeholder'));
479
487
 
480
488
  const updateEvent = new CustomEvent('switch-to-lookup');
481
489
  this.dispatchEvent(updateEvent);
@@ -501,46 +509,33 @@ class iamAddressLookup extends HTMLElement {
501
509
  lookupWrapper.scrollIntoView();
502
510
  });
503
511
 
504
- lookup.addEventListener('keyup', async (e) => {
505
-
506
- if (![40,38,13].includes(e.keyCode) && lookup.value.length >= minChars){
507
- const valid = await search(lookup.value);
508
-
509
- console.log(errorMsg)
510
- console.log(valid)
511
-
512
- if(valid != true){
513
- lookup?.classList.add('is-invalid');
514
- errorMsg?.innerHTML = valid;
515
- }
516
- }
517
-
518
- if (e.keyCode == 13){
519
- const valid = await search(lookup.value);
520
-
521
- if(valid != true){
522
- lookup?.classList.add('is-invalid');
523
- errorMsg?.innerHTML = valid;
524
- }
512
+ lookup.addEventListener('keyup', (e) => {
513
+ if (e.keyCode === 13) {
514
+ triggerSearch(lookup.value, false, true);
525
515
  }
526
516
  });
527
517
 
528
- lookup.addEventListener('change', async () => {
518
+ lookup.addEventListener('input', () => {
519
+ lookup.classList.remove('is-invalid');
520
+ if (errorMsg) errorMsg.innerHTML = '';
529
521
 
530
- if (lookup.value.length >= minChars) {
522
+ const v = (lookup.value ?? '').trim();
531
523
 
532
- const valid = await search(lookup.value);
533
-
534
- if(valid != true){
535
- lookup?.classList.add('is-invalid');
536
- errorMsg?.innerHTML = valid;
524
+ if (v.length < minChars) {
525
+ list.innerHTML = '';
526
+ if (paginationWrapper) {
527
+ paginationWrapper.innerHTML = '';
537
528
  }
529
+ list?.classList.remove('loading', 'noresults');
530
+ cacheSearchQuery = '';
531
+ return;
538
532
  }
533
+
534
+ triggerSearch(v);
539
535
  });
540
536
 
541
537
  list.addEventListener('click', (e) => {
542
- if(e.target.tagName == "OPTION"){
543
-
538
+ if (e.target.tagName == 'OPTION') {
544
539
  const values = JSON.parse(e.target.getAttribute('data-values'));
545
540
 
546
541
  fillInputs(values);
@@ -551,71 +546,44 @@ class iamAddressLookup extends HTMLElement {
551
546
  });
552
547
 
553
548
  atleastone?.addEventListener('input', (e) => {
554
-
555
549
  Array.from(atleastone.querySelectorAll('[data-required]')).forEach((input) => {
556
550
  input.setAttribute('required', 'true');
557
551
  });
558
-
559
552
 
560
553
  atleastoneValidate();
561
554
  });
562
555
 
563
- postcodeSubmit?.addEventListener('click', async () => {
564
- const valid = await search(lookup.value);
565
-
566
- if(valid != true){
567
- lookup?.classList.add('is-invalid');
568
- errorMsg?.innerHTML = valid;
569
- }
570
- });
571
-
572
- this?.addEventListener('search', async () => {
573
- const valid = await search(lookup.value);
574
-
575
- if(valid != true){
576
- lookup?.classList.add('is-invalid');
577
- errorMsg?.innerHTML = valid;
578
- }
556
+ postcodeSubmit?.addEventListener('click', () => {
557
+ triggerSearch(lookup.value, false, true);
579
558
  });
580
559
 
581
560
  this?.addEventListener('close-button-pressed', () => {
582
-
583
- list.innerHTML = "";
561
+ list.innerHTML = '';
584
562
  list?.classList.remove('loading');
585
563
  list?.classList.remove('noresults');
586
564
  lookup?.classList.remove('is-invalid');
587
- errorMsg?.innerHTML = "";
565
+ errorMsg?.innerHTML = '';
588
566
  list?.classList.remove('show-welsh-banner');
589
567
 
590
568
  lookup.focus();
591
569
  });
592
-
593
- paginationWrapper?.addEventListener('click', async (e) => {
594
-
595
- if(e.target.tagName == "BUTTON"){
596
-
597
- const valid = await search(lookup.value, true);
598
570
 
599
- if(valid != true){
600
- lookup?.classList.add('is-invalid');
601
- errorMsg?.innerHTML = valid;
602
- }
571
+ paginationWrapper?.addEventListener('click', (e) => {
572
+ if (e.target.tagName === 'BUTTON') {
573
+ triggerSearch(lookup.value, true, true);
603
574
  }
604
575
  });
576
+
605
577
  // #endregion
606
578
 
607
579
  // #region Matched address
608
580
 
609
- if(this.hasAttribute('data-matched')){
610
-
581
+ if (this.hasAttribute('data-matched')) {
611
582
  matchedAddressWrapper?.classList.remove('d-none');
612
583
 
613
-
614
- if(this.hasAttribute('data-matched-label'))
615
- matchedAddress?.innerHTML = this.getAttribute('data-matched-label');
584
+ if (this.hasAttribute('data-matched-label')) matchedAddress?.innerHTML = this.getAttribute('data-matched-label');
616
585
 
617
586
  matchedAddressEntered?.addEventListener('click', () => {
618
-
619
587
  matchedAddressWrapper?.remove();
620
588
 
621
589
  const useCheckbox = this.shadowRoot?.querySelector('[name="use"]');
@@ -625,19 +593,17 @@ class iamAddressLookup extends HTMLElement {
625
593
  manualWrapper.classList.remove('js-hide');
626
594
 
627
595
  const values = JSON.parse(this.getAttribute('data-use'));
628
-
596
+
629
597
  Object.keys(values).forEach((key) => {
630
598
  const value = values[key];
631
599
  if (this.querySelector(`[data-name="${key}"]`)) this.querySelector(`[data-name="${key}"]`).value = value;
632
600
  else if (this.querySelector(`[name="${key}"]`)) this.querySelector(`[name="${key}"]`).value = value;
633
601
  });
634
-
602
+
635
603
  checkFilled(this);
636
604
  });
637
605
 
638
-
639
606
  matchedAddressUse?.addEventListener('click', () => {
640
-
641
607
  matchedAddressWrapper?.remove();
642
608
 
643
609
  const values = JSON.parse(this.getAttribute('data-matched'));
@@ -645,8 +611,7 @@ class iamAddressLookup extends HTMLElement {
645
611
  fillInputs(values);
646
612
  checkFilled(this);
647
613
  });
648
- }
649
- else {
614
+ } else {
650
615
  matchedAddressWrapper?.remove();
651
616
  }
652
617
  // #endregion
@@ -659,7 +624,6 @@ class iamAddressLookup extends HTMLElement {
659
624
  }
660
625
 
661
626
  attributeChangedCallback(attrName, oldVal, newVal): void {
662
-
663
627
  const addressComponent = this.querySelector('iam-address-lookup');
664
628
 
665
629
  switch (attrName) {