Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / RowExpander.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">Ext.ns('Ext.ux.grid');\r
9 \r
10 <div id="cls-Ext.ux.grid.RowExpander"></div>/**\r
11  * @class Ext.ux.grid.RowExpander\r
12  * @extends Ext.util.Observable\r
13  * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables\r
14  * a second row body which expands/contracts.  The expand/contract behavior is configurable to react\r
15  * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.\r
16  *\r
17  * @ptype rowexpander\r
18  */\r
19 Ext.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, {\r
20     <div id="cfg-Ext.ux.grid.RowExpander-expandOnEnter"></div>/**\r
21      * @cfg {Boolean} expandOnEnter\r
22      * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter\r
23      * key is pressed (defaults to <tt>true</tt>).\r
24      */\r
25     expandOnEnter : true,\r
26     <div id="cfg-Ext.ux.grid.RowExpander-expandOnDblClick"></div>/**\r
27      * @cfg {Boolean} expandOnDblClick\r
28      * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked\r
29      * (defaults to <tt>true</tt>).\r
30      */\r
31     expandOnDblClick : true,\r
32 \r
33     header : '',\r
34     width : 20,\r
35     sortable : false,\r
36     fixed : true,\r
37     menuDisabled : true,\r
38     dataIndex : '',\r
39     id : 'expander',\r
40     lazyRender : true,\r
41     enableCaching : true,\r
42 \r
43     constructor: function(config){\r
44         Ext.apply(this, config);\r
45 \r
46         this.addEvents({\r
47             <div id="event-Ext.ux.grid.RowExpander-beforeexpand"></div>/**\r
48              * @event beforeexpand\r
49              * Fires before the row expands. Have the listener return false to prevent the row from expanding.\r
50              * @param {Object} this RowExpander object.\r
51              * @param {Object} Ext.data.Record Record for the selected row.\r
52              * @param {Object} body body element for the secondary row.\r
53              * @param {Number} rowIndex The current row index.\r
54              */\r
55             beforeexpand: true,\r
56             <div id="event-Ext.ux.grid.RowExpander-expand"></div>/**\r
57              * @event expand\r
58              * Fires after the row expands.\r
59              * @param {Object} this RowExpander object.\r
60              * @param {Object} Ext.data.Record Record for the selected row.\r
61              * @param {Object} body body element for the secondary row.\r
62              * @param {Number} rowIndex The current row index.\r
63              */\r
64             expand: true,\r
65             <div id="event-Ext.ux.grid.RowExpander-beforecollapse"></div>/**\r
66              * @event beforecollapse\r
67              * Fires before the row collapses. Have the listener return false to prevent the row from collapsing.\r
68              * @param {Object} this RowExpander object.\r
69              * @param {Object} Ext.data.Record Record for the selected row.\r
70              * @param {Object} body body element for the secondary row.\r
71              * @param {Number} rowIndex The current row index.\r
72              */\r
73             beforecollapse: true,\r
74             <div id="event-Ext.ux.grid.RowExpander-collapse"></div>/**\r
75              * @event collapse\r
76              * Fires after the row collapses.\r
77              * @param {Object} this RowExpander object.\r
78              * @param {Object} Ext.data.Record Record for the selected row.\r
79              * @param {Object} body body element for the secondary row.\r
80              * @param {Number} rowIndex The current row index.\r
81              */\r
82             collapse: true\r
83         });\r
84 \r
85         Ext.ux.grid.RowExpander.superclass.constructor.call(this);\r
86 \r
87         if(this.tpl){\r
88             if(typeof this.tpl == 'string'){\r
89                 this.tpl = new Ext.Template(this.tpl);\r
90             }\r
91             this.tpl.compile();\r
92         }\r
93 \r
94         this.state = {};\r
95         this.bodyContent = {};\r
96     },\r
97 \r
98     getRowClass : function(record, rowIndex, p, ds){\r
99         p.cols = p.cols-1;\r
100         var content = this.bodyContent[record.id];\r
101         if(!content && !this.lazyRender){\r
102             content = this.getBodyContent(record, rowIndex);\r
103         }\r
104         if(content){\r
105             p.body = content;\r
106         }\r
107         return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';\r
108     },\r
109 \r
110     init : function(grid){\r
111         this.grid = grid;\r
112 \r
113         var view = grid.getView();\r
114         view.getRowClass = this.getRowClass.createDelegate(this);\r
115 \r
116         view.enableRowBody = true;\r
117 \r
118 \r
119         grid.on('render', this.onRender, this);\r
120         grid.on('destroy', this.onDestroy, this);\r
121     },\r
122 \r
123     // @private\r
124     onRender: function() {\r
125         var grid = this.grid;\r
126         var mainBody = grid.getView().mainBody;\r
127         mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'});\r
128         if (this.expandOnEnter) {\r
129             this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), {\r
130                 'enter' : this.onEnter,\r
131                 scope: this\r
132             });\r
133         }\r
134         if (this.expandOnDblClick) {\r
135             grid.on('rowdblclick', this.onRowDblClick, this);\r
136         }\r
137     },\r
138     \r
139     // @private    \r
140     onDestroy: function() {\r
141         if(this.keyNav){\r
142             this.keyNav.disable();\r
143             delete this.keyNav;\r
144         }\r
145         /*\r
146          * A majority of the time, the plugin will be destroyed along with the grid,\r
147          * which means the mainBody won't be available. On the off chance that the plugin\r
148          * isn't destroyed with the grid, take care of removing the listener.\r
149          */\r
150         var mainBody = this.grid.getView().mainBody;\r
151         if(mainBody){\r
152             mainBody.un('mousedown', this.onMouseDown, this);\r
153         }\r
154     },\r
155     // @private\r
156     onRowDblClick: function(grid, rowIdx, e) {\r
157         this.toggleRow(rowIdx);\r
158     },\r
159 \r
160     onEnter: function(e) {\r
161         var g = this.grid;\r
162         var sm = g.getSelectionModel();\r
163         var sels = sm.getSelections();\r
164         for (var i = 0, len = sels.length; i < len; i++) {\r
165             var rowIdx = g.getStore().indexOf(sels[i]);\r
166             this.toggleRow(rowIdx);\r
167         }\r
168     },\r
169 \r
170     getBodyContent : function(record, index){\r
171         if(!this.enableCaching){\r
172             return this.tpl.apply(record.data);\r
173         }\r
174         var content = this.bodyContent[record.id];\r
175         if(!content){\r
176             content = this.tpl.apply(record.data);\r
177             this.bodyContent[record.id] = content;\r
178         }\r
179         return content;\r
180     },\r
181 \r
182     onMouseDown : function(e, t){\r
183         e.stopEvent();\r
184         var row = e.getTarget('.x-grid3-row');\r
185         this.toggleRow(row);\r
186     },\r
187 \r
188     renderer : function(v, p, record){\r
189         p.cellAttr = 'rowspan="2"';\r
190         return '<div class="x-grid3-row-expander">&#160;</div>';\r
191     },\r
192 \r
193     beforeExpand : function(record, body, rowIndex){\r
194         if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){\r
195             if(this.tpl && this.lazyRender){\r
196                 body.innerHTML = this.getBodyContent(record, rowIndex);\r
197             }\r
198             return true;\r
199         }else{\r
200             return false;\r
201         }\r
202     },\r
203 \r
204     toggleRow : function(row){\r
205         if(typeof row == 'number'){\r
206             row = this.grid.view.getRow(row);\r
207         }\r
208         this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);\r
209     },\r
210 \r
211     expandRow : function(row){\r
212         if(typeof row == 'number'){\r
213             row = this.grid.view.getRow(row);\r
214         }\r
215         var record = this.grid.store.getAt(row.rowIndex);\r
216         var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);\r
217         if(this.beforeExpand(record, body, row.rowIndex)){\r
218             this.state[record.id] = true;\r
219             Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');\r
220             this.fireEvent('expand', this, record, body, row.rowIndex);\r
221         }\r
222     },\r
223 \r
224     collapseRow : function(row){\r
225         if(typeof row == 'number'){\r
226             row = this.grid.view.getRow(row);\r
227         }\r
228         var record = this.grid.store.getAt(row.rowIndex);\r
229         var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);\r
230         if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){\r
231             this.state[record.id] = false;\r
232             Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');\r
233             this.fireEvent('collapse', this, record, body, row.rowIndex);\r
234         }\r
235     }\r
236 });\r
237 \r
238 Ext.preg('rowexpander', Ext.ux.grid.RowExpander);\r
239 \r
240 //backwards compat\r
241 Ext.grid.RowExpander = Ext.ux.grid.RowExpander;</pre>
242 </body>
243 </html>