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