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