PDA

View Full Version : LockingGridPanel - Frozen Columns



jchau
Aug 06, 2009, 12:01 AM
Coolite implementation of Condor's LockingGridPanel extension.http://extjs.com/forum/showthread.php?p=369120


You should be able to open the solution and make sure the reference to Coolite dlls are correct.

plykkegaard
Oct 18, 2009, 11:21 AM
Thanks for sharing :)

I am mainly using codebehind in order to autogenerate grids to display data from various SQL server tables based upon an xml configuration file

I have some problems getting your control to work as intended
Your sample runs ok and I can see that you're wrapping the gridpanel and column objects

I have added the webcontrol to my solution and changed references to ext.GridPanel to use ux.LockingGridPanel likewise with all columns

I have also set the Locked property on the first columns in my grid, but don't "see" any locked columns

Is it possible to use the control in codebehind or is only for markup?

Thanks in advance

jchau
Oct 19, 2009, 10:15 AM
I also generate my grid from codebehind because of dynamic column configs from the database. It works for me. I can even change columns on ajaxevents. Can you post a code sample?

Also, what version are you using? I believe the newest Coolite is using ExtJS 2.3 which does not support this extension. That's the main reason why I haven't updated from SVN in awhile.

plykkegaard
Oct 19, 2009, 10:33 AM
Hi

I am using Coolite 8.1
I will try to downgrade to see if it works on earlier versions just to check my implementation
If it turns out to be a problem I'll throw together a sample later

8.1 is the earliest I can use in prod due to a little nasty bug in the gridpanel
http://forums.ext.net/showthread.php?threadid=14891-5-1.aspx

EDIT: I am also using 8.1 when running the small testapp you have provided, it's not the version then
I'll build a small sample

I am using Accordians/Treeview in a Viewport where I have the GridPanel in the center
Both topbar (toolbar) and bottombar (pagingtoolbar) are used in the GridPanel

Thanks

jchau
Oct 19, 2009, 10:48 AM
That sounds like the same setup I have. A treepanel in West region, tabs and gridpanel in Center. I am using 0.8.2.1.

plykkegaard
Oct 22, 2009, 2:50 PM
I have thrown together a small sample which is working execellent :-)

EDIT: First of all I am using "ColumnModel.Columns.AddRange" returning af range of columns using a method to return a range of columns based upon an xml configuration
I am also using a range of different types of columns eg date, checkbox etc

I will assume that all columns needs to have the locked property to have it all work properly?

EDIT2: I can confirm that AddRange is working nicely and as expected

I haven't tested the "all columns needs to have the locked property set" thing, but when examining the clientside sourcecode behind IE I noticed that the property is only send to the client if it's set explicit in code (nice) - looks like it is not nessecary to extend the checkColumn class - this is not tested

I have managed to drill down my problem though :-)
I have been using a customized gridview in order to translate eg EmptyText
I commented out the sourcecode involved and everything started working as designed

Offending code:

// Add customized gridview
ext.GridView gridview = new ext.GridView();
gridview.ID = "gridView";
gridview.EmptyText = String.Format(Language.Danish.View_EmptyText, table.Label);
gridPanel.View.Add(gridview);

Thanks

plykkegaard
Oct 24, 2009, 4:16 PM
Ups I have a problem with misalignment of rows due to height of the row as I have an icon in my first column

Any ideas?

EDIT: I am using detailsrenderer as in this example
http://examples1.ext.net/#/GridPanel/Miscellaneous/Details_Window_Remote/

I have added "margin-top: -2px; margin-bottom: -2px;" to the style section of the javascript function, eg:


var detailsRenderer = function ()
{
return '<img class="imgEdit"
ext:qtip="Klik for at se / redigere detaljer"
style="cursor:pointer; margin-top: -2px; margin-bottom: -2px;"
src="images/vcard_edit.png" />';
}

rgds

jchau
Oct 25, 2009, 4:17 AM
I had a similar issue because I was using a row command in one of the columns. I ended up increasing the size of each row. Please try adding the following styles to your page (the last one is optional to turn on vertical gridlines).

I believe I also made a few more updates to the lockinggridpanel js file for some bug fixes with IE6 scrolling. I will try and post an updated file soon.



