From d00f143a348ab10be6324b3b34fd23374821e83c Mon Sep 17 00:00:00 2001 From: Juan Munoz Date: Mon, 30 Oct 2023 14:30:17 +0100 Subject: [PATCH] refactor: Implement debounce to improve performance (#46) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: implement debounce for input event listener Signed-off-by: Juan Muñoz * test: fix tests by awaiting the onFilterInput fn Signed-off-by: Juan Muñoz * chore: update README Signed-off-by: Juan Muñoz * chore: remove unused reject fn in promise Signed-off-by: Juan Muñoz * chore: making 500 the default delay for debounce Signed-off-by: Juan Muñoz --------- Signed-off-by: Juan Muñoz --- README.md | 24 ++++++++++++------------ src/oscd-filtered-list.ts | 25 +++++++++++++++++++------ test/oscd-filtered-list.spec.ts | 20 ++++++++++---------- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 598f346..3233bdf 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,15 @@ npm start To run a local development server that serves the basic demo located in `demo/index.html` +## `src/OscdFilteredList.ts`: + +### Exports + +| Kind | Name | Declaration | Module | Package | +| --------------------------- | -------------------- | ---------------- | -------------------------- | ------- | +| `custom-element-definition` | `oscd-filtered-list` | OscdFilteredList | /src/oscd-filtered-list.js | | +| `js` | `OscdFilteredList` | OscdFilteredList | src/OscdFilteredList.ts | | + ## `src/oscd-filtered-list.ts`: ### class: `OscdFilteredList`, `oscd-filtered-list` @@ -115,9 +124,9 @@ To run a local development server that serves the basic demo located in `demo/in #### Methods -| Name | Privacy | Description | Parameters | Return | Inherited From | -| --------------- | ------- | ----------- | ---------- | ------ | -------------- | -| `onFilterInput` | | | | `void` | | +| Name | Privacy | Description | Parameters | Return | Inherited From | +| --------------- | ------- | ----------- | ---------- | --------------- | -------------- | +| `onFilterInput` | public | | | `Promise` | | #### Events @@ -143,14 +152,5 @@ To run a local development server that serves the basic demo located in `demo/in | `js` | `redispatchEvent` | redispatchEvent | src/oscd-filtered-list.ts | | | `js` | `OscdFilteredList` | OscdFilteredList | src/oscd-filtered-list.ts | | -## `src/OscdFilteredList.ts`: - -### Exports - -| Kind | Name | Declaration | Module | Package | -| --------------------------- | -------------------- | ---------------- | -------------------------- | ------- | -| `custom-element-definition` | `oscd-filtered-list` | OscdFilteredList | /src/oscd-filtered-list.js | | -| `js` | `OscdFilteredList` | OscdFilteredList | src/OscdFilteredList.ts | | - © 2023 Alliander N.V. diff --git a/src/oscd-filtered-list.ts b/src/oscd-filtered-list.ts index ab3204f..354eff7 100644 --- a/src/oscd-filtered-list.ts +++ b/src/oscd-filtered-list.ts @@ -20,6 +20,17 @@ import { TextField } from '@material/mwc-textfield'; import '@material/mwc-list/mwc-list-item-base'; import { ListItem } from '@material/mwc-list/mwc-list-item'; +function debounce(callback: () => void, delay = 500): Promise { + let timeout: any; + return new Promise(resolve => { + clearTimeout(timeout); + timeout = setTimeout(() => { + callback(); + resolve(); + }, delay); + }); +} + function slotItem(item: Element): Element { if (!item.closest('oscd-filtered-list') || !item.parentElement) return item; if (item.parentElement instanceof OscdFilteredList) return item; @@ -145,12 +156,14 @@ export class OscdFilteredList extends LitElement { .forEach(item => (item.selected = select)); } - onFilterInput(): void { - Array.from( - this.querySelectorAll( - 'mwc-list-item, mwc-check-list-item, mwc-radio-list-item' - ) - ).forEach(item => hideFiltered(item as ListItem, this.searchField.value)); + public async onFilterInput(): Promise { + return debounce(() => { + Array.from( + this.querySelectorAll( + 'mwc-list-item, mwc-check-list-item, mwc-radio-list-item' + ) + ).forEach(item => hideFiltered(item as ListItem, this.searchField.value)); + }); } firstUpdated(): void { diff --git a/test/oscd-filtered-list.spec.ts b/test/oscd-filtered-list.spec.ts index 409718c..a240cc7 100644 --- a/test/oscd-filtered-list.spec.ts +++ b/test/oscd-filtered-list.spec.ts @@ -142,7 +142,7 @@ describe('oscd-filtered-list', () => { describe('allows to filter on', () => { it('directly slotted mwc-check-list-item', async () => { element.searchField.value = 'item1'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; @@ -155,7 +155,7 @@ describe('oscd-filtered-list', () => { it('directly slotted twoline mwc-check-list-item', async () => { element.searchField.value = 'item2sec'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; @@ -168,7 +168,7 @@ describe('oscd-filtered-list', () => { it('uses space as logic AND ', async () => { element.searchField.value = 'item item3sec'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems = @@ -180,7 +180,7 @@ describe('oscd-filtered-list', () => { it('nested mwc-list-item elements', async () => { element.searchField.value = 'nesteditem5'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems = @@ -192,7 +192,7 @@ describe('oscd-filtered-list', () => { it('nested mwc-radio-list-item elements', async () => { element.searchField.value = 'nesteditem6'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems = @@ -204,7 +204,7 @@ describe('oscd-filtered-list', () => { it('items value attribute', async () => { element.searchField.value = 'item7'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems = @@ -216,7 +216,7 @@ describe('oscd-filtered-list', () => { it('allows filtering with a ? wildcard', async () => { element.searchField.value = 'item?'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const hiddenItems = element.querySelectorAll('.hidden').length; @@ -225,7 +225,7 @@ describe('oscd-filtered-list', () => { it('allows filtering with a * wildcard', async () => { element.searchField.value = 'te*sec'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const hiddenItems = element.querySelectorAll('.hidden').length; @@ -239,7 +239,7 @@ describe('oscd-filtered-list', () => { it('allows filtering with two ? wildcards', async () => { element.searchField.value = 'nest??item'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems = @@ -253,7 +253,7 @@ describe('oscd-filtered-list', () => { it('allows filtering with a * and ? wildcard', async () => { element.searchField.value = 'n*tem?'; - element.onFilterInput(); + await element.onFilterInput(); element.requestUpdate(); await element.updateComplete; const visibleItems =