makana
29 Sep 2008, 2:07 AM
I want to autoadjust the column width in grid panels by double clicking between the two adjacent header cells (like you know from excel or windows explorer). In Ext, the cursor turns into a "col-resize", but there isn't a function, that provides autosizing by default.
Using only the "headerdblclick" event from Ext.grid.GridPanel to fire a custum function doesn't work, because there are two single click events, too, which respectively cause sorting of the data.
To prevent this, I overrode the onHeaderClick function in Ext.grid.GridView and added a onHeaderDblClick function that provides autosizing for the clicked column in all of my grids by default. The new width becomes the width of the largest content in the column (including margins, paddings...).
It's only testet and works well in FF3 and IE6 on WinXP.
Ext.override(Ext.grid.GridView, {
resizeIndex: -1,
// private
initUI : function(grid){
grid.on("headerclick", this.onHeaderClick, this);
// handle dblclick on header cells
grid.on("headerdblclick", this.onHeaderDblClick, this);
if(grid.trackMouseOver){
grid.on("mouseover", this.onRowOver, this);
grid.on("mouseout", this.onRowOut, this);
}
},
// override normal click handler on header cells
onHeaderClick : function(g, index, e){
if(this.headersDisabled){
return;
}
// reset
this.resizeIndex = -1;
// check if mouse is over the splitter
var resizeCursor = this.activeHd.style.cursor;
resizeCursor = (Ext.isAir && resizeCursor == 'move') || (Ext.isSafari && (resizeCursor == 'e-resize' || resizeCursor == 'w-resize')) || resizeCursor == 'col-resize';
if (resizeCursor) {
g.stopEditing(true);
this.resizeIndex = index;
// if cursor in next column header, use index of previous column
var cell = Ext.fly(g.getView().getHeaderCell(index));
if ((this.cm.getColumnWidth(index) / 2) + cell.getLeft() > e.getPageX()) this.resizeIndex--;
// ignore hidden columns
while (this.cm.isHidden(this.resizeIndex)) {
this.resizeIndex--;
if (this.resizeIndex < 0) break;
}
// handle normal header click (original function)
} else if (this.cm.isSortable(index)) {
g.stopEditing(true);
g.store.sort(this.cm.getDataIndex(index));
}
return;
},
// handle dblclick on header cells
onHeaderDblClick: function(g, index, e) {
e.stopEvent();
// check if resizeIndex exists (mouse over splitter)
if (this.resizeIndex >= 0 && g.getStore().getTotalCount() > 0) {
var sz = 0;
var el, w;
// check content width of each row
for (i = 0; i < g.getStore().getTotalCount(); i++) {
el = Ext.fly(this.getCell(i, this.resizeIndex)); // cell element <td>
w = el.getWidth(); // get cell width
el = el.first('div.x-grid3-cell-inner'); // inner cell element <td><div>
w -= el.getWidth(true); // subtract inner cell width, content only (keep borders, margins, paddings... from cell and inner cell elements)
w += el.getTextWidth(Ext.util.Format.stripTags(el.innerHTML)); // add width of content
if (w > sz) sz = w; // use biggest value
}
// set biggest value as width of the column
g.getColumnModel().setColumnWidth(this.resizeIndex, sz);
g.fireEvent('columnresize', this.resizeIndex, sz);
}
}
});
Using only the "headerdblclick" event from Ext.grid.GridPanel to fire a custum function doesn't work, because there are two single click events, too, which respectively cause sorting of the data.
To prevent this, I overrode the onHeaderClick function in Ext.grid.GridView and added a onHeaderDblClick function that provides autosizing for the clicked column in all of my grids by default. The new width becomes the width of the largest content in the column (including margins, paddings...).
It's only testet and works well in FF3 and IE6 on WinXP.
Ext.override(Ext.grid.GridView, {
resizeIndex: -1,
// private
initUI : function(grid){
grid.on("headerclick", this.onHeaderClick, this);
// handle dblclick on header cells
grid.on("headerdblclick", this.onHeaderDblClick, this);
if(grid.trackMouseOver){
grid.on("mouseover", this.onRowOver, this);
grid.on("mouseout", this.onRowOut, this);
}
},
// override normal click handler on header cells
onHeaderClick : function(g, index, e){
if(this.headersDisabled){
return;
}
// reset
this.resizeIndex = -1;
// check if mouse is over the splitter
var resizeCursor = this.activeHd.style.cursor;
resizeCursor = (Ext.isAir && resizeCursor == 'move') || (Ext.isSafari && (resizeCursor == 'e-resize' || resizeCursor == 'w-resize')) || resizeCursor == 'col-resize';
if (resizeCursor) {
g.stopEditing(true);
this.resizeIndex = index;
// if cursor in next column header, use index of previous column
var cell = Ext.fly(g.getView().getHeaderCell(index));
if ((this.cm.getColumnWidth(index) / 2) + cell.getLeft() > e.getPageX()) this.resizeIndex--;
// ignore hidden columns
while (this.cm.isHidden(this.resizeIndex)) {
this.resizeIndex--;
if (this.resizeIndex < 0) break;
}
// handle normal header click (original function)
} else if (this.cm.isSortable(index)) {
g.stopEditing(true);
g.store.sort(this.cm.getDataIndex(index));
}
return;
},
// handle dblclick on header cells
onHeaderDblClick: function(g, index, e) {
e.stopEvent();
// check if resizeIndex exists (mouse over splitter)
if (this.resizeIndex >= 0 && g.getStore().getTotalCount() > 0) {
var sz = 0;
var el, w;
// check content width of each row
for (i = 0; i < g.getStore().getTotalCount(); i++) {
el = Ext.fly(this.getCell(i, this.resizeIndex)); // cell element <td>
w = el.getWidth(); // get cell width
el = el.first('div.x-grid3-cell-inner'); // inner cell element <td><div>
w -= el.getWidth(true); // subtract inner cell width, content only (keep borders, margins, paddings... from cell and inner cell elements)
w += el.getTextWidth(Ext.util.Format.stripTags(el.innerHTML)); // add width of content
if (w > sz) sz = w; // use biggest value
}
// set biggest value as width of the column
g.getColumnModel().setColumnWidth(this.resizeIndex, sz);
g.fireEvent('columnresize', this.resizeIndex, sz);
}
}
});