123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- // feature idea to enable Ajax loading and then the content
- // cache would actually make sense. Should we dictate that they use
- // data or support raw html as well?
- /**
- * @class Ext.ux.RowExpander
- * @extends Ext.AbstractPlugin
- * Plugin (ptype = 'rowexpander') that adds the ability to have a Column in a grid which enables
- * a second row body which expands/contracts. The expand/contract behavior is configurable to react
- * on clicking of the column, double click of the row, and/or hitting enter while a row is selected.
- *
- * @ptype rowexpander
- */
- Ext.define('Ext.ux.RowExpander', {
- extend: 'Ext.AbstractPlugin',
- requires: [
- 'Ext.grid.feature.RowBody',
- 'Ext.grid.feature.RowWrap'
- ],
- alias: 'plugin.rowexpander',
- rowBodyTpl: null,
- /**
- * @cfg {Boolean} expandOnEnter
- * <tt>true</tt> to toggle selected row(s) between expanded/collapsed when the enter
- * key is pressed (defaults to <tt>true</tt>).
- */
- expandOnEnter: true,
- /**
- * @cfg {Boolean} expandOnDblClick
- * <tt>true</tt> to toggle a row between expanded/collapsed when double clicked
- * (defaults to <tt>true</tt>).
- */
- expandOnDblClick: true,
- /**
- * @cfg {Boolean} selectRowOnExpand
- * <tt>true</tt> to select a row when clicking on the expander icon
- * (defaults to <tt>false</tt>).
- */
- selectRowOnExpand: false,
- rowBodyTrSelector: '.x-grid-rowbody-tr',
- rowBodyHiddenCls: 'x-grid-row-body-hidden',
- rowCollapsedCls: 'x-grid-row-collapsed',
- renderer: function(value, metadata, record, rowIdx, colIdx) {
- if (colIdx === 0) {
- metadata.tdCls = 'x-grid-td-expander';
- }
- return '<div class="x-grid-row-expander"> </div>';
- },
- /**
- * @event expandbody
- * <b<Fired through the grid's View</b>
- * @param {HTMLElement} rowNode The <tr> element which owns the expanded row.
- * @param {Ext.data.Model} record The record providing the data.
- * @param {HTMLElement} expandRow The <tr> element containing the expanded data.
- */
- /**
- * @event collapsebody
- * <b<Fired through the grid's View.</b>
- * @param {HTMLElement} rowNode The <tr> element which owns the expanded row.
- * @param {Ext.data.Model} record The record providing the data.
- * @param {HTMLElement} expandRow The <tr> element containing the expanded data.
- */
- constructor: function() {
- this.callParent(arguments);
- var grid = this.getCmp();
- this.recordsExpanded = {};
- // <debug>
- if (!this.rowBodyTpl) {
- Ext.Error.raise("The 'rowBodyTpl' config is required and is not defined.");
- }
- // </debug>
- // TODO: if XTemplate/Template receives a template as an arg, should
- // just return it back!
- var rowBodyTpl = Ext.create('Ext.XTemplate', this.rowBodyTpl),
- features = [{
- ftype: 'rowbody',
- columnId: this.getHeaderId(),
- recordsExpanded: this.recordsExpanded,
- rowBodyHiddenCls: this.rowBodyHiddenCls,
- rowCollapsedCls: this.rowCollapsedCls,
- getAdditionalData: this.getRowBodyFeatureData,
- getRowBodyContents: function(data) {
- return rowBodyTpl.applyTemplate(data);
- }
- },{
- ftype: 'rowwrap'
- }];
- if (grid.features) {
- grid.features = features.concat(grid.features);
- } else {
- grid.features = features;
- }
- // NOTE: features have to be added before init (before Table.initComponent)
- },
- init: function(grid) {
- this.callParent(arguments);
- // Columns have to be added in init (after columns has been used to create the
- // headerCt). Otherwise, shared column configs get corrupted, e.g., if put in the
- // prototype.
- grid.headerCt.insert(0, this.getHeaderConfig());
- grid.on('render', this.bindView, this, {single: true});
- },
- getHeaderId: function() {
- if (!this.headerId) {
- this.headerId = Ext.id();
- }
- return this.headerId;
- },
- getRowBodyFeatureData: function(data, idx, record, orig) {
- var o = Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments),
- id = this.columnId;
- o.rowBodyColspan = o.rowBodyColspan - 1;
- o.rowBody = this.getRowBodyContents(data);
- o.rowCls = this.recordsExpanded[record.internalId] ? '' : this.rowCollapsedCls;
- o.rowBodyCls = this.recordsExpanded[record.internalId] ? '' : this.rowBodyHiddenCls;
- o[id + '-tdAttr'] = ' valign="top" rowspan="2" ';
- if (orig[id+'-tdAttr']) {
- o[id+'-tdAttr'] += orig[id+'-tdAttr'];
- }
- return o;
- },
- bindView: function() {
- var view = this.getCmp().getView(),
- viewEl;
- if (!view.rendered) {
- view.on('render', this.bindView, this, {single: true});
- } else {
- viewEl = view.getEl();
- if (this.expandOnEnter) {
- this.keyNav = Ext.create('Ext.KeyNav', viewEl, {
- 'enter' : this.onEnter,
- scope: this
- });
- }
- if (this.expandOnDblClick) {
- view.on('itemdblclick', this.onDblClick, this);
- }
- this.view = view;
- }
- },
- onEnter: function(e) {
- var view = this.view,
- ds = view.store,
- sm = view.getSelectionModel(),
- sels = sm.getSelection(),
- ln = sels.length,
- i = 0,
- rowIdx;
- for (; i < ln; i++) {
- rowIdx = ds.indexOf(sels[i]);
- this.toggleRow(rowIdx);
- }
- },
- toggleRow: function(rowIdx) {
- var rowNode = this.view.getNode(rowIdx),
- row = Ext.get(rowNode),
- nextBd = Ext.get(row).down(this.rowBodyTrSelector),
- record = this.view.getRecord(rowNode),
- grid = this.getCmp();
- if (row.hasCls(this.rowCollapsedCls)) {
- row.removeCls(this.rowCollapsedCls);
- nextBd.removeCls(this.rowBodyHiddenCls);
- this.recordsExpanded[record.internalId] = true;
- this.view.fireEvent('expandbody', rowNode, record, nextBd.dom);
- } else {
- row.addCls(this.rowCollapsedCls);
- nextBd.addCls(this.rowBodyHiddenCls);
- this.recordsExpanded[record.internalId] = false;
- this.view.fireEvent('collapsebody', rowNode, record, nextBd.dom);
- }
- },
- onDblClick: function(view, cell, rowIdx, cellIndex, e) {
- this.toggleRow(rowIdx);
- },
- getHeaderConfig: function() {
- var me = this,
- toggleRow = Ext.Function.bind(me.toggleRow, me),
- selectRowOnExpand = me.selectRowOnExpand;
- return {
- id: this.getHeaderId(),
- width: 24,
- sortable: false,
- resizable: false,
- draggable: false,
- hideable: false,
- menuDisabled: true,
- cls: Ext.baseCSSPrefix + 'grid-header-special',
- renderer: function(value, metadata) {
- metadata.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
- return '<div class="' + Ext.baseCSSPrefix + 'grid-row-expander"> </div>';
- },
- processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
- if (type == "mousedown" && e.getTarget('.x-grid-row-expander')) {
- var row = e.getTarget('.x-grid-row');
- toggleRow(row);
- return selectRowOnExpand;
- }
- }
- };
- }
- });
|