@financial-times/o-autocomplete 2.0.0 → 2.2.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.
- package/CHANGELOG.md +19 -0
- package/package.json +1 -1
- package/src/js/autocomplete.js +52 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.2.0](https://github.com/Financial-Times/origami/compare/o-autocomplete-v2.1.0...o-autocomplete-v2.2.0) (2026-01-12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Add o-autocomplete showNoOptionsFound option ([a869a04](https://github.com/Financial-Times/origami/commit/a869a04ffc045d526bb1facf7c89215c4933754f))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Add o-autocomplete clear button post-click logic ([67f4fed](https://github.com/Financial-Times/origami/commit/67f4fed14380e8e7b12d3d36156604e0a51e6446))
|
|
14
|
+
|
|
15
|
+
## [2.1.0](https://github.com/Financial-Times/origami/compare/o-autocomplete-v2.0.0...o-autocomplete-v2.1.0) (2025-11-13)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Add o-autocomplete configurable highlighting ([b0b7d01](https://github.com/Financial-Times/origami/commit/b0b7d015ec9c2fe07c18ab57bddafb49468bc3c1))
|
|
21
|
+
|
|
3
22
|
## [2.0.0](https://github.com/Financial-Times/origami/compare/o-autocomplete-v1.10.0...o-autocomplete-v2.0.0) (2025-02-20)
|
|
4
23
|
|
|
5
24
|
### ⚠ BREAKING CHANGES
|
package/package.json
CHANGED
package/src/js/autocomplete.js
CHANGED
|
@@ -16,18 +16,19 @@ import accessibleAutocomplete from '@financial-times/accessible-autocomplete';
|
|
|
16
16
|
/**
|
|
17
17
|
* @param {string} suggestion - Text which is going to be suggested to the user
|
|
18
18
|
* @param {string} query - Text which was typed into the autocomplete text input field by the user
|
|
19
|
+
* @param {boolean} isHighlightCorrespondingToMatch - Boolean to determine whether matching or non-matching characters should be highlighted.
|
|
19
20
|
* @returns {CharacterHighlight[]} An array of arrays which contain two items, the first is the character in the suggestion, the second is a boolean which indicates whether the character should be highlighted.
|
|
20
21
|
*/
|
|
21
|
-
function highlightSuggestion(suggestion, query) {
|
|
22
|
+
function highlightSuggestion(suggestion, query, isHighlightCorrespondingToMatch) {
|
|
22
23
|
const result = suggestion.split('');
|
|
23
24
|
|
|
24
25
|
const matchIndex = suggestion.toLocaleLowerCase().indexOf(query.toLocaleLowerCase());
|
|
25
26
|
return result.map(function(character, index) {
|
|
26
|
-
let shouldHighlight =
|
|
27
|
+
let shouldHighlight = !isHighlightCorrespondingToMatch;
|
|
27
28
|
const hasMatched = matchIndex > -1;
|
|
28
29
|
const characterIsWithinMatch = index >= matchIndex && index <= matchIndex + query.length - 1;
|
|
29
30
|
if (hasMatched && characterIsWithinMatch) {
|
|
30
|
-
shouldHighlight =
|
|
31
|
+
shouldHighlight = isHighlightCorrespondingToMatch;
|
|
31
32
|
}
|
|
32
33
|
return [character, shouldHighlight];
|
|
33
34
|
});
|
|
@@ -182,6 +183,7 @@ function initClearButton(instance) {
|
|
|
182
183
|
* @property {MapOptionToSuggestedValue} [mapOptionToSuggestedValue] - Function which transforms a suggestion before rendering.
|
|
183
184
|
* @property {onConfirm} [onConfirm] - Function which is called when the user selects an option
|
|
184
185
|
* @property {SuggestionTemplate} [suggestionTemplate] - Function to override how a suggestion item is rendered.
|
|
186
|
+
* @property {boolean} [isHighlightCorrespondingToMatch] - Boolean to determine whether matching or non-matching characters should be highlighted.
|
|
185
187
|
* @property {boolean} [autoselect] - Boolean to specify whether first option in suggestions list is highlighted.
|
|
186
188
|
*/
|
|
187
189
|
|
|
@@ -207,9 +209,11 @@ class Autocomplete {
|
|
|
207
209
|
if (opts.onConfirm) {
|
|
208
210
|
this.options.onConfirm = opts.onConfirm;
|
|
209
211
|
}
|
|
212
|
+
this.options.showNoOptionsFound = opts.showNoOptionsFound || false;
|
|
210
213
|
if (opts.suggestionTemplate) {
|
|
211
214
|
this.options.suggestionTemplate = opts.suggestionTemplate;
|
|
212
215
|
}
|
|
216
|
+
this.options.isHighlightCorrespondingToMatch = Boolean(opts.isHighlightCorrespondingToMatch);
|
|
213
217
|
if (opts.autoselect) {
|
|
214
218
|
this.options.autoselect = opts.autoselect;
|
|
215
219
|
}
|
|
@@ -244,7 +248,33 @@ class Autocomplete {
|
|
|
244
248
|
* @returns {void}
|
|
245
249
|
*/
|
|
246
250
|
this.options.source = (query, populateOptions) => {
|
|
247
|
-
|
|
251
|
+
// One way this function can be invoked is following a clearButton click event.
|
|
252
|
+
|
|
253
|
+
// The consumer-provided `customSource()` function can be wrapped in `debounce()`, creating the potential
|
|
254
|
+
// for a user-defined delay between the invocation of the `customSource()` and `callback()` functions.
|
|
255
|
+
// This delay could be longer than the 100ms frequency at which accessible-autocomplete polls the value of the input.
|
|
256
|
+
|
|
257
|
+
// The following code blocks accommodate the coincident of these circumstances.
|
|
258
|
+
|
|
259
|
+
// A clearButton click event will hide the loading pane and set the input value as an empty string.
|
|
260
|
+
if (query) {
|
|
261
|
+
// Therefore only show the loading pane if a `query` (i.e. input) value is present
|
|
262
|
+
// so as to avoid temporarily re-showing the loading pane prior to this function's callback hiding it once again.
|
|
263
|
+
showLoadingPane(this);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// A clearButton click event will blur the input field, resulting in the listbox of options becoming hidden
|
|
267
|
+
// (but without de-populating the options).
|
|
268
|
+
if (!query) {
|
|
269
|
+
// If the accessible-autocomplete poll occurs after a clearButton click event
|
|
270
|
+
// but before this function's callback is invoked then the listbox and its options will be re-displayed.
|
|
271
|
+
// When the callback eventually runs, it will de-populate the options, consequently re-hiding the listbox.
|
|
272
|
+
// To prevent this, in the event of no `query` value being present
|
|
273
|
+
// (where, logically, there will be no corresponding options),
|
|
274
|
+
// immediately de-populate the options rather than waiting for the callback to do so.
|
|
275
|
+
populateOptions([]);
|
|
276
|
+
}
|
|
277
|
+
|
|
248
278
|
/**
|
|
249
279
|
* @param {Array<string>} options - The options which match the rext which was typed into the autocomplete by the user
|
|
250
280
|
* @returns {void}
|
|
@@ -282,7 +312,7 @@ class Autocomplete {
|
|
|
282
312
|
cssNamespace: 'o-autocomplete',
|
|
283
313
|
displayMenu: 'overlay',
|
|
284
314
|
defaultValue: this.options.defaultValue || '',
|
|
285
|
-
showNoOptionsFound:
|
|
315
|
+
showNoOptionsFound: this.options.showNoOptionsFound,
|
|
286
316
|
autoselect: this.options.autoselect || false,
|
|
287
317
|
templates: {
|
|
288
318
|
/**
|
|
@@ -293,10 +323,17 @@ class Autocomplete {
|
|
|
293
323
|
* @returns {string|undefined} HTML string to represent a single suggestion.
|
|
294
324
|
*/
|
|
295
325
|
suggestion: (option, query) => {
|
|
326
|
+
const isHighlightCorrespondingToMatch = this.options.isHighlightCorrespondingToMatch;
|
|
327
|
+
|
|
296
328
|
// If the suggestionTemplate override option is provided,
|
|
297
329
|
// use that to render the suggestion.
|
|
298
330
|
if(typeof this.options.suggestionTemplate === 'function') {
|
|
299
|
-
return this.options.suggestionTemplate(
|
|
331
|
+
return this.options.suggestionTemplate(
|
|
332
|
+
option,
|
|
333
|
+
query,
|
|
334
|
+
highlightSuggestion,
|
|
335
|
+
isHighlightCorrespondingToMatch
|
|
336
|
+
);
|
|
300
337
|
}
|
|
301
338
|
if (typeof option === 'object') {
|
|
302
339
|
// If the `mapOptionToSuggestedValue` function is defined
|
|
@@ -315,7 +352,7 @@ class Autocomplete {
|
|
|
315
352
|
throw new Error(`The option trying to be displayed as a suggestion is not a string, it is "${typeof option}". o-autocomplete can only display strings as suggestions. Define a \`mapOptionToSuggestedValue\` function to convert the option into a string to be used as the suggestion.`);
|
|
316
353
|
}
|
|
317
354
|
|
|
318
|
-
return this.suggestionTemplate(option);
|
|
355
|
+
return this.suggestionTemplate(option, isHighlightCorrespondingToMatch);
|
|
319
356
|
},
|
|
320
357
|
/**
|
|
321
358
|
* Used when a suggestion is selected, the return value of this will be used as the value for the input element.
|
|
@@ -371,7 +408,7 @@ class Autocomplete {
|
|
|
371
408
|
placeholder: '',
|
|
372
409
|
cssNamespace: 'o-autocomplete',
|
|
373
410
|
displayMenu: 'overlay',
|
|
374
|
-
showNoOptionsFound:
|
|
411
|
+
showNoOptionsFound: this.options.showNoOptionsFound,
|
|
375
412
|
templates: {
|
|
376
413
|
suggestion: this.suggestionTemplate.bind(this)
|
|
377
414
|
}
|
|
@@ -387,15 +424,20 @@ class Autocomplete {
|
|
|
387
424
|
* Used when rendering suggestions, the return value of this will be used as the innerHTML for a single suggestion.
|
|
388
425
|
*
|
|
389
426
|
* @param {string} suggestedValue The suggestion to apply the template with.
|
|
427
|
+
* @param {boolean} isHighlightCorrespondingToMatch Boolean to determine whether matching or non-matching characters should be highlighted.
|
|
390
428
|
* @returns {string} HTML string to be represent a single suggestion.
|
|
391
429
|
*/
|
|
392
|
-
suggestionTemplate (suggestedValue) {
|
|
430
|
+
suggestionTemplate (suggestedValue, isHighlightCorrespondingToMatch) {
|
|
393
431
|
// o-autocomplete has a UI design to highlight characters in the suggestions.
|
|
394
432
|
const input = this.autocompleteEl.querySelector('input');
|
|
395
433
|
/**
|
|
396
434
|
* @type {CharacterHighlight[]} An array of arrays which contain two items, the first is the character in the suggestion, the second is a boolean which indicates whether the character should be highlighted.
|
|
397
435
|
*/
|
|
398
|
-
const characters = highlightSuggestion(
|
|
436
|
+
const characters = highlightSuggestion(
|
|
437
|
+
suggestedValue,
|
|
438
|
+
input ? input.value : suggestedValue,
|
|
439
|
+
isHighlightCorrespondingToMatch
|
|
440
|
+
);
|
|
399
441
|
|
|
400
442
|
let output = '';
|
|
401
443
|
for (const [character, shoudHighlight] of characters) {
|