@@ -9,23 +9,25 @@ import {
9
9
OperatorString ,
10
10
SearchTerm ,
11
11
} from './../models/index' ;
12
-
13
- // using external non-typed js libraries
14
- declare const $ : any ;
12
+ import { BindingEventService } from '../services/bindingEvent.service' ;
13
+ import { emptyElement } from '../services/utilities' ;
15
14
16
15
export class InputFilter implements Filter {
16
+ protected _bindEventService : BindingEventService ;
17
17
protected _clearFilterTriggered = false ;
18
18
protected _debounceTypingDelay = 0 ;
19
19
protected _shouldTriggerQuery = true ;
20
20
protected _inputType = 'text' ;
21
21
protected _timer ?: any ;
22
- protected $filterElm : any ;
23
- grid : any ;
22
+ protected _filterElm ! : HTMLInputElement ;
23
+ grid ! : any ;
24
24
searchTerms : SearchTerm [ ] = [ ] ;
25
25
columnDef ! : Column ;
26
26
callback ! : FilterCallback ;
27
27
28
- constructor ( ) { }
28
+ constructor ( ) {
29
+ this . _bindEventService = new BindingEventService ( ) ;
30
+ }
29
31
30
32
/** Getter for the Column Filter */
31
33
get columnFilter ( ) : ColumnFilter {
@@ -49,7 +51,7 @@ export class InputFilter implements Filter {
49
51
50
52
/** Getter of the Operator to use when doing the filter comparing */
51
53
get operator ( ) : OperatorType | OperatorString {
52
- return this . columnFilter && this . columnFilter . operator || this . defaultOperator ;
54
+ return this . columnFilter ?. operator ?? this . defaultOperator ;
53
55
}
54
56
55
57
/** Setter for the filter operator */
@@ -84,43 +86,38 @@ export class InputFilter implements Filter {
84
86
// filter input can only have 1 search term, so we will use the 1st array index if it exist
85
87
const searchTerm = ( Array . isArray ( this . searchTerms ) && this . searchTerms . length >= 0 ) ? this . searchTerms [ 0 ] : '' ;
86
88
87
- // step 1, create HTML string template
88
- const filterTemplate = this . buildTemplateHtmlString ( ) ;
89
+ // step 1, create the DOM Element of the filter & initialize it if searchTerm is filled
90
+ this . _filterElm = this . createDomElement ( searchTerm ) ;
89
91
90
- // step 2, create the DOM Element of the filter & initialize it if searchTerm is filled
91
- this . $filterElm = this . createDomElement ( filterTemplate , searchTerm ) ;
92
-
93
- // step 3, subscribe to the input change event and run the callback when that happens
92
+ // step 2, subscribe to the input event and run the callback when that happens
94
93
// also add/remove "filled" class for styling purposes
95
94
// we'll use all necessary events to cover the following (keyup, change, mousewheel & spinner)
96
- this . $filterElm . on ( 'keyup blur change wheel' , this . handleInputChange . bind ( this ) ) ;
95
+ this . _bindEventService . bind ( this . _filterElm , [ 'keyup' , ' blur' , ' change' , ' wheel'] , this . handleInputChange . bind ( this ) ) ;
97
96
}
98
97
99
98
/**
100
99
* Clear the filter value
101
100
*/
102
101
clear ( shouldTriggerQuery = true ) {
103
- if ( this . $filterElm ) {
102
+ if ( this . _filterElm ) {
104
103
this . _clearFilterTriggered = true ;
105
104
this . _shouldTriggerQuery = shouldTriggerQuery ;
106
105
this . searchTerms = [ ] ;
107
- this . $filterElm . val ( '' ) ;
108
- this . $filterElm . trigger ( 'change' ) ;
106
+ this . _filterElm . value = '' ;
107
+ this . _filterElm . dispatchEvent ( new Event ( 'change' ) ) ;
109
108
}
110
109
}
111
110
112
111
/**
113
112
* destroy the filter
114
113
*/
115
114
destroy ( ) {
116
- if ( this . $filterElm ) {
117
- this . $filterElm . off ( 'keyup blur change wheel' ) . remove ( ) ;
118
- }
119
- this . $filterElm = null ;
115
+ this . _bindEventService . unbindAll ( ) ;
116
+ this . _filterElm ?. remove ?.( ) ;
120
117
}
121
118
122
- getValue ( ) {
123
- return this . $filterElm . val ( ) ;
119
+ getValue ( ) : string {
120
+ return this . _filterElm . value ;
124
121
}
125
122
126
123
/** Set value(s) on the DOM element */
@@ -129,7 +126,7 @@ export class InputFilter implements Filter {
129
126
let searchValue : SearchTerm = '' ;
130
127
for ( const value of searchValues ) {
131
128
searchValue = operator ? this . addOptionalOperatorIntoSearchString ( value , operator ) : value ;
132
- this . $filterElm . val ( searchValue ) ;
129
+ this . _filterElm . value = ` ${ searchValue ?? '' } ` ;
133
130
}
134
131
135
132
// set the operator when defined
@@ -141,14 +138,14 @@ export class InputFilter implements Filter {
141
138
// ------------------
142
139
143
140
/**
144
- * When loading the search string from the outside into the input text field, we should also add the prefix/suffix of the operator.
145
- * We do this so that if it was loaded by a Grid Presets then we should also add the operator into the search string
146
- * Let's take these 3 examples:
147
- * 1. (operator: '>=', searchTerms:[55]) should display as ">=55"
148
- * 2. (operator: 'StartsWith', searchTerms:['John']) should display as "John*"
149
- * 3. (operator: 'EndsWith', searchTerms:['John']) should display as "*John"
150
- * @param operator - operator string
151
- */
141
+ * When loading the search string from the outside into the input text field, we should also add the prefix/suffix of the operator.
142
+ * We do this so that if it was loaded by a Grid Presets then we should also add the operator into the search string
143
+ * Let's take these 3 examples:
144
+ * 1. (operator: '>=', searchTerms:[55]) should display as ">=55"
145
+ * 2. (operator: 'StartsWith', searchTerms:['John']) should display as "John*"
146
+ * 3. (operator: 'EndsWith', searchTerms:['John']) should display as "*John"
147
+ * @param operator - operator string
148
+ */
152
149
protected addOptionalOperatorIntoSearchString ( inputValue : SearchTerm , operator : OperatorType | OperatorString ) : string {
153
150
let searchTermPrefix = '' ;
154
151
let searchTermSuffix = '' ;
@@ -181,64 +178,62 @@ export class InputFilter implements Filter {
181
178
return outputValue ;
182
179
}
183
180
184
- /**
185
- * Create the HTML template as a string
186
- */
187
- protected buildTemplateHtmlString ( ) {
188
- const fieldId = this . columnDef && this . columnDef . id ;
189
- let placeholder = ( this . gridOptions ) ? ( this . gridOptions . defaultFilterPlaceholder || '' ) : '' ;
190
- if ( this . columnFilter && this . columnFilter . placeholder ) {
191
- placeholder = this . columnFilter . placeholder ;
192
- }
193
- return `<input type="${ this . _inputType || 'text' } " role="presentation" autocomplete="off" class="form-control search-filter filter-${ fieldId } " placeholder="${ placeholder } "><span></span>` ;
194
- }
195
-
196
181
/**
197
182
* From the html template string, create a DOM element
198
- * @param filterTemplate
183
+ * @param {Object } searchTerm - filter search term
184
+ * @returns {Object } DOM element filter
199
185
*/
200
- protected createDomElement ( filterTemplate : string , searchTerm ?: SearchTerm ) {
201
- const fieldId = this . columnDef && this . columnDef . id ;
202
- const $ headerElm = this . grid . getHeaderRowColumn ( fieldId ) ;
203
- $ ( $ headerElm) . empty ( ) ;
186
+ protected createDomElement ( searchTerm ?: SearchTerm ) : HTMLInputElement {
187
+ const columnId = this . columnDef ?. id ?? '' ;
188
+ const headerElm = this . grid . getHeaderRowColumn ( columnId ) ;
189
+ emptyElement ( headerElm ) ;
204
190
205
191
// create the DOM element & add an ID and filter class
206
- const $filterElm = $ ( filterTemplate ) ;
192
+ let placeholder = this . gridOptions ?. defaultFilterPlaceholder ?? '' ;
193
+ if ( this . columnFilter ?. placeholder ) {
194
+ placeholder = this . columnFilter . placeholder ;
195
+ }
196
+
197
+ const inputElm = document . createElement ( 'input' ) ;
198
+ inputElm . type = this . _inputType || 'text' ;
199
+ inputElm . className = `form-control search-filter filter-${ columnId } ` ;
200
+ inputElm . autocomplete = 'off' ;
201
+ inputElm . placeholder = placeholder ;
202
+ inputElm . setAttribute ( 'role' , 'presentation' ) ;
207
203
208
- $filterElm . val ( searchTerm ) ;
209
- $filterElm . data ( 'columnId' , fieldId ) ;
204
+ inputElm . value = ( searchTerm ?? '' ) as string ;
205
+ inputElm . dataset . columnid = ` ${ columnId } ` ;
210
206
211
207
// if there's a search term, we will add the "filled" class for styling purposes
212
208
if ( searchTerm ) {
213
- $filterElm . addClass ( 'filled' ) ;
209
+ inputElm . classList . add ( 'filled' ) ;
214
210
}
215
211
216
- // append the new DOM element to the header row
217
- if ( $filterElm && typeof $filterElm . appendTo === 'function' ) {
218
- $filterElm . appendTo ( $headerElm ) ;
219
- }
212
+ // append the new DOM element to the header row & an empty span
213
+ headerElm . appendChild ( inputElm ) ;
214
+ headerElm . appendChild ( document . createElement ( 'span' ) ) ;
220
215
221
- return $filterElm ;
216
+ return inputElm ;
222
217
}
223
218
224
219
/**
225
220
* Event handler to cover the following (keyup, change, mousewheel & spinner)
226
221
* We will trigger the Filter Service callback from this handler
227
222
*/
228
- protected handleInputChange ( event : KeyboardEvent & { target : any ; } ) {
223
+ protected handleInputChange ( event : Event ) {
229
224
if ( this . _clearFilterTriggered ) {
230
225
this . callback ( event , { columnDef : this . columnDef , clearFilterTriggered : this . _clearFilterTriggered , shouldTriggerQuery : this . _shouldTriggerQuery } ) ;
231
- this . $filterElm . removeClass ( 'filled' ) ;
226
+ this . _filterElm . classList . remove ( 'filled' ) ;
232
227
} else {
233
228
const eventType = event ?. type ?? '' ;
234
- let value = event ?. target ?. value ?? '' ;
229
+ let value = ( event ?. target as HTMLInputElement ) ?. value ?? '' ;
235
230
const enableWhiteSpaceTrim = this . gridOptions . enableFilterTrimWhiteSpace || this . columnFilter . enableTrimWhiteSpace ;
236
231
if ( typeof value === 'string' && enableWhiteSpaceTrim ) {
237
232
value = value . trim ( ) ;
238
233
}
239
- value === '' ? this . $filterElm . removeClass ( 'filled' ) : this . $filterElm . addClass ( 'filled' ) ;
234
+ value === '' ? this . _filterElm . classList . remove ( 'filled' ) : this . _filterElm . classList . add ( 'filled' ) ;
240
235
const callbackArgs = { columnDef : this . columnDef , operator : this . operator , searchTerms : [ value ] , shouldTriggerQuery : this . _shouldTriggerQuery } ;
241
- const typingDelay = ( eventType === 'keyup' && event ?. key !== 'Enter' ) ? this . _debounceTypingDelay : 0 ;
236
+ const typingDelay = ( eventType === 'keyup' && ( event as KeyboardEvent ) ?. key !== 'Enter' ) ? this . _debounceTypingDelay : 0 ;
242
237
243
238
if ( typingDelay > 0 ) {
244
239
clearTimeout ( this . _timer ) ;
0 commit comments