Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / src / widgets / grid / GridPanel.js
1 /*!
2  * Ext JS Library 3.1.1
3  * Copyright(c) 2006-2010 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.grid.GridPanel\r
9  * @extends Ext.Panel\r
10  * <p>This class represents the primary interface of a component based grid control to represent data\r
11  * in a tabular format of rows and columns. The GridPanel is composed of the following:</p>\r
12  * <div class="mdetail-params"><ul>\r
13  * <li><b>{@link Ext.data.Store Store}</b> : The Model holding the data records (rows)\r
14  * <div class="sub-desc"></div></li>\r
15  * <li><b>{@link Ext.grid.ColumnModel Column model}</b> : Column makeup\r
16  * <div class="sub-desc"></div></li>\r
17  * <li><b>{@link Ext.grid.GridView View}</b> : Encapsulates the user interface \r
18  * <div class="sub-desc"></div></li>\r
19  * <li><b>{@link Ext.grid.AbstractSelectionModel selection model}</b> : Selection behavior \r
20  * <div class="sub-desc"></div></li>\r
21  * </ul></div>\r
22  * <p>Example usage:</p>\r
23  * <pre><code>\r
24 var grid = new Ext.grid.GridPanel({\r
25     {@link #store}: new {@link Ext.data.Store}({\r
26         {@link Ext.data.Store#autoDestroy autoDestroy}: true,\r
27         {@link Ext.data.Store#reader reader}: reader,\r
28         {@link Ext.data.Store#data data}: xg.dummyData\r
29     }),\r
30     {@link #colModel}: new {@link Ext.grid.ColumnModel}({\r
31         {@link Ext.grid.ColumnModel#defaults defaults}: {\r
32             width: 120,\r
33             sortable: true\r
34         },\r
35         {@link Ext.grid.ColumnModel#columns columns}: [\r
36             {id: 'company', header: 'Company', width: 200, sortable: true, dataIndex: 'company'},\r
37             {header: 'Price', renderer: Ext.util.Format.usMoney, dataIndex: 'price'},\r
38             {header: 'Change', dataIndex: 'change'},\r
39             {header: '% Change', dataIndex: 'pctChange'},\r
40             // instead of specifying renderer: Ext.util.Format.dateRenderer('m/d/Y') use xtype\r
41             {\r
42                 header: 'Last Updated', width: 135, dataIndex: 'lastChange',\r
43                 xtype: 'datecolumn', format: 'M d, Y'\r
44             }\r
45         ],\r
46     }),\r
47     {@link #viewConfig}: {\r
48         {@link Ext.grid.GridView#forceFit forceFit}: true,\r
49 \r
50 //      Return CSS class to apply to rows depending upon data values\r
51         {@link Ext.grid.GridView#getRowClass getRowClass}: function(record, index) {\r
52             var c = record.{@link Ext.data.Record#get get}('change');\r
53             if (c < 0) {\r
54                 return 'price-fall';\r
55             } else if (c > 0) {\r
56                 return 'price-rise';\r
57             }\r
58         }\r
59     },\r
60     {@link #sm}: new Ext.grid.RowSelectionModel({singleSelect:true}),\r
61     width: 600,\r
62     height: 300,\r
63     frame: true,\r
64     title: 'Framed with Row Selection and Horizontal Scrolling',\r
65     iconCls: 'icon-grid'\r
66 });\r
67  * </code></pre>\r
68  * <p><b><u>Notes:</u></b></p>\r
69  * <div class="mdetail-params"><ul>\r
70  * <li>Although this class inherits many configuration options from base classes, some of them\r
71  * (such as autoScroll, autoWidth, layout, items, etc) are not used by this class, and will\r
72  * have no effect.</li>\r
73  * <li>A grid <b>requires</b> a width in which to scroll its columns, and a height in which to\r
74  * scroll its rows. These dimensions can either be set explicitly through the\r
75  * <tt>{@link Ext.BoxComponent#height height}</tt> and <tt>{@link Ext.BoxComponent#width width}</tt>\r
76  * configuration options or implicitly set by using the grid as a child item of a\r
77  * {@link Ext.Container Container} which will have a {@link Ext.Container#layout layout manager}\r
78  * provide the sizing of its child items (for example the Container of the Grid may specify\r
79  * <tt>{@link Ext.Container#layout layout}:'fit'</tt>).</li>\r
80  * <li>To access the data in a Grid, it is necessary to use the data model encapsulated\r
81  * by the {@link #store Store}. See the {@link #cellclick} event for more details.</li>\r
82  * </ul></div>\r
83  * @constructor\r
84  * @param {Object} config The config object\r
85  * @xtype grid\r
86  */\r
87 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {\r
88     /**\r
89      * @cfg {String} autoExpandColumn\r
90      * <p>The <tt>{@link Ext.grid.Column#id id}</tt> of a {@link Ext.grid.Column column} in\r
91      * this grid that should expand to fill unused space. This value specified here can not\r
92      * be <tt>0</tt>.</p>\r
93      * <br><p><b>Note</b>: If the Grid's {@link Ext.grid.GridView view} is configured with\r
94      * <tt>{@link Ext.grid.GridView#forceFit forceFit}=true</tt> the <tt>autoExpandColumn</tt>\r
95      * is ignored. See {@link Ext.grid.Column}.<tt>{@link Ext.grid.Column#width width}</tt>\r
96      * for additional details.</p>\r
97      * <p>See <tt>{@link #autoExpandMax}</tt> and <tt>{@link #autoExpandMin}</tt> also.</p>\r
98      */\r
99     autoExpandColumn : false,\r
100     /**\r
101      * @cfg {Number} autoExpandMax The maximum width the <tt>{@link #autoExpandColumn}</tt>\r
102      * can have (if enabled). Defaults to <tt>1000</tt>.\r
103      */\r
104     autoExpandMax : 1000,\r
105     /**\r
106      * @cfg {Number} autoExpandMin The minimum width the <tt>{@link #autoExpandColumn}</tt>\r
107      * can have (if enabled). Defaults to <tt>50</tt>.\r
108      */\r
109     autoExpandMin : 50,\r
110     /**\r
111      * @cfg {Boolean} columnLines <tt>true</tt> to add css for column separation lines.\r
112      * Default is <tt>false</tt>.\r
113      */\r
114     columnLines : false,\r
115     /**\r
116      * @cfg {Object} cm Shorthand for <tt>{@link #colModel}</tt>.\r
117      */\r
118     /**\r
119      * @cfg {Object} colModel The {@link Ext.grid.ColumnModel} to use when rendering the grid (required).\r
120      */\r
121     /**\r
122      * @cfg {Array} columns An array of {@link Ext.grid.Column columns} to auto create a\r
123      * {@link Ext.grid.ColumnModel}.  The ColumnModel may be explicitly created via the\r
124      * <tt>{@link #colModel}</tt> configuration property.\r
125      */\r
126     /**\r
127      * @cfg {String} ddGroup The DD group this GridPanel belongs to. Defaults to <tt>'GridDD'</tt> if not specified.\r
128      */\r
129     /**\r
130      * @cfg {String} ddText\r
131      * Configures the text in the drag proxy.  Defaults to:\r
132      * <pre><code>\r
133      * ddText : '{0} selected row{1}'\r
134      * </code></pre>\r
135      * <tt>{0}</tt> is replaced with the number of selected rows.\r
136      */\r
137     ddText : '{0} selected row{1}',\r
138     /**\r
139      * @cfg {Boolean} deferRowRender <P>Defaults to <tt>true</tt> to enable deferred row rendering.</p>\r
140      * <p>This allows the GridPanel to be initially rendered empty, with the expensive update of the row\r
141      * structure deferred so that layouts with GridPanels appear more quickly.</p>\r
142      */\r
143     deferRowRender : true,\r
144     /**\r
145      * @cfg {Boolean} disableSelection <p><tt>true</tt> to disable selections in the grid. Defaults to <tt>false</tt>.</p>\r
146      * <p>Ignored if a {@link #selModel SelectionModel} is specified.</p>\r
147      */\r
148     /**\r
149      * @cfg {Boolean} enableColumnResize <tt>false</tt> to turn off column resizing for the whole grid. Defaults to <tt>true</tt>.\r
150      */\r
151     /**\r
152      * @cfg {Boolean} enableColumnHide\r
153      * Defaults to <tt>true</tt> to enable {@link Ext.grid.Column#hidden hiding of columns}\r
154      * with the {@link #enableHdMenu header menu}.\r
155      */\r
156     enableColumnHide : true,\r
157     /**\r
158      * @cfg {Boolean} enableColumnMove Defaults to <tt>true</tt> to enable drag and drop reorder of columns. <tt>false</tt>\r
159      * to turn off column reordering via drag drop.\r
160      */\r
161     enableColumnMove : true,\r
162     /**\r
163      * @cfg {Boolean} enableDragDrop <p>Enables dragging of the selected rows of the GridPanel. Defaults to <tt>false</tt>.</p>\r
164      * <p>Setting this to <b><tt>true</tt></b> causes this GridPanel's {@link #getView GridView} to\r
165      * create an instance of {@link Ext.grid.GridDragZone}. <b>Note</b>: this is available only <b>after</b>\r
166      * the Grid has been rendered as the GridView's <tt>{@link Ext.grid.GridView#dragZone dragZone}</tt>\r
167      * property.</p>\r
168      * <p>A cooperating {@link Ext.dd.DropZone DropZone} must be created who's implementations of\r
169      * {@link Ext.dd.DropZone#onNodeEnter onNodeEnter}, {@link Ext.dd.DropZone#onNodeOver onNodeOver},\r
170      * {@link Ext.dd.DropZone#onNodeOut onNodeOut} and {@link Ext.dd.DropZone#onNodeDrop onNodeDrop} are able\r
171      * to process the {@link Ext.grid.GridDragZone#getDragData data} which is provided.</p>\r
172      */\r
173     enableDragDrop : false,\r
174     /**\r
175      * @cfg {Boolean} enableHdMenu Defaults to <tt>true</tt> to enable the drop down button for menu in the headers.\r
176      */\r
177     enableHdMenu : true,\r
178     /**\r
179      * @cfg {Boolean} hideHeaders True to hide the grid's header. Defaults to <code>false</code>.\r
180      */\r
181     /**\r
182      * @cfg {Object} loadMask An {@link Ext.LoadMask} config or true to mask the grid while\r
183      * loading. Defaults to <code>false</code>.\r
184      */\r
185     loadMask : false,\r
186     /**\r
187      * @cfg {Number} maxHeight Sets the maximum height of the grid - ignored if <tt>autoHeight</tt> is not on.\r
188      */\r
189     /**\r
190      * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Defaults to <tt>25</tt>.\r
191      */\r
192     minColumnWidth : 25,\r
193     /**\r
194      * @cfg {Object} sm Shorthand for <tt>{@link #selModel}</tt>.\r
195      */\r
196     /**\r
197      * @cfg {Object} selModel Any subclass of {@link Ext.grid.AbstractSelectionModel} that will provide\r
198      * the selection model for the grid (defaults to {@link Ext.grid.RowSelectionModel} if not specified).\r
199      */\r
200     /**\r
201      * @cfg {Ext.data.Store} store The {@link Ext.data.Store} the grid should use as its data source (required).\r
202      */\r
203     /**\r
204      * @cfg {Boolean} stripeRows <tt>true</tt> to stripe the rows. Default is <tt>false</tt>.\r
205      * <p>This causes the CSS class <tt><b>x-grid3-row-alt</b></tt> to be added to alternate rows of\r
206      * the grid. A default CSS rule is provided which sets a background colour, but you can override this\r
207      * with a rule which either overrides the <b>background-color</b> style using the '!important'\r
208      * modifier, or which uses a CSS selector of higher specificity.</p>\r
209      */\r
210     stripeRows : false,\r
211     /**\r
212      * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is <tt>true</tt>\r
213      * for GridPanel, but <tt>false</tt> for EditorGridPanel.\r
214      */\r
215     trackMouseOver : true,\r
216     /**\r
217      * @cfg {Array} stateEvents\r
218      * An array of events that, when fired, should trigger this component to save its state.\r
219      * Defaults to:<pre><code>\r
220      * stateEvents: ['columnmove', 'columnresize', 'sortchange', 'groupchange']\r
221      * </code></pre>\r
222      * <p>These can be any types of events supported by this component, including browser or\r
223      * custom events (e.g., <tt>['click', 'customerchange']</tt>).</p>\r
224      * <p>See {@link Ext.Component#stateful} for an explanation of saving and restoring\r
225      * Component state.</p>\r
226      */\r
227     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],\r
228     /**\r
229      * @cfg {Object} view The {@link Ext.grid.GridView} used by the grid. This can be set\r
230      * before a call to {@link Ext.Component#render render()}.\r
231      */\r
232     view : null,\r
233     \r
234     /**\r
235      * @cfg {Array} bubbleEvents\r
236      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
237      * See {@link Ext.util.Observable#enableBubble}. \r
238      * Defaults to <tt>[]</tt>.\r
239      */\r
240     bubbleEvents: [],\r
241     \r
242     /**\r
243      * @cfg {Object} viewConfig A config object that will be applied to the grid's UI view.  Any of\r
244      * the config options available for {@link Ext.grid.GridView} can be specified here. This option\r
245      * is ignored if <tt>{@link #view}</tt> is specified.\r
246      */\r
247 \r
248     // private\r
249     rendered : false,\r
250     // private\r
251     viewReady : false,\r
252 \r
253     // private\r
254     initComponent : function(){\r
255         Ext.grid.GridPanel.superclass.initComponent.call(this);\r
256 \r
257         if(this.columnLines){\r
258             this.cls = (this.cls || '') + ' x-grid-with-col-lines';\r
259         }\r
260         // override any provided value since it isn't valid\r
261         // and is causing too many bug reports ;)\r
262         this.autoScroll = false;\r
263         this.autoWidth = false;\r
264 \r
265         if(Ext.isArray(this.columns)){\r
266             this.colModel = new Ext.grid.ColumnModel(this.columns);\r
267             delete this.columns;\r
268         }\r
269 \r
270         // check and correct shorthanded configs\r
271         if(this.ds){\r
272             this.store = this.ds;\r
273             delete this.ds;\r
274         }\r
275         if(this.cm){\r
276             this.colModel = this.cm;\r
277             delete this.cm;\r
278         }\r
279         if(this.sm){\r
280             this.selModel = this.sm;\r
281             delete this.sm;\r
282         }\r
283         this.store = Ext.StoreMgr.lookup(this.store);\r
284 \r
285         this.addEvents(\r
286             // raw events\r
287             /**\r
288              * @event click\r
289              * The raw click event for the entire grid.\r
290              * @param {Ext.EventObject} e\r
291              */\r
292             'click',\r
293             /**\r
294              * @event dblclick\r
295              * The raw dblclick event for the entire grid.\r
296              * @param {Ext.EventObject} e\r
297              */\r
298             'dblclick',\r
299             /**\r
300              * @event contextmenu\r
301              * The raw contextmenu event for the entire grid.\r
302              * @param {Ext.EventObject} e\r
303              */\r
304             'contextmenu',\r
305             /**\r
306              * @event mousedown\r
307              * The raw mousedown event for the entire grid.\r
308              * @param {Ext.EventObject} e\r
309              */\r
310             'mousedown',\r
311             /**\r
312              * @event mouseup\r
313              * The raw mouseup event for the entire grid.\r
314              * @param {Ext.EventObject} e\r
315              */\r
316             'mouseup',\r
317             /**\r
318              * @event mouseover\r
319              * The raw mouseover event for the entire grid.\r
320              * @param {Ext.EventObject} e\r
321              */\r
322             'mouseover',\r
323             /**\r
324              * @event mouseout\r
325              * The raw mouseout event for the entire grid.\r
326              * @param {Ext.EventObject} e\r
327              */\r
328             'mouseout',\r
329             /**\r
330              * @event keypress\r
331              * The raw keypress event for the entire grid.\r
332              * @param {Ext.EventObject} e\r
333              */\r
334             'keypress',\r
335             /**\r
336              * @event keydown\r
337              * The raw keydown event for the entire grid.\r
338              * @param {Ext.EventObject} e\r
339              */\r
340             'keydown',\r
341 \r
342             // custom events\r
343             /**\r
344              * @event cellmousedown\r
345              * Fires before a cell is clicked\r
346              * @param {Grid} this\r
347              * @param {Number} rowIndex\r
348              * @param {Number} columnIndex\r
349              * @param {Ext.EventObject} e\r
350              */\r
351             'cellmousedown',\r
352             /**\r
353              * @event rowmousedown\r
354              * Fires before a row is clicked\r
355              * @param {Grid} this\r
356              * @param {Number} rowIndex\r
357              * @param {Ext.EventObject} e\r
358              */\r
359             'rowmousedown',\r
360             /**\r
361              * @event headermousedown\r
362              * Fires before a header is clicked\r
363              * @param {Grid} this\r
364              * @param {Number} columnIndex\r
365              * @param {Ext.EventObject} e\r
366              */\r
367             'headermousedown',\r
368             \r
369             /**\r
370              * @event groupmousedown\r
371              * Fires before a group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
372              * @param {Grid} this\r
373              * @param {String} groupField\r
374              * @param {String} groupValue\r
375              * @param {Ext.EventObject} e\r
376              */\r
377             'groupmousedown',\r
378             \r
379             /**\r
380              * @event rowbodymousedown\r
381              * Fires before the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
382              * @param {Grid} this\r
383              * @param {Number} rowIndex\r
384              * @param {Ext.EventObject} e\r
385              */\r
386             'rowbodymousedown',\r
387             \r
388             /**\r
389              * @event containermousedown\r
390              * Fires before the container is clicked. The container consists of any part of the grid body that is not covered by a row.\r
391              * @param {Grid} this\r
392              * @param {Ext.EventObject} e\r
393              */\r
394             'containermousedown',\r
395 \r
396             /**\r
397              * @event cellclick\r
398              * Fires when a cell is clicked.\r
399              * The data for the cell is drawn from the {@link Ext.data.Record Record}\r
400              * for this row. To access the data in the listener function use the\r
401              * following technique:\r
402              * <pre><code>\r
403 function(grid, rowIndex, columnIndex, e) {\r
404     var record = grid.getStore().getAt(rowIndex);  // Get the Record\r
405     var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name\r
406     var data = record.get(fieldName);\r
407 }\r
408 </code></pre>\r
409              * @param {Grid} this\r
410              * @param {Number} rowIndex\r
411              * @param {Number} columnIndex\r
412              * @param {Ext.EventObject} e\r
413              */\r
414             'cellclick',\r
415             /**\r
416              * @event celldblclick\r
417              * Fires when a cell is double clicked\r
418              * @param {Grid} this\r
419              * @param {Number} rowIndex\r
420              * @param {Number} columnIndex\r
421              * @param {Ext.EventObject} e\r
422              */\r
423             'celldblclick',\r
424             /**\r
425              * @event rowclick\r
426              * Fires when a row is clicked\r
427              * @param {Grid} this\r
428              * @param {Number} rowIndex\r
429              * @param {Ext.EventObject} e\r
430              */\r
431             'rowclick',\r
432             /**\r
433              * @event rowdblclick\r
434              * Fires when a row is double clicked\r
435              * @param {Grid} this\r
436              * @param {Number} rowIndex\r
437              * @param {Ext.EventObject} e\r
438              */\r
439             'rowdblclick',\r
440             /**\r
441              * @event headerclick\r
442              * Fires when a header is clicked\r
443              * @param {Grid} this\r
444              * @param {Number} columnIndex\r
445              * @param {Ext.EventObject} e\r
446              */\r
447             'headerclick',\r
448             /**\r
449              * @event headerdblclick\r
450              * Fires when a header cell is double clicked\r
451              * @param {Grid} this\r
452              * @param {Number} columnIndex\r
453              * @param {Ext.EventObject} e\r
454              */\r
455             'headerdblclick',\r
456             /**\r
457              * @event groupclick\r
458              * Fires when group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
459              * @param {Grid} this\r
460              * @param {String} groupField\r
461              * @param {String} groupValue\r
462              * @param {Ext.EventObject} e\r
463              */\r
464             'groupclick',\r
465             /**\r
466              * @event groupdblclick\r
467              * Fires when group header is double clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
468              * @param {Grid} this\r
469              * @param {String} groupField\r
470              * @param {String} groupValue\r
471              * @param {Ext.EventObject} e\r
472              */\r
473             'groupdblclick',\r
474             /**\r
475              * @event containerclick\r
476              * Fires when the container is clicked. The container consists of any part of the grid body that is not covered by a row.\r
477              * @param {Grid} this\r
478              * @param {Ext.EventObject} e\r
479              */\r
480             'containerclick',\r
481             /**\r
482              * @event containerdblclick\r
483              * Fires when the container is double clicked. The container consists of any part of the grid body that is not covered by a row.\r
484              * @param {Grid} this\r
485              * @param {Ext.EventObject} e\r
486              */\r
487             'containerdblclick',\r
488             \r
489             /**\r
490              * @event rowbodyclick\r
491              * Fires when the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
492              * @param {Grid} this\r
493              * @param {Number} rowIndex\r
494              * @param {Ext.EventObject} e\r
495              */\r
496             'rowbodyclick',\r
497             /**\r
498              * @event rowbodydblclick\r
499              * Fires when the row body is double clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
500              * @param {Grid} this\r
501              * @param {Number} rowIndex\r
502              * @param {Ext.EventObject} e\r
503              */\r
504             'rowbodydblclick',\r
505             \r
506             /**\r
507              * @event rowcontextmenu\r
508              * Fires when a row is right clicked\r
509              * @param {Grid} this\r
510              * @param {Number} rowIndex\r
511              * @param {Ext.EventObject} e\r
512              */\r
513             'rowcontextmenu',\r
514             /**\r
515              * @event cellcontextmenu\r
516              * Fires when a cell is right clicked\r
517              * @param {Grid} this\r
518              * @param {Number} rowIndex\r
519              * @param {Number} cellIndex\r
520              * @param {Ext.EventObject} e\r
521              */\r
522             'cellcontextmenu',\r
523             /**\r
524              * @event headercontextmenu\r
525              * Fires when a header is right clicked\r
526              * @param {Grid} this\r
527              * @param {Number} columnIndex\r
528              * @param {Ext.EventObject} e\r
529              */\r
530             'headercontextmenu',\r
531             /**\r
532              * @event groupcontextmenu\r
533              * Fires when group header is right clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
534              * @param {Grid} this\r
535              * @param {String} groupField\r
536              * @param {String} groupValue\r
537              * @param {Ext.EventObject} e\r
538              */\r
539             'groupcontextmenu',\r
540             /**\r
541              * @event containercontextmenu\r
542              * Fires when the container is right clicked. The container consists of any part of the grid body that is not covered by a row.\r
543              * @param {Grid} this\r
544              * @param {Ext.EventObject} e\r
545              */\r
546             'containercontextmenu',\r
547             /**\r
548              * @event rowbodycontextmenu\r
549              * Fires when the row body is right clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
550              * @param {Grid} this\r
551              * @param {Number} rowIndex\r
552              * @param {Ext.EventObject} e\r
553              */\r
554             'rowbodycontextmenu',\r
555             /**\r
556              * @event bodyscroll\r
557              * Fires when the body element is scrolled\r
558              * @param {Number} scrollLeft\r
559              * @param {Number} scrollTop\r
560              */\r
561             'bodyscroll',\r
562             /**\r
563              * @event columnresize\r
564              * Fires when the user resizes a column\r
565              * @param {Number} columnIndex\r
566              * @param {Number} newSize\r
567              */\r
568             'columnresize',\r
569             /**\r
570              * @event columnmove\r
571              * Fires when the user moves a column\r
572              * @param {Number} oldIndex\r
573              * @param {Number} newIndex\r
574              */\r
575             'columnmove',\r
576             /**\r
577              * @event sortchange\r
578              * Fires when the grid's store sort changes\r
579              * @param {Grid} this\r
580              * @param {Object} sortInfo An object with the keys field and direction\r
581              */\r
582             'sortchange',\r
583             /**\r
584              * @event groupchange\r
585              * Fires when the grid's grouping changes (only applies for grids with a {@link Ext.grid.GroupingView GroupingView})\r
586              * @param {Grid} this\r
587              * @param {String} groupField A string with the grouping field, null if the store is not grouped.\r
588              */\r
589             'groupchange',\r
590             /**\r
591              * @event reconfigure\r
592              * Fires when the grid is reconfigured with a new store and/or column model.\r
593              * @param {Grid} this\r
594              * @param {Ext.data.Store} store The new store\r
595              * @param {Ext.grid.ColumnModel} colModel The new column model\r
596              */\r
597             'reconfigure',\r
598             /**\r
599              * @event viewready\r
600              * Fires when the grid view is available (use this for selecting a default row). \r
601              * @param {Grid} this\r
602              */\r
603             'viewready'\r
604         );\r
605     },\r
606 \r
607     // private\r
608     onRender : function(ct, position){\r
609         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);\r
610 \r
611         var c = this.getGridEl();\r
612 \r
613         this.el.addClass('x-grid-panel');\r
614 \r
615         this.mon(c, {\r
616             scope: this,\r
617             mousedown: this.onMouseDown,\r
618             click: this.onClick,\r
619             dblclick: this.onDblClick,\r
620             contextmenu: this.onContextMenu\r
621         });\r
622 \r
623         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);\r
624 \r
625         var view = this.getView();\r
626         view.init(this);\r
627         view.render();\r
628         this.getSelectionModel().init(this);\r
629     },\r
630 \r
631     // private\r
632     initEvents : function(){\r
633         Ext.grid.GridPanel.superclass.initEvents.call(this);\r
634 \r
635         if(this.loadMask){\r
636             this.loadMask = new Ext.LoadMask(this.bwrap,\r
637                     Ext.apply({store:this.store}, this.loadMask));\r
638         }\r
639     },\r
640 \r
641     initStateEvents : function(){\r
642         Ext.grid.GridPanel.superclass.initStateEvents.call(this);\r
643         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});\r
644     },\r
645 \r
646     applyState : function(state){\r
647         var cm = this.colModel,\r
648             cs = state.columns,\r
649             store = this.store,\r
650             s,\r
651             c,\r
652             oldIndex;\r
653             \r
654         if(cs){\r
655             for(var i = 0, len = cs.length; i < len; i++){\r
656                 s = cs[i];\r
657                 c = cm.getColumnById(s.id);\r
658                 if(c){\r
659                     c.hidden = s.hidden;\r
660                     c.width = s.width;\r
661                     oldIndex = cm.getIndexById(s.id);\r
662                     if(oldIndex != i){\r
663                         cm.moveColumn(oldIndex, i);\r
664                     }\r
665                 }\r
666             }\r
667         }\r
668         if(store){\r
669             s = state.sort;\r
670             if(s){\r
671                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);\r
672             }\r
673             s = state.group;\r
674             if(store.groupBy){\r
675                 if(s){\r
676                     store.groupBy(s);\r
677                 }else{\r
678                     store.clearGrouping();\r
679                 }\r
680             }\r
681 \r
682         }\r
683         var o = Ext.apply({}, state);\r
684         delete o.columns;\r
685         delete o.sort;\r
686         Ext.grid.GridPanel.superclass.applyState.call(this, o);\r
687     },\r
688 \r
689     getState : function(){\r
690         var o = {columns: []},\r
691             store = this.store,\r
692             ss,\r
693             gs;\r
694             \r
695         for(var i = 0, c; (c = this.colModel.config[i]); i++){\r
696             o.columns[i] = {\r
697                 id: c.id,\r
698                 width: c.width\r
699             };\r
700             if(c.hidden){\r
701                 o.columns[i].hidden = true;\r
702             }\r
703         }\r
704         if(store){\r
705             ss = store.getSortState();\r
706             if(ss){\r
707                 o.sort = ss;\r
708             }\r
709             if(store.getGroupState){\r
710                 gs = store.getGroupState();\r
711                 if(gs){\r
712                     o.group = gs;\r
713                 }\r
714             }\r
715         }\r
716         return o;\r
717     },\r
718 \r
719     // private\r
720     afterRender : function(){\r
721         Ext.grid.GridPanel.superclass.afterRender.call(this);\r
722         var v = this.view;\r
723         this.on('bodyresize', v.layout, v);\r
724         v.layout();\r
725         if(this.deferRowRender){\r
726             v.afterRender.defer(10, this.view);\r
727         }else{\r
728             v.afterRender();\r
729         }\r
730         this.viewReady = true;\r
731     },\r
732 \r
733     /**\r
734      * <p>Reconfigures the grid to use a different Store and Column Model\r
735      * and fires the 'reconfigure' event. The View will be bound to the new\r
736      * objects and refreshed.</p>\r
737      * <p>Be aware that upon reconfiguring a GridPanel, certain existing settings <i>may</i> become\r
738      * invalidated. For example the configured {@link #autoExpandColumn} may no longer exist in the\r
739      * new ColumnModel. Also, an existing {@link Ext.PagingToolbar PagingToolbar} will still be bound\r
740      * to the old Store, and will need rebinding. Any {@link #plugins} might also need reconfiguring\r
741      * with the new data.</p>\r
742      * @param {Ext.data.Store} store The new {@link Ext.data.Store} object\r
743      * @param {Ext.grid.ColumnModel} colModel The new {@link Ext.grid.ColumnModel} object\r
744      */\r
745     reconfigure : function(store, colModel){\r
746         var rendered = this.rendered;\r
747         if(rendered){\r
748             if(this.loadMask){\r
749                 this.loadMask.destroy();\r
750                 this.loadMask = new Ext.LoadMask(this.bwrap,\r
751                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));\r
752             }\r
753         }\r
754         if(this.view){\r
755             this.view.initData(store, colModel);\r
756         }\r
757         this.store = store;\r
758         this.colModel = colModel;\r
759         if(rendered){\r
760             this.view.refresh(true);\r
761         }\r
762         this.fireEvent('reconfigure', this, store, colModel);\r
763     },\r
764 \r
765     // private\r
766     onDestroy : function(){\r
767         if(this.rendered){\r
768             Ext.destroy(this.view, this.loadMask);\r
769         }else if(this.store && this.store.autoDestroy){\r
770             this.store.destroy();\r
771         }\r
772         Ext.destroy(this.colModel, this.selModel);\r
773         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;\r
774         Ext.grid.GridPanel.superclass.onDestroy.call(this);\r
775     },\r
776 \r
777     // private\r
778     processEvent : function(name, e){\r
779         this.fireEvent(name, e);\r
780         var t = e.getTarget(),\r
781             v = this.view,\r
782             header = v.findHeaderIndex(t);\r
783             \r
784         if(header !== false){\r
785             this.fireEvent('header' + name, this, header, e);\r
786         }else{\r
787             var row = v.findRowIndex(t),\r
788                 cell,\r
789                 body;\r
790             if(row !== false){\r
791                 this.fireEvent('row' + name, this, row, e);\r
792                 cell = v.findCellIndex(t);\r
793                 body = v.findRowBody(t);\r
794                 if(cell !== false){\r
795                     this.fireEvent('cell' + name, this, row, cell, e);\r
796                 }\r
797                 if(body){\r
798                     this.fireEvent('rowbody' + name, this, row, e);\r
799                 }\r
800             }else{\r
801                 this.fireEvent('container' + name, this, e);\r
802             }\r
803         }\r
804         this.view.processEvent(name, e);\r
805     },\r
806 \r
807     // private\r
808     onClick : function(e){\r
809         this.processEvent('click', e);\r
810     },\r
811 \r
812     // private\r
813     onMouseDown : function(e){\r
814         this.processEvent('mousedown', e);\r
815     },\r
816 \r
817     // private\r
818     onContextMenu : function(e, t){\r
819         this.processEvent('contextmenu', e);\r
820     },\r
821 \r
822     // private\r
823     onDblClick : function(e){\r
824         this.processEvent('dblclick', e);\r
825     },\r
826 \r
827     // private\r
828     walkCells : function(row, col, step, fn, scope){\r
829         var cm = this.colModel, \r
830             clen = cm.getColumnCount(),\r
831             ds = this.store, \r
832             rlen = ds.getCount(), \r
833             first = true;\r
834         if(step < 0){\r
835             if(col < 0){\r
836                 row--;\r
837                 first = false;\r
838             }\r
839             while(row >= 0){\r
840                 if(!first){\r
841                     col = clen-1;\r
842                 }\r
843                 first = false;\r
844                 while(col >= 0){\r
845                     if(fn.call(scope || this, row, col, cm) === true){\r
846                         return [row, col];\r
847                     }\r
848                     col--;\r
849                 }\r
850                 row--;\r
851             }\r
852         } else {\r
853             if(col >= clen){\r
854                 row++;\r
855                 first = false;\r
856             }\r
857             while(row < rlen){\r
858                 if(!first){\r
859                     col = 0;\r
860                 }\r
861                 first = false;\r
862                 while(col < clen){\r
863                     if(fn.call(scope || this, row, col, cm) === true){\r
864                         return [row, col];\r
865                     }\r
866                     col++;\r
867                 }\r
868                 row++;\r
869             }\r
870         }\r
871         return null;\r
872     },\r
873 \r
874     // private\r
875     onResize : function(){\r
876         Ext.grid.GridPanel.superclass.onResize.apply(this, arguments);\r
877         if(this.viewReady){\r
878             this.view.layout();\r
879         }\r
880     },\r
881 \r
882     /**\r
883      * Returns the grid's underlying element.\r
884      * @return {Element} The element\r
885      */\r
886     getGridEl : function(){\r
887         return this.body;\r
888     },\r
889 \r
890     // private for compatibility, overridden by editor grid\r
891     stopEditing : Ext.emptyFn,\r
892 \r
893     /**\r
894      * Returns the grid's selection model configured by the <code>{@link #selModel}</code>\r
895      * configuration option. If no selection model was configured, this will create\r
896      * and return a {@link Ext.grid.RowSelectionModel RowSelectionModel}.\r
897      * @return {SelectionModel}\r
898      */\r
899     getSelectionModel : function(){\r
900         if(!this.selModel){\r
901             this.selModel = new Ext.grid.RowSelectionModel(\r
902                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);\r
903         }\r
904         return this.selModel;\r
905     },\r
906 \r
907     /**\r
908      * Returns the grid's data store.\r
909      * @return {Ext.data.Store} The store\r
910      */\r
911     getStore : function(){\r
912         return this.store;\r
913     },\r
914 \r
915     /**\r
916      * Returns the grid's ColumnModel.\r
917      * @return {Ext.grid.ColumnModel} The column model\r
918      */\r
919     getColumnModel : function(){\r
920         return this.colModel;\r
921     },\r
922 \r
923     /**\r
924      * Returns the grid's GridView object.\r
925      * @return {Ext.grid.GridView} The grid view\r
926      */\r
927     getView : function(){\r
928         if(!this.view){\r
929             this.view = new Ext.grid.GridView(this.viewConfig);\r
930         }\r
931         return this.view;\r
932     },\r
933     /**\r
934      * Called to get grid's drag proxy text, by default returns this.ddText.\r
935      * @return {String} The text\r
936      */\r
937     getDragDropText : function(){\r
938         var count = this.selModel.getCount();\r
939         return String.format(this.ddText, count, count == 1 ? '' : 's');\r
940     }\r
941 \r
942     /** \r
943      * @cfg {String/Number} activeItem \r
944      * @hide \r
945      */\r
946     /** \r
947      * @cfg {Boolean} autoDestroy \r
948      * @hide \r
949      */\r
950     /** \r
951      * @cfg {Object/String/Function} autoLoad \r
952      * @hide \r
953      */\r
954     /** \r
955      * @cfg {Boolean} autoWidth \r
956      * @hide \r
957      */\r
958     /** \r
959      * @cfg {Boolean/Number} bufferResize \r
960      * @hide \r
961      */\r
962     /** \r
963      * @cfg {String} defaultType \r
964      * @hide \r
965      */\r
966     /** \r
967      * @cfg {Object} defaults \r
968      * @hide \r
969      */\r
970     /** \r
971      * @cfg {Boolean} hideBorders \r
972      * @hide \r
973      */\r
974     /** \r
975      * @cfg {Mixed} items \r
976      * @hide \r
977      */\r
978     /** \r
979      * @cfg {String} layout \r
980      * @hide \r
981      */\r
982     /** \r
983      * @cfg {Object} layoutConfig \r
984      * @hide \r
985      */\r
986     /** \r
987      * @cfg {Boolean} monitorResize \r
988      * @hide \r
989      */\r
990     /** \r
991      * @property items \r
992      * @hide \r
993      */\r
994     /** \r
995      * @method add \r
996      * @hide \r
997      */\r
998     /** \r
999      * @method cascade \r
1000      * @hide \r
1001      */\r
1002     /** \r
1003      * @method doLayout \r
1004      * @hide \r
1005      */\r
1006     /** \r
1007      * @method find \r
1008      * @hide \r
1009      */\r
1010     /** \r
1011      * @method findBy \r
1012      * @hide \r
1013      */\r
1014     /** \r
1015      * @method findById \r
1016      * @hide \r
1017      */\r
1018     /** \r
1019      * @method findByType \r
1020      * @hide \r
1021      */\r
1022     /** \r
1023      * @method getComponent \r
1024      * @hide \r
1025      */\r
1026     /** \r
1027      * @method getLayout \r
1028      * @hide \r
1029      */\r
1030     /** \r
1031      * @method getUpdater \r
1032      * @hide \r
1033      */\r
1034     /** \r
1035      * @method insert \r
1036      * @hide \r
1037      */\r
1038     /** \r
1039      * @method load \r
1040      * @hide \r
1041      */\r
1042     /** \r
1043      * @method remove \r
1044      * @hide \r
1045      */\r
1046     /** \r
1047      * @event add \r
1048      * @hide \r
1049      */\r
1050     /** \r
1051      * @event afterlayout \r
1052      * @hide \r
1053      */\r
1054     /** \r
1055      * @event beforeadd \r
1056      * @hide \r
1057      */\r
1058     /** \r
1059      * @event beforeremove \r
1060      * @hide \r
1061      */\r
1062     /** \r
1063      * @event remove \r
1064      * @hide \r
1065      */\r
1066 \r
1067 \r
1068 \r
1069     /**\r
1070      * @cfg {String} allowDomMove  @hide\r
1071      */\r
1072     /**\r
1073      * @cfg {String} autoEl @hide\r
1074      */\r
1075     /**\r
1076      * @cfg {String} applyTo  @hide\r
1077      */\r
1078     /**\r
1079      * @cfg {String} autoScroll  @hide\r
1080      */\r
1081     /**\r
1082      * @cfg {String} bodyBorder  @hide\r
1083      */\r
1084     /**\r
1085      * @cfg {String} bodyStyle  @hide\r
1086      */\r
1087     /**\r
1088      * @cfg {String} contentEl  @hide\r
1089      */\r
1090     /**\r
1091      * @cfg {String} disabledClass  @hide\r
1092      */\r
1093     /**\r
1094      * @cfg {String} elements  @hide\r
1095      */\r
1096     /**\r
1097      * @cfg {String} html  @hide\r
1098      */\r
1099     /**\r
1100      * @cfg {Boolean} preventBodyReset\r
1101      * @hide\r
1102      */\r
1103     /**\r
1104      * @property disabled\r
1105      * @hide\r
1106      */\r
1107     /**\r
1108      * @method applyToMarkup\r
1109      * @hide\r
1110      */\r
1111     /**\r
1112      * @method enable\r
1113      * @hide\r
1114      */\r
1115     /**\r
1116      * @method disable\r
1117      * @hide\r
1118      */\r
1119     /**\r
1120      * @method setDisabled\r
1121      * @hide\r
1122      */\r
1123 });\r
1124 Ext.reg('grid', Ext.grid.GridPanel);