]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/src/grid/feature/RowBody.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / src / grid / feature / RowBody.js
CommitLineData
6527f429
DM
1/**\r
2 * The rowbody feature enhances the grid's markup to have an additional\r
3 * tr -> td -> div which spans the entire width of the original row.\r
4 *\r
5 * This is useful to to associate additional information with a particular\r
6 * record in an Ext.grid.Grid.\r
7 *\r
8 * Rowbodies are initially hidden unless you override {@link #getAdditionalData}.\r
9 *\r
10 * The events fired by RowBody are relayed to the owning \r
11 * {@link Ext.view.Table grid view} (and subsequently the owning grid).\r
12 *\r
13 * # Example\r
14 *\r
15 * @example\r
16 * Ext.define('Animal', {\r
17 * extend: 'Ext.data.Model',\r
18 * fields: ['name', 'latin', 'desc', 'lifespan']\r
19 * });\r
20 * \r
21 * Ext.create('Ext.grid.Panel', {\r
22 * width: 400,\r
23 * height: 300,\r
24 * renderTo: Ext.getBody(),\r
25 * store: {\r
26 * model: 'Animal',\r
27 * data: [{\r
28 * name: 'Tiger',\r
29 * latin: 'Panthera tigris',\r
30 * desc: 'The largest cat species, weighing up to 306 kg (670 lb).',\r
31 * lifespan: '20 - 26 years (in captivity)'\r
32 * }, {\r
33 * name: 'Roman snail',\r
34 * latin: 'Helix pomatia',\r
35 * desc: 'A species of large, edible, air-breathing land snail.',\r
36 * lifespan: '20 - 35 years'\r
37 * }, {\r
38 * name: 'Yellow-winged darter',\r
39 * latin: 'Sympetrum flaveolum',\r
40 * desc: 'A dragonfly found in Europe and mid and Northern China.',\r
41 * lifespan: '4 - 6 weeks'\r
42 * }, {\r
43 * name: 'Superb Fairy-wren',\r
44 * latin: 'Malurus cyaneus',\r
45 * desc: 'Common and familiar across south-eastern Australia.',\r
46 * lifespan: '5 - 6 years'\r
47 * }]\r
48 * },\r
49 * columns: [{\r
50 * dataIndex: 'name',\r
51 * text: 'Common name',\r
52 * width: 125\r
53 * }, {\r
54 * dataIndex: 'latin',\r
55 * text: 'Scientific name',\r
56 * flex: 1\r
57 * }],\r
58 * features: [{\r
59 * ftype: 'rowbody',\r
60 * getAdditionalData: function (data, idx, record, orig) {\r
61 * // Usually you would style the my-body-class in a CSS file\r
62 * return {\r
63 * rowBody: '<div style="padding: 1em">' + record.get("desc") + '</div>',\r
64 * rowBodyCls: "my-body-class"\r
65 * };\r
66 * }\r
67 * }],\r
68 * listeners: {\r
69 * rowbodyclick: function(view, rowEl, e, eOpts) {\r
70 * var itemEl = Ext.get(rowEl).up(view.itemSelector),\r
71 * rec = view.getRecord(itemEl);\r
72 * \r
73 * Ext.Msg.alert(rec.get('name') + ' life span', rec.get('lifespan'));\r
74 * }\r
75 * }\r
76 * });\r
77 *\r
78 * # Cell Editing and Cell Selection Model\r
79 *\r
80 * Note that if {@link Ext.grid.plugin.CellEditing cell editing} or the {@link Ext.selection.CellModel cell selection model} are going\r
81 * to be used, then the {@link Ext.grid.feature.RowBody RowBody} feature, or {@link Ext.grid.plugin.RowExpander RowExpander} plugin MUST\r
82 * be used for intra-cell navigation to be correct.\r
83 */\r
84Ext.define('Ext.grid.feature.RowBody', {\r
85 extend: 'Ext.grid.feature.Feature',\r
86 alias: 'feature.rowbody',\r
87\r
88 rowBodyCls: Ext.baseCSSPrefix + 'grid-row-body',\r
89 rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',\r
90 rowBodyTdSelector: 'td.' + Ext.baseCSSPrefix + 'grid-cell-rowbody',\r
91 eventPrefix: 'rowbody',\r
92 eventSelector: 'tr.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',\r
93\r
94 colSpanDecrement: 0,\r
95\r
96 /**\r
97 * @cfg {Boolean} [bodyBefore=false]\r
98 * Configure as `true` to put the row expander body *before* the data row.\r
99 */\r
100 bodyBefore: false,\r
101\r
102 outerTpl: {\r
103 fn: function(out, values, parent) {\r
104 var view = values.view,\r
105 rowValues = view.rowValues;\r
106\r
107 this.rowBody.setup(values.rows, rowValues);\r
108 this.nextTpl.applyOut(values, out, parent);\r
109 this.rowBody.cleanup(values.rows, rowValues);\r
110 },\r
111 priority: 100\r
112 },\r
113\r
114 extraRowTpl: [\r
115 '{%',\r
116 'if(this.rowBody.bodyBefore) {',\r
117 // MUST output column sizing elements because the first row in this table\r
118 // contains one colspanning TD, and that overrides subsequent column width settings.\r
119 'values.view.renderColumnSizer(values, out);',\r
120 '} else {',\r
121 'this.nextTpl.applyOut(values, out, parent);',\r
122 '}',\r
123 'values.view.rowBodyFeature.setupRowData(values.record, values.recordIndex, values);',\r
124 '%}',\r
125 '<tr class="' + Ext.baseCSSPrefix + 'grid-rowbody-tr {rowBodyCls}" {ariaRowAttr}>',\r
126 '<td class="' + Ext.baseCSSPrefix + 'grid-td ' + Ext.baseCSSPrefix + 'grid-cell-rowbody" colspan="{rowBodyColspan}" {ariaCellAttr}>',\r
127 '<div class="' + Ext.baseCSSPrefix + 'grid-rowbody {rowBodyDivCls}" {ariaCellInnerAttr}>{rowBody}</div>',\r
128 '</td>',\r
129 '</tr>',\r
130 '{%',\r
131 'if(this.rowBody.bodyBefore) {',\r
132 'this.nextTpl.applyOut(values, out, parent);',\r
133 '}',\r
134 '%}', {\r
135 priority: 100,\r
136\r
137 beginRowSync: function (rowSync) {\r
138 rowSync.add('rowBody', this.owner.eventSelector);\r
139 },\r
140\r
141 syncContent: function(destRow, sourceRow, columnsToUpdate) {\r
142 var owner = this.owner,\r
143 destRowBody = Ext.fly(destRow).down(owner.eventSelector, true),\r
144 sourceRowBody;\r
145\r
146 // Sync the heights of row body elements in each row if they need it.\r
147 if (destRowBody && (sourceRowBody = Ext.fly(sourceRow).down(owner.eventSelector, true))) {\r
148 Ext.fly(destRowBody).syncContent(sourceRowBody);\r
149 }\r
150 }\r
151 }\r
152 ],\r
153\r
154 init: function(grid) {\r
155 var me = this,\r
156 view = me.view = grid.getView();\r
157\r
158 // The extra data means variableRowHeight\r
159 grid.variableRowHeight = view.variableRowHeight = true;\r
160 view.rowBodyFeature = me;\r
161\r
162 grid.mon(view, {\r
163 element: 'el',\r
164 click: me.onClick,\r
165 scope: me\r
166 });\r
167\r
168 view.headerCt.on({\r
169 columnschanged: me.onColumnsChanged,\r
170 scope: me\r
171 });\r
172 view.addTpl(me.outerTpl).rowBody = me;\r
173 view.addRowTpl(Ext.XTemplate.getTpl(this, 'extraRowTpl')).rowBody = me;\r
174 me.callParent(arguments);\r
175 },\r
176\r
177 // Needed to select the data row when clicked on the body row.\r
178 onClick: function(e) {\r
179 var me = this,\r
180 tableRow = e.getTarget(me.eventSelector);\r
181\r
182 // If we have clicked on a row body TR and its previous (or next - we can put the body first) sibling is a grid row,\r
183 // pass that onto the view for processing\r
184 if (tableRow && Ext.fly(tableRow = (tableRow.previousSibling || tableRow.nextSibling)).is(me.view.rowSelector)) {\r
185 e.target = tableRow;\r
186 me.view.handleEvent(e);\r
187 }\r
188 },\r
189\r
190 getSelectedRow: function(view, rowIndex) {\r
191 var selectedRow = view.getNode(rowIndex);\r
192 if (selectedRow) {\r
193 return Ext.fly(selectedRow).down(this.eventSelector);\r
194 }\r
195 return null;\r
196 },\r
197\r
198 // When columns added/removed, keep row body colspan in sync with number of columns.\r
199 onColumnsChanged: function(headerCt) {\r
200 var items = this.view.el.query(this.rowBodyTdSelector),\r
201 colspan = headerCt.getVisibleGridColumns().length,\r
202 len = items.length,\r
203 i;\r
204\r
205 for (i = 0; i < len; ++i) {\r
206 items[i].setAttribute('colSpan', colspan);\r
207 }\r
208 },\r
209\r
210 /**\r
211 * @method getAdditionalData\r
212 * @protected\r
213 * @template\r
214 * Provides additional data to the prepareData call within the grid view.\r
215 * The rowbody feature adds 3 additional variables into the grid view's template.\r
216 * These are `rowBody`, `rowBodyCls`, and `rowBodyColspan`.\r
217 * \r
218 * - **rowBody:** *{String}* The HTML to display in the row body element. Defaults \r
219 * to *undefined*.\r
220 * - **rowBodyCls:** *{String}* An optional CSS class (or multiple classes \r
221 * separated by spaces) to apply to the row body element. Defaults to \r
222 * {@link #rowBodyCls}.\r
223 * - **rowBodyColspan:** *{Number}* The number of columns that the row body element \r
224 * should span. Defaults to the number of visible columns.\r
225 * \r
226 * @param {Object} data The data for this particular record.\r
227 * @param {Number} idx The row index for this record.\r
228 * @param {Ext.data.Model} record The record instance\r
229 * @param {Object} orig The original result from the prepareData call to massage.\r
230 * @return {Object} An object containing additional variables for use in the grid \r
231 * view's template\r
232 */\r
233 \r
234 /*\r
235 * @private\r
236 */\r
237 setupRowData: function(record, rowIndex, rowValues) {\r
238 if (this.getAdditionalData) {\r
239 Ext.apply(rowValues, this.getAdditionalData(record.data, rowIndex, record, rowValues));\r
240 }\r
241 },\r
242\r
243 setup: function(rows, rowValues) {\r
244 rowValues.rowBodyCls = this.rowBodyCls;\r
245 rowValues.rowBodyColspan = this.view.headerCt.visibleColumnManager.getColumns().length - this.colSpanDecrement;\r
246 },\r
247\r
248 cleanup: function(rows, rowValues) {\r
249 rowValues.rowBodyCls = rowValues.rowBodyColspan = rowValues.rowBody = null;\r
250 }\r
251 \r
252 /**\r
253 * @event beforerowbodymousedown\r
254 * @preventable\r
255 * @member Ext.view.Table\r
256 * Fires before the mousedown event on a row body element is processed. Return false \r
257 * to cancel the default action.\r
258 * \r
259 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
260 * used.\r
261 * \r
262 * @param {Ext.view.View} view The rowbody's owning View\r
263 * @param {HTMLElement} rowBodyEl The row body's element\r
264 * @param {Ext.event.Event} e The raw event object\r
265 */\r
266\r
267 /**\r
268 * @event beforerowbodymouseup\r
269 * @preventable\r
270 * @member Ext.view.Table\r
271 * Fires before the mouseup event on a row body element is processed. Return false \r
272 * to cancel the default action.\r
273 * \r
274 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
275 * used.\r
276 * \r
277 * @inheritdoc #beforerowbodymousedown\r
278 */\r
279\r
280 /**\r
281 * @event beforerowbodyclick\r
282 * @preventable\r
283 * @member Ext.view.Table\r
284 * Fires before the click event on a row body element is processed. Return false to \r
285 * cancel the default action.\r
286 * \r
287 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
288 * used.\r
289 * \r
290 * @inheritdoc #beforerowbodymousedown\r
291 */\r
292\r
293 /**\r
294 * @event beforerowbodydblclick\r
295 * @preventable\r
296 * @member Ext.view.Table\r
297 * Fires before the dblclick event on a row body element is processed. Return false \r
298 * to cancel the default action.\r
299 * \r
300 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
301 * used.\r
302 * \r
303 * @inheritdoc #beforerowbodymousedown\r
304 */\r
305\r
306 /**\r
307 * @event beforerowbodycontextmenu\r
308 * @preventable\r
309 * @member Ext.view.Table\r
310 * Fires before the contextmenu event on a row body element is processed. Return \r
311 * false to cancel the default action.\r
312 * \r
313 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
314 * used.\r
315 * \r
316 * @inheritdoc #beforerowbodymousedown\r
317 */\r
318 \r
319 /**\r
320 * @event beforerowbodylongpress\r
321 * @preventable\r
322 * @member Ext.view.Table\r
323 * Fires before the longpress event on a row body element is processed. Return \r
324 * false to cancel the default action.\r
325 * \r
326 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
327 * used.\r
328 * \r
329 * @inheritdoc #beforerowbodymousedown\r
330 */\r
331\r
332 /**\r
333 * @event beforerowbodykeydown\r
334 * @preventable\r
335 * @member Ext.view.Table\r
336 * Fires before the keydown event on a row body element is processed. Return false \r
337 * to cancel the default action.\r
338 * \r
339 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
340 * used.\r
341 * \r
342 * @inheritdoc #beforerowbodymousedown\r
343 */\r
344\r
345 /**\r
346 * @event beforerowbodykeyup\r
347 * @preventable\r
348 * @member Ext.view.Table\r
349 * Fires before the keyup event on a row body element is processed. Return false to \r
350 * cancel the default action.\r
351 * \r
352 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
353 * used.\r
354 * \r
355 * @inheritdoc #beforerowbodymousedown\r
356 */\r
357\r
358 /**\r
359 * @event beforerowbodykeypress\r
360 * @preventable\r
361 * @member Ext.view.Table\r
362 * Fires before the keypress event on a row body element is processed. Return false \r
363 * to cancel the default action.\r
364 * \r
365 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
366 * used.\r
367 * \r
368 * @inheritdoc #beforerowbodymousedown\r
369 */\r
370\r
371 /**\r
372 * @event rowbodymousedown\r
373 * @member Ext.view.Table\r
374 * Fires when there is a mouse down on a row body element\r
375 * \r
376 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
377 * used.\r
378 * \r
379 * @inheritdoc #beforerowbodymousedown\r
380 */\r
381\r
382 /**\r
383 * @event rowbodymouseup\r
384 * @member Ext.view.Table\r
385 * Fires when there is a mouse up on a row body element\r
386 * \r
387 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
388 * used.\r
389 * \r
390 * @inheritdoc #beforerowbodymousedown\r
391 */\r
392\r
393 /**\r
394 * @event rowbodyclick\r
395 * @member Ext.view.Table\r
396 * Fires when a row body element is clicked\r
397 * \r
398 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
399 * used.\r
400 * \r
401 * @inheritdoc #beforerowbodymousedown\r
402 */\r
403\r
404 /**\r
405 * @event rowbodydblclick\r
406 * @member Ext.view.Table\r
407 * Fires when a row body element is double clicked\r
408 * \r
409 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
410 * used.\r
411 * \r
412 * @inheritdoc #beforerowbodymousedown\r
413 */\r
414\r
415 /**\r
416 * @event rowbodycontextmenu\r
417 * @member Ext.view.Table\r
418 * Fires when a row body element is right clicked\r
419 * \r
420 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
421 * used.\r
422 * \r
423 * @inheritdoc #beforerowbodymousedown\r
424 */\r
425 \r
426 /**\r
427 * @event rowbodylongpress\r
428 * @member Ext.view.Table\r
429 * Fires on a row body element longpress event\r
430 * \r
431 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
432 * used.\r
433 * \r
434 * @inheritdoc #beforerowbodymousedown\r
435 */\r
436\r
437 /**\r
438 * @event rowbodykeydown\r
439 * @member Ext.view.Table\r
440 * Fires when a key is pressed down while a row body element is currently selected\r
441 * \r
442 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
443 * used.\r
444 * \r
445 * @inheritdoc #beforerowbodymousedown\r
446 */\r
447\r
448 /**\r
449 * @event rowbodykeyup\r
450 * @member Ext.view.Table\r
451 * Fires when a key is released while a row body element is currently selected\r
452 * \r
453 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
454 * used.\r
455 * \r
456 * @inheritdoc #beforerowbodymousedown\r
457 */\r
458\r
459 /**\r
460 * @event rowbodykeypress\r
461 * @member Ext.view.Table\r
462 * Fires when a key is pressed while a row body element is currently selected.\r
463 * \r
464 * **Note:** This event is fired only when the Ext.grid.feature.RowBody feature is \r
465 * used.\r
466 * \r
467 * @inheritdoc #beforerowbodymousedown\r
468 */\r
469});\r