Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / RowModel.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-selection.RowModel'>/**
2 </span> * @class Ext.selection.RowModel
3  * @extends Ext.selection.Model
4  * 
5  * Implement row based navigation via keyboard.
6  *
7  * Must synchronize across grid sections
8  */
9 Ext.define('Ext.selection.RowModel', {
10     extend: 'Ext.selection.Model',
11     alias: 'selection.rowmodel',
12     requires: ['Ext.util.KeyNav'],
13     
14 <span id='Ext-selection.RowModel-property-deltaScroll'>    /**
15 </span>     * @private
16      * Number of pixels to scroll to the left/right when pressing
17      * left/right keys.
18      */
19     deltaScroll: 5,
20     
21 <span id='Ext-selection.RowModel-cfg-enableKeyNav'>    /**
22 </span>     * @cfg {Boolean} enableKeyNav
23      * 
24      * Turns on/off keyboard navigation within the grid. Defaults to true.
25      */
26     enableKeyNav: true,
27     
28     constructor: function(){
29         this.addEvents(
30 <span id='Ext-selection.RowModel-event-deselect'>            /**
31 </span>             * @event deselect
32              * Fired after a record is deselected
33              * @param {Ext.selection.RowSelectionModel} this
34              * @param {Ext.data.Model} record The deselected record
35              * @param {Number} index The row index deselected
36              */
37             'deselect',
38             
39 <span id='Ext-selection.RowModel-event-select'>            /**
40 </span>             * @event select
41              * Fired after a record is selected
42              * @param {Ext.selection.RowSelectionModel} this
43              * @param {Ext.data.Model} record The selected record
44              * @param {Number} index The row index selected
45              */
46             'select'
47         );
48         this.callParent(arguments);    
49     },
50
51     bindComponent: function(view) {
52         var me = this;
53         
54         me.views = me.views || [];
55         me.views.push(view);
56         me.bind(view.getStore(), true);
57
58         view.on({
59             itemmousedown: me.onRowMouseDown,
60             scope: me
61         });
62
63         if (me.enableKeyNav) {
64             me.initKeyNav(view);
65         }
66     },
67
68     initKeyNav: function(view) {
69         var me = this;
70         
71         if (!view.rendered) {
72             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
73             return;
74         }
75
76         view.el.set({
77             tabIndex: -1
78         });
79
80         // view.el has tabIndex -1 to allow for
81         // keyboard events to be passed to it.
82         me.keyNav = new Ext.util.KeyNav(view.el, {
83             up: me.onKeyUp,
84             down: me.onKeyDown,
85             right: me.onKeyRight,
86             left: me.onKeyLeft,
87             pageDown: me.onKeyPageDown,
88             pageUp: me.onKeyPageUp,
89             home: me.onKeyHome,
90             end: me.onKeyEnd,
91             scope: me
92         });
93         view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
94     },
95
96     // Returns the number of rows currently visible on the screen or
97     // false if there were no rows. This assumes that all rows are
98     // of the same height and the first view is accurate.
99     getRowsVisible: function() {
100         var rowsVisible = false,
101             view = this.views[0],
102             row = view.getNode(0),
103             rowHeight, gridViewHeight;
104
105         if (row) {
106             rowHeight = Ext.fly(row).getHeight();
107             gridViewHeight = view.el.getHeight();
108             rowsVisible = Math.floor(gridViewHeight / rowHeight);
109         }
110
111         return rowsVisible;
112     },
113
114     // go to last visible record in grid.
115     onKeyEnd: function(e, t) {
116         var me = this,
117             last = me.store.getAt(me.store.getCount() - 1);
118             
119         if (last) {
120             if (e.shiftKey) {
121                 me.selectRange(last, me.lastFocused || 0);
122                 me.setLastFocused(last);
123             } else if (e.ctrlKey) {
124                 me.setLastFocused(last);
125             } else {
126                 me.doSelect(last);
127             }
128         }
129     },
130
131     // go to first visible record in grid.
132     onKeyHome: function(e, t) {
133         var me = this,
134             first = me.store.getAt(0);
135             
136         if (first) {
137             if (e.shiftKey) {
138                 me.selectRange(first, me.lastFocused || 0);
139                 me.setLastFocused(first);
140             } else if (e.ctrlKey) {
141                 me.setLastFocused(first);
142             } else {
143                 me.doSelect(first, false);
144             }
145         }
146     },
147
148     // Go one page up from the lastFocused record in the grid.
149     onKeyPageUp: function(e, t) {
150         var me = this,
151             rowsVisible = me.getRowsVisible(),
152             selIdx,
153             prevIdx,
154             prevRecord,
155             currRec;
156             
157         if (rowsVisible) {
158             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
159             prevIdx = selIdx - rowsVisible;
160             if (prevIdx &lt; 0) {
161                 prevIdx = 0;
162             }
163             prevRecord = me.store.getAt(prevIdx);
164             if (e.shiftKey) {
165                 currRec = me.store.getAt(selIdx);
166                 me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
167                 me.setLastFocused(prevRecord);
168             } else if (e.ctrlKey) {
169                 e.preventDefault();
170                 me.setLastFocused(prevRecord);
171             } else {
172                 me.doSelect(prevRecord);
173             }
174
175         }
176     },
177
178     // Go one page down from the lastFocused record in the grid.
179     onKeyPageDown: function(e, t) {
180         var me = this,
181             rowsVisible = me.getRowsVisible(),
182             selIdx,
183             nextIdx,
184             nextRecord,
185             currRec;
186             
187         if (rowsVisible) {
188             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
189             nextIdx = selIdx + rowsVisible;
190             if (nextIdx &gt;= me.store.getCount()) {
191                 nextIdx = me.store.getCount() - 1;
192             }
193             nextRecord = me.store.getAt(nextIdx);
194             if (e.shiftKey) {
195                 currRec = me.store.getAt(selIdx);
196                 me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
197                 me.setLastFocused(nextRecord);
198             } else if (e.ctrlKey) {
199                 // some browsers, this means go thru browser tabs
200                 // attempt to stop.
201                 e.preventDefault();
202                 me.setLastFocused(nextRecord);
203             } else {
204                 me.doSelect(nextRecord);
205             }
206         }
207     },
208
209     // Select/Deselect based on pressing Spacebar.
210     // Assumes a SIMPLE selectionmode style
211     onKeyPress: function(e, t) {
212         if (e.getKey() === e.SPACE) {
213             e.stopEvent();
214             var me = this,
215                 record = me.lastFocused;
216                 
217             if (record) {
218                 if (me.isSelected(record)) {
219                     me.doDeselect(record, false);
220                 } else {
221                     me.doSelect(record, true);
222                 }
223             }
224         }
225     },
226
227     // Navigate one record up. This could be a selection or
228     // could be simply focusing a record for discontiguous
229     // selection. Provides bounds checking.
230     onKeyUp: function(e, t) {
231         var me = this,
232             view = me.views[0],
233             idx  = me.store.indexOf(me.lastFocused),
234             record;
235             
236         if (idx &gt; 0) {
237             // needs to be the filtered count as thats what
238             // will be visible.
239             record = me.store.getAt(idx - 1);
240             if (e.shiftKey &amp;&amp; me.lastFocused) {
241                 if (me.isSelected(me.lastFocused) &amp;&amp; me.isSelected(record)) {
242                     me.doDeselect(me.lastFocused, true);
243                     me.setLastFocused(record);
244                 } else if (!me.isSelected(me.lastFocused)) {
245                     me.doSelect(me.lastFocused, true);
246                     me.doSelect(record, true);
247                 } else {
248                     me.doSelect(record, true);
249                 }
250             } else if (e.ctrlKey) {
251                 me.setLastFocused(record);
252             } else {
253                 me.doSelect(record);
254                 //view.focusRow(idx - 1);
255             }
256         }
257         // There was no lastFocused record, and the user has pressed up
258         // Ignore??
259         //else if (this.selected.getCount() == 0) {
260         //    
261         //    this.doSelect(record);
262         //    //view.focusRow(idx - 1);
263         //}
264     },
265
266     // Navigate one record down. This could be a selection or
267     // could be simply focusing a record for discontiguous
268     // selection. Provides bounds checking.
269     onKeyDown: function(e, t) {
270         var me = this,
271             view = me.views[0],
272             idx  = me.store.indexOf(me.lastFocused),
273             record;
274             
275         // needs to be the filtered count as thats what
276         // will be visible.
277         if (idx + 1 &lt; me.store.getCount()) {
278             record = me.store.getAt(idx + 1);
279             if (me.selected.getCount() === 0) {
280                 me.doSelect(record);
281                 //view.focusRow(idx + 1);
282             } else if (e.shiftKey &amp;&amp; me.lastFocused) {
283                 if (me.isSelected(me.lastFocused) &amp;&amp; me.isSelected(record)) {
284                     me.doDeselect(me.lastFocused, true);
285                     me.setLastFocused(record);
286                 } else if (!me.isSelected(me.lastFocused)) {
287                     me.doSelect(me.lastFocused, true);
288                     me.doSelect(record, true);
289                 } else {
290                     me.doSelect(record, true);
291                 }
292             } else if (e.ctrlKey) {
293                 me.setLastFocused(record);
294             } else {
295                 me.doSelect(record);
296                 //view.focusRow(idx + 1);
297             }
298         }
299     },
300     
301     scrollByDeltaX: function(delta) {
302         var view    = this.views[0],
303             section = view.up(),
304             hScroll = section.horizontalScroller;
305             
306         if (hScroll) {
307             hScroll.scrollByDeltaX(delta);
308         }
309     },
310     
311     onKeyLeft: function(e, t) {
312         this.scrollByDeltaX(-this.deltaScroll);
313     },
314     
315     onKeyRight: function(e, t) {
316         this.scrollByDeltaX(this.deltaScroll);
317     },
318
319     // Select the record with the event included so that
320     // we can take into account ctrlKey, shiftKey, etc
321     onRowMouseDown: function(view, record, item, index, e) {
322         view.el.focus();
323         this.selectWithEvent(record, e);
324     },
325
326     // Allow the GridView to update the UI by
327     // adding/removing a CSS class from the row.
328     onSelectChange: function(record, isSelected, suppressEvent) {
329         var me      = this,
330             views   = me.views,
331             viewsLn = views.length,
332             store   = me.store,
333             rowIdx  = store.indexOf(record),
334             i = 0;
335             
336         for (; i &lt; viewsLn; i++) {
337             if (isSelected) {
338                 views[i].onRowSelect(rowIdx, suppressEvent);
339                 if (!suppressEvent) {
340                     me.fireEvent('select', me, record, rowIdx);
341                 }
342             } else {
343                 views[i].onRowDeselect(rowIdx, suppressEvent);
344                 if (!suppressEvent) {
345                     me.fireEvent('deselect', me, record, rowIdx);
346                 }
347             }
348         }
349     },
350
351     // Provide indication of what row was last focused via
352     // the gridview.
353     onLastFocusChanged: function(oldFocused, newFocused, supressFocus) {
354         var views   = this.views,
355             viewsLn = views.length,
356             store   = this.store,
357             rowIdx,
358             i = 0;
359             
360         if (oldFocused) {
361             rowIdx = store.indexOf(oldFocused);
362             if (rowIdx != -1) {
363                 for (; i &lt; viewsLn; i++) {
364                     views[i].onRowFocus(rowIdx, false);
365                 }
366             }
367         }
368
369         if (newFocused) {
370             rowIdx = store.indexOf(newFocused);
371             if (rowIdx != -1) {
372                 for (i = 0; i &lt; viewsLn; i++) {
373                     views[i].onRowFocus(rowIdx, true, supressFocus);
374                 }
375             }
376         }
377     },
378     
379     onEditorTab: function(editingPlugin, e) {
380         var me = this,
381             view = me.views[0],
382             record = editingPlugin.getActiveRecord(),
383             header = editingPlugin.getActiveColumn(),
384             position = view.getPosition(record, header),
385             direction = e.shiftKey ? 'left' : 'right',
386             newPosition  = view.walkCells(position, direction, e, this.preventWrap);
387             
388         if (newPosition) {
389             editingPlugin.startEditByPosition(newPosition);
390         }
391     },
392     
393     selectByPosition: function(position) {
394         var record = this.store.getAt(position.row);
395         this.select(record);
396     }
397 });</pre></pre></body></html>