/*!
 * Ext JS Library 3.3.1
 * Copyright(c) 2006-2010 Sencha Inc.
 * licensing@sencha.com
 * http://www.sencha.com/license
 */
Ext.ns('Ext.ux.grid');

/** * @class Ext.ux.grid.RowExpander * @extends Ext.util.Observable * 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.ux.grid.RowExpander = Ext.extend(Ext.util.Observable, {
/** * @cfg {Boolean} expandOnEnter * true to toggle selected row(s) between expanded/collapsed when the enter * key is pressed (defaults to true). */ expandOnEnter : true,
/** * @cfg {Boolean} expandOnDblClick * true to toggle a row between expanded/collapsed when double clicked * (defaults to true). */ expandOnDblClick : true, header : '', width : 20, sortable : false, fixed : true, hideable: false, menuDisabled : true, dataIndex : '', id : 'expander', lazyRender : true, enableCaching : true, constructor: function(config){ Ext.apply(this, config); this.addEvents({
/** * @event beforeexpand * Fires before the row expands. Have the listener return false to prevent the row from expanding. * @param {Object} this RowExpander object. * @param {Object} Ext.data.Record Record for the selected row. * @param {Object} body body element for the secondary row. * @param {Number} rowIndex The current row index. */ beforeexpand: true,
/** * @event expand * Fires after the row expands. * @param {Object} this RowExpander object. * @param {Object} Ext.data.Record Record for the selected row. * @param {Object} body body element for the secondary row. * @param {Number} rowIndex The current row index. */ expand: true,
/** * @event beforecollapse * Fires before the row collapses. Have the listener return false to prevent the row from collapsing. * @param {Object} this RowExpander object. * @param {Object} Ext.data.Record Record for the selected row. * @param {Object} body body element for the secondary row. * @param {Number} rowIndex The current row index. */ beforecollapse: true,
/** * @event collapse * Fires after the row collapses. * @param {Object} this RowExpander object. * @param {Object} Ext.data.Record Record for the selected row. * @param {Object} body body element for the secondary row. * @param {Number} rowIndex The current row index. */ collapse: true }); Ext.ux.grid.RowExpander.superclass.constructor.call(this); if(this.tpl){ if(typeof this.tpl == 'string'){ this.tpl = new Ext.Template(this.tpl); } this.tpl.compile(); } this.state = {}; this.bodyContent = {}; }, getRowClass : function(record, rowIndex, p, ds){ p.cols = p.cols-1; var content = this.bodyContent[record.id]; if(!content && !this.lazyRender){ content = this.getBodyContent(record, rowIndex); } if(content){ p.body = content; } return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; }, init : function(grid){ this.grid = grid; var view = grid.getView(); view.getRowClass = this.getRowClass.createDelegate(this); view.enableRowBody = true; grid.on('render', this.onRender, this); grid.on('destroy', this.onDestroy, this); }, // @private onRender: function() { var grid = this.grid; var mainBody = grid.getView().mainBody; mainBody.on('mousedown', this.onMouseDown, this, {delegate: '.x-grid3-row-expander'}); if (this.expandOnEnter) { this.keyNav = new Ext.KeyNav(this.grid.getGridEl(), { 'enter' : this.onEnter, scope: this }); } if (this.expandOnDblClick) { grid.on('rowdblclick', this.onRowDblClick, this); } }, // @private onDestroy: function() { if(this.keyNav){ this.keyNav.disable(); delete this.keyNav; } /* * A majority of the time, the plugin will be destroyed along with the grid, * which means the mainBody won't be available. On the off chance that the plugin * isn't destroyed with the grid, take care of removing the listener. */ var mainBody = this.grid.getView().mainBody; if(mainBody){ mainBody.un('mousedown', this.onMouseDown, this); } }, // @private onRowDblClick: function(grid, rowIdx, e) { this.toggleRow(rowIdx); }, onEnter: function(e) { var g = this.grid; var sm = g.getSelectionModel(); var sels = sm.getSelections(); for (var i = 0, len = sels.length; i < len; i++) { var rowIdx = g.getStore().indexOf(sels[i]); this.toggleRow(rowIdx); } }, getBodyContent : function(record, index){ if(!this.enableCaching){ return this.tpl.apply(record.data); } var content = this.bodyContent[record.id]; if(!content){ content = this.tpl.apply(record.data); this.bodyContent[record.id] = content; } return content; }, onMouseDown : function(e, t){ e.stopEvent(); var row = e.getTarget('.x-grid3-row'); this.toggleRow(row); }, renderer : function(v, p, record){ p.cellAttr = 'rowspan="2"'; return '
 
'; }, beforeExpand : function(record, body, rowIndex){ if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){ if(this.tpl && this.lazyRender){ body.innerHTML = this.getBodyContent(record, rowIndex); } return true; }else{ return false; } }, toggleRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); }, expandRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } var record = this.grid.store.getAt(row.rowIndex); var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); if(this.beforeExpand(record, body, row.rowIndex)){ this.state[record.id] = true; Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); this.fireEvent('expand', this, record, body, row.rowIndex); } }, collapseRow : function(row){ if(typeof row == 'number'){ row = this.grid.view.getRow(row); } var record = this.grid.store.getAt(row.rowIndex); var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){ this.state[record.id] = false; Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); this.fireEvent('collapse', this, record, body, row.rowIndex); } } }); Ext.preg('rowexpander', Ext.ux.grid.RowExpander); //backwards compat Ext.grid.RowExpander = Ext.ux.grid.RowExpander;