Skip to content

Commit

Permalink
feat(controller/autocomplete): adding new setting that prevents bindi…
Browse files Browse the repository at this point in the history
…ng the document click event
  • Loading branch information
korgon committed Oct 24, 2024
1 parent 8b31d14 commit 7aaa6ee
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,70 @@ describe('Autocomplete Controller', () => {
});
});

it('closes autocomplete via `setFocused` call when the document click events are made', async () => {
acConfig.selector = '.ss-ac';
document.body.innerHTML = '<div class="click-me"><input type="text" class="ss-ac"/></div>';

const inputEl: HTMLInputElement = document.querySelectorAll('.ss-ac')[0] as HTMLInputElement;

const controller = new AutocompleteController(acConfig, {
client: new MockClient(globals, {}),
store: new AutocompleteStore(acConfig, services),
urlManager,
eventManager: new EventManager(),
profiler: new Profiler(),
logger: new Logger(),
tracker: new Tracker(globals),
});

const setFocusedSpy = jest.spyOn(controller, 'setFocused');

await controller.bind();
const query = 'bumpers';
inputEl.value = query;
inputEl.dispatchEvent(new Event('input'));

document.querySelector('.click-me')?.dispatchEvent(new Event('click', { bubbles: true }));

expect(setFocusedSpy).toHaveBeenCalled();
});

it('disables document click (settings.disableClickOutside)', async () => {
acConfig.selector = '.ss-ac';
document.body.innerHTML = '<div class="click-me"><input type="text" class="ss-ac"/></div>';

const config = {
...acConfig,
settings: {
...acConfig.settings,
disableClickOutside: true,
},
};

const inputEl: HTMLInputElement = document.querySelectorAll('.ss-ac')[0] as HTMLInputElement;

const controller = new AutocompleteController(config, {
client: new MockClient(globals, {}),
store: new AutocompleteStore(acConfig, services),
urlManager,
eventManager: new EventManager(),
profiler: new Profiler(),
logger: new Logger(),
tracker: new Tracker(globals),
});

const setFocusedSpy = jest.spyOn(controller, 'setFocused');

await controller.bind();
const query = 'bumpers';
inputEl.value = query;
inputEl.dispatchEvent(new Event('input'));

document.querySelector('.click-me')?.dispatchEvent(new Event('click', { bubbles: true }));

expect(setFocusedSpy).not.toHaveBeenCalled();
});

it('does not serialize other form input elements normally (settings.serializeForm)', async () => {
document.body.innerHTML =
'<div><form action="/search.html"><input type="hidden" name="view" value="shop"/><input type="text" id="search_query"/></form></div>';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,10 @@ export class AutocompleteController extends AbstractController {
this.searchTrending();
}

document.addEventListener('click', this.handlers.document.click);
// if we are not preventing via `disableClickOutside` setting
if (!this.config.settings?.disableClickOutside) {
document.addEventListener('click', this.handlers.document.click);
}
}

searchTrending = async (): Promise<void> => {
Expand Down
1 change: 1 addition & 0 deletions packages/snap-controller/src/Autocomplete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The `AutocompleteController` is used when making queries to the API `autocomplet
| globals | keys defined here will be passed to the API request (can overwrite global config)|| |
| settings.integratedSpellCorrection | integrated spell correction feature flag | false | |
| settings.initializeFromUrl | initialize the controller with query parameter from URL (pre-fill input with current search) | true | |
| settings.disableClickOutside | prevent the autocomplete from closing on clicks to the document | false | |
| settings.syncInputs | if the selector targets multiple inputs, the value of those inputs will be synced | true | |
| settings.serializeForm | if no action is specified in the config and a form element is found for the input, additional elements that are found will be added to the generated URLs (eg. hidden form input) | false | |
| settings.facets.trim | facets that do not change results will be removed | true | |
Expand Down
1 change: 1 addition & 0 deletions packages/snap-store-mobx/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export type AutocompleteStoreConfigSettings = {
initializeFromUrl?: boolean;
syncInputs?: boolean;
serializeForm?: boolean;
disableClickOutside?: boolean;
facets?: FacetStoreConfig & {
fields?: {
[field: string]: FacetStoreConfig;
Expand Down

0 comments on commit 7aaa6ee

Please sign in to comment.