]>
Commit | Line | Data |
---|---|---|
c4685c84 TL |
1 | /** |
2 | * Represents a filter that can be applied to a {@link Ext.util.MixedCollection MixedCollection}. Can either simply | |
3 | * filter on a property/value pair or pass in a filter function with custom logic. Filters are always used in the | |
4 | * context of MixedCollections, though {@link Ext.data.Store Store}s frequently create them when filtering and searching | |
5 | * on their records. Example usage: | |
6 | * | |
7 | * // Set up a fictional MixedCollection containing a few people to filter on | |
8 | * var allNames = new Ext.util.MixedCollection(); | |
9 | * allNames.addAll([ | |
10 | * { id: 1, name: 'Ed', age: 25 }, | |
11 | * { id: 2, name: 'Jamie', age: 37 }, | |
12 | * { id: 3, name: 'Abe', age: 32 }, | |
13 | * { id: 4, name: 'Aaron', age: 26 }, | |
14 | * { id: 5, name: 'David', age: 32 } | |
15 | * ]); | |
16 | * | |
17 | * var ageFilter = new Ext.util.Filter({ | |
18 | * property: 'age', | |
19 | * value : 32 | |
20 | * }); | |
21 | * | |
22 | * var longNameFilter = new Ext.util.Filter({ | |
23 | * filterFn: function(item) { | |
24 | * return item.name.length > 4; | |
25 | * } | |
26 | * }); | |
27 | * | |
28 | * // a new MixedCollection with the 3 names longer than 4 characters | |
29 | * var longNames = allNames.filter(longNameFilter); | |
30 | * | |
31 | * // a new MixedCollection with the 2 people of age 32: | |
32 | * var youngFolk = allNames.filter(ageFilter); | |
33 | */ | |
34 | Ext.define('Ext.util.Filter', { | |
35 | isFilter: true, | |
36 | ||
37 | config: { | |
38 | /** | |
39 | * @cfg {String} [property=null] | |
40 | * The property to filter on. Required unless a `filter` is passed | |
41 | */ | |
42 | property: null, | |
43 | ||
44 | /** | |
45 | * @cfg {RegExp/Mixed} [value=null] | |
46 | * The value you want to match against. Can be a regular expression which will be used as matcher or any other | |
47 | * value. Mixed can be an object or an array of objects. | |
48 | */ | |
49 | value: null, | |
50 | ||
51 | /** | |
52 | * @cfg {Function} filterFn | |
53 | * A custom filter function which is passed each item in the {@link Ext.util.MixedCollection} in turn. Should | |
54 | * return true to accept each item or false to reject it | |
55 | */ | |
56 | filterFn: Ext.emptyFn, | |
57 | ||
58 | /** | |
59 | * @cfg {Boolean} [anyMatch=false] | |
60 | * True to allow any match - no regex start/end line anchors will be added. | |
61 | */ | |
62 | anyMatch: false, | |
63 | ||
64 | /** | |
65 | * @cfg {Boolean} [exactMatch=false] | |
66 | * True to force exact match (^ and $ characters added to the regex). Ignored if anyMatch is true. | |
67 | */ | |
68 | exactMatch: false, | |
69 | ||
70 | /** | |
71 | * @cfg {Boolean} [caseSensitive=false] | |
72 | * True to make the regex case sensitive (adds 'i' switch to regex). | |
73 | */ | |
74 | caseSensitive: false, | |
75 | ||
76 | /** | |
77 | * @cfg {String} [root=null] | |
78 | * Optional root property. This is mostly useful when filtering a Store, in which case we set the root to 'data' | |
79 | * to make the filter pull the {@link #property} out of the data object of each item | |
80 | */ | |
81 | root: null, | |
82 | ||
83 | /** | |
84 | * @cfg {String} id | |
85 | * An optional id this filter can be keyed by in Collections. If no id is specified it will generate an id by | |
86 | * first trying a combination of property-value, and if none if these were specified (like when having a | |
87 | * filterFn) it will generate a random id. | |
88 | */ | |
89 | id: undefined, | |
90 | ||
91 | /** | |
92 | * @cfg {Object} [scope=null] | |
93 | * The scope in which to run the filterFn | |
94 | */ | |
95 | scope: null | |
96 | }, | |
97 | ||
98 | applyId: function(id) { | |
99 | if (!id) { | |
100 | if (this.getProperty()) { | |
101 | id = this.getProperty() + '-' + String(this.getValue()); | |
102 | } | |
103 | if (!id) { | |
104 | id = Ext.id(null, 'ext-filter-'); | |
105 | } | |
106 | } | |
107 | ||
108 | return id; | |
109 | }, | |
110 | ||
111 | /** | |
112 | * Creates new Filter. | |
113 | * @param {Object} config Config object | |
114 | */ | |
115 | constructor: function(config) { | |
116 | this.initConfig(config); | |
117 | }, | |
118 | ||
119 | applyFilterFn: function(filterFn) { | |
120 | if (filterFn === Ext.emptyFn) { | |
121 | filterFn = this.getInitialConfig('filter'); | |
122 | if (filterFn) { | |
123 | return filterFn; | |
124 | } | |
125 | ||
126 | var value = this.getValue(); | |
127 | if (!this.getProperty() && !value && value !== 0) { | |
128 | // <debug> | |
129 | Ext.Logger.error('A Filter requires either a property and value, or a filterFn to be set'); | |
130 | // </debug> | |
131 | return Ext.emptyFn; | |
132 | } | |
133 | else { | |
134 | return this.createFilterFn(); | |
135 | } | |
136 | } | |
137 | return filterFn; | |
138 | }, | |
139 | ||
140 | /** | |
141 | * @private | |
142 | * Creates a filter function for the configured property/value/anyMatch/caseSensitive options for this Filter | |
143 | */ | |
144 | createFilterFn: function() { | |
145 | var me = this, | |
146 | matcher = me.createValueMatcher(); | |
147 | ||
148 | return function(item) { | |
149 | var root = me.getRoot(), | |
150 | property = me.getProperty(); | |
151 | ||
152 | if (root) { | |
153 | item = item[root]; | |
154 | } | |
155 | ||
156 | return matcher.test(item[property]); | |
157 | }; | |
158 | }, | |
159 | ||
160 | /** | |
161 | * @private | |
162 | * Returns a regular expression based on the given value and matching options | |
163 | */ | |
164 | createValueMatcher: function() { | |
165 | var me = this, | |
166 | value = me.getValue(), | |
167 | anyMatch = me.getAnyMatch(), | |
168 | exactMatch = me.getExactMatch(), | |
169 | caseSensitive = me.getCaseSensitive(), | |
170 | escapeRe = Ext.String.escapeRegex; | |
171 | ||
172 | if (value === null || value === undefined || !value.exec) { // not a regex | |
173 | value = String(value); | |
174 | ||
175 | if (anyMatch === true) { | |
176 | value = escapeRe(value); | |
177 | } else { | |
178 | value = '^' + escapeRe(value); | |
179 | if (exactMatch === true) { | |
180 | value += '$'; | |
181 | } | |
182 | } | |
183 | value = new RegExp(value, caseSensitive ? '' : 'i'); | |
184 | } | |
185 | ||
186 | return value; | |
187 | } | |
188 | }); |