From 3a80996bec96e465d23a30387af707289f4089e3 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 27 May 2021 23:54:44 -0400 Subject: [PATCH 1/4] feat(filters): convert jQuery to native elements on multiple filters --- .../common/src/filters/compoundDateFilter.ts | 16 +-- .../common/src/filters/compoundInputFilter.ts | 128 ++++++++++-------- .../common/src/filters/dateRangeFilter.ts | 4 +- packages/common/src/filters/inputFilter.ts | 96 +++++++------ .../common/src/filters/inputMaskFilter.ts | 71 +++++----- .../common/src/filters/nativeSelectFilter.ts | 2 +- .../services/__tests__/filter.service.spec.ts | 9 +- 7 files changed, 171 insertions(+), 155 deletions(-) diff --git a/packages/common/src/filters/compoundDateFilter.ts b/packages/common/src/filters/compoundDateFilter.ts index 31532d7f4..014bc6fd2 100644 --- a/packages/common/src/filters/compoundDateFilter.ts +++ b/packages/common/src/filters/compoundDateFilter.ts @@ -140,12 +140,8 @@ export class CompoundDateFilter implements Filter { destroyObjectDomElementProps(this.flatInstance); } } - if (this._filterElm) { - this._filterElm.remove(); - } - if (this._selectOperatorElm) { - this._selectOperatorElm.remove(); - } + this._filterElm?.remove?.(); + this._selectOperatorElm?.remove?.(); } hide() { @@ -225,14 +221,16 @@ export class CompoundDateFilter implements Filter { }; // add the time picker when format is UTC (Z) or has the 'h' (meaning hours) - if (outputFormat && (outputFormat === 'Z' || outputFormat.toLowerCase().indexOf('h') > -1)) { + if (outputFormat && (outputFormat === 'Z' || outputFormat.toLowerCase().includes('h'))) { pickerOptions.enableTime = true; } // merge options with optional user's custom options this._flatpickrOptions = { ...pickerOptions, ...userFilterOptions }; - let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : ''; - if (this.columnFilter && this.columnFilter.placeholder) { + + // create the DOM element & add an ID and filter class + let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? ''; + if (this.columnFilter?.placeholder) { placeholder = this.columnFilter.placeholder; } diff --git a/packages/common/src/filters/compoundInputFilter.ts b/packages/common/src/filters/compoundInputFilter.ts index 71b0823b0..c9660df2e 100644 --- a/packages/common/src/filters/compoundInputFilter.ts +++ b/packages/common/src/filters/compoundInputFilter.ts @@ -11,18 +11,20 @@ import { OperatorDetail, SlickGrid, } from '../interfaces/index'; -import { buildSelectOperatorHtmlString } from './filterUtilities'; -import { getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; +import { buildSelectOperator } from './filterUtilities'; +import { emptyElement, getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; +import { BindingEventService } from '../services/bindingEvent.service'; import { TranslaterService } from '../services/translater.service'; export class CompoundInputFilter implements Filter { + protected _bindEventService: BindingEventService; protected _clearFilterTriggered = false; protected _debounceTypingDelay = 0; protected _shouldTriggerQuery = true; protected _inputType = 'text'; - protected $filterElm: any; - protected $filterInputElm: any; - protected $selectOperatorElm: any; + protected _filterElm!: HTMLDivElement; + protected _filterInputElm!: HTMLInputElement; + protected _selectOperatorElm!: HTMLSelectElement; protected _operator?: OperatorType | OperatorString; grid!: SlickGrid; searchTerms: SearchTerm[] = []; @@ -30,14 +32,16 @@ export class CompoundInputFilter implements Filter { callback!: FilterCallback; timer?: NodeJS.Timeout; - constructor(protected readonly translaterService: TranslaterService) { } + constructor(protected readonly translaterService: TranslaterService) { + this._bindEventService = new BindingEventService(); + } /** Getter for the Grid Options pulled through the Grid Object */ protected get gridOptions(): GridOption { return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; } - /** Getter for the Filter Operator */ + /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { return this.columnDef && this.columnDef.filter || {}; } @@ -83,7 +87,7 @@ export class CompoundInputFilter implements Filter { this.grid = args.grid; this.callback = args.callback; this.columnDef = args.columnDef; - this.operator = args.operator || ''; + this.operator = args.operator as OperatorString; this.searchTerms = (args.hasOwnProperty('searchTerms') ? args.searchTerms : []) || []; // analyze if we have any keyboard debounce delay (do we wait for user to finish typing before querying) @@ -96,25 +100,25 @@ export class CompoundInputFilter implements Filter { // step 1, create the DOM Element of the filter which contain the compound Operator+Input // and initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(searchTerm); + this._filterElm = this.createDomElement(searchTerm); - // step 3, subscribe to the input change event and run the callback when that happens + // step 3, subscribe to the keyup event and run the callback when that happens // also add/remove "filled" class for styling purposes // we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner) - this.$filterInputElm.on('keyup blur change wheel', this.onTriggerEvent.bind(this)); - this.$selectOperatorElm.on('change', this.onTriggerEvent.bind(this)); + this._bindEventService.bind(this._filterInputElm, ['keyup', 'blur', 'change', 'wheel'], this.onTriggerEvent.bind(this)); + this._bindEventService.bind(this._selectOperatorElm, 'change', this.onTriggerEvent.bind(this)); } /** * Clear the filter value */ clear(shouldTriggerQuery = true) { - if (this.$filterElm && this.$selectOperatorElm) { + if (this._filterElm && this._selectOperatorElm) { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; - this.$selectOperatorElm.val(0); - this.$filterInputElm.val(''); + this._selectOperatorElm.value = ''; + this._filterInputElm.value = ''; this.onTriggerEvent(undefined); } } @@ -123,26 +127,23 @@ export class CompoundInputFilter implements Filter { * destroy the filter */ destroy() { - if (this.$filterElm && this.$selectOperatorElm) { - this.$filterElm.off('keyup blur change wheel').remove(); - this.$selectOperatorElm.off('change'); - } - this.$filterElm = null; - this.$selectOperatorElm = null; + this._bindEventService.unbindAll(); + this._filterElm?.remove?.(); + this._selectOperatorElm?.remove?.(); } - /** Set value(s) on the DOM element */ + /** Set value(s) on the DOM element */ setValues(values: SearchTerm[] | SearchTerm, operator?: OperatorType | OperatorString) { if (values) { const newValue = Array.isArray(values) ? values[0] : values; - this.$filterInputElm.val(newValue); + this._filterInputElm.value = `${newValue ?? ''}`; } // set the operator, in the DOM as well, when defined this.operator = operator || this.defaultOperator; - if (operator && this.$selectOperatorElm) { + if (operator && this._selectOperatorElm) { const operatorShorthand = mapOperatorToShorthandDesignation(this.operator); - this.$selectOperatorElm.val(operatorShorthand); + this._selectOperatorElm.value = operatorShorthand; } } @@ -150,13 +151,23 @@ export class CompoundInputFilter implements Filter { // protected functions // ------------------ - protected buildInputHtmlString() { + protected buildInputElement(): HTMLInputElement { const columnId = this.columnDef?.id ?? ''; - let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : ''; - if (this.columnFilter && this.columnFilter.placeholder) { + + // create the DOM element & add an ID and filter class + let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? ''; + if (this.columnFilter?.placeholder) { placeholder = this.columnFilter.placeholder; } - return ``; + + const inputElm = document.createElement('input'); + inputElm.type = this._inputType || 'text'; + inputElm.className = `form-control compound-input filter-${columnId}`; + inputElm.autocomplete = 'off'; + inputElm.placeholder = placeholder; + inputElm.setAttribute('role', 'presentation'); + + return inputElm; } /** Get the available operator option values to populate the operator select dropdown list */ @@ -212,16 +223,22 @@ export class CompoundInputFilter implements Filter { */ protected createDomElement(searchTerm?: SearchTerm) { const columnId = this.columnDef?.id ?? ''; - const $headerElm = this.grid.getHeaderRowColumn(columnId); - $($headerElm).empty(); + const headerElm = this.grid.getHeaderRowColumn(columnId); + emptyElement(headerElm); // create the DOM Select dropdown for the Operator - const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues()); - this.$selectOperatorElm = $(selectOperatorHtmlString); - this.$filterInputElm = $(this.buildInputHtmlString()); - const $filterContainerElm = $(`
`); - const $containerInputGroup = $(`
`); - const $operatorInputGroupAddon = $(`
`); + this._selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues()); + this._filterInputElm = this.buildInputElement(); + const emptySpanElm = document.createElement('span'); + + const filterContainerElm = document.createElement('div'); + filterContainerElm.className = `form-group search-filter filter-${columnId}`; + + const containerInputGroupElm = document.createElement('div'); + containerInputGroupElm.className = 'input-group'; + + const operatorInputGroupAddonElm = document.createElement('div'); + operatorInputGroupAddonElm.className = 'input-group-addon input-group-prepend operator'; /* the DOM element final structure will be
@@ -231,54 +248,55 @@ export class CompoundInputFilter implements Filter {
*/ - $operatorInputGroupAddon.append(this.$selectOperatorElm); - $containerInputGroup.append($operatorInputGroupAddon); - $containerInputGroup.append(this.$filterInputElm); + operatorInputGroupAddonElm.appendChild(this._selectOperatorElm); + containerInputGroupElm.appendChild(operatorInputGroupAddonElm); + containerInputGroupElm.appendChild(this._filterInputElm); + containerInputGroupElm.appendChild(emptySpanElm); // create the DOM element & add an ID and filter class - $filterContainerElm.append($containerInputGroup); + filterContainerElm.appendChild(containerInputGroupElm); - this.$filterInputElm.val(searchTerm); - this.$filterInputElm.data('columnId', columnId); + this._filterInputElm.value = `${searchTerm ?? ''}`; + this._filterInputElm.dataset.columnid = `${columnId}`; if (this.operator) { const operatorShorthand = mapOperatorToShorthandDesignation(this.operator); - this.$selectOperatorElm.val(operatorShorthand); + this._selectOperatorElm.value = operatorShorthand; } // if there's a search term, we will add the "filled" class for styling purposes if (searchTerm) { - $filterContainerElm.addClass('filled'); + this._filterInputElm.classList.add('filled'); } // append the new DOM element to the header row - if ($filterContainerElm && typeof $filterContainerElm.appendTo === 'function') { - $filterContainerElm.appendTo($headerElm); + if (filterContainerElm) { + headerElm.appendChild(filterContainerElm); } - return $filterContainerElm; + return filterContainerElm; } /** * Event trigger, could be called by the Operator dropdown or the input itself and we will cover the following (keyup, change, mousewheel & spinner) * We will trigger the Filter Service callback from this handler */ - protected onTriggerEvent(event: KeyboardEvent | undefined) { + protected onTriggerEvent(event: Event | undefined) { if (this._clearFilterTriggered) { this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); - this.$filterElm.removeClass('filled'); + this._filterElm.classList.remove('filled'); } else { const eventType = event?.type ?? ''; - const selectedOperator = this.$selectOperatorElm.find('option:selected').val(); - let value = this.$filterInputElm.val() as string; + const selectedOperator = this._selectOperatorElm.value as OperatorString; + let value = this._filterInputElm.value as string; const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace; if (typeof value === 'string' && enableWhiteSpaceTrim) { value = value.trim(); } - (value !== null && value !== undefined && value !== '') ? this.$filterElm.addClass('filled') : this.$filterElm.removeClass('filled'); - const callbackArgs = { columnDef: this.columnDef, searchTerms: (value ? [value] : null), operator: selectedOperator || '', shouldTriggerQuery: this._shouldTriggerQuery }; - const typingDelay = (eventType === 'keyup' && event?.key !== 'Enter') ? this._debounceTypingDelay : 0; + (value !== null && value !== undefined && value !== '') ? this._filterElm.classList.add('filled') : this._filterElm.classList.remove('filled'); + const callbackArgs = { columnDef: this.columnDef, searchTerms: (value ? [value] : null), operator: selectedOperator, shouldTriggerQuery: this._shouldTriggerQuery }; + const typingDelay = (eventType === 'keyup' && (event as KeyboardEvent)?.key !== 'Enter') ? this._debounceTypingDelay : 0; if (typingDelay > 0) { clearTimeout(this.timer as NodeJS.Timeout); diff --git a/packages/common/src/filters/dateRangeFilter.ts b/packages/common/src/filters/dateRangeFilter.ts index 254787a62..6ccfc4bbc 100644 --- a/packages/common/src/filters/dateRangeFilter.ts +++ b/packages/common/src/filters/dateRangeFilter.ts @@ -132,9 +132,7 @@ export class DateRangeFilter implements Filter { destroyObjectDomElementProps(this.flatInstance); } } - if (this._filterElm) { - this._filterElm.remove(); - } + this._filterElm?.remove?.(); } hide() { diff --git a/packages/common/src/filters/inputFilter.ts b/packages/common/src/filters/inputFilter.ts index f5099efe3..a023d843a 100644 --- a/packages/common/src/filters/inputFilter.ts +++ b/packages/common/src/filters/inputFilter.ts @@ -8,20 +8,25 @@ import { SlickGrid, } from '../interfaces/index'; import { OperatorType, OperatorString, SearchTerm } from '../enums/index'; +import { BindingEventService } from '../services/bindingEvent.service'; +import { emptyElement } from '../services'; export class InputFilter implements Filter { + protected _bindEventService: BindingEventService; protected _clearFilterTriggered = false; protected _debounceTypingDelay = 0; protected _shouldTriggerQuery = true; protected _inputType = 'text'; protected _timer?: NodeJS.Timeout; - protected $filterElm: any; + protected _filterElm!: HTMLInputElement; grid!: SlickGrid; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; - constructor() { } + constructor() { + this._bindEventService = new BindingEventService(); + } /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { @@ -80,28 +85,25 @@ export class InputFilter implements Filter { // filter input can only have 1 search term, so we will use the 1st array index if it exist const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : ''; - // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); - - // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(filterTemplate, searchTerm); + // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled + this._filterElm = this.createDomElement(searchTerm); - // step 3, subscribe to the input event and run the callback when that happens + // step 2, subscribe to the input event and run the callback when that happens // also add/remove "filled" class for styling purposes // we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner) - this.$filterElm.on('keyup blur change wheel', this.handleInputChange.bind(this)); + this._bindEventService.bind(this._filterElm, ['keyup', 'blur', 'change', 'wheel'], this.handleInputChange.bind(this)); } /** * Clear the filter value */ clear(shouldTriggerQuery = true) { - if (this.$filterElm) { + if (this._filterElm) { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; - this.$filterElm.val(''); - this.$filterElm.trigger('change'); + this._filterElm.value = ''; + this._filterElm.dispatchEvent(new Event('change')); } } @@ -109,14 +111,12 @@ export class InputFilter implements Filter { * destroy the filter */ destroy() { - if (this.$filterElm) { - this.$filterElm.off('keyup blur change wheel').remove(); - } - this.$filterElm = null; + this._bindEventService.unbindAll(); + this._filterElm?.remove?.(); } - getValue() { - return this.$filterElm.val(); + getValue(): string { + return this._filterElm.value; } /** Set value(s) on the DOM element */ @@ -125,7 +125,7 @@ export class InputFilter implements Filter { let searchValue: SearchTerm = ''; for (const value of searchValues) { searchValue = operator ? this.addOptionalOperatorIntoSearchString(value, operator) : value; - this.$filterElm.val(searchValue); + this._filterElm.value = `${searchValue ?? ''}`; } // set the operator when defined @@ -177,64 +177,62 @@ export class InputFilter implements Filter { return outputValue; } - /** - * Create the HTML template as a string - */ - protected buildTemplateHtmlString() { - const columnId = this.columnDef?.id ?? ''; - let placeholder = (this.gridOptions) ? (this.gridOptions.defaultFilterPlaceholder || '') : ''; - if (this.columnFilter && this.columnFilter.placeholder) { - placeholder = this.columnFilter.placeholder; - } - return ``; - } - /** * From the html template string, create a DOM element - * @param filterTemplate + * @param {Object} searchTerm - filter search term + * @returns {Object} DOM element filter */ - protected createDomElement(filterTemplate: string, searchTerm?: SearchTerm) { + protected createDomElement(searchTerm?: SearchTerm) { const columnId = this.columnDef?.id ?? ''; - const $headerElm = this.grid.getHeaderRowColumn(columnId); - $($headerElm).empty(); + const headerElm = this.grid.getHeaderRowColumn(columnId); + emptyElement(headerElm); // create the DOM element & add an ID and filter class - const $filterElm = $(filterTemplate); + let placeholder = this.gridOptions?.defaultFilterPlaceholder ?? ''; + if (this.columnFilter?.placeholder) { + placeholder = this.columnFilter.placeholder; + } + + const inputElm = document.createElement('input'); + inputElm.type = this._inputType || 'text'; + inputElm.className = `form-control search-filter filter-${columnId}`; + inputElm.autocomplete = 'off'; + inputElm.placeholder = placeholder; + inputElm.setAttribute('role', 'presentation'); - $filterElm.val(searchTerm as string); - $filterElm.data('columnId', columnId); + inputElm.value = (searchTerm ?? '') as string; + inputElm.dataset.columnid = `${columnId}`; // if there's a search term, we will add the "filled" class for styling purposes if (searchTerm) { - $filterElm.addClass('filled'); + inputElm.classList.add('filled'); } - // append the new DOM element to the header row - if ($filterElm && typeof $filterElm.appendTo === 'function') { - $filterElm.appendTo($headerElm); - } + // append the new DOM element to the header row & an empty span + headerElm.appendChild(inputElm); + headerElm.appendChild(document.createElement('span')); - return $filterElm; + return inputElm; } /** * Event handler to cover the following (keyup, change, mousewheel & spinner) * We will trigger the Filter Service callback from this handler */ - protected handleInputChange(event: KeyboardEvent & { target: any; }) { + protected handleInputChange(event: Event) { if (this._clearFilterTriggered) { this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); - this.$filterElm.removeClass('filled'); + this._filterElm.classList.remove('filled'); } else { const eventType = event?.type ?? ''; - let value = event?.target?.value ?? ''; + let value = (event?.target as HTMLInputElement)?.value ?? ''; const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace; if (typeof value === 'string' && enableWhiteSpaceTrim) { value = value.trim(); } - value === '' ? this.$filterElm.removeClass('filled') : this.$filterElm.addClass('filled'); + value === '' ? this._filterElm.classList.remove('filled') : this._filterElm.classList.add('filled'); const callbackArgs = { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery }; - const typingDelay = (eventType === 'keyup' && event?.key !== 'Enter') ? this._debounceTypingDelay : 0; + const typingDelay = (eventType === 'keyup' && (event as KeyboardEvent)?.key !== 'Enter') ? this._debounceTypingDelay : 0; if (typingDelay > 0) { clearTimeout(this._timer as NodeJS.Timeout); diff --git a/packages/common/src/filters/inputMaskFilter.ts b/packages/common/src/filters/inputMaskFilter.ts index 9c20568d5..b4b2644d7 100644 --- a/packages/common/src/filters/inputMaskFilter.ts +++ b/packages/common/src/filters/inputMaskFilter.ts @@ -42,47 +42,50 @@ export class InputMaskFilter extends InputFilter { // filter input can only have 1 search term, so we will use the 1st array index if it exist const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : ''; - // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); + // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled + this._filterElm = this.createDomElement(searchTerm); - // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(filterTemplate, searchTerm); - - // step 3, subscribe to the keyup blur change event and run the callback when that happens + // step 2, subscribe to the input event and run the callback when that happens // also add/remove "filled" class for styling purposes + // we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner) + this._bindEventService.bind(this._filterElm, ['keyup', 'blur', 'change'], this.handleInputChange.bind(this)); + } - this.$filterElm.on('keyup blur change', (e: any) => { - let value = ''; - if (e && e.target && e.target.value) { - let targetValue = e.target.value; - const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace; - if (typeof targetValue === 'string' && enableWhiteSpaceTrim) { - targetValue = targetValue.trim(); - } + /** + * Event handler to cover the following (keyup, change, mousewheel & spinner) + * We will trigger the Filter Service callback from this handler + */ + protected handleInputChange(event: Event) { + let value = ''; + if ((event?.target as HTMLInputElement)?.value) { + let targetValue = (event?.target as HTMLInputElement)?.value ?? ''; + const enableWhiteSpaceTrim = this.gridOptions.enableFilterTrimWhiteSpace || this.columnFilter.enableTrimWhiteSpace; + if (typeof targetValue === 'string' && enableWhiteSpaceTrim) { + targetValue = targetValue.trim(); + } - // if it has a mask, we need to do a bit more work - // and replace the filter string by the masked output without triggering an event - const unmaskedValue = this.unmaskValue(targetValue); - const maskedValue = this.maskValue(unmaskedValue); - value = unmaskedValue; + // if it has a mask, we need to do a bit more work + // and replace the filter string by the masked output without triggering an event + const unmaskedValue = this.unmaskValue(targetValue); + const maskedValue = this.maskValue(unmaskedValue); + value = unmaskedValue; - if (e.keyCode >= 48) { - this.$filterElm.val(maskedValue); // replace filter string with masked string - e.preventDefault(); - } + if ((event as KeyboardEvent)?.keyCode >= 48) { + this._filterElm.value = maskedValue; // replace filter string with masked string + event.preventDefault(); } + } - if (this._clearFilterTriggered) { - this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); - this.$filterElm.removeClass('filled'); - } else { - this.$filterElm.addClass('filled'); - this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery }); - } - // reset both flags for next use - this._clearFilterTriggered = false; - this._shouldTriggerQuery = true; - }); + if (this._clearFilterTriggered) { + this.callback(event, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); + this._filterElm.classList.remove('filled'); + } else { + this._filterElm.classList.add('filled'); + this.callback(event, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery }); + } + // reset both flags for next use + this._clearFilterTriggered = false; + this._shouldTriggerQuery = true; } /** From a regular string, we will use the mask to output a new string */ diff --git a/packages/common/src/filters/nativeSelectFilter.ts b/packages/common/src/filters/nativeSelectFilter.ts index 4105b12e2..bfe2c1149 100644 --- a/packages/common/src/filters/nativeSelectFilter.ts +++ b/packages/common/src/filters/nativeSelectFilter.ts @@ -72,7 +72,7 @@ export class NativeSelectFilter implements Filter { // filter input can only have 1 search term, so we will use the 1st array index if it exist let searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : ''; if (typeof searchTerm === 'boolean' || typeof searchTerm === 'number') { - searchTerm = `${searchTerm}`; + searchTerm = `${searchTerm ?? ''}`; } // step 1, create HTML string template diff --git a/packages/common/src/services/__tests__/filter.service.spec.ts b/packages/common/src/services/__tests__/filter.service.spec.ts index 9def3ec2e..53c011b3a 100644 --- a/packages/common/src/services/__tests__/filter.service.spec.ts +++ b/packages/common/src/services/__tests__/filter.service.spec.ts @@ -19,7 +19,7 @@ import { SlickGrid, SlickNamespace, } from '../../interfaces/index'; -import { Filters } from '../../filters'; +import { Filters, InputFilter } from '../../filters'; import { FilterService } from '../filter.service'; import { FilterFactory } from '../../filters/filterFactory'; import { getParsedSearchTermsByFieldType } from '../../filter-conditions'; @@ -133,6 +133,7 @@ describe('FilterService', () => { const filterFactory = new FilterFactory(slickgridConfig, translateService, collectionService); service = new FilterService(filterFactory, pubSubServiceStub, sharedService, backendUtilityService, rxjsResourceStub); slickgridEventHandler = service.eventHandler; + jest.spyOn(gridStub, 'getHeaderRowColumn').mockReturnValue(div); }); afterEach(() => { @@ -175,7 +176,7 @@ describe('FilterService', () => { expect(columnFilters).toEqual({}); expect(filterMetadataArray.length).toBe(1); - expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]); + expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]); }); @@ -261,7 +262,7 @@ describe('FilterService', () => { expect(columnFilters).toEqual({}); expect(filterMetadataArray.length).toBe(1); - expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]); + expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]); }); @@ -1564,7 +1565,7 @@ describe('FilterService', () => { expect(spySetSortCols).toHaveBeenCalledWith([{ columnId: 'file', sortAsc: true }]); expect(columnFilters).toEqual({}); expect(filterMetadataArray.length).toBe(1); - expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]); + expect(filterMetadataArray[0] instanceof InputFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', []]); }); From 7d5e1e859a0331699d6fb07d2d35797d7274d1df Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Sat, 29 May 2021 00:18:50 -0400 Subject: [PATCH 2/4] feat: convert jQuery to native element on few more filters --- .../common/src/filters/nativeSelectFilter.ts | 109 ++++++++++-------- .../services/__tests__/filter.service.spec.ts | 23 ++-- .../common/src/services/filter.service.ts | 5 +- 3 files changed, 74 insertions(+), 63 deletions(-) diff --git a/packages/common/src/filters/nativeSelectFilter.ts b/packages/common/src/filters/nativeSelectFilter.ts index bfe2c1149..f7c120b2e 100644 --- a/packages/common/src/filters/nativeSelectFilter.ts +++ b/packages/common/src/filters/nativeSelectFilter.ts @@ -8,19 +8,24 @@ import { SlickGrid, } from '../interfaces/index'; import { OperatorType, OperatorString, SearchTerm } from '../enums/index'; +import { emptyElement } from '../services/utilities'; import { TranslaterService } from '../services/translater.service'; +import { BindingEventService } from '../services/bindingEvent.service'; export class NativeSelectFilter implements Filter { + protected _bindEventService: BindingEventService; protected _clearFilterTriggered = false; protected _shouldTriggerQuery = true; protected _currentValues: any | any[] = []; - $filterElm: any; + filterElm!: HTMLSelectElement; grid!: SlickGrid; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; - constructor(protected readonly translater: TranslaterService) { } + constructor(protected readonly translater: TranslaterService) { + this._bindEventService = new BindingEventService(); + } /** Getter for the Column Filter itself */ protected get columnFilter(): ColumnFilter { @@ -75,28 +80,25 @@ export class NativeSelectFilter implements Filter { searchTerm = `${searchTerm ?? ''}`; } - // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); - - // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(filterTemplate, searchTerm); + // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled + this.filterElm = this.createDomElement(searchTerm); - // step 3, subscribe to the change event and run the callback when that happens + // step 2, subscribe to the change event and run the callback when that happens // also add/remove "filled" class for styling purposes - this.$filterElm.change(this.handleOnChange.bind(this)); + this._bindEventService.bind(this.filterElm, 'change', this.handleOnChange.bind(this)); } /** * Clear the filter values */ clear(shouldTriggerQuery = true) { - if (this.$filterElm) { + if (this.filterElm) { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; this._currentValues = []; - this.$filterElm.val(''); - this.$filterElm.trigger('change'); + this.filterElm.value = ''; + this.filterElm.dispatchEvent(new Event('change')); } } @@ -104,10 +106,8 @@ export class NativeSelectFilter implements Filter { * destroy the filter */ destroy() { - if (this.$filterElm) { - this.$filterElm.off('change').remove(); - } - this.$filterElm = null; + this._bindEventService.unbindAll(); + this.filterElm?.remove?.(); } /** @@ -121,10 +121,10 @@ export class NativeSelectFilter implements Filter { /** Set value(s) on the DOM element */ setValues(values: SearchTerm | SearchTerm[], operator?: OperatorType | OperatorString) { if (Array.isArray(values)) { - this.$filterElm.val(values[0]); + this.filterElm.value = `${values[0] ?? ''}`; this._currentValues = values; } else if (values) { - this.$filterElm.val(values); + this.filterElm.value = `${values ?? ''}`; this._currentValues = [values]; } @@ -136,63 +136,76 @@ export class NativeSelectFilter implements Filter { // protected functions // ------------------ - protected buildTemplateHtmlString() { - const collection = this.columnFilter && this.columnFilter.collection || []; - if (!Array.isArray(collection)) { - throw new Error('The "collection" passed to the Native Select Filter is not a valid array.'); - } - + /** + * Create and return a select dropdown HTML element created from a collection + * @param {Array} values - list of option values/labels + * @returns {Object} selectElm - Select Dropdown HTML Element + */ + buildFilterSelectFromCollection(collection: any[]): HTMLSelectElement { const columnId = this.columnDef?.id ?? ''; - const labelName = (this.columnFilter.customStructure) ? this.columnFilter.customStructure.label : 'label'; - const valueName = (this.columnFilter.customStructure) ? this.columnFilter.customStructure.value : 'value'; - const isEnabledTranslate = (this.columnFilter.enableTranslateLabel) ? this.columnFilter.enableTranslateLabel : false; + const selectElm = document.createElement('select'); + selectElm.className = `form-control search-filter filter-${columnId}`; - let options = ''; + const labelName = this.columnFilter.customStructure?.label ?? 'label'; + const valueName = this.columnFilter.customStructure?.value ?? 'value'; + const isEnabledTranslate = this.columnFilter?.enableTranslateLabel ?? false; // collection could be an Array of Strings OR Objects if (collection.every(x => typeof x === 'string')) { - collection.forEach((option: string) => { - options += ``; - }); + for (const option of collection) { + const selectOption = document.createElement('option'); + selectOption.value = option; + selectOption.label = option; + selectOption.textContent = option; + selectElm.appendChild(selectOption); + } } else { - collection.forEach((option: any) => { + for (const option of collection) { if (!option || (option[labelName] === undefined && option.labelKey === undefined)) { throw new Error(`A collection with value/label (or value/labelKey when using Locale) is required to populate the Native Select Filter list, for example:: { filter: model: Filters.select, collection: [ { value: '1', label: 'One' } ]')`); } + const labelKey = option.labelKey || option[labelName]; const textLabel = ((option.labelKey || isEnabledTranslate) && this.translater && this.translater.translate && this.translater.getCurrentLanguage && this.translater.getCurrentLanguage()) ? this.translater.translate(labelKey || ' ') : labelKey; - options += ``; - }); + + const selectOption = document.createElement('option'); + selectOption.value = option[valueName]; + selectOption.textContent = textLabel; + selectElm.appendChild(selectOption); + } } - return ``; + + return selectElm; } /** * From the html template string, create a DOM element * @param filterTemplate */ - protected createDomElement(filterTemplate: string, searchTerm?: SearchTerm) { + protected createDomElement(searchTerm?: SearchTerm): HTMLSelectElement { const columnId = this.columnDef?.id ?? ''; - const $headerElm = this.grid.getHeaderRowColumn(columnId); - $($headerElm).empty(); + const headerElm = this.grid.getHeaderRowColumn(columnId); + emptyElement(headerElm); // create the DOM element & add an ID and filter class - const $filterElm = $(filterTemplate); const searchTermInput = (searchTerm || '') as string; - $filterElm.val(searchTermInput); - $filterElm.data('columnId', columnId); + const collection = this.columnFilter?.collection ?? []; + if (!Array.isArray(collection)) { + throw new Error('The "collection" passed to the Native Select Filter is not a valid array.'); + } + + const selectElm = this.buildFilterSelectFromCollection(collection); + selectElm.value = searchTermInput; + selectElm.dataset.columnid = `${columnId || ''}`; if (searchTermInput) { this._currentValues = [searchTermInput]; } - // append the new DOM element to the header row - if ($filterElm && typeof $filterElm.appendTo === 'function') { - $filterElm.appendTo($headerElm); - } + headerElm.appendChild(selectElm); - return $filterElm; + return selectElm; } protected handleOnChange(e: any) { @@ -201,9 +214,9 @@ export class NativeSelectFilter implements Filter { if (this._clearFilterTriggered) { this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); - this.$filterElm.removeClass('filled'); + this.filterElm.classList.remove('filled'); } else { - value === '' ? this.$filterElm.removeClass('filled') : this.$filterElm.addClass('filled'); + value === '' ? this.filterElm.classList.remove('filled') : this.filterElm.classList.add('filled'); this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery }); } diff --git a/packages/common/src/services/__tests__/filter.service.spec.ts b/packages/common/src/services/__tests__/filter.service.spec.ts index 53c011b3a..a2bb61fc0 100644 --- a/packages/common/src/services/__tests__/filter.service.spec.ts +++ b/packages/common/src/services/__tests__/filter.service.spec.ts @@ -19,7 +19,7 @@ import { SlickGrid, SlickNamespace, } from '../../interfaces/index'; -import { Filters, InputFilter } from '../../filters'; +import { Filters, InputFilter, NativeSelectFilter } from '../../filters'; import { FilterService } from '../filter.service'; import { FilterFactory } from '../../filters/filterFactory'; import { getParsedSearchTermsByFieldType } from '../../filter-conditions'; @@ -31,7 +31,6 @@ import { TranslateServiceStub } from '../../../../../test/translateServiceStub'; import { PubSubService } from '../pubSub.service'; import { RxJsResourceStub } from '../../../../../test/rxjsResourceStub'; -jest.mock('flatpickr', () => { }); declare const Slick: SlickNamespace; const DOM_ELEMENT_ID = 'row-detail123'; @@ -201,7 +200,7 @@ describe('FilterService', () => { isActive: { columnDef: mockColumn, columnId: 'isActive', operator: 'EQ', searchTerms: [true], parsedSearchTerms: true, type: FieldType.boolean }, }); expect(filterMetadataArray.length).toBe(1); - expect(filterMetadataArray[0]).toContainEntry(['$filterElm', expect.anything()]); + expect(filterMetadataArray[0] instanceof NativeSelectFilter).toBeTruthy(); expect(filterMetadataArray[0]).toContainEntry(['searchTerms', [true]]); }); @@ -342,7 +341,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); - service.getFiltersMetadata()[0].callback(new CustomEvent('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); + service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); setTimeout(() => { expect(service.getColumnFilters()).toContainEntry(['firstName', expectationColumnFilter]); @@ -371,7 +370,7 @@ describe('FilterService', () => { service.bindLocalOnFilter(gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); - const mockEvent = new CustomEvent('input'); + const mockEvent = new Event('input'); Object.defineProperty(mockEvent, 'target', { writable: true, configurable: true, value: { value: 'John' } }); service.getFiltersMetadata()[0].callback(mockEvent, { columnDef: mockColumn, operator: 'EQ', shouldTriggerQuery: true }); @@ -393,7 +392,7 @@ describe('FilterService', () => { service.init(gridStub); service.bindLocalOnFilter(gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); - service.getFiltersMetadata()[0].callback(new CustomEvent('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); + service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); expect(service.getColumnFilters()).toEqual({}); }); @@ -407,7 +406,7 @@ describe('FilterService', () => { service.bindLocalOnFilter(gridStub); mockArgs.column.filter = { emptySearchTermReturnAllValues: false }; gridStub.onHeaderRowCellRendered.notify(mockArgs as any, new Slick.EventData(), gridStub); - service.getFiltersMetadata()[0].callback(new CustomEvent('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); + service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); expect(service.getColumnFilters()).toContainEntry(['firstName', expectationColumnFilter]); expect(spySearchChange).toHaveBeenCalledWith({ @@ -468,9 +467,9 @@ describe('FilterService', () => { gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs3 as any, new Slick.EventData(), gridStub); - service.getFiltersMetadata()[1].callback(new CustomEvent('input'), { columnDef: mockColumn3 }); - service.getFiltersMetadata()[0].callback(new CustomEvent('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); - service.getFiltersMetadata()[1].callback(new CustomEvent('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); + service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn3 }); + service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); + service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); }); describe('clearFilterByColumnId method', () => { @@ -605,8 +604,8 @@ describe('FilterService', () => { service.bindLocalOnFilter(gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs1 as any, new Slick.EventData(), gridStub); gridStub.onHeaderRowCellRendered.notify(mockArgs2 as any, new Slick.EventData(), gridStub); - service.getFiltersMetadata()[0].callback(new CustomEvent('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); - service.getFiltersMetadata()[1].callback(new CustomEvent('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); + service.getFiltersMetadata()[0].callback(new Event('input'), { columnDef: mockColumn1, operator: 'EQ', searchTerms: ['John'], shouldTriggerQuery: true }); + service.getFiltersMetadata()[1].callback(new Event('input'), { columnDef: mockColumn2, operator: 'NE', searchTerms: ['Doe'], shouldTriggerQuery: true }); }); describe('clearFilterByColumnId method', () => { diff --git a/packages/common/src/services/filter.service.ts b/packages/common/src/services/filter.service.ts index bf869346e..d045b0f5b 100644 --- a/packages/common/src/services/filter.service.ts +++ b/packages/common/src/services/filter.service.ts @@ -117,9 +117,8 @@ export class FilterService { dispose() { // unsubscribe all SlickGrid events - if (this._eventHandler && this._eventHandler.unsubscribeAll) { - this._eventHandler.unsubscribeAll(); - } + this._eventHandler.unsubscribeAll(); + if (this.httpCancelRequests$ && this.rxjs?.isObservable(this.httpCancelRequests$)) { this.httpCancelRequests$.next(); // this cancels any pending http requests this.httpCancelRequests$.complete(); From b46eb5ebdb177e7d0d6c93cb6df541cedc7eb5d1 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Sun, 30 May 2021 22:47:45 -0400 Subject: [PATCH 3/4] feat(filters): convert jQuery to native element on more filters --- .../common/src/filters/compoundInputFilter.ts | 8 +- .../src/filters/compoundSliderFilter.ts | 221 +++++++++--------- .../common/src/filters/filterUtilities.ts | 9 - packages/common/src/filters/sliderFilter.ts | 177 +++++++------- test/cypress/integration/example05.spec.js | 2 +- 5 files changed, 210 insertions(+), 207 deletions(-) diff --git a/packages/common/src/filters/compoundInputFilter.ts b/packages/common/src/filters/compoundInputFilter.ts index c9660df2e..668f18b39 100644 --- a/packages/common/src/filters/compoundInputFilter.ts +++ b/packages/common/src/filters/compoundInputFilter.ts @@ -38,12 +38,12 @@ export class CompoundInputFilter implements Filter { /** Getter for the Grid Options pulled through the Grid Object */ protected get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions?.() ?? {}; } /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { - return this.columnDef && this.columnDef.filter || {}; + return this.columnDef?.filter ?? {}; } /** Getter to know what would be the default operator when none is specified */ @@ -117,7 +117,7 @@ export class CompoundInputFilter implements Filter { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; - this._selectOperatorElm.value = ''; + this._selectOperatorElm.selectedIndex = 0; this._filterInputElm.value = ''; this.onTriggerEvent(undefined); } @@ -128,8 +128,8 @@ export class CompoundInputFilter implements Filter { */ destroy() { this._bindEventService.unbindAll(); - this._filterElm?.remove?.(); this._selectOperatorElm?.remove?.(); + this._filterElm?.remove?.(); } /** Set value(s) on the DOM element */ diff --git a/packages/common/src/filters/compoundSliderFilter.ts b/packages/common/src/filters/compoundSliderFilter.ts index d4ddae836..ed52cfea7 100644 --- a/packages/common/src/filters/compoundSliderFilter.ts +++ b/packages/common/src/filters/compoundSliderFilter.ts @@ -11,8 +11,9 @@ import { } from '../interfaces/index'; import { Constants } from '../constants'; import { OperatorString, OperatorType, SearchTerm } from '../enums/index'; -import { buildSelectOperatorHtmlString } from './filterUtilities'; -import { getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; +import { buildSelectOperator } from './filterUtilities'; +import { emptyElement, getTranslationPrefix, mapOperatorToShorthandDesignation } from '../services/utilities'; +import { BindingEventService } from '../services/bindingEvent.service'; import { TranslaterService } from '../services/translater.service'; const DEFAULT_MIN_VALUE = 0; @@ -20,22 +21,26 @@ const DEFAULT_MAX_VALUE = 100; const DEFAULT_STEP = 1; export class CompoundSliderFilter implements Filter { + protected _bindEventService: BindingEventService; protected _clearFilterTriggered = false; protected _currentValue?: number; protected _shouldTriggerQuery = true; protected _elementRangeInputId = ''; protected _elementRangeOutputId = ''; protected _operator?: OperatorType | OperatorString; - protected $containerInputGroupElm: any; - protected $filterElm: any; - protected $filterInputElm: any; - protected $selectOperatorElm: any; + protected containerInputGroupElm?: HTMLDivElement; + protected filterElm!: HTMLDivElement; + protected filterInputElm!: HTMLInputElement; + protected filterNumberElm?: HTMLSpanElement; + protected selectOperatorElm!: HTMLSelectElement; grid!: SlickGrid; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; - constructor(protected readonly translaterService: TranslaterService) { } + constructor(protected readonly translaterService: TranslaterService) { + this._bindEventService = new BindingEventService(); + } /** Getter for the Filter Operator */ get columnFilter(): ColumnFilter { @@ -59,7 +64,7 @@ export class CompoundSliderFilter implements Filter { /** Getter for the Grid Options pulled through the Grid Object */ protected get gridOptions(): GridOption { - return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; + return this.grid?.getOptions?.() ?? {}; } /** Getter for the single Locale texts provided by the user in main file or else use default English locales via the Constants */ @@ -88,7 +93,7 @@ export class CompoundSliderFilter implements Filter { this.callback = args.callback; this.columnDef = args.columnDef; this.operator = args.operator || ''; - this.searchTerms = (args.hasOwnProperty('searchTerms') ? args.searchTerms : []) || []; + this.searchTerms = args?.searchTerms ?? []; // define the input & slider number IDs this._elementRangeInputId = `rangeInput_${this.columnDef.field}`; @@ -99,29 +104,17 @@ export class CompoundSliderFilter implements Filter { // step 1, create the DOM Element of the filter which contain the compound Operator+Input // and initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(searchTerm); + this.filterElm = this.createDomElement(searchTerm); - // step 3, subscribe to the input change event and run the callback when that happens + // step 2, subscribe to the input change event and run the callback when that happens // also add/remove "filled" class for styling purposes - this.$filterInputElm.change((e: any) => { - this.onTriggerEvent(e); - }); - this.$selectOperatorElm.change((e: any) => { - this.onTriggerEvent(e); - }); + this._bindEventService.bind(this.filterInputElm, 'change', this.onTriggerEvent.bind(this)); + this._bindEventService.bind(this.selectOperatorElm, 'change', this.onTriggerEvent.bind(this)); // if user chose to display the slider number on the right side, then update it every time it changes // we need to use both "input" and "change" event to be all cross-browser if (!this.filterParams.hideSliderNumber) { - this.$filterInputElm.on('input change', (e: { target: HTMLInputElement }) => { - const value = e && e.target && e.target.value; - if (value && document) { - const elements = document.getElementsByClassName(this._elementRangeOutputId || ''); - if (elements && elements.length > 0 && elements[0].innerHTML) { - elements[0].innerHTML = value; - } - } - }); + this._bindEventService.bind(this.filterInputElm, ['input', 'change'], this.handleInputChange.bind(this)); } } @@ -129,19 +122,19 @@ export class CompoundSliderFilter implements Filter { * Clear the filter value */ clear(shouldTriggerQuery = true) { - if (this.$filterElm && this.$selectOperatorElm) { + if (this.filterElm && this.selectOperatorElm) { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; - const clearedValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : DEFAULT_MIN_VALUE; + const clearedValue = this.filterParams?.sliderStartValue ?? DEFAULT_MIN_VALUE; this._currentValue = +clearedValue; - this.$selectOperatorElm.val(0); - this.$filterInputElm.val(clearedValue); - if (!this.filterParams.hideSliderNumber) { - this.$containerInputGroupElm.children('div.input-group-addon.input-group-append').children().last().html(clearedValue); + this.selectOperatorElm.selectedIndex = 0; + this.filterInputElm.value = clearedValue; + if (this.filterNumberElm) { + this.filterNumberElm.textContent = clearedValue; } this.onTriggerEvent(undefined); - this.$filterElm.removeClass('filled'); + this.filterElm.classList.remove('filled'); } } @@ -149,13 +142,10 @@ export class CompoundSliderFilter implements Filter { * destroy the filter */ destroy() { - if (this.$filterInputElm) { - this.$filterInputElm.off('input change').remove(); - this.$selectOperatorElm.off('change').remove(); - } - this.$filterInputElm = null; - this.$filterElm = null; - this.$selectOperatorElm = null; + this._bindEventService.unbindAll(); + this.selectOperatorElm?.remove?.(); + emptyElement(this.filterElm); + this.filterElm?.remove?.(); } /** @@ -170,14 +160,16 @@ export class CompoundSliderFilter implements Filter { setValues(values: SearchTerm | SearchTerm[], operator?: OperatorType | OperatorString) { const newValue = Array.isArray(values) ? values[0] : values; this._currentValue = +newValue; - this.$filterInputElm.val(newValue); - this.$containerInputGroupElm.children('div.input-group-addon.input-group-append').children().last().html(newValue); + this.filterInputElm.value = `${newValue ?? ''}`; + if (this.filterNumberElm) { + this.filterNumberElm.textContent = `${newValue ?? ''}`; + } // set the operator, in the DOM as well, when defined this.operator = operator || this.defaultOperator; - if (operator && this.$selectOperatorElm) { + if (operator && this.selectOperatorElm) { const operatorShorthand = mapOperatorToShorthandDesignation(this.operator); - this.$selectOperatorElm.val(operatorShorthand); + this.selectOperatorElm.value = operatorShorthand; } } @@ -185,26 +177,6 @@ export class CompoundSliderFilter implements Filter { // protected functions // ------------------ - /** Build HTML Template for the input range (slider) */ - protected buildTemplateHtmlString() { - const minValue = this.filterProperties.hasOwnProperty('minValue') ? this.filterProperties.minValue : DEFAULT_MIN_VALUE; - const maxValue = this.filterProperties.hasOwnProperty('maxValue') ? this.filterProperties.maxValue : DEFAULT_MAX_VALUE; - const defaultValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue; - const step = this.filterProperties.hasOwnProperty('valueStep') ? this.filterProperties.valueStep : DEFAULT_STEP; - - return ``; - } - - /** Build HTML Template for the text (number) that is shown appended to the slider */ - protected buildTemplateSliderTextHtmlString() { - const minValue = this.filterProperties.hasOwnProperty('minValue') ? this.filterProperties.minValue : DEFAULT_MIN_VALUE; - const defaultValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue; - - return `
${defaultValue}
`; - } - /** Get the available operator option values to populate the operator select dropdown list */ protected getOperatorOptionValues(): OperatorDetail[] { if (this.columnFilter?.compoundOperatorList) { @@ -234,12 +206,15 @@ export class CompoundSliderFilter implements Filter { /** * Create the DOM element */ - protected createDomElement(searchTerm?: SearchTerm) { + protected createDomElement(searchTerm?: SearchTerm): HTMLDivElement { const columnId = this.columnDef?.id ?? ''; - const minValue = (this.filterProperties.hasOwnProperty('minValue') && this.filterProperties.minValue) ? this.filterProperties.minValue : DEFAULT_MIN_VALUE; - const startValue = +(this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue); - const $headerElm = this.grid.getHeaderRowColumn(this.columnDef.id); - $($headerElm).empty(); + const minValue = this.filterProperties?.minValue ?? DEFAULT_MIN_VALUE; + const maxValue = this.filterProperties?.maxValue ?? DEFAULT_MAX_VALUE; + const defaultValue = this.filterParams?.sliderStartValue ?? minValue; + const step = this.filterProperties?.valueStep ?? DEFAULT_STEP; + const startValue = +(this.filterParams?.sliderStartValue ?? minValue); + const headerElm = this.grid.getHeaderRowColumn(this.columnDef.id); + emptyElement(headerElm); let searchTermInput = (searchTerm || '0') as string; if (+searchTermInput < minValue) { @@ -250,66 +225,102 @@ export class CompoundSliderFilter implements Filter { } this._currentValue = +searchTermInput; - // create the DOM Select dropdown for the Operator - const selectOperatorHtmlString = buildSelectOperatorHtmlString(this.getOperatorOptionValues()); - this.$selectOperatorElm = $(selectOperatorHtmlString); - this.$filterInputElm = $(this.buildTemplateHtmlString()); - const $filterContainerElm = $(`
`); - this.$containerInputGroupElm = $(`
`); - const $operatorInputGroupAddon = $(``); - - /* the DOM element final structure will be -
-
- + /* + Full DOM Element Template:: +
+
+ + + + +
+ 0 +
- -
0
*/ - $operatorInputGroupAddon.append(this.$selectOperatorElm); - this.$containerInputGroupElm.append($operatorInputGroupAddon); - this.$containerInputGroupElm.append(this.$filterInputElm); + + // create the DOM Select dropdown for the Operator + this.selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues()); + + const spanPrependElm = document.createElement('span'); + spanPrependElm.className = 'input-group-addon input-group-prepend operator'; + spanPrependElm.appendChild(this.selectOperatorElm); + + // create the DOM element + this.filterInputElm = document.createElement('input'); + this.filterInputElm.type = 'range'; + this.filterInputElm.className = `form-control slider-filter-input range compound-slider ${this._elementRangeInputId}`; + this.filterInputElm.defaultValue = defaultValue; + this.filterInputElm.value = searchTermInput; + this.filterInputElm.min = `${minValue}`; + this.filterInputElm.max = `${maxValue}`; + this.filterInputElm.step = `${step}`; + this.filterInputElm.name = this._elementRangeInputId; + + const divContainerFilterElm = document.createElement('div'); + divContainerFilterElm.className = `form-group search-filter slider-container filter-${columnId}`; + + // this.containerInputGroupElm = $(`
`); + this.containerInputGroupElm = document.createElement('div'); + this.containerInputGroupElm.className = `input-group search-filter filter-${columnId}`; + this.containerInputGroupElm.appendChild(spanPrependElm); + this.containerInputGroupElm.appendChild(this.filterInputElm); + divContainerFilterElm.appendChild(this.containerInputGroupElm); + if (!this.filterParams.hideSliderNumber) { - const $sliderTextInputAppendAddon = $(this.buildTemplateSliderTextHtmlString()); - $sliderTextInputAppendAddon.children().html(searchTermInput); - this.$containerInputGroupElm.append($sliderTextInputAppendAddon); - } + this.containerInputGroupElm.classList.add('input-group'); + this.filterInputElm.value = searchTermInput; - // create the DOM element & add an ID and filter class - $filterContainerElm.append(this.$containerInputGroupElm); + const divGroupAppendElm = document.createElement('div'); + divGroupAppendElm.className = 'input-group-addon input-group-append slider-value'; + + this.filterNumberElm = document.createElement('span'); + this.filterNumberElm.className = `input-group-text ${this._elementRangeOutputId}`; + this.filterNumberElm.textContent = searchTermInput; + divGroupAppendElm.appendChild(this.filterNumberElm); + this.containerInputGroupElm.appendChild(divGroupAppendElm); + } - this.$filterInputElm.val(searchTermInput); - this.$filterInputElm.data('columnId', columnId); + // this.filterNumberElm.html(searchTermInput); + divContainerFilterElm.dataset.columnid = `${columnId}`; if (this.operator) { const operatorShorthand = mapOperatorToShorthandDesignation(this.operator); - this.$selectOperatorElm.val(operatorShorthand); + this.selectOperatorElm.value = operatorShorthand; } // if there's a search term, we will add the "filled" class for styling purposes - if (searchTerm !== '') { - $filterContainerElm.addClass('filled'); + if (searchTerm) { + divContainerFilterElm.classList.add('filled'); } // append the new DOM element to the header row - if ($filterContainerElm && typeof $filterContainerElm.appendTo === 'function') { - $filterContainerElm.appendTo($headerElm); - } + headerElm.appendChild(divContainerFilterElm); + + return divContainerFilterElm; + } - return $filterContainerElm; + protected handleInputChange(event: Event) { + const value = (event?.target as HTMLInputElement).value; + if (value !== undefined && value !== null) { + const element = document.querySelector(`.${this._elementRangeOutputId || ''}`); + if (element?.textContent) { + element.textContent = value; + } + } } protected onTriggerEvent(e: Event | undefined) { - const value = this.$filterInputElm.val(); + const value = this.filterInputElm.value; this._currentValue = +value; if (this._clearFilterTriggered) { - this.$filterElm.removeClass('filled'); + this.filterElm.classList.remove('filled'); this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, shouldTriggerQuery: this._shouldTriggerQuery }); } else { - this.$filterElm.addClass('filled'); - const selectedOperator = this.$selectOperatorElm.find('option:selected').val(); + this.filterElm.classList.add('filled'); + const selectedOperator = this.selectOperatorElm.value as OperatorString; this.callback(e, { columnDef: this.columnDef, searchTerms: (value ? [value || '0'] : null), operator: selectedOperator || '', shouldTriggerQuery: this._shouldTriggerQuery }); } diff --git a/packages/common/src/filters/filterUtilities.ts b/packages/common/src/filters/filterUtilities.ts index 1cb386714..65705e231 100644 --- a/packages/common/src/filters/filterUtilities.ts +++ b/packages/common/src/filters/filterUtilities.ts @@ -3,15 +3,6 @@ import { Column } from '../interfaces/index'; import { Observable, RxJsFacade, Subject, Subscription } from '../services/rxjsFacade'; import { castObservableToPromise, getDescendantProperty, htmlEncodedStringWithPadding } from '../services/utilities'; -export function buildSelectOperatorHtmlString(optionValues: Array<{ operator: OperatorString, description: string }>) { - let optionValueString = ''; - optionValues.forEach(option => { - optionValueString += ``; - }); - - return ``; -} - /** * Create and return a select dropdown HTML element with a list of Operators with descriptions * @param {Array} optionValues - list of operators and their descriptions diff --git a/packages/common/src/filters/sliderFilter.ts b/packages/common/src/filters/sliderFilter.ts index 6d706fc9c..38a3e83a3 100644 --- a/packages/common/src/filters/sliderFilter.ts +++ b/packages/common/src/filters/sliderFilter.ts @@ -7,28 +7,35 @@ import { FilterCallback, SlickGrid, } from './../interfaces/index'; +import { emptyElement } from '../services/utilities'; +import { BindingEventService } from '../services/bindingEvent.service'; const DEFAULT_MIN_VALUE = 0; const DEFAULT_MAX_VALUE = 100; const DEFAULT_STEP = 1; export class SliderFilter implements Filter { + protected _bindEventService: BindingEventService; protected _clearFilterTriggered = false; protected _currentValue?: number; protected _shouldTriggerQuery = true; protected _elementRangeInputId = ''; protected _elementRangeOutputId = ''; - protected $filterElm: any; - protected $filterInputElm: any; - protected $filterNumberElm: any; + protected filterElm!: HTMLDivElement; + protected filterInputElm!: HTMLInputElement; + protected filterNumberElm?: HTMLSpanElement; grid!: SlickGrid; searchTerms: SearchTerm[] = []; columnDef!: Column; callback!: FilterCallback; + constructor() { + this._bindEventService = new BindingEventService(); + } + /** Getter for the Column Filter */ get columnFilter(): ColumnFilter { - return this.columnDef && this.columnDef.filter || {}; + return this.columnDef?.filter ?? {}; } /** Getter to know what would be the default operator when none is specified */ @@ -38,12 +45,12 @@ export class SliderFilter implements Filter { /** Getter for the Filter Generic Params */ protected get filterParams(): any { - return this.columnDef && this.columnDef.filter && this.columnDef.filter.params || {}; + return this.columnDef?.filter?.params ?? {}; } /** Getter for the `filter` properties */ protected get filterProperties(): ColumnFilter { - return this.columnDef && this.columnDef.filter || {}; + return this.columnDef?.filter ?? {}; } /** Getter for the current Operator */ @@ -77,28 +84,17 @@ export class SliderFilter implements Filter { // filter input can only have 1 search term, so we will use the 1st array index if it exist const searchTerm = (Array.isArray(this.searchTerms) && this.searchTerms.length >= 0) ? this.searchTerms[0] : ''; - // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); - - // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled - this.$filterElm = this.createDomElement(filterTemplate, searchTerm); + // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled + this.filterElm = this.createDomElement(searchTerm); - // step 3, subscribe to the change event and run the callback when that happens + // step 2, subscribe to the change event and run the callback when that happens // also add/remove "filled" class for styling purposes - this.$filterInputElm.change(this.handleOnChange.bind(this)); + this._bindEventService.bind(this.filterInputElm, 'change', this.handleOnChange.bind(this)); // if user chose to display the slider number on the right side, then update it every time it changes // we need to use both "input" and "change" event to be all cross-browser if (!this.filterParams.hideSliderNumber) { - this.$filterInputElm.on('input change', (e: { target: HTMLInputElement }) => { - const value = e && e.target && e.target.value; - if (value !== undefined && value !== null && document) { - const elements = document.getElementsByClassName(this._elementRangeOutputId || ''); - if (elements && elements.length > 0 && elements[0].innerHTML) { - elements[0].innerHTML = value; - } - } - }); + this._bindEventService.bind(this.filterInputElm, ['input', 'change'], this.handleInputChange.bind(this)); } } @@ -106,15 +102,17 @@ export class SliderFilter implements Filter { * Clear the filter value */ clear(shouldTriggerQuery = true) { - if (this.$filterElm) { + if (this.filterElm) { this._clearFilterTriggered = true; this._shouldTriggerQuery = shouldTriggerQuery; this.searchTerms = []; - const clearedValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : DEFAULT_MIN_VALUE; + const clearedValue = this.filterParams?.sliderStartValue ?? DEFAULT_MIN_VALUE; this._currentValue = +clearedValue; - this.$filterInputElm.val(clearedValue); - this.$filterNumberElm.html(clearedValue); - this.$filterInputElm.trigger('change'); + this.filterInputElm.value = clearedValue; + if (this.filterNumberElm) { + this.filterNumberElm.textContent = clearedValue; + } + this.filterInputElm.dispatchEvent(new Event('change')); } } @@ -122,11 +120,9 @@ export class SliderFilter implements Filter { * destroy the filter */ destroy() { - if (this.$filterInputElm) { - this.$filterInputElm.off('input change').remove(); - } - this.$filterInputElm = null; - this.$filterElm = null; + this._bindEventService.unbindAll(); + emptyElement(this.filterElm); + this.filterElm?.remove?.(); } /** @@ -140,11 +136,13 @@ export class SliderFilter implements Filter { /** Set value(s) on the DOM element */ setValues(values: SearchTerm | SearchTerm[], operator?: OperatorType | OperatorString) { if (Array.isArray(values)) { - this.$filterInputElm.val(`${values[0]}`); - this.$filterNumberElm.html(`${values[0]}`); + this.filterInputElm.value = `${values[0]}`; + if (this.filterNumberElm) { + this.filterNumberElm.textContent = `${values[0]}`; + } this._currentValue = +values[0]; } else if (values) { - this.$filterInputElm.val(values); + this.filterInputElm.value = `${values ?? ''}`; this._currentValue = +values; } @@ -157,51 +155,20 @@ export class SliderFilter implements Filter { // ------------------ /** - * Create the HTML template as a string - */ - protected buildTemplateHtmlString() { - const columnId = this.columnDef?.id ?? ''; - const minValue = this.filterProperties.hasOwnProperty('minValue') ? this.filterProperties.minValue : DEFAULT_MIN_VALUE; - const maxValue = this.filterProperties.hasOwnProperty('maxValue') ? this.filterProperties.maxValue : DEFAULT_MAX_VALUE; - const defaultValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue; - const step = this.filterProperties.hasOwnProperty('valueStep') ? this.filterProperties.valueStep : DEFAULT_STEP; - - if (this.filterParams.hideSliderNumber) { - return ` -
- -
`; - } - - return ` -
- -
- ${defaultValue} -
-
`; - } - - /** - * From the html template string, create a DOM element - * @param filterTemplate string + * Create the Filter DOM element * @param searchTerm optional preset search terms */ - protected createDomElement(filterTemplate: string, searchTerm?: SearchTerm) { - const columnId = this.columnDef && this.columnDef.id; - const minValue = (this.filterProperties.hasOwnProperty('minValue') && this.filterProperties.minValue !== undefined) ? this.filterProperties.minValue : DEFAULT_MIN_VALUE; - const startValue = +(this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue); - const $headerElm = this.grid.getHeaderRowColumn(columnId); - $($headerElm).empty(); + protected createDomElement(searchTerm?: SearchTerm) { + const columnId = this.columnDef?.id ?? ''; + const minValue = this.filterProperties?.minValue ?? DEFAULT_MIN_VALUE; + const maxValue = this.filterProperties?.maxValue ?? DEFAULT_MAX_VALUE; + const defaultValue = this.filterParams?.sliderStartValue ?? minValue; + const step = this.filterProperties?.valueStep ?? DEFAULT_STEP; + const startValue = +(this.filterParams?.sliderStartValue ?? minValue); + const headerElm = this.grid.getHeaderRowColumn(columnId); + emptyElement(headerElm); // create the DOM element & add an ID and filter class - const $filterElm = $(filterTemplate); let searchTermInput = (searchTerm || '0') as string; if (+searchTermInput < minValue) { searchTermInput = `${minValue}`; @@ -211,23 +178,57 @@ export class SliderFilter implements Filter { } this._currentValue = +searchTermInput; - this.$filterInputElm = $filterElm.children('input'); - this.$filterNumberElm = $filterElm.children('div.input-group-addon.input-group-append').children(); - this.$filterInputElm.val(searchTermInput); - this.$filterNumberElm.html(searchTermInput); - $filterElm.data('columnId', columnId); + // create the DOM element + this.filterInputElm = document.createElement('input'); + this.filterInputElm.type = 'range'; + this.filterInputElm.className = `form-control slider-filter-input range ${this._elementRangeInputId}`; + this.filterInputElm.defaultValue = defaultValue; + this.filterInputElm.value = searchTermInput; + this.filterInputElm.min = `${minValue}`; + this.filterInputElm.max = `${maxValue}`; + this.filterInputElm.step = `${step}`; + this.filterInputElm.name = this._elementRangeInputId; + + const divContainerFilterElm = document.createElement('div'); + divContainerFilterElm.className = `search-filter slider-container filter-${columnId}`; + divContainerFilterElm.appendChild(this.filterInputElm); + + if (!this.filterParams.hideSliderNumber) { + divContainerFilterElm.classList.add('input-group'); + this.filterInputElm.value = searchTermInput; + + const divGroupAppendElm = document.createElement('div'); + divGroupAppendElm.className = 'input-group-addon input-group-append slider-value'; + + this.filterNumberElm = document.createElement('span'); + this.filterNumberElm.className = `input-group-text ${this._elementRangeOutputId}`; + this.filterNumberElm.textContent = searchTermInput; + divGroupAppendElm.appendChild(this.filterNumberElm); + divContainerFilterElm.appendChild(divGroupAppendElm); + } + + // this.filterNumberElm.html(searchTermInput); + divContainerFilterElm.dataset.columnid = `${columnId}`; // if there's a search term, we will add the "filled" class for styling purposes if (searchTerm) { - $filterElm.addClass('filled'); + divContainerFilterElm.classList.add('filled'); } // append the new DOM element to the header row - if ($filterElm && typeof $filterElm.appendTo === 'function') { - $filterElm.appendTo($headerElm); - } + headerElm.appendChild(divContainerFilterElm); - return $filterElm; + return divContainerFilterElm; + } + + protected handleInputChange(event: Event) { + const value = (event?.target as HTMLInputElement).value; + if (value !== undefined && value !== null) { + const element = document.querySelector(`.${this._elementRangeOutputId || ''}`); + if (element?.textContent) { + element.textContent = value; + } + } } protected handleOnChange(e: any) { @@ -235,10 +236,10 @@ export class SliderFilter implements Filter { this._currentValue = +value; if (this._clearFilterTriggered) { - this.$filterElm.removeClass('filled'); + this.filterElm.classList.remove('filled'); this.callback(e, { columnDef: this.columnDef, clearFilterTriggered: this._clearFilterTriggered, searchTerms: [], shouldTriggerQuery: this._shouldTriggerQuery }); } else { - this.$filterElm.addClass('filled'); + this.filterElm.classList.add('filled'); this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value || '0'], shouldTriggerQuery: this._shouldTriggerQuery }); } // reset both flags for next use diff --git a/test/cypress/integration/example05.spec.js b/test/cypress/integration/example05.spec.js index 73a6a1c5c..0eb44edb6 100644 --- a/test/cypress/integration/example05.spec.js +++ b/test/cypress/integration/example05.spec.js @@ -143,7 +143,7 @@ describe('Example 05 - Tree Data (from a flat dataset with parentId references)' it('should no longer have filters and it should show the full item count in the footer', () => { cy.get('.search-filter.filter-percentComplete .operator .form-control') - .should('have.value', null); + .should('have.value', ''); cy.get('.rangeInput_percentComplete') .invoke('val') From e946feff2ae389b3688072798b7ffc4ed5266e1b Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Tue, 1 Jun 2021 12:21:58 -0400 Subject: [PATCH 4/4] refactor: removed commented out lines as per code review --- packages/common/src/filters/compoundSliderFilter.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/common/src/filters/compoundSliderFilter.ts b/packages/common/src/filters/compoundSliderFilter.ts index ed52cfea7..a35195619 100644 --- a/packages/common/src/filters/compoundSliderFilter.ts +++ b/packages/common/src/filters/compoundSliderFilter.ts @@ -261,7 +261,6 @@ export class CompoundSliderFilter implements Filter { const divContainerFilterElm = document.createElement('div'); divContainerFilterElm.className = `form-group search-filter slider-container filter-${columnId}`; - // this.containerInputGroupElm = $(`
`); this.containerInputGroupElm = document.createElement('div'); this.containerInputGroupElm.className = `input-group search-filter filter-${columnId}`; this.containerInputGroupElm.appendChild(spanPrependElm); @@ -282,7 +281,6 @@ export class CompoundSliderFilter implements Filter { this.containerInputGroupElm.appendChild(divGroupAppendElm); } - // this.filterNumberElm.html(searchTermInput); divContainerFilterElm.dataset.columnid = `${columnId}`; if (this.operator) {