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