/* Bigger row height to accomodate review column */
.x-grid3-row td, .x-grid3-summary-row td
{
line-height: 15px !important;
padding-left: 0px;
padding-right: 0px;
}


/* Fix locked row numberer */
.x-grid3-body .x-grid3-td-numberer .x-grid3-cell-inner
{
padding-bottom: 3px !important;
}


/* Vertical grid lines */.
.x-grid3-col
{
border-left: 1px solid #FFFFFF;
border-right: 1px solid #EEEEEE;
}

plykkegaard
Oct 25, 2009, 6:30 PM
Thanks a lot

I have a minor problem though
As I wrote I had added a gridview in codebehind which is in conflict with the view you're adding in the javascript (only added if a view is not created)

The more advanced part of ExtJS and clientside scripting is a little too much for me too fully grasp what's going on :)

In my code I am changing the background color based on row status
Codefragments:


<style type="text/css">
/* Styles for setting different row colors */
.dirty-row {
background:#fffdd8;
}
.new-row {
background:#c8ffc8;
}


<body>
<form id="form1" runat="server">
<script type="text/javascript">
//<![CDATA[
function getRowClass(record) {
if (record.newRecord) {
return 'new-row';
}
if (record.dirty) {
return 'dirty-row';
}
}
//]]>
</script>


// Add customized gridview
ext.GridView gridview = new ext.GridView();
gridview.ID = "gridView";
gridview.EmptyText = String.Format(Language.Danish.View_EmptyText, table.Label);
// There is a bug in the gridview component
// ref: http://forums.ext.net/showthread.php?threadid=7837-4-1.aspx?Highlight=Gridview+getrowclass
ext.JFunction fn = new ext.JFunction();
fn.Fn = "getRowClass";
gridview.GetRowClass = fn;
gridPanel.View.Add(gridview);
gridPanel.Listeners.RowContextMenu.Handler = Scripts.DataGrid.RowContextMenu;

This also gives me a belt across the grid based upon cursorposition of the mouse
Any ideas on how to add the above to your code?

Thanks

plykkegaard
Oct 28, 2009, 5:40 PM
jchau (10/25/2009)


I believe I also made a few more updates to the lockinggridpanel js file for some bug fixes with IE6 scrolling. I will try and post an updated file soon.

Thanks

I just found a little but confusing bug in the header row
I am using the rowfilters and lockinggridpanel interferes and recoloring of the header cell is misaligned to the right depending on the number of rows currently locked
Not so pretty

Any ideas?

I will check the ExtJS forums and see if I can find something

rgds

jchau
Oct 30, 2009, 10:54 AM
Sorry I did not get a chance to look into this. Do you have an example of row filters? Is that just the grid filter plugin?

jchau
Oct 30, 2009, 11:35 AM
Please replace your current LockingGridPanel.js with this new one. I added a fix to the gridfilter plugin so it will look at both locked and unlocked portion of the grid. Before, the plugin only looked at the unlocked part of the grid so it was setting the filterCls wrong. This new version should also fix a few IE6 bugs with horizontal scrolling.


Do you still need help with your other issue related to customizing the emptyText and getRowClass of the view? That one is simple to fix too. You just need to create a serverside component for LockingGridView and use that instead of the normal GridView.




/* Locking Grid Panel for frozen columns */
if (typeof Coolite.Ext.GridPanel != 'undefined') {
Ext.grid.LockingGridPanel = Ext.extend(Coolite.Ext.GridPanel, {
getView: function() {
if (!this.view) {
this.view = new Ext.grid.LockingGridView(this.viewConfig);
}
return this.view;
},


initComponent: function() {
this.addEvents("columnlock");
Ext.grid.LockingGridPanel.superclass.initComponent .call(this);
}
});


Ext.reg("lockinggridpanel", Ext.grid.LockingGridPanel);
}


