]>
Commit | Line | Data |
---|---|---|
c4685c84 TL |
1 | //<debug> |
2 | Ext.Loader.setPath({ | |
3 | 'Ext': '../../src' | |
4 | }); | |
5 | //</debug> | |
6 | ||
7 | /** | |
8 | * This is a simple demontration of the Ext.List component with a binded Ext.data.Store. | |
9 | * It also included a search field which has functionality built in to filter the data in | |
10 | * the store, on key up. | |
11 | */ | |
12 | ||
13 | //define our application | |
14 | Ext.application({ | |
15 | //setup the startup screens and icon for mobile devices | |
16 | startupImage: { | |
17 | '320x460': 'resources/startup/Default.jpg', // Non-retina iPhone, iPod touch, and all Android devices | |
18 | '640x920': 'resources/startup/640x920.png', // Retina iPhone and iPod touch | |
19 | '640x1096': 'resources/startup/640x1096.png', // iPhone 5 and iPod touch (fifth generation) | |
20 | '768x1004': 'resources/startup/768x1004.png', // Non-retina iPad (first and second generation) in portrait orientation | |
21 | '748x1024': 'resources/startup/748x1024.png', // Non-retina iPad (first and second generation) in landscape orientation | |
22 | '1536x2008': 'resources/startup/1536x2008.png', // : Retina iPad (third generation) in portrait orientation | |
23 | '1496x2048': 'resources/startup/1496x2048.png' // : Retina iPad (third generation) in landscape orientation | |
24 | }, | |
25 | ||
26 | isIconPrecomposed: false, | |
27 | icon: { | |
28 | 57: 'resources/icons/icon.png', | |
29 | 72: 'resources/icons/icon@72.png', | |
30 | 114: 'resources/icons/icon@2x.png', | |
31 | 144: 'resources/icons/icon@144.png' | |
32 | }, | |
33 | ||
34 | // require any components we are using in this example | |
35 | requires: [ | |
36 | 'Ext.data.Store', | |
37 | 'Ext.List', | |
38 | 'Ext.field.Search', | |
39 | 'Ext.Toolbar', | |
40 | 'Ext.Panel' | |
41 | ], | |
42 | ||
43 | /** | |
44 | * The launch method is called when the browser is ready, and the application can launch. | |
45 | * | |
46 | * Inside our launch method we create the list and show in in the viewport. We get the lists configuration | |
47 | * using the getListConfiguration method which we defined below. | |
48 | * | |
49 | * If the user is not on a phone, we wrap the list inside a panel which is centered on the page. | |
50 | */ | |
51 | launch: function() { | |
52 | //get the configuration of the list | |
53 | var listConfiguration = this.getListConfiguration(); | |
54 | ||
55 | //check if the device is a phone | |
56 | if (!Ext.os.is.Phone) { | |
57 | //add a panel into the viewport | |
58 | Ext.Viewport.add({ | |
59 | //panel gets special styling when it is floating | |
60 | xtype: 'panel', | |
61 | ||
62 | //give it a fixed width and height | |
63 | width: 380, | |
64 | height: 420, | |
65 | ||
66 | //center the panel | |
67 | centered: true, | |
68 | ||
69 | //modal gives it a mask | |
70 | modal: true, | |
71 | ||
72 | //disable the hide on mask tap functionality of modal | |
73 | hideOnMaskTap: false, | |
74 | ||
75 | //give it a fit layout so the list item stretches to the size of this panel | |
76 | layout: 'fit', | |
77 | ||
78 | //give it 1 item which is the listConfiguration | |
79 | items: [listConfiguration] | |
80 | }).show(); | |
81 | } else { | |
82 | //add the list into the viewport | |
83 | Ext.Viewport.add(listConfiguration); | |
84 | } | |
85 | }, | |
86 | ||
87 | /** | |
88 | * Returns the configuration of the list for this example, to be inserted into the viewport in the launch method. | |
89 | */ | |
90 | getListConfiguration: function() { | |
91 | return { | |
92 | //give it an xtype of list | |
93 | xtype: 'list', | |
94 | ||
95 | ui: 'round', | |
96 | ||
97 | pinHeaders: false, | |
98 | ||
99 | //itemTpl defines the template for each item in the list | |
100 | itemTpl: '<div class="contact">{firstName} <strong>{lastName}</strong></div>', | |
101 | ||
102 | //give it a link to the store instance | |
103 | store: this.getStore(), | |
104 | ||
105 | useSimpleItems: true, | |
106 | ||
107 | grouped: true, | |
108 | emptyText: '<div style="margin-top: 20px; text-align: center">No Matching Items</div>', | |
109 | disableSelection: true, | |
110 | ||
111 | items: [ | |
112 | { | |
113 | xtype: 'toolbar', | |
114 | docked: 'top', | |
115 | ||
116 | items: [ | |
117 | { xtype: 'spacer' }, | |
118 | { | |
119 | xtype: 'searchfield', | |
120 | placeHolder: 'Search...', | |
121 | listeners: { | |
122 | scope: this, | |
123 | clearicontap: this.onSearchClearIconTap, | |
124 | keyup: this.onSearchKeyUp | |
125 | } | |
126 | }, | |
127 | { xtype: 'spacer' } | |
128 | ] | |
129 | } | |
130 | ] | |
131 | }; | |
132 | }, | |
133 | ||
134 | /** | |
135 | * Returns a new store instance if one hasn't been created yet | |
136 | * @return {Ext.data.Store} | |
137 | */ | |
138 | getStore: function() { | |
139 | //check if a store has already been set | |
140 | if (!this.store) { | |
141 | //if not, create one | |
142 | this.store = Ext.create('Ext.data.Store', { | |
143 | //define the stores fields | |
144 | fields: ['firstName', 'lastName'], | |
145 | ||
146 | //sort the store using the lastname field | |
147 | sorters: 'lastName', | |
148 | ||
149 | //group the store using the lastName field | |
150 | groupField: 'lastName', | |
151 | ||
152 | //and give it some data | |
153 | data: [ | |
154 | { firstName: 'Tommy', lastName: 'Maintz' }, | |
155 | { firstName: 'Rob', lastName: 'Dougan' }, | |
156 | { firstName: 'Ed', lastName: 'Avins' }, | |
157 | { firstName: 'Jamie', lastName: 'Avins' }, | |
158 | { firstName: 'Dave', lastName: 'Dougan' }, | |
159 | { firstName: 'Abraham', lastName: 'Elias' }, | |
160 | { firstName: 'Jacky', lastName: 'Ngyuyen' }, | |
161 | { firstName: 'Jay', lastName: 'Ngyuyen' }, | |
162 | { firstName: 'Jay', lastName: 'Robinson' }, | |
163 | { firstName: 'Rob', lastName: 'Avins' }, | |
164 | { firstName: 'Ed', lastName: 'Dougan' }, | |
165 | { firstName: 'Jamie', lastName: 'Poulden' }, | |
166 | { firstName: 'Dave', lastName: 'Spencer' }, | |
167 | { firstName: 'Abraham', lastName: 'Avins' }, | |
168 | { firstName: 'Jacky', lastName: 'Avins' }, | |
169 | { firstName: 'Rob', lastName: 'Kaneda' }, | |
170 | { firstName: 'Ed', lastName: 'Elias' }, | |
171 | { firstName: 'Tommy', lastName: 'Dougan' }, | |
172 | { firstName: 'Rob', lastName: 'Robinson' } | |
173 | ] | |
174 | }); | |
175 | } | |
176 | ||
177 | //return the store instance | |
178 | return this.store; | |
179 | }, | |
180 | ||
181 | /** | |
182 | * Called when the search field has a keyup event. | |
183 | * | |
184 | * This will filter the store based on the fields content. | |
185 | */ | |
186 | onSearchKeyUp: function(field) { | |
187 | //get the store and the value of the field | |
188 | var value = field.getValue(), | |
189 | store = this.getStore(); | |
190 | ||
191 | //first clear any current filters on the store. If there is a new value, then suppress the refresh event | |
192 | store.clearFilter(!!value); | |
193 | ||
194 | //check if a value is set first, as if it isnt we dont have to do anything | |
195 | if (value) { | |
196 | //the user could have entered spaces, so we must split them so we can loop through them all | |
197 | var searches = value.split(','), | |
198 | regexps = [], | |
199 | i, regex; | |
200 | ||
201 | //loop them all | |
202 | for (i = 0; i < searches.length; i++) { | |
203 | //if it is nothing, continue | |
204 | if (!searches[i]) continue; | |
205 | ||
206 | regex = searches[i].trim(); | |
207 | regex = regex.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); | |
208 | ||
209 | //if found, create a new regular expression which is case insenstive | |
210 | regexps.push(new RegExp(regex.trim(), 'i')); | |
211 | } | |
212 | ||
213 | //now filter the store by passing a method | |
214 | //the passed method will be called for each record in the store | |
215 | store.filter(function(record) { | |
216 | var matched = []; | |
217 | ||
218 | //loop through each of the regular expressions | |
219 | for (i = 0; i < regexps.length; i++) { | |
220 | var search = regexps[i], | |
221 | didMatch = search.test(record.get('firstName') + ' ' + record.get('lastName')); | |
222 | ||
223 | //if it matched the first or last name, push it into the matches array | |
224 | matched.push(didMatch); | |
225 | } | |
226 | ||
227 | return (regexps.length && matched.indexOf(true) !== -1); | |
228 | }); | |
229 | } | |
230 | }, | |
231 | ||
232 | /** | |
233 | * Called when the user taps on the clear icon in the search field. | |
234 | * It simply removes the filter form the store | |
235 | */ | |
236 | onSearchClearIconTap: function() { | |
237 | //call the clearFilter method on the store instance | |
238 | this.getStore().clearFilter(); | |
239 | } | |
240 | }); |