]> git.proxmox.com Git - sencha-touch.git/blame - src/examples/list-search/app.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / examples / list-search / app.js
CommitLineData
c4685c84
TL
1//<debug>
2Ext.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
14Ext.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});