Ext.grid.LockingGridView = Ext.extend(Ext.grid.GridView, {


lockText: "Lock",
unlockText: "Unlock",


initTemplates: function() {
if (!this.templates) {
this.templates = {};
}
if (!this.templates.master) {
this.templates.master = new Ext.Template(
'<div class="x-grid3" hidefocus="true">',
'<div class="x-grid3-locked">',
'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{lockedHeader}

<div class="x-clear">

',
'<div class="x-grid3-scroller"><div class="x-grid3-body">{lockedBody}
<div class="x-grid3-scroll-spacer">

',
'
',
'<div class="x-grid3-viewport">',
'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset">{header}

<div class="x-clear">

',
'<div class="x-grid3-scroller"><div class="x-grid3-body">{body}
<a href="#" class="x-grid3-focus" tabIndex="-1"></a>
',
'
',
'<div class="x-grid3-resize-marker">&amp;#160;
',
'<div class="x-grid3-resize-proxy">&amp;#160;
',
'
'
);
}
Ext.grid.LockingGridView.superclass.initTemplates. call(this);
},


initElements: function() {
var E = Ext.Element;
var el = this.grid.getGridEl();
el = el.dom.firstChild;
var cs = el.childNodes;
this.el = new E(el);
this.lockedWrap = new E(cs[0]);
this.lockedHd = new E(this.lockedWrap.dom.firstChild);
this.lockedInnerHd = this.lockedHd.dom.firstChild;
this.lockedScroller = new E(this.lockedWrap.dom.childNodes[1]);
this.lockedBody = new E(this.lockedScroller.dom.firstChild);
this.mainWrap = new E(cs[1]);
this.mainHd = new E(this.mainWrap.dom.firstChild);
this.innerHd = this.mainHd.dom.firstChild;
this.scroller = new E(this.mainWrap.dom.childNodes[1]);
if (this.forceFit) {
this.scroller.setStyle('overflow-x', 'hidden');
}
this.mainBody = new E(this.scroller.dom.firstChild);
this.focusEl = new E(this.scroller.dom.childNodes[1]);
this.focusEl.swallowEvent("click", true);
this.resizeMarker = new E(cs[2]);
this.resizeProxy = new E(cs[3]);
},


getLockedRows: function() {
return this.hasRows() ? this.lockedBody.dom.childNodes : [];
},


getLockedRow: function(row) {
return this.getLockedRows()[row];
},


getCell: function(rowIndex, colIndex) {
var locked = this.cm.getLockedCount();
var row;
if (colIndex < locked) {
row = this.getLockedRow(rowIndex);
} else {
row = this.getRow(rowIndex);
colIndex -= locked;
}
return row.getElementsByTagName('td')[colIndex];
},


getHeaderCell: function(index) {
var locked = this.cm.getLockedCount();
if (index < locked) {
return this.lockedHd.dom.getElementsByTagName('td')[index];
} else {
return this.mainHd.dom.getElementsByTagName('td')[(index - locked)];
}
},


scrollToTop: function() {
Ext.grid.LockingGridView.superclass.scrollToTop.ca ll(this);
this.syncScroll();
},


syncScroll: function(e) {
if (Ext.isIE6) {
var mb = this.scroller.dom;
this.innerHd.style.width = '10000px';
var leftOffset = '-' + mb.scrollLeft + 'px';
this.innerHd.style.left = leftOffset;
this.grid.fireEvent("bodyscroll", mb.scrollLeft, mb.scrollTop);
this.lockedScroller.dom.scrollTop = mb.scrollTop;
} else {
Ext.grid.LockingGridView.superclass.syncScroll.cal l(this, e);
var mb = this.scroller.dom;
this.lockedScroller.dom.scrollTop = mb.scrollTop;
}
},


processRows: function(startRow, skipStripe) {
if (this.ds.getCount() < 1) {
return;
}
skipStripe = skipStripe || !this.grid.stripeRows;
startRow = startRow || 0;
var cls = ' x-grid3-row-alt ';
var rows = this.getRows();
var lrows = this.getLockedRows();
for (var i = startRow, len = rows.length; i < len; i++) {
var row = rows[i];
var lrow = lrows[i];
row.rowIndex = i;
lrow.rowIndex = i;
if (!skipStripe) {
var isAlt = ((i + 1) % 2 === 0);
var hasAlt = (' ' + row.className + ' ').indexOf(cls) != -1;
if (isAlt == hasAlt) {
continue;
}
if (isAlt) {
row.className += " x-grid3-row-alt";
lrow.className += " x-grid3-row-alt";
} else {
row.className = row.className.replace("x-grid3-row-alt", "");
lrow.className = lrow.className.replace("x-grid3-row-alt", "");
}
}
}
},


updateSortIcon: function(col, dir) {
var sc = this.sortClasses;
var clen = this.cm.getColumnCount();
var lclen = this.cm.getLockedCount();
var hds = this.mainHd.select('td').removeClass(sc);
var lhds = this.lockedHd.select('td').removeClass(sc);
if (lclen > 0 &amp;&amp; col < lclen) {
lhds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
} else {
hds.item(col - lclen).addClass(sc[dir == "DESC" ? 1 : 0]);
}
},


updateColumnHidden: function(col, hidden) {
var tw = this.cm.getTotalWidth();
var lw = this.cm.getTotalLockedWidth();
var lclen = this.cm.getLockedCount();
this.innerHd.firstChild.firstChild.style.width = tw + 'px';
var display = hidden ? 'none' : '';
var hd = this.getHeaderCell(col);
hd.style.display = display;
var ns, gw;
if (col < lclen) {
ns = this.getLockedRows();
gw = lw;
this.lockedHd.dom.firstChild.firstChild.style.widt h = gw + 'px';
this.mainWrap.dom.style.left = this.cm.getTotalLockedWidth() + 'px';
} else {
ns = this.getRows();
gw = tw - lw;
col -= lclen;
this.innerHd.firstChild.firstChild.style.width = gw + 'px';
}
for (var i = 0, len = ns.length; i < len; i++) {
ns[i].style.width = gw + 'px';
ns[i].firstChild.style.width = gw + 'px';
ns[i].firstChild.rows[0].childNodes[col].style.display = display;
}
this.onColumnHiddenUpdated(col, hidden, tw);
delete this.lastViewWidth;
this.layout();
},


syncHeaderHeight: function() {
if (this.lockedInnerHd === undefined || this.innerHd === undefined) {
return;
}
this.lockedInnerHd.firstChild.firstChild.style.hei ght = "auto";
this.innerHd.firstChild.firstChild.style.height = "auto";
var height = (this.lockedInnerHd.firstChild.firstChild.offsetHe ight > this.innerHd.firstChild.firstChild.offsetHeight) ?
this.lockedInnerHd.firstChild.firstChild.offsetHei ght : this.innerHd.firstChild.firstChild.offsetHeight;
this.lockedInnerHd.firstChild.firstChild.style.hei ght = height + 'px';
this.innerHd.firstChild.firstChild.style.height = height + 'px';
},


doRender: function(cs, rs, ds, startRow, colCount, stripe) {
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount - 1;
var tw = this.cm.getTotalWidth();
var lw = this.cm.getTotalLockedWidth();
var clen = this.cm.getColumnCount();
var lclen = this.cm.getLockedCount();
var tstyle = 'width:' + this.getTotalWidth() + ';';
var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = { tstyle: tstyle }, r;
for (var j = 0, len = rs.length; j < len; j++) {
r = rs[j]; cb = []; lcb = [];
var rowIndex = (j + startRow);
for (var i = 0; i < colCount; i++) {
c = cs[i];
p.id = c.id;
p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
p.style = c.style;
if (p.value === undefined || p.value === "") {
p.value = "&amp;#160;";
}
if (r.dirty &amp;&amp; typeof r.modified[c.name] !== 'undefined') {
p.css += ' x-grid3-dirty-cell';
}
if (c.locked) {
lcb[lcb.length] = ct.apply(p);
} else {
cb[cb.length] = ct.apply(p);
}
}
var alt = [];
if (stripe &amp;&amp; ((rowIndex + 1) % 2 === 0)) {
alt[0] = "x-grid3-row-alt";
}
if (r.dirty) {
alt[1] = " x-grid3-dirty-row";
}
rp.cols = colCount;
if (this.getRowClass) {
alt[2] = this.getRowClass(r, rowIndex, rp, ds);
}
rp.alt = alt.join(" ");
rp.cells = lcb.join("");
rp.tstyle = 'width:' + lw + 'px;';
lbuf[lbuf.length] = rt.apply(rp);
rp.cells = cb.join("");
rp.tstyle = 'width:' + (tw - lw) + 'px;';
buf[buf.length] = rt.apply(rp);
}
return [buf.join(""), lbuf.join("")];
},


layout: function() {
if (!this.mainBody) {
return;
}
var g = this.grid;
var c = g.getGridEl(), cm = this.cm,
expandCol = g.autoExpandColumn,
gv = this;
var lw = cm.getTotalLockedWidth();
var csize = c.getSize(true);
var vw = csize.width;
if (vw < 20 || csize.height < 20) {
return;
}
this.syncHeaderHeight();
if (g.autoHeight) {
this.scroller.dom.style.overflow = 'visible';
this.lockedScroller.dom.style.overflow = 'visible';
} else {
this.el.setSize(csize.width, csize.height);
var vh = csize.height - this.mainHd.getHeight();
this.lockedScroller.setSize(lw, vh);
this.scroller.setSize(vw - lw, vh);
if (this.innerHd) {
this.innerHd.style.width = (vw) + 'px';
}
}
if (this.forceFit) {
if (this.lastViewWidth != vw) {
this.fitColumns(false, false);
this.lastViewWidth = vw;
}
} else {
this.autoExpand();
lw = cm.getTotalLockedWidth();
}
this.mainWrap.dom.style.left = lw + 'px';
this.onLayout(vw, vh);
},


renderHeaders: function() {
var cm = this.cm, ts = this.templates;
var ct = ts.hcell;
var tw = this.cm.getTotalWidth();
var lw = this.cm.getTotalLockedWidth();
var cb = [], lb = [], sb = [], lsb = [], p = {};
for (var i = 0, len = cm.getColumnCount(); i < len; i++) {
p.id = cm.getColumnId(i);
p.value = cm.getColumnHeader(i) || "";
p.style = this.getColumnStyle(i, true);
p.tooltip = this.getColumnTooltip(i);
if (cm.config[i].align == 'right') {
p.istyle = 'padding-right:16px';
}
if (cm.isLocked(i)) {
lb[lb.length] = ct.apply(p);
} else {
cb[cb.length] = ct.apply(p);
}
}
return [ts.header.apply({ cells: cb.join(""), tstyle: 'width:' + (tw - lw) + ';' }),
ts.header.apply({ cells: lb.join(""), tstyle: 'width:' + (lw) + ';' })];
},


getColumnTooltip: function(i) {
var tt = this.cm.getColumnTooltip(i);
if (tt) {
if (Ext.QuickTips.isEnabled()) {
return 'ext:qtip="' + tt + '"';
} else {
return 'title="' + tt + '"';
}
}
return "";
},


updateHeaders: function() {
var hd = this.renderHeaders();
this.innerHd.firstChild.innerHTML = hd[0];
this.lockedInnerHd.firstChild.innerHTML = hd[1];
},


getResolvedXY: function(resolved) {
if (!resolved) {
return null;
}
var c = resolved.cell, r = resolved.row;
return c ? Ext.fly(c).getXY() : [this.scroller.getX(), Ext.fly(r).getY()];
},


insertRows: function(dm, firstRow, lastRow, isUpdate) {
if (firstRow === 0 &amp;&amp; lastRow == dm.getCount() - 1) {
this.refresh();
} else {
if (!isUpdate) {
this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
}
var html = this.renderRows(firstRow, lastRow);
var before = this.getRow(firstRow);
if (before) {
Ext.DomHelper.insertHtml('beforeBegin', before, html[0]);
} else {
Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html[0]);
}
var beforeLocked = this.getLockedRow(firstRow);
if (beforeLocked) {
Ext.DomHelper.insertHtml('beforeBegin', beforeLocked, html[1]);
} else {
Ext.DomHelper.insertHtml('beforeEnd', this.lockedBody.dom, html[1]);
}
if (!isUpdate) {
this.fireEvent("rowsinserted", this, firstRow, lastRow);
this.processRows(firstRow);
}
}
},


removeRow: function(row) {
Ext.removeNode(this.getRow(row));
if (this.cm.getLockedCount() > 0) {
Ext.removeNode(this.getLockedRow(row));
}
},


getColumnData: function() {
var cs = [], cm = this.cm, colCount = cm.getColumnCount();
for (var i = 0; i < colCount; i++) {
var name = cm.getDataIndex(i);
cs[i] = {
name: (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),
renderer: cm.getRenderer(i),
id: cm.getColumnId(i),
style: this.getColumnStyle(i),
locked: cm.isLocked(i)
};
}
return cs;
},


renderBody: function() {
var markup = this.renderRows();
return [this.templates.body.apply({ rows: markup[0] }), this.templates.body.apply({ rows: markup[1] })];
},


refresh: function(headersToo) {
this.fireEvent("beforerefresh", this);
this.grid.stopEditing();
var result = this.renderBody();
this.mainBody.update(result[0]);
this.lockedBody.update(result[1]);
if (headersToo === true) {
this.updateHeaders();
this.updateHeaderSortState();
}
this.processRows(0, true);
this.layout();
this.applyEmptyText();
this.fireEvent("refresh", this);
},


handleLockChange: function() {
this.refresh(true);
},


onDenyColumnHide: function() {
},


onColumnLock: function() {
this.handleLockChange.apply(this, arguments);
},


addRowClass: function(row, cls) {
var r = this.getRow(row);
if (r) {
this.fly(r).addClass(cls);
r = this.getLockedRow(row);
this.fly(r).addClass(cls);
}
},


removeRowClass: function(row, cls) {
var r = this.getRow(row);
if (r) {
this.fly(r).removeClass(cls);
r = this.getLockedRow(row);
this.fly(r).removeClass(cls);
}
},


handleHdMenuClick: function(item) {
var index = this.hdCtxIndex;
var cm = this.cm, ds = this.ds, lc;
switch (item.id) {
case "asc":
ds.sort(cm.getDataIndex(index), "ASC");
break;
case "desc":
ds.sort(cm.getDataIndex(index), "DESC");
break;
case "lock":
lc = cm.getLockedCount();
if (cm.getColumnCount(true) <= lc + 1) {
this.onDenyColumnLock();
return;
}
if (lc != index) {
cm.setLocked(index, true, true);
cm.moveColumn(index, lc);
this.grid.fireEvent("columnmove", index, lc);
} else {
cm.setLocked(index, true);
this.grid.fireEvent("columnlock", index, true);
}
break;
case "unlock":
lc = cm.getLockedCount();
if ((lc - 1) != index) {
cm.setLocked(index, false, true);
cm.moveColumn(index, lc - 1);
this.grid.fireEvent("columnmove", index, lc - 1);
} else {
cm.setLocked(index, false);
this.grid.fireEvent("columnlock", index, false);
}
break;
default:
index = cm.getIndexById(item.id.substr(4));
if (index != -1) {
if (item.checked &amp;&amp; cm.getColumnsBy(this.isHideableColumn, this).length <= 1) {
this.onDenyColumnHide();
return false;
}
cm.setHidden(index, item.checked);
}
}
return true;
},


handleHdDown: function(e, t) {
if (Ext.fly(t).hasClass('x-grid3-hd-btn')) {
e.stopEvent();
var hd = this.findHeaderCell(t);
Ext.fly(hd).addClass('x-grid3-hd-menu-open');
var index = this.getCellIndex(hd);
this.hdCtxIndex = index;
var ms = this.hmenu.items, cm = this.cm;
ms.get("asc").setDisabled(!cm.isSortable(index));
ms.get("desc").setDisabled(!cm.isSortable(index));
if (this.grid.enableColLock !== false) {
ms.get("lock").setDisabled(cm.isLocked(index));
ms.get("unlock").setDisabled(!cm.isLocked(index));
}
this.hmenu.on("hide", function() {
Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
}, this, { single: true });
this.hmenu.show(t, "tl-bl?");
}
},


renderUI: function() {
var header = this.renderHeaders();
var body = this.templates.body.apply({ rows: '' });
var html = this.templates.master.apply({
body: body,
header: header[0],
lockedBody: body,
lockedHeader: header[1]
});
var g = this.grid;
g.getGridEl().dom.innerHTML = html;
this.initElements();
Ext.fly(this.innerHd).on("click", this.handleHdDown, this);
Ext.fly(this.lockedInnerHd).on("click", this.handleHdDown, this);
this.mainHd.on("mouseover", this.handleHdOver, this);
this.mainHd.on("mouseout", this.handleHdOut, this);
this.mainHd.on("mousemove", this.handleHdMove, this);
this.lockedHd.on("mouseover", this.handleHdOver, this);
this.lockedHd.on("mouseout", this.handleHdOut, this);
this.lockedHd.on("mousemove", this.handleHdMove, this);
this.mainWrap.dom.style.left = this.cm.getTotalLockedWidth() + 'px';
this.scroller.on('scroll', this.syncScroll, this);
if (g.enableColumnResize !== false) {
this.splitone = new Ext.grid.GridView.SplitDragZone(g, this.lockedHd.dom);
this.splitone.setOuterHandleElId(Ext.id(this.locke dHd.dom));
this.splitone.setOuterHandleElId(Ext.id(this.mainH d.dom));
}
if (g.enableColumnMove) {
this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
}
if (g.enableHdMenu !== false) {
if (g.enableColumnHide !== false) {
this.colMenu = new Ext.menu.Menu({ id: g.id + "-hcols-menu" });
this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
this.colMenu.on("itemclick", this.handleHdMenuClick, this);
}
this.hmenu = new Ext.menu.Menu({ id: g.id + "-hctx" });
this.hmenu.add(
{ id: "asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc" },


{ id: "desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc" }
);
if (this.grid.enableColLock !== false) {
this.hmenu.add('-',
{ id: "lock", text: this.lockText, cls: "xg-hmenu-lock" },


{ id: "unlock", text: this.unlockText, cls: "xg-hmenu-unlock" }
);
}
if (g.enableColumnHide !== false) {
this.hmenu.add('-',
{ id: "columns", text: this.columnsText, menu: this.colMenu, iconCls: 'x-cols-icon' }
);
}
this.hmenu.on("itemclick", this.handleHdMenuClick, this);
}
if (g.enableDragDrop || g.enableDrag) {
var dd = new Ext.grid.GridDragZone(g, {
ddGroup: g.ddGroup || 'GridDD'
});
}
this.updateHeaderSortState();
},


afterRender: function() {
var bd = this.renderRows();
if (bd === '') {
bd = ['', ''];
}
this.mainBody.dom.innerHTML = bd[0];
this.lockedBody.dom.innerHTML = bd[1];
this.processRows(0, true);
if (this.deferEmptyText !== true) {
this.applyEmptyText();
}
this.fireEvent("afterRender", this);
},


updateAllColumnWidths: function() {
var tw = this.cm.getTotalWidth();
var lw = this.cm.getTotalLockedWidth();
var clen = this.cm.getColumnCount();
var lclen = this.cm.getLockedCount();
var ws = [];
var i;
for (i = 0; i < clen; i++) {
ws[i] = this.getColumnWidth(i);
}
this.innerHd.firstChild.firstChild.style.width = (tw - lw) + 'px';
this.mainWrap.dom.style.left = lw + 'px';
this.lockedInnerHd.firstChild.firstChild.style.wid th = lw + 'px';
for (i = 0; i < clen; i++) {
var hd = this.getHeaderCell(i);
hd.style.width = ws[i] + 'px';
}
var ns = this.getRows();
var lns = this.getLockedRows();
for (i = 0, len = ns.length; i < len; i++) {
ns[i].style.width = (tw - lw) + 'px';
ns[i].firstChild.style.width = (tw - lw) + 'px';
lns[i].style.width = lw + 'px';
lns[i].firstChild.style.width = lw + 'px';
var j, row;
for (j = 0; j < lclen; j++) {
row = lns[i].firstChild.rows[0];
row.childNodes[j].style.width = ws[j] + 'px';
}
for (j = lclen; j < clen; j++) {
row = ns[i].firstChild.rows[0];
row.childNodes[j].style.width = ws[j] + 'px';
}
}
this.onAllColumnWidthsUpdated(ws, tw);
},


updateColumnWidth: function(col, width) {
var w = this.getColumnWidth(col);
var tw = this.cm.getTotalWidth();
var lclen = this.cm.getLockedCount();
var lw = this.cm.getTotalLockedWidth();
var hd = this.getHeaderCell(col);
hd.style.width = w;
var ns, gw;
var ncol = col;
if (col < lclen) {
ns = this.getLockedRows();
gw = lw;
this.lockedInnerHd.firstChild.firstChild.style.wid th = gw + 'px';
this.mainWrap.dom.style.left = this.cm.getTotalLockedWidth() + 'px';
this.mainWrap.dom.style.display = 'none';
this.mainWrap.dom.style.display = '';
} else {
ns = this.getRows();
gw = tw - lw;
ncol -= lclen;
this.innerHd.firstChild.firstChild.style.width = gw + 'px';
}
for (var i = 0, len = ns.length; i < len; i++) {
ns[i].style.width = gw + 'px';
ns[i].firstChild.style.width = gw + 'px';
ns[i].firstChild.rows[0].childNodes[ncol].style.width = w;
}
this.onColumnWidthUpdated(col, w, tw);
this.layout();
},


getEditorParent: function(ed) {
return this.el.dom;
},


refreshRow: function(record) {
Ext.grid.LockingGridView.superclass.refreshRow.cal l(this, record);
var index = this.ds.indexOf(record);
this.getLockedRow(index).rowIndex = index;
}
});


