255 lines
No EOL
8.4 KiB
JavaScript
255 lines
No EOL
8.4 KiB
JavaScript
/*
|
|
This file is part of Ext JS 3.4
|
|
|
|
Copyright (c) 2011-2013 Sencha Inc
|
|
|
|
Contact: http://www.sencha.com/contact
|
|
|
|
GNU General Public License Usage
|
|
This file may be used under the terms of the GNU General Public License version 3.0 as
|
|
published by the Free Software Foundation and appearing in the file LICENSE included in the
|
|
packaging of this file.
|
|
|
|
Please review the following information to ensure the GNU General Public License version 3.0
|
|
requirements will be met: http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
If you are unsure which license is appropriate for your use, please contact the sales department
|
|
at http://www.sencha.com/contact.
|
|
|
|
Build date: 2013-04-03 15:07:25
|
|
*/
|
|
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
|
|
* <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,
|
|
|
|
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 '<div class="x-grid3-row-expander"> </div>';
|
|
},
|
|
|
|
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; |