Ext.grid.ColumnModel.override({
getTotalLockedWidth: function() {
var totalWidth = 0;
for (var i = 0; i < this.config.length; i++) {
if (this.isLocked(i) &amp;&amp; !this.isHidden(i)) {
totalWidth += this.getColumnWidth(i);
}
}
return totalWidth;
}
});


Ext.override(Ext.grid.RowNumberer, {
locked: true
});



if (typeof Ext.grid.GridFilters != 'undefined') {
Ext.override(Ext.grid.GridFilters, {
updateColumnHeadings: function(view) {
if (!view || !view.mainHd) {
return;
}

//remove filter css from both locked and main grid
view.mainHd.select('td').removeClass(this.filterCl s);
if (view.lockedHd) {
view.lockedHd.select('td').removeClass(this.filter Cls);
}

//add filter css to currently filtered columns
for (var i = 0, len = view.cm.config.length; i < len; i++) {
var filter = this.getFilter(view.cm.config[i].dataIndex);
if (filter &amp;&amp; filter.active) {
Ext.fly(view.getHeaderCell(i)).addClass(this.filte rCls);
}
}
}


});
}

plykkegaard
Oct 30, 2009, 9:35 PM
Thanks a million and don't worry about the delays
I was planning to have to different grids based on usersettings as the gridfilters are seldom used but by me and I don't need the columnlocking for my own usage

But I can't get the new script to work as expected?
And yep I am using my new js file as I have tried to rename the lock/unlock labels on the menuitems
Had a problem until I decided to remove the reference from the main project and add a new reference to the lockinggrid project

I will try the new code with the sample you provided in the download

Btw any ideas on how to copy paste from the code panel?
I spent a few hours reformatting the code and removing a few misplaced smilies, and other web related stuff

rgds

geoffrey.mcgill
Nov 04, 2009, 7:28 PM
Hi,

I just wanted to let everyone know that the LockingGridView and LockingColumnModel UX components will be included in the v1.0 release and will be officially supported. The code should hit svn later this week.


I'll post another update once committed to svn.


Hope this helps.

jchau
Nov 04, 2009, 7:33 PM
Sweet! I was just about to get condor's 3.0 version. Is that what ExtJS is using in their official release? Can't wait to test it in our application.

geoffrey.mcgill
Nov 04, 2009, 7:40 PM
I was just about to get condor's 3.0 version. Is that what ExtJS is using in their official release?

Yes, I believe that is the case.

plykkegaard
Nov 06, 2009, 6:41 PM
geoffrey.mcgill (11/4/2009)

> I just wanted to let everyone know that the LockingGridView and
> LockingColumnModel UX components will be included in the v1.0
> release and will be officially supported.

Some really cool news you're breaking :-)

On a sidenote: I found a minor bug in the lockinggridpanel thing
When you delete a row (deleteSelected) the two grids goes out of sync as the rows are misaligned
When you scroll up'n'down the rows will eventually aligned after a few scrolls

rgds

plykkegaard
Nov 27, 2009, 3:40 AM
I have discovered another bug in the lockinggridpanel

If you hide columns using the column menu the editors are misaligned and some are not opening even if you tab across the grid
The bug does not always show itself

[EDIT] I have some more information regarding this issue
I build the grid in codebehind and the user can save gridsettings eg which columns is frozen/locked and which are hidden etc
First time the grid is opened with hidden/frosen columns I have the bug with the editors
If I then unlock/lock the rightmost frozen column the editor seems to be in place - hth

rgds/Peter