PDA

View Full Version : Locking Grid Row Selection



lukefowell89
14 Dec 2010, 8:02 AM
Hi,

Having a problem selecting a row on my Locking Tree Grid from the the Locked Column, I can click on the non-locked pane and it will select the entire row fine, but if I click on an item in the locked pane, it will not select the row. Even though it will return the correct row index.

I also cannot do drag and drop from the locked column, but I can from the non-locked columns.

23818

Any ideas?

lukefowell89
15 Dec 2010, 1:20 AM
Any response what-so-ever? Or am I being ignored?

mankz
15 Dec 2010, 1:46 AM
Any response what-so-ever? Or am I being ignored?

Asking for help on a home-built version of a 3rd party UX without any code posted will likely not draw much attention ;)

lukefowell89
15 Dec 2010, 1:53 AM
Ok fair enough, its just ive asked for simple help time and time again and just been ignored everytime. Just getting abit annoyed since it seems everyone else at least gets a response even if it isnt helpful.

mankz
15 Dec 2010, 1:57 AM
Understand, well the key thing needed to get support is some code to look at. Crystal balls are really expensive :)

lukefowell89
15 Dec 2010, 2:07 AM
Well... theres alot of it but ok....

LockingTreeGrid Extension:


Ext.namespace('Ext.ux.lf');

Ext.ux.lf.AbstractTreeStore = Ext.extend(Ext.data.Store,
{
leaf_field_name : '_is_leaf',
page_offset : 0,
active_node : null,

constructor : function(config)
{
Ext.ux.lf.AbstractTreeStore.superclass.constructor.call(this, config);

if (!this.paramNames.active_node) {
this.paramNames.active_node = 'anode';
}

this.addEvents(
'beforeexpandnode',
'expandnode',
'expandnodefailed',
'beforecollapsenode',
'collapsenode',
'beforeactivenodechange',
'activenodechange'
);
},

remove : function(record)
{
if (record === this.active_node) {
this.setActiveNode(null);
}
this.removeNodeDescendants(record);
Ext.ux.lf.AbstractTreeStore.superclass.remove.call(this, record);
},

move : function(record, index)
{
var index = this.data.indexOf(record);
if(index > -1){
record.join(null);
this.data.removeAt(index);
}
if(index > -1){
this.fireEvent('remove', this, record, index);
}
this.insert(index, record);

},

subtractFromAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current - value).toFixed(2) + "'");
});
}
});
},

addToAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current + value).toFixed(2) + "'");
});
}
});
},

clearFieldsInRec : function(rec)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
rec.set(key, 0.00);
}
});
},

copyToRec : function(rec, record)
{
var keys = this.fields.keys;

// copy values for all fields to rec
Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));
rec.set(key, value);
}
});
},

removeNodeDescendants : function(rc)
{
var i, len, children = this.getNodeChildren(rc);
for (i = 0, len = children.length; i < len; i++) {
this.remove(children[i]);
}
},

load : function(options)
{
if (options) {
if (options.params) {
if (options.params[this.paramNames.active_node] === undefined) {
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options.params = {};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options = {params: {}};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}

if (options.params[this.paramNames.active_node] !== null) {
options.add = true;
}

return Ext.ux.lf.AbstractTreeStore.superclass.load.call(this, options);
},

loadRecords : function(o, options, success)
{
if (!o || success === false) {
if (success !== false) {
this.fireEvent("load", this, [], options);
}
if (options.callback) {
options.callback.call(options.scope || this, [], options, false);
}
return;
}

var r = o.records, t = o.totalRecords || r.length,
page_offset = this.getPageOffsetFromOptions(options),
loaded_node_id = this.getLoadedNodeIdFromOptions(options),
loaded_node, i, len, prev_record, record, idx, updated, self = this;

if (!options || options.add !== true/* || loaded_node_id === null*/) {
if (this.pruneModifiedRecords) {
this.modified = [];
}
for (var i = 0, len = r.length; i < len; i++) {
r[i].join(this);
}
if (this.snapshot) {
this.data = this.snapshot;
delete this.snapshot;
}
this.data.clear();
this.data.addAll(r);
this.page_offset = page_offset;
this.totalLength = t;
this.applySort();
this.fireEvent("datachanged", this);
}
else {
if (loaded_node_id) {
loaded_node = this.getById(loaded_node_id);
}
if (loaded_node) {
this.setNodeLoaded(loaded_node, true);
this.setNodeChildrenOffset(loaded_node, page_offset);
this.setNodeChildrenTotalCount(loaded_node, Math.max(t, r.length));
this.removeNodeDescendants(loaded_node);
}
this.suspendEvents();
updated = {};
for (i = 0, len = r.length; i < len; i++) {
record = r[i];
idx = this.indexOfId(record.id);
if (idx == -1) {
updated[record.id] = false;
this.add(record);
}
else {
updated[record.id] = true;
prev_record = this.getAt(idx);
prev_record.reject();
prev_record.data = record.data;
r[i] = prev_record;
}
}
this.applySort();
this.resumeEvents();

r.sort(function(r1, r2) {
var idx1 = self.data.indexOf(r1),
idx2 = self.data.indexOf(r2),
result;

if (idx1 > idx2) {
result = 1;
}
else {
result = -1;
}
return result;
});

for (i = 0, len = r.length; i < len; i++) {
record = r[i];
if (updated[record.id] == true) {
this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
}
else {
this.fireEvent("add", this, [record], this.data.indexOf(record));
}
}
}
this.fireEvent("load", this, r, options);
if (options.callback) {
options.callback.call(options.scope || this, r, options, true);
}
},

sort : function(fieldName, dir)
{
if (this.remoteSort) {
this.setActiveNode(null);
if (this.lastOptions) {
this.lastOptions.add = false;
if (this.lastOptions.params) {
this.lastOptions.params[this.paramNames.active_node] = null;
}
}
}

return Ext.ux.lf.AbstractTreeStore.superclass.sort.call(this, fieldName, dir);
},

applySort : function()
{
if(this.sortInfo && !this.remoteSort){
var s = this.sortInfo, f = s.field;
this.sortData(f, s.direction);
}
else {
this.applyTreeSort();
}
},

sortData : function(f, direction)
{
direction = direction || 'ASC';
var st = this.fields.get(f).sortType;
var fn = function(r1, r2){
var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
};
this.data.sort(direction, fn);
if(this.snapshot && this.snapshot != this.data){
this.snapshot.sort(direction, fn);
}
this.applyTreeSort();
},

applyTreeSort : function()
{
var i, len, temp,
rec, records = [],
roots = this.getRootNodes();

for (i = 0, len = roots.length; i < len; i++) {
rec = roots[i];
records.push(rec);
this.collectNodeChildrenTreeSorted(records, rec);
}

if (records.length > 0) {
this.data.clear();
this.data.addAll(records);
}

if (this.snapshot && this.snapshot !== this.data) {
temp = this.data;
this.data = this.snapshot;
this.snapshot = null;
this.applyTreeSort();
this.snapshot = this.data;
this.data = temp;
}
},

collectNodeChildrenTreeSorted : function(records, rec)
{
var i, len,
child,
children = this.getNodeChildren(rec);

for (i = 0, len = children.length; i < len; i++) {
child = children[i];
records.push(child);
this.collectNodeChildrenTreeSorted(records, child);
}
},

getActiveNode : function()
{
return this.active_node;
},

setActiveNode : function(rc)
{
if (this.active_node !== rc) {
if (rc) {
if (this.data.indexOf(rc) != -1) {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
else {
throw "Given record is not from the store.";
}
}
else {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
}
},

isExpandedNode : function(rc)
{
return rc.ux_maximgb_tg_expanded === true;
},

setNodeExpanded : function(rc, value)
{
rc.ux_maximgb_tg_expanded = value;
},

isVisibleNode : function(rc)
{
var i, len,
ancestors = this.getNodeAncestors(rc),
result = true;

for (i = 0, len = ancestors.length; i < len; i++) {
result = result && this.isExpandedNode(ancestors[i]);
if (!result) {
break;
}
}
return result;
},

isLeafNode : function(rc)
{
return rc.get(this.leaf_field_name) == true;
},

isLoadedNode : function(rc)
{
var result;

if (rc.ux_maximgb_tg_loaded !== undefined) {
result = rc.ux_maximgb_tg_loaded;
}
else if (this.isLeafNode(rc) || this.hasChildNodes(rc)) {
result = true;
}
else {
result = false;
}

return result;
},

setNodeLoaded : function(rc, value)
{
rc.ux_maximgb_tg_loaded = value;
},

getNodeChildrenOffset : function(rc)
{
return rc.ux_maximgb_tg_offset || 0;
},

setNodeChildrenOffset : function(rc, value)
{
rc.ux_maximgb_tg_offset = value;
},

getNodeChildrenTotalCount : function(rc)
{
return rc.ux_maximgb_tg_total || 0;
},

setNodeChildrenTotalCount : function(rc, value)
{
rc.ux_maximgb_tg_total = value;
},

collapseNode : function(rc)
{
if (
this.isExpandedNode(rc) &&
this.fireEvent('beforecollapsenode', this, rc) !== false
) {
this.setNodeExpanded(rc, false);
this.fireEvent('collapsenode', this, rc);
}
},

expandNode : function(rc)
{
var params;
if (!this.isExpandedNode(rc) && this.fireEvent('beforeexpandnode', this, rc) !== false)
{
if (this.isLoadedNode(rc))
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
else if(this.getNodeChildrenCount(rc) == 0)
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
}
},

expandAll : function()
{

var r, i, len, records = this.data.getRange();
this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (!this.isExpandedNode(r)) {
this.expandNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

collapseAll : function()
{
var r, i, len, records = this.data.getRange();

this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (this.isExpandedNode(r)) {
this.collapseNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

getLoadedNodeIdFromOptions : function(options)
{
var result = null;
if (options && options.params && options.params[this.paramNames.active_node]) {
result = options.params[this.paramNames.active_node];
}
return result;
},

getPageOffsetFromOptions : function(options)
{
var result = 0;
if (options && options.params && options.params[this.paramNames.start]) {
result = parseInt(options.params[this.paramNames.start], 10);
if (isNaN(result)) {
result = 0;
}
}
return result;
},

hasNextSiblingNode : function(rc)
{
return this.getNodeNextSibling(rc) !== null;
},

hasPrevSiblingNode : function(rc)
{
return this.getNodePrevSibling(rc) !== null;
},

hasChildNodes : function(rc)
{
return this.getNodeChildrenCount(rc) > 0;
},

getNodeAncestors : function(rc)
{
var ancestors = [],
parent;

parent = this.getNodeParent(rc);
while (parent) {
ancestors.push(parent);
parent = this.getNodeParent(parent);
}

return ancestors;
},

getNodeChildrenCount : function(rc)
{
return this.getNodeChildren(rc).length;
},

getNodeNextSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);

if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);

if (index < siblings.length - 1) {
result = siblings[index + 1];
}

return result;
},

getNodePrevSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);
if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);
if (index > 0) {
result = siblings[index - 1];
}

return result;
},

getRootNodes : function()
{
throw 'Abstract method call';
},

getNodeDepth : function(rc)
{
throw 'Abstract method call';
},

getNodeParent : function(rc)
{
throw 'Abstract method call';
},

getNodeChildren : function(rc)
{
throw 'Abstract method call';
},

addToNode : function(parent, child)
{
throw 'Abstract method call';
},

removeFromNode : function(parent, child)
{
throw 'Abstract method call';
},

getPageOffset : function()
{
return this.page_offset;
},

getActiveNodePageOffset : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenOffset(this.active_node);
}
else {
result = this.getPageOffset();
}

return result;
},

getActiveNodeCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenCount(this.active_node);
}
else {
result = this.getRootNodes().length;
}

return result;
},

getActiveNodeTotalCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenTotalCount(this.active_node);
}
else {
result = this.getTotalCount();
}

return result;
}
});


Ext.ux.lf.LockingTreeGridStore = Ext.extend(Ext.ux.lf.AbstractTreeStore,
{
parent_id_field_name : '_parent',

getRootNodes : function()
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == null) {
result.push(records[i]);
}
}

return result;
},

getNodeDepth : function(rc)
{
return this.getNodeAncestors(rc).length;
},

getNodeParent : function(rc)
{
return this.getById(rc.get(this.parent_id_field_name));
},

getNodeChildren : function(rc)
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == rc.id) {
result.push(records[i]);
}
}

return result;
},

addToNode : function(parent, child)
{
child.set(this.parent_id_field_name, parent.id);
this.addSorted(child);
},

removeFromNode : function(parent, child)
{
this.remove(child);
}
});

Ext.ux.lf.LockingTreeGridView = Ext.extend(Ext.grid.GridView,
{
expanded_icon_class : 'ux-maximgb-tg-elbow-minus',
collapsed_icon_class : 'ux-maximgb-tg-elbow-plus',

last_expanded_icon_class : 'ux-maximgb-tg-elbow-end-minus',
last_collapsed_icon_class : 'ux-maximgb-tg-elbow-end-plus',

nl_expanded_icon_class : 'ux-maximgb-tg-nl-minus',
nl_collapsed_icon_class : 'ux-maximgb-tg-nl-plus',

skip_width_update_class: 'ux-maximgb-tg-skip-width-update',

expanded_folder_class : 'ux-maximgb-tg-expanded-folder',
collapsed_folder_class : 'ux-maximgb-tg-collapsed-folder',

lockText : 'Lock',
unlockText : 'Unlock',
rowBorderWidth : 1,
lockedBorderWidth : 1,

syncHeights: false,

initTemplates : function()
{
var ts = this.templates || {};


if (!ts.masterTpl) {
ts.masterTpl = 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" style="{lstyle}">{lockedHeader}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{lstyle}">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
'</div>',
'<div class="x-grid3-viewport x-grid3-unlocked">',
'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{mainbody}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
'</div>',
'<div class="x-grid3-resize-marker">&#160;</div>',
'<div class="x-grid3-resize-proxy">&#160;</div>',
'</div>'
);
}

if (!ts.row) {
ts.row = new Ext.Template(
'<div class="x-grid3-row ux-maximgb-tg-level-{level} ux-maximgb-tg-border {alt}" style="{tstyle} {display_style}">',
'<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
'<tbody>',
'<tr>{cells}</tr>',
(
this.enableRowBody ?
'<tr class="x-grid3-row-body-tr" style="{bodyStyle}">' +
'<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">'+
'<div class="x-grid3-row-body">{body}</div>'+
'</td>'+
'</tr>'
:
''
),
'</tbody>',
'</table>',
'</div>'
);
}


if (!ts.mastercell) {
ts.mastercell = new Ext.Template(
'<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
'<div class="ux-maximgb-tg-mastercell-wrap">', // This is for editor to place itself right
'{treeui}',
'<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr} style="padding-top:3px">{value}</div>',
'</div>',
'</td>'
);
}

if (!ts.treeui) {
ts.treeui = new Ext.Template(
'<div class="ux-maximgb-tg-uiwrap" style="width: {wrap_width}px">',
'{elbow_line}',
'<div style="left: {left}px" class="{cls}">&#160;</div>',
'</div>'
);
}

if (!ts.elbow_line) {
ts.elbow_line = new Ext.Template(
'<div style="left: {left}px;" class="{cls}"></div>'
);
}

this.templates = ts;
Ext.ux.lf.LockingTreeGridView.superclass.initTemplates.call(this);
},

initElements : function(){
var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
scroller = mainWrap.child('div.x-grid3-scroller');

if (this.grid.hideHeaders) {
lockedHd.setDisplayed(false);
mainHd.setDisplayed(false);
}

if(this.forceFit){
scroller.setStyle('overflow-x', 'hidden');
}

Ext.apply(this, {
el : el,
mainWrap: mainWrap,
mainHd : mainHd,
innerHd : mainHd.dom.firstChild,
scroller: scroller,
mainBody: scroller.child('div.x-grid3-body'),
focusEl : scroller.child('a'),
resizeMarker: el.child('div.x-grid3-resize-marker'),
resizeProxy : el.child('div.x-grid3-resize-proxy'),
lockedWrap: lockedWrap,
lockedHd: lockedHd,
lockedScroller: lockedScroller,
lockedBody: lockedScroller.child('div.x-grid3-body'),
lockedInnerHd: lockedHd.child('div.x-grid3-header-inner', true)
});


this.focusEl.swallowEvent('click', true);
},

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

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

getCell : function(row, col){
if(col < 1){
return this.getLockedRow(row).getElementsByTagName('td')[col];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getCell.call(this, row, col - lockedLen);
},

getHeaderCell : function(index){
var lockedLen = 1;
if(index < lockedLen){
return this.lockedHd.dom.getElementsByTagName('td')[index];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getHeaderCell.call(this, index - lockedLen);
},

addRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).addClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.addRowClass.call(this, row, cls);
},

removeRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).removeClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRowClass.call(this, row, cls);
},

removeRow : function(row) {
Ext.removeNode(this.getLockedRow(row));
Ext.ux.lf.LockingTreeGridView.superclass.removeRow.call(this, row);
},

removeRows : function(firstRow, lastRow){
var lockedBody = this.lockedBody.dom,
rowIndex = firstRow;
for(; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(lockedBody.childNodes[firstRow]);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRows.call(this, firstRow, lastRow);
},

syncScroll : function(e){
this.lockedScroller.dom.scrollTop = this.scroller.dom.scrollTop;
Ext.ux.lf.LockingTreeGridView.superclass.syncScroll.call(this, e);
},

updateSortIcon : function(col, dir){
var sortClasses = this.sortClasses,
lockedHeaders = this.lockedHd.select('td').removeClass(sortClasses),
headers = this.mainHd.select('td').removeClass(sortClasses),
lockedLen = 1,
cls = sortClasses[dir == 'DESC' ? 1 : 0];

if(col < lockedLen){
lockedHeaders.item(col).addClass(cls);
}else{
headers.item(col - lockedLen).addClass(cls);
}
},

updateAllColumnWidths : function(){
var tw = this.getTotalWidth(),
clen = this.cm.getColumnCount(),
lw = this.getLockedWidth(),
llen = 1,
widths = [], len, i;
for(i = 0; i < clen; i++)
{
widths[i] = this.getColumnWidth(i);
var hd = this.getHeaderCell(i);
hd.style.width = widths[i];
}
var lns = this.getLockedRows(), ns = this.getRows(), row, trow, j;
for(i = 0, len = ns.length; i < len; i++)
{
row = lns[i];
row.style.width = lw;
if(row.firstChild)
{
row.firstChild.style.width = lw;
trow = row.firstChild.rows[0];
trow.childNodes[0].style.width = widths[0];

}
row = ns[i];
row.style.width = tw;
if(row.firstChild)
{
row.firstChild.style.width = tw;
trow = row.firstChild.rows[0];
for (j = llen; j < clen; j++)
{
trow.childNodes[j - llen].style.width = widths[j];
}
}
}
this.onAllColumnWidthsUpdated(widths, tw);
//this.syncHeaderHeight();
},

updateColumnWidth : function(col, width){
var w = this.getColumnWidth(col),
llen = 1,
ns, rw, c, row;
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.width = w;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.width = w;
}
}
this.onColumnWidthUpdated(col, w, this.getTotalWidth());
//this.syncHeaderHeight();
},

updateColumnHidden : function(col, hidden){
var llen = this.cm.getLockedCount(),
ns, rw, c, row,
display = hidden ? 'none' : '';
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.display = display;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.display = display;
}
}
this.onColumnHiddenUpdated(col, hidden, this.getTotalWidth());
delete this.lastViewWidth;
this.layout();
},

doRender: function(columns, records, store, startRow, colCount, stripe){

var templates = this.templates;
var cell_template = templates.mastercell;
var cell_template2 = templates.cell;
var row_template = templates.row;
var last = colCount-1;
var tstyle = 'width:'+this.getTotalWidth()+';';
var lstyle = 'width:'+this.getLockedWidth()+';';
var buffer = [];
var locked_buffer = [];
var column_buffer = [];
var locked_column_buffer = [];
var column;
var params = {};
var row_params = {};
var record;


for (var x = 0, len = records.length; x < len; x++) {
record = records[x];
column_buffer = [];
locked_column_buffer = [];

this.store.setNodeExpanded(record, true);

var rowIndex = x + startRow;
var row_render_res = this.renderRow(record, rowIndex, colCount, store, this.cm.getTotalWidth());

if (row_render_res === false) {
for (var i = 0; i < colCount; i++) {

column = columns[i];
params.id = column.id;
params.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
params.attr = params.cellAttr = "";
params.value = column.renderer.call(column.scope, record.data[column.name], params, record, rowIndex, i, store);
params.style = column.style;

if (Ext.isEmpty(params.value)) {
params.value = "&#160;";
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] !== 'undefined') {
params.css += ' x-grid3-dirty-cell';
}

if (column.id == this.grid.master_column_id) {
params.treeui = this.renderCellTreeUI(record, store);
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
else {
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
if (column.id == this.grid.master_column_id) {
locked_column_buffer[locked_column_buffer.length] = cell_template.apply(params);
}
else {
column_buffer[column_buffer.length] = cell_template2.apply(params);
}

}
}
else {
column_buffer.push(row_render_res);
}

var alt = [];
if (stripe && ((rowIndex + 1) % 2 == 0)) {
alt[0] = "x-grid3-row-alt";
}
if (record.dirty) {
alt[1] = " x-grid3-dirty-row";
}
row_params.cols = colCount;
if (this.getRowClass) {
alt[2] = this.getRowClass(r, rowIndex, rp, store);
}

row_params.alt = alt.join(" ");
row_params.cells = locked_column_buffer.join("");
row_params.lstyle = lstyle;
locked_buffer[locked_buffer.length] = row_template.apply(row_params);

row_params.cells = column_buffer.join("");
row_params.tstyle = tstyle;
buffer[buffer.length] = row_template.apply(row_params);

}
return [buffer.join(""),locked_buffer.join("")];

},



renderCellTreeUI : function(record, store)
{
var template = this.templates.treeui,
line_template = this.templates.elbow_line,
template_data = {},
rec, parent,
depth = level = store.getNodeDepth(record);
template_data.elbow_line = '';
rec = record;
left = 0;

if (store.isLeafNode(rec))
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-item'
});
}
else
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-expanded-folder'
});
}

template_data.wrap_width = (depth + 1) * 16 + 16;
if (level > 0) {

while(level--) {
parent = store.getNodeParent(rec);
if (parent) {
if (store.hasNextSiblingNode(parent)) {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-line',
}) +
template_data.elbow_line;
}
else {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-empty',
}) +
template_data.elbow_line;
}
}
else {
throw [
"Tree inconsistency can't get level ",
level + 1,
" node(id=", rec.id, ") parent."
].join("");
}
rec = parent;
}
}
if (store.isLeafNode(record)) {
if (store.hasNextSiblingNode(record)) {
template_data.cls = 'ux-maximgb-tg-elbow';
}
else {
template_data.cls = 'ux-maximgb-tg-elbow-end';
}
}
else {

template_data.cls = 'ux-maximgb-tg-elbow-active ';

if (store.isExpandedNode(record)) {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.expanded_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_expanded_icon_class;
} else {
template_data.cls += this.nl_expanded_icon_class;
}
}
else {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.collapsed_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_collapsed_icon_class;
} else {
template_data.cls += this.nl_collapsed_icon_class;
}
}
}
template_data.left = 1 + depth * 16;
return template.apply(template_data);
},

renderRow : function(record, index, col_count, store, total_width)
{
return false;
},

afterRender : function()
{
if(!this.store || !this.cm){
return;
}
var body = this.renderRows() || ['&#160;', '&#160;'];

this.mainBody.dom.innerHTML = body[0];
this.lockedBody.dom.innerHTML = body[1];
this.processRows(0, true);
if(this.deferEmptyText !== true){
this.applyEmptyText();
}
this.grid.fireEvent('viewready', this.grid);
this.updateAllColumnWidths();
},

renderUI : function()
{
var templates = this.templates,
header = this.renderHeaders(),
body = templates.body.apply({rows:'&#160;'});


return templates.masterTpl.apply({
mainbody : body[0],
header: header[0],
ostyle: 'width:' + this.getOffsetWidth() + ';',
bstyle: 'width:' + this.getTotalWidth() + ';',
lockedBody: body[1],
lockedHeader: header[1],
lstyle: 'width:'+this.getLockedWidth()+';'
});
},

getOffsetWidth : function()
{
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0) + this.getScrollOffset()) + 'px';
},

afterRenderUI: function()
{
var grid = this.grid;
this.initElements();
Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
Ext.fly(this.lockedInnerHd).on('click', this.handleHdDown, this);
this.mainHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.lockedHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.scroller.on('scroll', this.syncScroll, this);
if(grid.enableColumnResize !== false){
this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
this.splitZone2 = new Ext.grid.GridView.SplitDragZone(grid, this.lockedHd.dom);
this.splitZone2.setOuterHandleElId(Ext.id(this.lockedHd.dom));
this.splitZone.setOuterHandleElId(Ext.id(this.mainHd.dom));
}
if(grid.enableColumnMove){
this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
this.columnDrag2 = new Ext.grid.GridView.ColumnDragZone(grid, this.lockedInnerHd);
this.columnDrag2.setOuterHandleElId(Ext.id(this.lockedInnerHd));
this.columnDrag.setOuterHandleElId(Ext.id(this.innerHd));
this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
}
if(grid.enableHdMenu !== false){
this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
this.hmenu.add(
{itemId: 'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
{itemId: 'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
);

if(grid.enableColumnHide !== false){
this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
this.colMenu.on({
scope: this,
beforeshow: this.beforeColMenuShow,
itemclick: this.handleHdMenuClick
});
this.hmenu.add('-', {
itemId:'columns',
hideOnClick: false,
text: this.columnsText,
menu: this.colMenu,
iconCls: 'x-cols-icon'
});
}
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
}
if(grid.trackMouseOver){
this.mainBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
this.lockedBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
}

if(grid.enableDragDrop || grid.enableDrag){
this.dragZone = new Ext.grid.GridDragZone(grid, {
ddGroup : grid.ddGroup || 'GridDD'
});
}
this.updateHeaderSortState();
},

layout : function(){
if(!this.mainBody){
return;
}
var grid = this.grid;
var grid_el = grid.getGridEl();
var cell_size = grid_el.getSize(true);
if(!grid.hideHeaders && (cell_size.width < 20 || cell_size.height < 20)){
return;
}

if(grid.autoHeight){
this.scroller.dom.style.overflow = 'visible';
this.lockedScroller.dom.style.overflow = 'visible';
if(Ext.isWebKit){
this.scroller.dom.style.position = 'static';
this.lockedScroller.dom.style.position = 'static';
}
}else{
this.el.setSize(cell_size.width, cell_size.height);
var hdHeight = this.mainHd.getHeight();
var cell_height = cell_size.height - (hdHeight);
}
this.updateLockedWidth();
if(this.forceFit){
if(this.lastViewWidth != cell_size.width){
this.fitColumns(false, false);
this.lastViewWidth = cell_size.width;
}
}else {
this.autoExpand();
this.syncHeaderScroll();
}
this.onLayout(cell_size.width, cell_height);
},

renderHeaders : function()
{
var column_model = this.cm,
templates = this.templates,
ct = templates.hcell,
cb = [], locked_cb = [],
params = {},
len = column_model.getColumnCount(),
last = len - 1;
for(var i = 0; i < len; i++)
{
params.id = column_model.getColumnId(i);
params.value = column_model.getColumnHeader(i) || '';
params.style = this.getColumnStyle(i, true);
params.tooltip = this.getColumnTooltip(i);
params.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
(column_model.config[i].headerCls ? ' ' + column_model.config[i].headerCls : '');
if(column_model.config[i].align == 'right'){
params.istyle = 'padding-right:16px';
} else {
delete params.istyle;
}
if(i == 0)
{
locked_cb[locked_cb.length] = ct.apply(params);
}
else
{
cb[cb.length] = ct.apply(params);
}
}
return [templates.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'}),
templates.header.apply({cells: locked_cb.join(''), tstyle:'width:'+this.getLockedWidth()+';'})];
},

updateHeaders : function()
{
var header = this.renderHeaders();
this.innerHd.firstChild.innerHTML = header[0];
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
this.lockedInnerHd.firstChild.innerHTML = header[1];
var locked_width = this.getLockedWidth();
this.lockedInnerHd.firstChild.style.width = locked_width;
this.lockedInnerHd.firstChild.firstChild.style.width = locked_width;
},

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

syncFocusEl : function(row, col, hscroll){
Ext.ux.lf.LockingTreeGridView.superclass.syncFocusEl.call(this, row, col, col < 1 ? false : hscroll);
},
/*
updateAllColumnWidths : function()
{
var total_width = this.getTotalWidth(),
column_length = this.cm.getColumnCount(),
widths = [],
length,
i;
for(i = 0; i < column_length; i++){
widths[i] = this.getColumnWidth(i);
}
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
for(i = 0; i < column_length; i++){
var header = this.getHeaderCell(i);
header.style.width = widths[i];
}

var rows = this.getRows(), row, trow;
for(i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
total_row = row.firstChild.rows[0];
for (var j = 0; j < column_length && j < total_row.childNodes.length; j++) {
if (!Ext.fly(total_row.childNodes[j]).hasClass(this.skip_width_update_class)) {
total_row.childNodes[j].style.width = widths[j];
}
}
}
}

this.onAllColumnWidthsUpdated(widths, total_width);
},

updateColumnWidth : function(col, width)
{
var col_width = this.getColumnWidth(col);
var total_width = this.getTotalWidth();

this.lockedInnerHd.firstChild.style.width = this.getOffsetWidth();
this.lockedInnerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var header = this.getHeaderCell(col);
header.style.width = col_width;

var rows = this.getRows(), row;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.width = col_width;
}
}
}
}

this.onColumnWidthUpdated(col, col_width, total_width);
},

updateColumnHidden : function(col, hidden)
{
var total_width = this.getTotalWidth();
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var display = hidden ? 'none' : '';

var header = this.getHeaderCell(col);
header.style.display = display;

var rows = this.getRows(), row, cell;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.display = display;
}
}
}
}

this.onColumnHiddenUpdated(col, hidden, total_width);
delete this.lastViewWidth; // force recalc
this.layout();
},
*/
processRows : function(startRow, skipStripe)
{
if(!this.store || this.store.getCount() < 1){
return;
}

var rows = this.getRows(),
locked_rows = this.getLockedRows(),
row, locked_row;
var processed_count = 0;

skipStripe = !this.grid.stripeRows;
startRow = startRow || 0;

for(var i = 0, len = rows.length; i < len; ++i){
row = rows[i];
locked_row = locked_rows[i];
row.rowIndex = i;
locked_row.rowIndex = i;

if(!skipStripe){
row.className = row.className.replace(this.rowClsRe, ' ');
locked_row.className = locked_row.className.replace(this.rowClsRe, ' ');
if ((i + 1) % 2 === 0){
row.className += ' x-grid3-row-alt';
locked_row.className += ' x-grid3-row-alt';
}
}
this.syncRowHeights(row, locked_row);
}

if(startRow === 0){
Ext.fly(rows[0]).addClass(this.firstRowCls);
Ext.fly(locked_rows[0]).addClass(this.firstRowCls);
}
Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
Ext.fly(locked_rows[locked_rows.length - 1]).addClass(this.lastRowCls);
},

ensureVisible : function(row, col, hscroll)
{
var ancestors, record = this.store.getAt(row);
if (!this.store.isVisibleNode(record))
{
ancestors = this.store.getNodeAncestors(record);

while (ancestors.length > 0)
{
record = ancestors.shift();

if (!this.store.isExpandedNode(record))
{
this.store.expandNode(record);
}
}
}
return Ext.ux.lf.LockingTreeGridView.superclass.ensureVisible.call(this, row, col, col < 1 ? false : hscroll);

},

expandRow : function(record, skip_process)
{
var store = this.store,
i, len, row, locked_row, pmel, lpmel, children, index, child_index;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');

if (pmel) {
pmel.removeClass(this.collapsed_icon_class);
pmel.removeClass(this.last_collapsed_icon_class);
pmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_expanded_icon_class);
} else {
pmel.addClass(this.nl_expanded_icon_class);
}
}

if (lpmel) {
lpmel.removeClass(this.collapsed_icon_class);
lpmel.removeClass(this.last_collapsed_icon_class);
lpmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_expanded_icon_class);
} else {
lpmel.addClass(this.nl_expanded_icon_class);
}
}

pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');

lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');

if (pmel) {
pmel.removeClass(this.collapsed_folder_class);
pmel.addClass(this.expanded_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.collapsed_folder_class);
lpmel.addClass(this.expanded_folder_class);
}
if (store.isVisibleNode(record)) {
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
row.style.display = 'block';
locked_row.style.display = 'block';

if (store.isExpandedNode(children[i])) {
this.expandRow(child_index, true);
}
}
}
if (!skip_process) {
this.processRows(0);
}
},

collapseRow : function(record, skip_process)
{
var store = this.store,
i, len, children, row, locked_row, index, child_index, pmel, lpmel;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');
if (pmel) {
pmel.removeClass(this.expanded_icon_class);
pmel.removeClass(this.last_expanded_icon_class);
pmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_collapsed_icon_class);
} else {
pmel.addClass(this.nl_collapsed_icon_class);
}
}
if (lpmel) {
lpmel.removeClass(this.expanded_icon_class);
lpmel.removeClass(this.last_expanded_icon_class);
lpmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_collapsed_icon_class);
} else {
lpmel.addClass(this.nl_collapsed_icon_class);
}
}
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');
if (pmel) {
pmel.removeClass(this.expanded_folder_class);
pmel.addClass(this.collapsed_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.expanded_folder_class);
lpmel.addClass(this.collapsed_folder_class);
}
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
if (row.style.display != 'none') {
row.style.display = 'none';
this.collapseRow(child_index, true);
}
if (locked_row.style.display != 'none') {
locked_row.style.display = 'none';
this.collapseRow(child_index, true);
}
}
if (!skip_process) {
this.processRows(0);
}
},

initData : function(store, column_model)
{
if(this.cm){
this.cm.un('columnlockchange', this.onColumnLock, this);
}
this.store = this.ds = store;
Ext.ux.lf.LockingTreeGridView.superclass.initData.call(this, store, column_model);
if (this.store) {
this.store.un('expandnode', this.onStoreExpandNode, this);
this.store.un('collapsenode', this.onStoreCollapseNode, this);
}
if (store) {
store.on('expandnode', this.onStoreExpandNode, this);
store.on('collapsenode', this.onStoreCollapseNode, this);
}
if(this.cm){
this.cm.on('columnlockchange', this.onColumnLock, this);
}
},

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

handleHdMenuClick : function(item)
{
var index = this.hdCtxIndex,
cm = this.cm,
id = item.getItemId()
switch(id){
default:
return Ext.ux.lf.LockingTreeGridView.superclass.handleHdMenuClick.call(this, item);
}
return true;
},

handleHdDown : function(e, t)
{
Ext.ux.lf.LockingTreeGridView.superclass.handleHdDown.call(this, e, t);
if(this.grid.enableColLock !== false){
if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
var hd = this.findHeaderCell(t),
index = this.getCellIndex(hd),
ms = this.hmenu.items, cm = this.cm;
}
}
},

onLoad : function(store, records, options)
{
var ridx;
if (
options &&
options.params &&
(
options.params[store.paramNames.active_node] === null ||
store.indexOfId(options.params[store.paramNames.active_node]) == -1
)
) {
Ext.ux.lf.LockingTreeGridView.superclass.onLoad.call(this, store, records, options);
}
},

onAdd : function(store, records, index)
{
Ext.ux.lf.LockingTreeGridView.superclass.onAdd.call(this, store, records, index);
if (this.mainWrap) {
this.processRows(0);
}
},

onRemove : function(store, record, index, isUpdate)
{
Ext.ux.lf.LockingTreeGridView.superclass.onRemove.call(this, store, record, index, isUpdate);
if(isUpdate !== true){
if (this.mainWrap) {
this.processRows(0);
}
}
},

onUpdate : function(store, record)
{
Ext.ux.lf.LockingTreeGridView.superclass.onUpdate.call(this, store, record);
if (this.mainWrap) {
this.processRows(0);
}
},

onStoreExpandNode : function(store, record)
{
this.expandRow(record);
},

onStoreCollapseNode : function(store, record)
{
this.collapseRow(record);
},

getColumnStyle : function(col, isHeader)
{
var style = !isHeader ? this.cm.config[col].cellStyle || this.cm.config[col].css || '' : this.cm.config[col].headerStyle || '';
style += 'width:'+this.getColumnWidth(col)+';';
if(this.cm.isHidden(col)){
style += 'display:none;';
}
var align = this.cm.config[col].align;
if(align){
style += 'text-align:'+align+';';
}
return style;
},

getLockedWidth : function() {
return this.cm.getColumnWidth(0) + 'px';
},

getTotalWidth : function() {
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0)) + 'px';
},

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 : (!Ext.isDefined(name) ? this.store.fields.get(i).name : name),
renderer : cm.getRenderer(i),
id : cm.getColumnId(i),
style : this.getColumnStyle(i),
locked : i == 0 ? true : false
};
}
return cs;
},

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

refreshRow: function(record){
var store = this.store,
colCount = this.cm.getColumnCount(),
columns = this.getColumnData(),
last = colCount - 1,
cls = ['x-grid3-row'],
rowParams = {
tstyle: String.format("width: {0};", this.getTotalWidth())
},
lockedRowParams = {
tstyle: String.format("width: {0};", this.getLockedWidth())
},
colBuffer = [],
lockedColBuffer = [],
cellTpl = this.templates.cell,
rowIndex,
row,
lockedRow,
column,
meta,
css,
i;

if (Ext.isNumber(record)) {
rowIndex = record;
record = store.getAt(rowIndex);
} else {
rowIndex = store.indexOf(record);
}

if (!record || rowIndex < 0) {
return;
}

for (i = 0; i < colCount; i++) {
column = columns[i];

if (i == 0) {
css = 'x-grid3-cell-first';
} else {
css = (i == last) ? 'x-grid3-cell-last ' : '';
}

meta = {
id: column.id,
style: column.style,
css: css,
attr: "",
cellAttr: ""
};

meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);

if (Ext.isEmpty(meta.value)) {
meta.value = ' ';
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
meta.css += ' x-grid3-dirty-cell';
}

if (column.locked) {
lockedColBuffer[i] = cellTpl.apply(meta);
} else {
colBuffer[i] = cellTpl.apply(meta);
}
}

row = this.getRow(rowIndex);
row.className = '';
lockedRow = this.getLockedRow(rowIndex);
lockedRow.className = '';

if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
cls.push('x-grid3-row-alt');
}

if (this.getRowClass) {
rowParams.cols = colCount;
cls.push(this.getRowClass(record, rowIndex, rowParams, store));
}

// Unlocked rows
this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
rowParams.cells = colBuffer.join("");
row.innerHTML = this.templates.rowInner.apply(rowParams);

// Locked rows
this.fly(lockedRow).addClass(cls).setStyle(lockedRowParams.tstyle);
lockedRowParams.cells = lockedColBuffer.join("");
lockedRow.innerHTML = this.templates.rowInner.apply(lockedRowParams);
lockedRow.rowIndex = rowIndex;
this.syncRowHeights(row, lockedRow);
this.fireEvent('rowupdated', this, rowIndex, record);
},

syncRowHeights: function(row1, row2){
if(this.syncHeights){
var el1 = Ext.get(row1),
el2 = Ext.get(row2),
h1 = el1.getHeight(),
h2 = el2.getHeight();

if(h1 > h2){
el2.setHeight(h1);
}else if(h2 > h1){
el1.setHeight(h2);
}
}
},

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

updateLockedWidth: function()
{
var lw = this.cm.getColumnWidth(0),
tw = this.cm.getTotalWidth() - lw,
csize = this.grid.getGridEl().getSize(true),
lp = Ext.isBorderBox ? 0 : this.lockedBorderWidth,
rp = Ext.isBorderBox ? 0 : this.rowBorderWidth,
vw = (csize.width - lw - lp - rp) + 'px',
so = this.getScrollOffset();
if(!this.grid.autoHeight)
{
var vh = (csize.height - this.mainHd.getHeight()) + 'px';
this.lockedScroller.dom.style.height = vh;
this.scroller.dom.style.height = vh;
}
this.lockedWrap.dom.style.width = (lw + rp) + 'px';
this.scroller.dom.style.width = vw;
this.mainWrap.dom.style.left = (lw + lp + rp) + 'px';
if(this.innerHd){
this.lockedInnerHd.firstChild.style.width = lw + 'px';
this.lockedInnerHd.firstChild.firstChild.style.width = lw + 'px';
this.innerHd.style.width = vw;
this.innerHd.firstChild.style.width = (tw + rp + so) + 'px';
this.innerHd.firstChild.firstChild.style.width = tw + 'px';
}
if(this.mainBody){
this.lockedBody.dom.style.width = (lw + rp) + 'px';
this.mainBody.dom.style.width = (tw + rp) + 'px';
}
}
});

Ext.ux.lf.LockingTreeGrid = Ext.extend(Ext.grid.GridPanel,
{
tg_cls : 'ux-maximgb-tg-panel',

constructor: function(config) {

Ext.ux.lf.LockingTreeGrid.superclass.constructor.call(this, config);
},

initComponent : function()
{
this.initComponentPreOverride();
Ext.ux.lf.LockingTreeGrid.superclass.initComponent.call(this);
this.getSelectionModel().on('selectionchange', this.onTreeGridSelectionChange, this);
this.initComponentPostOverride();
},

initComponentPreOverride : Ext.emptyFn,

initComponentPostOverride : Ext.emptyFn,

onRender : function(ct, position)
{
Ext.ux.lf.LockingTreeGrid.superclass.onRender.call(this, ct, position);
this.el.addClass(this.tg_cls);
},

getView : function()
{
if (!this.view) {
this.view = new Ext.ux.lf.LockingTreeGridView(this.viewConfig);
}
return this.view;
},

onClick : function(e)
{

var target = e.getTarget(),
view = this.getView(),
row = view.findRowIndex(target),
store = this.getStore(),
sm = this.getSelectionModel(),
record, record_id, do_default = true;

if (row !== false) {

if (Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {

record = store.getAt(row);

if (store.isExpandedNode(record)) {
store.collapseNode(record);
}
else {
store.expandNode(record);

}
do_default = false;
}
}

if (do_default) {
Ext.ux.lf.LockingTreeGrid.superclass.onClick.call(this, e);
}
},

onMouseDown : function(e)
{
var target = e.getTarget();

if (!Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {
Ext.ux.lf.LockingTreeGrid.superclass.onMouseDown.call(this, e);
}
},

onTreeGridSelectionChange : function(sm, selection)
{
var record, ancestors, store = this.getStore();

if (sm.getSelected) {
record = sm.getSelected();
store.setActiveNode(record);
}

else if (sm.getSelectedCell && selection) {
record = selection.record;
store.setActiveNode(record);
}

if (record) {
if (!store.isVisibleNode(record)) {
ancestors = store.getNodeAncestors(record);
while (ancestors.length > 0) {
store.expandNode(ancestors.pop());
}
}
}
}

});

Ext.reg('Ext.ux.lf.LockingTreeGrid', Ext.ux.lf.LockingTreeGrid);
Ext.reg('Ext.ux.lf.LockingTreeGridStore', Ext.ux.lf.LockingTreeGridStore);


Setting up Grid + Drag and Drop Stuff:




dashboardTabSummaryGrid = Ext.extend(Ext.ibc.DynamicColumnGridPanel, {
constructor: function(config) {
config = Ext.apply({
border : false,
trackMouseOver : false,
bodyStyle : 'border-top: 0;',
parameterType : 1,
templateID : config.queryRecord.get('TemplateID'),
enableDragDrop : true,
ddGroup :'dashboardTabSummaryGridDropZone',
contextMenu : Ext.getCmp('dashboardTabSummaryMenu')
}, config);

dashboardTabSummaryGrid.superclass.constructor.call(this, config);
},

initComponent: function() {
dashboardTabSummaryGrid.superclass.initComponent.apply(this, arguments);

this.store.grid = this;

this.on('cellclick', this.onCellClick, this);
this.on('beforecontextmenu', this.onBeforeContextMenu, this);
this.on('columnmove', this.onColumnMove, this);
this.on('columnresize', this.onColumnResize, this);
this.on('rowclick', this.onRowSelect, this);
},

onRowSelect: function(grid, row, e)
{
this.selModel.selectRow(row);
},

onColumnMove: function(oldIndex, newIndex) {

var columns = this.getColumnModel().config;
var nodes = [];
Ext.each(columns,function(column){
if (column.id != "master")
nodes.push(column.id);
});

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: {
action: 'REORDER',
nodes: nodes.join(',')
},
failure : function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onColumnResize: function(columnIndex, newSize) {
},

onCellClick: function(grid, rowIndex, columnIndex, e) {
var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

var summaryGrid = grid;
var detailTab = Ext.getCmp(grid.queryRecord.get('TemplateID') + 'DETAILTAB');

var record = this.selModel.getSelected();

if (grid.store.isLeafNode(record)) {
var tabHeight = summaryGrid.ownerCt.container.getHeight();
var newHeight = tabHeight - (summaryGrid.store.data.length * 19) - 100;

if (newHeight < 300) newHeight = 300;

detailTab.makeVisible(newHeight, record.get('Heading'));
detailTab.loadData(record.get('UserRuleName'), this.queryRecord.get('DetailTemplateID'), record, grid.queryRecord.get('TemplateID'));
}
},

onBeforeContextMenu: function(menu, record, column, rowindex) {
if (record.get('_is_leaf') === false) {
menu.enableDates();
} else {
menu.disableDates();
}

if (rowindex) {
menu.enableDeleteRow();
} else {
menu.disableDeleteRow();
}

if (column) {
menu.enableEdit();
} else {
menu.disableEdit();
}

menu.configure();
menu.doLayout();
},

setColumnAlignment: function(alignement) {
columnModel = this.getColumnModel().config;
columnModel[this.selectedColumn].align = alignement;
this.getColumnModel().setConfig(columnModel);

var column = columnModel[this.selectedColumn];
var params = {
//templateid: this._templateid,
id: column.id,
action: 'UPDATE',
number: column.number,
heading: column.header,
negativecolor: column.negativeColor,
renderer: column.renderer,
//invert: column.invert,
//calccolumn1: this._calccolumn1.getValue(),
//calcoperator: this._calcoperator.getValue(),
//calccolumn2: this._calccolumn2.getValue(),
columnalign: column.align,
//columntype: this._columntype.getValue(),
symbol: column.symbol,
ruleparameter: column.tagname
};

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: params,
scope: this,
failure: function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onRender: function(grid) {
dashboardTabSummaryGrid.superclass.onRender.apply(this, arguments);

var dropZoneOverrides = {
ddGroup : 'dashboardTabSummaryGridDropZone',
onContainerOver : function(ddSrc, evtObj, ddData) {
var destGrid = this.grid;
var tgtEl = evtObj.getTarget();
var destIndex = destGrid.getView().findRowIndex(tgtEl);
var destStore = destGrid.store;

var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
lockedBody = lockedScroller.child('div.x-grid3-body'),
scroller = mainWrap.child('div.x-grid3-scroller');

this.clearDDStyles();

if (destIndex === false) return;


// if drag before first row
if (destIndex == 0) destIndex = 1;
destIndex = (destStore.getCount() == 1 ? 0 : destIndex);

// is this a row?
if (typeof destIndex === 'number') {
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);

var tgtRowEl = Ext.get(tgtRow);
var tgtLockedRowEl = Ext.get(tgtLockedRow);
var tgtRowHeight = tgtRowEl.getHeight();
var tgtRowTop = tgtRowEl.getY();
var tgtRowCtr = tgtRowTop + Math.floor(tgtRowHeight / 2);

var tgtLockedRowHeight = tgtLockedRowEl.getHeight();
var tgtLockedRowTop = tgtLockedRowEl.getY();
var tgtLockedRowCtr = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 2);
var mouseY = evtObj.getXY()[1];

var tgtRow1 = tgtRowEl.getY();
var tgtRow2 = tgtRowTop + Math.floor(tgtRowHeight / 3);
var tgtRow3 = tgtRowTop + (Math.floor(tgtRowHeight / 3) * 2);

var tgtLockedRow1 = tgtLockedRowEl.getY();
var tgtLockedRow2 = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 3);
var tgtLockedRow3 = tgtLockedRowTop + (Math.floor(tgtLockedRowHeight / 3) * 2);

var destGrid = this.grid;
var destStore = destGrid.store;
var destRecord = destStore.getAt(destIndex);

var destPreviousRecord = destStore.getAt(destIndex-1);

if (destRecord.data._is_leaf) {
// below
if (mouseY >= tgtRowCtr) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// above
else if (mouseY < tgtRowCtr) {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');
tgtLockedRowEl.addClass('gridRowInsertTopLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}

} else {




// if root folder, insert below only
if (destIndex == 0) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');


// below
} else if (mouseY >= tgtRow3) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// middle
else if (mouseY >= tgtRow2) {
this.point = 'middle';
//destIndex ++;
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine')
}
// above
else {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');

tgtLockedRowEl.addClass('gridRowInsertTomLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}
}


this.overRow = [tgtRowEl, tgtLockedRowEl];
}
else {
destIndex = destGrid.store.getCount();
}

this.destIndex = destIndex;

//destGrid.body.addClass('gridBodyNotifyOver');

return this.dropAllowed;
},
notifyOut : function() {
this.clearDDStyles();
},
clearDDStyles : function() {
//this.grid.body.removeClass('gridBodyNotifyOver');
if (this.overRow) {
this.overRow[0].removeClass('table-drop-pin');

this.overRow[0].removeClass('gridRowInsertBottomLine');
this.overRow[0].removeClass('gridRowInsertMiddleLine');
this.overRow[0].removeClass('gridRowInsertTopLine');
this.overRow[1].removeClass('gridRowInsertBottomLine');
this.overRow[1].removeClass('gridRowInsertTopLine');
delete this.overRow;
}
},
onContainerDrop : function(ddSrc, evtObj, ddData){
if (!this.overRow) return;

var srcGrid = ddSrc.view.grid;
var srcStore = srcGrid.store;
var srcIndex = ddData.rowIndex;
var records = ddSrc.dragData.selections;
var srcRecord = records[0];

var destGrid = this.grid;
var destStore = destGrid.store;
var destIndex = this.destIndex > destStore.getCount() ? destStore.getCount() : this.destIndex;
var destRecord = destStore.getAt(destIndex);
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);


// clear grid drag styles
this.clearDDStyles();

// exit if destRecord is undefined or source and dest are the same
if (srcGrid.id == destGrid.id && srcIndex == destIndex) return false;
if (!destRecord) return false;

if (destStore.getCount() > 1) {

// set destRecord to parent folder if leaf selected
if (destRecord.data._is_leaf) {
destRecord = destStore.getNodeParent(destRecord);

if (this.point == 'above') {
destIndex--;
}

} else {
// if Top of folder, check previous sibling for expanded
if (this.point == 'above') {
var prevRecord = destStore.getNodePrevSibling(destRecord);
destRecord = destStore.getNodeParent(destRecord);
destIndex--;
}

// if middle of folder, destRecord doesnt change
if (this.point == 'middle') {
}

// if bottom of folder, check expanded
if (this.point == 'below') {
if (!destRecord.ux_maximgb_tg_expanded) {
destRecord = destStore.getNodeParent(destRecord);
}
}
}
}



if (srcGrid.type == "custom_items") {

// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
{name: 'Heading'}
]);

srcRecord = records[0];

// create Record and add to store
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:false,
Description:data.Heading,
ParentItemID:data._parent
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:false,
Heading:theRequest.data.Heading
}, x.id);

destStore.clearFieldsInRec(rc);
destStore.insert(destIndex+1, rc);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);

//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});


// ************************************************************************
// Show edit row name window
// ************************************************************************

destGrid.getSelectionModel().selectRecords([rc]);
destGrid.selectedRecord = rc;

var editRowName = Ext.getCmp('editRowName');
editRowName.edit(destGrid);
},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});




} else if (srcGrid.type == "rule_items") {
// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
'UserRuleName',
'Heading'
]);

// create Record and add to store
Ext.each(records,function(srcRecord){
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:true,
Description:data.Heading,
ParentItemID:data._parent,
UserRule:data.UserRuleName
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:theRequest.data._is_leaf,
UserRuleName:theRequest.data.UserRuleName,
Heading:theRequest.data.Heading
}, x.id);
destStore.insert(destIndex+1, rc);
destGrid.getSelectionModel().selectRecords([rc]);

destStore.applySort();
destGrid.view.refresh(true);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});



// ************************************************************************
// update rule data in realtime - dont refresh whole grid
// ************************************************************************


Ext.Ajax.request({
scope:this,
grid: destGrid,
rc: rc,
url: 'services/tree-run.exec',
params: {
userrulename : rc.get('UserRuleName'),
summary : 1,
id : destGrid.templateID
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);
x.data = x.data[0];

var ancestors = destStore.getNodeAncestors(theRequest.rc);

destStore.copyToRec(theRequest.rc, x);
destStore.addToAncestors(ancestors, theRequest.rc);

destGrid.view.refresh(true);
},
failure: function (theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});



},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});

});


} else {
// reorder rules
var record = records[0];
var ancestors = destStore.getNodeAncestors(record);

// subtract values from current ancestors
destStore.subtractFromAncestors(ancestors, record);

// move record to correct location
//if (srcIndex < destIndex) destIndex--;

// move record to new parent
//destStore.move(record,destIndex);
// set a new parent id
record.set('_parent',destRecord.get('_id'));

//sort grid and get new ancestors
//this.grid.store.applyTreeSort();
ancestors = destStore.getNodeAncestors(record);

// add values to new ancestors
destStore.addToAncestors(ancestors, record);

// Save new order and partent ids

// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************


var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: record.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
Ext.Msg.alert('Error','Error saving the changes');
}
});



// update the grid
//this.grid.store.applyTreeSort();
destStore.applySort();
destGrid.view.refresh(true);
}



return true;
}
};
// This will make sure we only drop to the view container
var leftGridDroptgtCfg = Ext.apply({}, dropZoneOverrides, {
grid : this
});
new Ext.dd.DropZone(this.el, leftGridDroptgtCfg);

}

});

Ext.reg('dashboardTabSummaryGrid', dashboardTabSummaryGrid);


dashboardTabSummaryGrid.descriptionRenderer = function(value, metadata, record, rowIndex, colIndex, store){
//if (rowIndex == 0) return '';

if (record.get('_is_leaf') === false && record.get('datefr') && record.get('datefr') != '') {

var dateStore = Ext.StoreMgr.item('dateStore');
var dateFr = record.get('datefr');
var dateTo = record.get('dateto');

var dateRec = dateStore.getById(dateFr);
if (dateRec) {
dateFr = dateRec.get('description');
} else {
dateFr = Date.parseDate(dateFr, 'Ymd').format('d/m/Y');
}

var dateRec = dateStore.getById(dateTo);
if (dateRec) {
dateTo = dateRec.get('description');
} else {
dateTo = Date.parseDate(dateTo, 'Ymd').format('d/m/Y');
}

return String.format('{0} ({1} - {2})', value, dateFr, dateTo);
} else {
return value;
}
};

Main issue at the moment is the drag drop stuff isnt working on the locked column, for some reason the normal row select isnt working when you click on that side, I had to hack it by putting in : -

var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

but I would prefer for it to select properly and then allow all the drag drop stuff to work.

Cheers

lukefowell89
15 Dec 2010, 2:11 AM
Ok, there is alot of code to look at though.....

Here it is!

The LockingTreeGrid Ext:


Ext.namespace('Ext.ux.lf');

Ext.ux.lf.AbstractTreeStore = Ext.extend(Ext.data.Store,
{
leaf_field_name : '_is_leaf',
page_offset : 0,
active_node : null,

constructor : function(config)
{
Ext.ux.lf.AbstractTreeStore.superclass.constructor.call(this, config);

if (!this.paramNames.active_node) {
this.paramNames.active_node = 'anode';
}

this.addEvents(
'beforeexpandnode',
'expandnode',
'expandnodefailed',
'beforecollapsenode',
'collapsenode',
'beforeactivenodechange',
'activenodechange'
);
},

remove : function(record)
{
if (record === this.active_node) {
this.setActiveNode(null);
}
this.removeNodeDescendants(record);
Ext.ux.lf.AbstractTreeStore.superclass.remove.call(this, record);
},

move : function(record, index)
{
var index = this.data.indexOf(record);
if(index > -1){
record.join(null);
this.data.removeAt(index);
}
if(index > -1){
this.fireEvent('remove', this, record, index);
}
this.insert(index, record);

},

subtractFromAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current - value).toFixed(2) + "'");
});
}
});
},

addToAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current + value).toFixed(2) + "'");
});
}
});
},

clearFieldsInRec : function(rec)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
rec.set(key, 0.00);
}
});
},

copyToRec : function(rec, record)
{
var keys = this.fields.keys;

// copy values for all fields to rec
Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));
rec.set(key, value);
}
});
},

removeNodeDescendants : function(rc)
{
var i, len, children = this.getNodeChildren(rc);
for (i = 0, len = children.length; i < len; i++) {
this.remove(children[i]);
}
},

load : function(options)
{
if (options) {
if (options.params) {
if (options.params[this.paramNames.active_node] === undefined) {
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options.params = {};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options = {params: {}};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}

if (options.params[this.paramNames.active_node] !== null) {
options.add = true;
}

return Ext.ux.lf.AbstractTreeStore.superclass.load.call(this, options);
},

loadRecords : function(o, options, success)
{
if (!o || success === false) {
if (success !== false) {
this.fireEvent("load", this, [], options);
}
if (options.callback) {
options.callback.call(options.scope || this, [], options, false);
}
return;
}

var r = o.records, t = o.totalRecords || r.length,
page_offset = this.getPageOffsetFromOptions(options),
loaded_node_id = this.getLoadedNodeIdFromOptions(options),
loaded_node, i, len, prev_record, record, idx, updated, self = this;

if (!options || options.add !== true/* || loaded_node_id === null*/) {
if (this.pruneModifiedRecords) {
this.modified = [];
}
for (var i = 0, len = r.length; i < len; i++) {
r[i].join(this);
}
if (this.snapshot) {
this.data = this.snapshot;
delete this.snapshot;
}
this.data.clear();
this.data.addAll(r);
this.page_offset = page_offset;
this.totalLength = t;
this.applySort();
this.fireEvent("datachanged", this);
}
else {
if (loaded_node_id) {
loaded_node = this.getById(loaded_node_id);
}
if (loaded_node) {
this.setNodeLoaded(loaded_node, true);
this.setNodeChildrenOffset(loaded_node, page_offset);
this.setNodeChildrenTotalCount(loaded_node, Math.max(t, r.length));
this.removeNodeDescendants(loaded_node);
}
this.suspendEvents();
updated = {};
for (i = 0, len = r.length; i < len; i++) {
record = r[i];
idx = this.indexOfId(record.id);
if (idx == -1) {
updated[record.id] = false;
this.add(record);
}
else {
updated[record.id] = true;
prev_record = this.getAt(idx);
prev_record.reject();
prev_record.data = record.data;
r[i] = prev_record;
}
}
this.applySort();
this.resumeEvents();

r.sort(function(r1, r2) {
var idx1 = self.data.indexOf(r1),
idx2 = self.data.indexOf(r2),
result;

if (idx1 > idx2) {
result = 1;
}
else {
result = -1;
}
return result;
});

for (i = 0, len = r.length; i < len; i++) {
record = r[i];
if (updated[record.id] == true) {
this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
}
else {
this.fireEvent("add", this, [record], this.data.indexOf(record));
}
}
}
this.fireEvent("load", this, r, options);
if (options.callback) {
options.callback.call(options.scope || this, r, options, true);
}
},

sort : function(fieldName, dir)
{
if (this.remoteSort) {
this.setActiveNode(null);
if (this.lastOptions) {
this.lastOptions.add = false;
if (this.lastOptions.params) {
this.lastOptions.params[this.paramNames.active_node] = null;
}
}
}

return Ext.ux.lf.AbstractTreeStore.superclass.sort.call(this, fieldName, dir);
},

applySort : function()
{
if(this.sortInfo && !this.remoteSort){
var s = this.sortInfo, f = s.field;
this.sortData(f, s.direction);
}
else {
this.applyTreeSort();
}
},

sortData : function(f, direction)
{
direction = direction || 'ASC';
var st = this.fields.get(f).sortType;
var fn = function(r1, r2){
var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
};
this.data.sort(direction, fn);
if(this.snapshot && this.snapshot != this.data){
this.snapshot.sort(direction, fn);
}
this.applyTreeSort();
},

applyTreeSort : function()
{
var i, len, temp,
rec, records = [],
roots = this.getRootNodes();

for (i = 0, len = roots.length; i < len; i++) {
rec = roots[i];
records.push(rec);
this.collectNodeChildrenTreeSorted(records, rec);
}

if (records.length > 0) {
this.data.clear();
this.data.addAll(records);
}

if (this.snapshot && this.snapshot !== this.data) {
temp = this.data;
this.data = this.snapshot;
this.snapshot = null;
this.applyTreeSort();
this.snapshot = this.data;
this.data = temp;
}
},

collectNodeChildrenTreeSorted : function(records, rec)
{
var i, len,
child,
children = this.getNodeChildren(rec);

for (i = 0, len = children.length; i < len; i++) {
child = children[i];
records.push(child);
this.collectNodeChildrenTreeSorted(records, child);
}
},

getActiveNode : function()
{
return this.active_node;
},

setActiveNode : function(rc)
{
if (this.active_node !== rc) {
if (rc) {
if (this.data.indexOf(rc) != -1) {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
else {
throw "Given record is not from the store.";
}
}
else {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
}
},

isExpandedNode : function(rc)
{
return rc.ux_maximgb_tg_expanded === true;
},

setNodeExpanded : function(rc, value)
{
rc.ux_maximgb_tg_expanded = value;
},

isVisibleNode : function(rc)
{
var i, len,
ancestors = this.getNodeAncestors(rc),
result = true;

for (i = 0, len = ancestors.length; i < len; i++) {
result = result && this.isExpandedNode(ancestors[i]);
if (!result) {
break;
}
}
return result;
},

isLeafNode : function(rc)
{
return rc.get(this.leaf_field_name) == true;
},

isLoadedNode : function(rc)
{
var result;

if (rc.ux_maximgb_tg_loaded !== undefined) {
result = rc.ux_maximgb_tg_loaded;
}
else if (this.isLeafNode(rc) || this.hasChildNodes(rc)) {
result = true;
}
else {
result = false;
}

return result;
},

setNodeLoaded : function(rc, value)
{
rc.ux_maximgb_tg_loaded = value;
},

getNodeChildrenOffset : function(rc)
{
return rc.ux_maximgb_tg_offset || 0;
},

setNodeChildrenOffset : function(rc, value)
{
rc.ux_maximgb_tg_offset = value;
},

getNodeChildrenTotalCount : function(rc)
{
return rc.ux_maximgb_tg_total || 0;
},

setNodeChildrenTotalCount : function(rc, value)
{
rc.ux_maximgb_tg_total = value;
},

collapseNode : function(rc)
{
if (
this.isExpandedNode(rc) &&
this.fireEvent('beforecollapsenode', this, rc) !== false
) {
this.setNodeExpanded(rc, false);
this.fireEvent('collapsenode', this, rc);
}
},

expandNode : function(rc)
{
var params;
if (!this.isExpandedNode(rc) && this.fireEvent('beforeexpandnode', this, rc) !== false)
{
if (this.isLoadedNode(rc))
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
else if(this.getNodeChildrenCount(rc) == 0)
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
}
},

expandAll : function()
{

var r, i, len, records = this.data.getRange();
this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (!this.isExpandedNode(r)) {
this.expandNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

collapseAll : function()
{
var r, i, len, records = this.data.getRange();

this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (this.isExpandedNode(r)) {
this.collapseNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

getLoadedNodeIdFromOptions : function(options)
{
var result = null;
if (options && options.params && options.params[this.paramNames.active_node]) {
result = options.params[this.paramNames.active_node];
}
return result;
},

getPageOffsetFromOptions : function(options)
{
var result = 0;
if (options && options.params && options.params[this.paramNames.start]) {
result = parseInt(options.params[this.paramNames.start], 10);
if (isNaN(result)) {
result = 0;
}
}
return result;
},

hasNextSiblingNode : function(rc)
{
return this.getNodeNextSibling(rc) !== null;
},

hasPrevSiblingNode : function(rc)
{
return this.getNodePrevSibling(rc) !== null;
},

hasChildNodes : function(rc)
{
return this.getNodeChildrenCount(rc) > 0;
},

getNodeAncestors : function(rc)
{
var ancestors = [],
parent;

parent = this.getNodeParent(rc);
while (parent) {
ancestors.push(parent);
parent = this.getNodeParent(parent);
}

return ancestors;
},

getNodeChildrenCount : function(rc)
{
return this.getNodeChildren(rc).length;
},

getNodeNextSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);

if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);

if (index < siblings.length - 1) {
result = siblings[index + 1];
}

return result;
},

getNodePrevSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);
if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);
if (index > 0) {
result = siblings[index - 1];
}

return result;
},

getRootNodes : function()
{
throw 'Abstract method call';
},

getNodeDepth : function(rc)
{
throw 'Abstract method call';
},

getNodeParent : function(rc)
{
throw 'Abstract method call';
},

getNodeChildren : function(rc)
{
throw 'Abstract method call';
},

addToNode : function(parent, child)
{
throw 'Abstract method call';
},

removeFromNode : function(parent, child)
{
throw 'Abstract method call';
},

getPageOffset : function()
{
return this.page_offset;
},

getActiveNodePageOffset : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenOffset(this.active_node);
}
else {
result = this.getPageOffset();
}

return result;
},

getActiveNodeCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenCount(this.active_node);
}
else {
result = this.getRootNodes().length;
}

return result;
},

getActiveNodeTotalCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenTotalCount(this.active_node);
}
else {
result = this.getTotalCount();
}

return result;
}
});


Ext.ux.lf.LockingTreeGridStore = Ext.extend(Ext.ux.lf.AbstractTreeStore,
{
parent_id_field_name : '_parent',

getRootNodes : function()
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == null) {
result.push(records[i]);
}
}

return result;
},

getNodeDepth : function(rc)
{
return this.getNodeAncestors(rc).length;
},

getNodeParent : function(rc)
{
return this.getById(rc.get(this.parent_id_field_name));
},

getNodeChildren : function(rc)
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == rc.id) {
result.push(records[i]);
}
}

return result;
},

addToNode : function(parent, child)
{
child.set(this.parent_id_field_name, parent.id);
this.addSorted(child);
},

removeFromNode : function(parent, child)
{
this.remove(child);
}
});

Ext.ux.lf.LockingTreeGridView = Ext.extend(Ext.grid.GridView,
{
expanded_icon_class : 'ux-maximgb-tg-elbow-minus',
collapsed_icon_class : 'ux-maximgb-tg-elbow-plus',

last_expanded_icon_class : 'ux-maximgb-tg-elbow-end-minus',
last_collapsed_icon_class : 'ux-maximgb-tg-elbow-end-plus',

nl_expanded_icon_class : 'ux-maximgb-tg-nl-minus',
nl_collapsed_icon_class : 'ux-maximgb-tg-nl-plus',

skip_width_update_class: 'ux-maximgb-tg-skip-width-update',

expanded_folder_class : 'ux-maximgb-tg-expanded-folder',
collapsed_folder_class : 'ux-maximgb-tg-collapsed-folder',

lockText : 'Lock',
unlockText : 'Unlock',
rowBorderWidth : 1,
lockedBorderWidth : 1,

syncHeights: false,

initTemplates : function()
{
var ts = this.templates || {};


if (!ts.masterTpl) {
ts.masterTpl = 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" style="{lstyle}">{lockedHeader}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{lstyle}">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
'</div>',
'<div class="x-grid3-viewport x-grid3-unlocked">',
'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{mainbody}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
'</div>',
'<div class="x-grid3-resize-marker">&#160;</div>',
'<div class="x-grid3-resize-proxy">&#160;</div>',
'</div>'
);
}

if (!ts.row) {
ts.row = new Ext.Template(
'<div class="x-grid3-row ux-maximgb-tg-level-{level} ux-maximgb-tg-border {alt}" style="{tstyle} {display_style}">',
'<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
'<tbody>',
'<tr>{cells}</tr>',
(
this.enableRowBody ?
'<tr class="x-grid3-row-body-tr" style="{bodyStyle}">' +
'<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">'+
'<div class="x-grid3-row-body">{body}</div>'+
'</td>'+
'</tr>'
:
''
),
'</tbody>',
'</table>',
'</div>'
);
}


if (!ts.mastercell) {
ts.mastercell = new Ext.Template(
'<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
'<div class="ux-maximgb-tg-mastercell-wrap">', // This is for editor to place itself right
'{treeui}',
'<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr} style="padding-top:3px">{value}</div>',
'</div>',
'</td>'
);
}

if (!ts.treeui) {
ts.treeui = new Ext.Template(
'<div class="ux-maximgb-tg-uiwrap" style="width: {wrap_width}px">',
'{elbow_line}',
'<div style="left: {left}px" class="{cls}">&#160;</div>',
'</div>'
);
}

if (!ts.elbow_line) {
ts.elbow_line = new Ext.Template(
'<div style="left: {left}px;" class="{cls}"></div>'
);
}

this.templates = ts;
Ext.ux.lf.LockingTreeGridView.superclass.initTemplates.call(this);
},

initElements : function(){
var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
scroller = mainWrap.child('div.x-grid3-scroller');

if (this.grid.hideHeaders) {
lockedHd.setDisplayed(false);
mainHd.setDisplayed(false);
}

if(this.forceFit){
scroller.setStyle('overflow-x', 'hidden');
}

Ext.apply(this, {
el : el,
mainWrap: mainWrap,
mainHd : mainHd,
innerHd : mainHd.dom.firstChild,
scroller: scroller,
mainBody: scroller.child('div.x-grid3-body'),
focusEl : scroller.child('a'),
resizeMarker: el.child('div.x-grid3-resize-marker'),
resizeProxy : el.child('div.x-grid3-resize-proxy'),
lockedWrap: lockedWrap,
lockedHd: lockedHd,
lockedScroller: lockedScroller,
lockedBody: lockedScroller.child('div.x-grid3-body'),
lockedInnerHd: lockedHd.child('div.x-grid3-header-inner', true)
});


this.focusEl.swallowEvent('click', true);
},

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

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

getCell : function(row, col){
if(col < 1){
return this.getLockedRow(row).getElementsByTagName('td')[col];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getCell.call(this, row, col - lockedLen);
},

getHeaderCell : function(index){
var lockedLen = 1;
if(index < lockedLen){
return this.lockedHd.dom.getElementsByTagName('td')[index];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getHeaderCell.call(this, index - lockedLen);
},

addRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).addClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.addRowClass.call(this, row, cls);
},

removeRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).removeClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRowClass.call(this, row, cls);
},

removeRow : function(row) {
Ext.removeNode(this.getLockedRow(row));
Ext.ux.lf.LockingTreeGridView.superclass.removeRow.call(this, row);
},

removeRows : function(firstRow, lastRow){
var lockedBody = this.lockedBody.dom,
rowIndex = firstRow;
for(; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(lockedBody.childNodes[firstRow]);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRows.call(this, firstRow, lastRow);
},

syncScroll : function(e){
this.lockedScroller.dom.scrollTop = this.scroller.dom.scrollTop;
Ext.ux.lf.LockingTreeGridView.superclass.syncScroll.call(this, e);
},

updateSortIcon : function(col, dir){
var sortClasses = this.sortClasses,
lockedHeaders = this.lockedHd.select('td').removeClass(sortClasses),
headers = this.mainHd.select('td').removeClass(sortClasses),
lockedLen = 1,
cls = sortClasses[dir == 'DESC' ? 1 : 0];

if(col < lockedLen){
lockedHeaders.item(col).addClass(cls);
}else{
headers.item(col - lockedLen).addClass(cls);
}
},

updateAllColumnWidths : function(){
var tw = this.getTotalWidth(),
clen = this.cm.getColumnCount(),
lw = this.getLockedWidth(),
llen = 1,
widths = [], len, i;
for(i = 0; i < clen; i++)
{
widths[i] = this.getColumnWidth(i);
var hd = this.getHeaderCell(i);
hd.style.width = widths[i];
}
var lns = this.getLockedRows(), ns = this.getRows(), row, trow, j;
for(i = 0, len = ns.length; i < len; i++)
{
row = lns[i];
row.style.width = lw;
if(row.firstChild)
{
row.firstChild.style.width = lw;
trow = row.firstChild.rows[0];
trow.childNodes[0].style.width = widths[0];

}
row = ns[i];
row.style.width = tw;
if(row.firstChild)
{
row.firstChild.style.width = tw;
trow = row.firstChild.rows[0];
for (j = llen; j < clen; j++)
{
trow.childNodes[j - llen].style.width = widths[j];
}
}
}
this.onAllColumnWidthsUpdated(widths, tw);
//this.syncHeaderHeight();
},

updateColumnWidth : function(col, width){
var w = this.getColumnWidth(col),
llen = 1,
ns, rw, c, row;
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.width = w;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.width = w;
}
}
this.onColumnWidthUpdated(col, w, this.getTotalWidth());
//this.syncHeaderHeight();
},

updateColumnHidden : function(col, hidden){
var llen = this.cm.getLockedCount(),
ns, rw, c, row,
display = hidden ? 'none' : '';
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.display = display;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.display = display;
}
}
this.onColumnHiddenUpdated(col, hidden, this.getTotalWidth());
delete this.lastViewWidth;
this.layout();
},

doRender: function(columns, records, store, startRow, colCount, stripe){

var templates = this.templates;
var cell_template = templates.mastercell;
var cell_template2 = templates.cell;
var row_template = templates.row;
var last = colCount-1;
var tstyle = 'width:'+this.getTotalWidth()+';';
var lstyle = 'width:'+this.getLockedWidth()+';';
var buffer = [];
var locked_buffer = [];
var column_buffer = [];
var locked_column_buffer = [];
var column;
var params = {};
var row_params = {};
var record;


for (var x = 0, len = records.length; x < len; x++) {
record = records[x];
column_buffer = [];
locked_column_buffer = [];

this.store.setNodeExpanded(record, true);

var rowIndex = x + startRow;
var row_render_res = this.renderRow(record, rowIndex, colCount, store, this.cm.getTotalWidth());

if (row_render_res === false) {
for (var i = 0; i < colCount; i++) {

column = columns[i];
params.id = column.id;
params.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
params.attr = params.cellAttr = "";
params.value = column.renderer.call(column.scope, record.data[column.name], params, record, rowIndex, i, store);
params.style = column.style;

if (Ext.isEmpty(params.value)) {
params.value = "&#160;";
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] !== 'undefined') {
params.css += ' x-grid3-dirty-cell';
}

if (column.id == this.grid.master_column_id) {
params.treeui = this.renderCellTreeUI(record, store);
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
else {
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
if (column.id == this.grid.master_column_id) {
locked_column_buffer[locked_column_buffer.length] = cell_template.apply(params);
}
else {
column_buffer[column_buffer.length] = cell_template2.apply(params);
}

}
}
else {
column_buffer.push(row_render_res);
}

var alt = [];
if (stripe && ((rowIndex + 1) % 2 == 0)) {
alt[0] = "x-grid3-row-alt";
}
if (record.dirty) {
alt[1] = " x-grid3-dirty-row";
}
row_params.cols = colCount;
if (this.getRowClass) {
alt[2] = this.getRowClass(r, rowIndex, rp, store);
}

row_params.alt = alt.join(" ");
row_params.cells = locked_column_buffer.join("");
row_params.lstyle = lstyle;
locked_buffer[locked_buffer.length] = row_template.apply(row_params);

row_params.cells = column_buffer.join("");
row_params.tstyle = tstyle;
buffer[buffer.length] = row_template.apply(row_params);

}
return [buffer.join(""),locked_buffer.join("")];

},



renderCellTreeUI : function(record, store)
{
var template = this.templates.treeui,
line_template = this.templates.elbow_line,
template_data = {},
rec, parent,
depth = level = store.getNodeDepth(record);
template_data.elbow_line = '';
rec = record;
left = 0;

if (store.isLeafNode(rec))
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-item'
});
}
else
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-expanded-folder'
});
}

template_data.wrap_width = (depth + 1) * 16 + 16;
if (level > 0) {

while(level--) {
parent = store.getNodeParent(rec);
if (parent) {
if (store.hasNextSiblingNode(parent)) {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-line',
}) +
template_data.elbow_line;
}
else {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-empty',
}) +
template_data.elbow_line;
}
}
else {
throw [
"Tree inconsistency can't get level ",
level + 1,
" node(id=", rec.id, ") parent."
].join("");
}
rec = parent;
}
}
if (store.isLeafNode(record)) {
if (store.hasNextSiblingNode(record)) {
template_data.cls = 'ux-maximgb-tg-elbow';
}
else {
template_data.cls = 'ux-maximgb-tg-elbow-end';
}
}
else {

template_data.cls = 'ux-maximgb-tg-elbow-active ';

if (store.isExpandedNode(record)) {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.expanded_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_expanded_icon_class;
} else {
template_data.cls += this.nl_expanded_icon_class;
}
}
else {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.collapsed_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_collapsed_icon_class;
} else {
template_data.cls += this.nl_collapsed_icon_class;
}
}
}
template_data.left = 1 + depth * 16;
return template.apply(template_data);
},

renderRow : function(record, index, col_count, store, total_width)
{
return false;
},

afterRender : function()
{
if(!this.store || !this.cm){
return;
}
var body = this.renderRows() || ['&#160;', '&#160;'];

this.mainBody.dom.innerHTML = body[0];
this.lockedBody.dom.innerHTML = body[1];
this.processRows(0, true);
if(this.deferEmptyText !== true){
this.applyEmptyText();
}
this.grid.fireEvent('viewready', this.grid);
this.updateAllColumnWidths();
},

renderUI : function()
{
var templates = this.templates,
header = this.renderHeaders(),
body = templates.body.apply({rows:'&#160;'});


return templates.masterTpl.apply({
mainbody : body[0],
header: header[0],
ostyle: 'width:' + this.getOffsetWidth() + ';',
bstyle: 'width:' + this.getTotalWidth() + ';',
lockedBody: body[1],
lockedHeader: header[1],
lstyle: 'width:'+this.getLockedWidth()+';'
});
},

getOffsetWidth : function()
{
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0) + this.getScrollOffset()) + 'px';
},

afterRenderUI: function()
{
var grid = this.grid;
this.initElements();
Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
Ext.fly(this.lockedInnerHd).on('click', this.handleHdDown, this);
this.mainHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.lockedHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.scroller.on('scroll', this.syncScroll, this);
if(grid.enableColumnResize !== false){
this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
this.splitZone2 = new Ext.grid.GridView.SplitDragZone(grid, this.lockedHd.dom);
this.splitZone2.setOuterHandleElId(Ext.id(this.lockedHd.dom));
this.splitZone.setOuterHandleElId(Ext.id(this.mainHd.dom));
}
if(grid.enableColumnMove){
this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
this.columnDrag2 = new Ext.grid.GridView.ColumnDragZone(grid, this.lockedInnerHd);
this.columnDrag2.setOuterHandleElId(Ext.id(this.lockedInnerHd));
this.columnDrag.setOuterHandleElId(Ext.id(this.innerHd));
this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
}
if(grid.enableHdMenu !== false){
this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
this.hmenu.add(
{itemId: 'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
{itemId: 'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
);

if(grid.enableColumnHide !== false){
this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
this.colMenu.on({
scope: this,
beforeshow: this.beforeColMenuShow,
itemclick: this.handleHdMenuClick
});
this.hmenu.add('-', {
itemId:'columns',
hideOnClick: false,
text: this.columnsText,
menu: this.colMenu,
iconCls: 'x-cols-icon'
});
}
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
}
if(grid.trackMouseOver){
this.mainBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
this.lockedBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
}

if(grid.enableDragDrop || grid.enableDrag){
this.dragZone = new Ext.grid.GridDragZone(grid, {
ddGroup : grid.ddGroup || 'GridDD'
});
}
this.updateHeaderSortState();
},

layout : function(){
if(!this.mainBody){
return;
}
var grid = this.grid;
var grid_el = grid.getGridEl();
var cell_size = grid_el.getSize(true);
if(!grid.hideHeaders && (cell_size.width < 20 || cell_size.height < 20)){
return;
}

if(grid.autoHeight){
this.scroller.dom.style.overflow = 'visible';
this.lockedScroller.dom.style.overflow = 'visible';
if(Ext.isWebKit){
this.scroller.dom.style.position = 'static';
this.lockedScroller.dom.style.position = 'static';
}
}else{
this.el.setSize(cell_size.width, cell_size.height);
var hdHeight = this.mainHd.getHeight();
var cell_height = cell_size.height - (hdHeight);
}
this.updateLockedWidth();
if(this.forceFit){
if(this.lastViewWidth != cell_size.width){
this.fitColumns(false, false);
this.lastViewWidth = cell_size.width;
}
}else {
this.autoExpand();
this.syncHeaderScroll();
}
this.onLayout(cell_size.width, cell_height);
},

renderHeaders : function()
{
var column_model = this.cm,
templates = this.templates,
ct = templates.hcell,
cb = [], locked_cb = [],
params = {},
len = column_model.getColumnCount(),
last = len - 1;
for(var i = 0; i < len; i++)
{
params.id = column_model.getColumnId(i);
params.value = column_model.getColumnHeader(i) || '';
params.style = this.getColumnStyle(i, true);
params.tooltip = this.getColumnTooltip(i);
params.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
(column_model.config[i].headerCls ? ' ' + column_model.config[i].headerCls : '');
if(column_model.config[i].align == 'right'){
params.istyle = 'padding-right:16px';
} else {
delete params.istyle;
}
if(i == 0)
{
locked_cb[locked_cb.length] = ct.apply(params);
}
else
{
cb[cb.length] = ct.apply(params);
}
}
return [templates.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'}),
templates.header.apply({cells: locked_cb.join(''), tstyle:'width:'+this.getLockedWidth()+';'})];
},

updateHeaders : function()
{
var header = this.renderHeaders();
this.innerHd.firstChild.innerHTML = header[0];
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
this.lockedInnerHd.firstChild.innerHTML = header[1];
var locked_width = this.getLockedWidth();
this.lockedInnerHd.firstChild.style.width = locked_width;
this.lockedInnerHd.firstChild.firstChild.style.width = locked_width;
},

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

syncFocusEl : function(row, col, hscroll){
Ext.ux.lf.LockingTreeGridView.superclass.syncFocusEl.call(this, row, col, col < 1 ? false : hscroll);
},
/*
updateAllColumnWidths : function()
{
var total_width = this.getTotalWidth(),
column_length = this.cm.getColumnCount(),
widths = [],
length,
i;
for(i = 0; i < column_length; i++){
widths[i] = this.getColumnWidth(i);
}
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
for(i = 0; i < column_length; i++){
var header = this.getHeaderCell(i);
header.style.width = widths[i];
}

var rows = this.getRows(), row, trow;
for(i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
total_row = row.firstChild.rows[0];
for (var j = 0; j < column_length && j < total_row.childNodes.length; j++) {
if (!Ext.fly(total_row.childNodes[j]).hasClass(this.skip_width_update_class)) {
total_row.childNodes[j].style.width = widths[j];
}
}
}
}

this.onAllColumnWidthsUpdated(widths, total_width);
},

updateColumnWidth : function(col, width)
{
var col_width = this.getColumnWidth(col);
var total_width = this.getTotalWidth();

this.lockedInnerHd.firstChild.style.width = this.getOffsetWidth();
this.lockedInnerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var header = this.getHeaderCell(col);
header.style.width = col_width;

var rows = this.getRows(), row;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.width = col_width;
}
}
}
}

this.onColumnWidthUpdated(col, col_width, total_width);
},

updateColumnHidden : function(col, hidden)
{
var total_width = this.getTotalWidth();
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var display = hidden ? 'none' : '';

var header = this.getHeaderCell(col);
header.style.display = display;

var rows = this.getRows(), row, cell;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.display = display;
}
}
}
}

this.onColumnHiddenUpdated(col, hidden, total_width);
delete this.lastViewWidth; // force recalc
this.layout();
},
*/
processRows : function(startRow, skipStripe)
{
if(!this.store || this.store.getCount() < 1){
return;
}

var rows = this.getRows(),
locked_rows = this.getLockedRows(),
row, locked_row;
var processed_count = 0;

skipStripe = !this.grid.stripeRows;
startRow = startRow || 0;

for(var i = 0, len = rows.length; i < len; ++i){
row = rows[i];
locked_row = locked_rows[i];
row.rowIndex = i;
locked_row.rowIndex = i;

if(!skipStripe){
row.className = row.className.replace(this.rowClsRe, ' ');
locked_row.className = locked_row.className.replace(this.rowClsRe, ' ');
if ((i + 1) % 2 === 0){
row.className += ' x-grid3-row-alt';
locked_row.className += ' x-grid3-row-alt';
}
}
this.syncRowHeights(row, locked_row);
}

if(startRow === 0){
Ext.fly(rows[0]).addClass(this.firstRowCls);
Ext.fly(locked_rows[0]).addClass(this.firstRowCls);
}
Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
Ext.fly(locked_rows[locked_rows.length - 1]).addClass(this.lastRowCls);
},

ensureVisible : function(row, col, hscroll)
{
var ancestors, record = this.store.getAt(row);
if (!this.store.isVisibleNode(record))
{
ancestors = this.store.getNodeAncestors(record);

while (ancestors.length > 0)
{
record = ancestors.shift();

if (!this.store.isExpandedNode(record))
{
this.store.expandNode(record);
}
}
}
return Ext.ux.lf.LockingTreeGridView.superclass.ensureVisible.call(this, row, col, col < 1 ? false : hscroll);

},

expandRow : function(record, skip_process)
{
var store = this.store,
i, len, row, locked_row, pmel, lpmel, children, index, child_index;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');

if (pmel) {
pmel.removeClass(this.collapsed_icon_class);
pmel.removeClass(this.last_collapsed_icon_class);
pmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_expanded_icon_class);
} else {
pmel.addClass(this.nl_expanded_icon_class);
}
}

if (lpmel) {
lpmel.removeClass(this.collapsed_icon_class);
lpmel.removeClass(this.last_collapsed_icon_class);
lpmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_expanded_icon_class);
} else {
lpmel.addClass(this.nl_expanded_icon_class);
}
}

pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');

lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');

if (pmel) {
pmel.removeClass(this.collapsed_folder_class);
pmel.addClass(this.expanded_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.collapsed_folder_class);
lpmel.addClass(this.expanded_folder_class);
}
if (store.isVisibleNode(record)) {
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
row.style.display = 'block';
locked_row.style.display = 'block';

if (store.isExpandedNode(children[i])) {
this.expandRow(child_index, true);
}
}
}
if (!skip_process) {
this.processRows(0);
}
},

collapseRow : function(record, skip_process)
{
var store = this.store,
i, len, children, row, locked_row, index, child_index, pmel, lpmel;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');
if (pmel) {
pmel.removeClass(this.expanded_icon_class);
pmel.removeClass(this.last_expanded_icon_class);
pmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_collapsed_icon_class);
} else {
pmel.addClass(this.nl_collapsed_icon_class);
}
}
if (lpmel) {
lpmel.removeClass(this.expanded_icon_class);
lpmel.removeClass(this.last_expanded_icon_class);
lpmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_collapsed_icon_class);
} else {
lpmel.addClass(this.nl_collapsed_icon_class);
}
}
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');
if (pmel) {
pmel.removeClass(this.expanded_folder_class);
pmel.addClass(this.collapsed_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.expanded_folder_class);
lpmel.addClass(this.collapsed_folder_class);
}
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
if (row.style.display != 'none') {
row.style.display = 'none';
this.collapseRow(child_index, true);
}
if (locked_row.style.display != 'none') {
locked_row.style.display = 'none';
this.collapseRow(child_index, true);
}
}
if (!skip_process) {
this.processRows(0);
}
},

initData : function(store, column_model)
{
if(this.cm){
this.cm.un('columnlockchange', this.onColumnLock, this);
}
this.store = this.ds = store;
Ext.ux.lf.LockingTreeGridView.superclass.initData.call(this, store, column_model);
if (this.store) {
this.store.un('expandnode', this.onStoreExpandNode, this);
this.store.un('collapsenode', this.onStoreCollapseNode, this);
}
if (store) {
store.on('expandnode', this.onStoreExpandNode, this);
store.on('collapsenode', this.onStoreCollapseNode, this);
}
if(this.cm){
this.cm.on('columnlockchange', this.onColumnLock, this);
}
},

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

handleHdMenuClick : function(item)
{
var index = this.hdCtxIndex,
cm = this.cm,
id = item.getItemId()
switch(id){
default:
return Ext.ux.lf.LockingTreeGridView.superclass.handleHdMenuClick.call(this, item);
}
return true;
},

handleHdDown : function(e, t)
{
Ext.ux.lf.LockingTreeGridView.superclass.handleHdDown.call(this, e, t);
if(this.grid.enableColLock !== false){
if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
var hd = this.findHeaderCell(t),
index = this.getCellIndex(hd),
ms = this.hmenu.items, cm = this.cm;
}
}
},

onLoad : function(store, records, options)
{
var ridx;
if (
options &&
options.params &&
(
options.params[store.paramNames.active_node] === null ||
store.indexOfId(options.params[store.paramNames.active_node]) == -1
)
) {
Ext.ux.lf.LockingTreeGridView.superclass.onLoad.call(this, store, records, options);
}
},

onAdd : function(store, records, index)
{
Ext.ux.lf.LockingTreeGridView.superclass.onAdd.call(this, store, records, index);
if (this.mainWrap) {
this.processRows(0);
}
},

onRemove : function(store, record, index, isUpdate)
{
Ext.ux.lf.LockingTreeGridView.superclass.onRemove.call(this, store, record, index, isUpdate);
if(isUpdate !== true){
if (this.mainWrap) {
this.processRows(0);
}
}
},

onUpdate : function(store, record)
{
Ext.ux.lf.LockingTreeGridView.superclass.onUpdate.call(this, store, record);
if (this.mainWrap) {
this.processRows(0);
}
},

onStoreExpandNode : function(store, record)
{
this.expandRow(record);
},

onStoreCollapseNode : function(store, record)
{
this.collapseRow(record);
},

getColumnStyle : function(col, isHeader)
{
var style = !isHeader ? this.cm.config[col].cellStyle || this.cm.config[col].css || '' : this.cm.config[col].headerStyle || '';
style += 'width:'+this.getColumnWidth(col)+';';
if(this.cm.isHidden(col)){
style += 'display:none;';
}
var align = this.cm.config[col].align;
if(align){
style += 'text-align:'+align+';';
}
return style;
},

getLockedWidth : function() {
return this.cm.getColumnWidth(0) + 'px';
},

getTotalWidth : function() {
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0)) + 'px';
},

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 : (!Ext.isDefined(name) ? this.store.fields.get(i).name : name),
renderer : cm.getRenderer(i),
id : cm.getColumnId(i),
style : this.getColumnStyle(i),
locked : i == 0 ? true : false
};
}
return cs;
},

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

refreshRow: function(record){
var store = this.store,
colCount = this.cm.getColumnCount(),
columns = this.getColumnData(),
last = colCount - 1,
cls = ['x-grid3-row'],
rowParams = {
tstyle: String.format("width: {0};", this.getTotalWidth())
},
lockedRowParams = {
tstyle: String.format("width: {0};", this.getLockedWidth())
},
colBuffer = [],
lockedColBuffer = [],
cellTpl = this.templates.cell,
rowIndex,
row,
lockedRow,
column,
meta,
css,
i;

if (Ext.isNumber(record)) {
rowIndex = record;
record = store.getAt(rowIndex);
} else {
rowIndex = store.indexOf(record);
}

if (!record || rowIndex < 0) {
return;
}

for (i = 0; i < colCount; i++) {
column = columns[i];

if (i == 0) {
css = 'x-grid3-cell-first';
} else {
css = (i == last) ? 'x-grid3-cell-last ' : '';
}

meta = {
id: column.id,
style: column.style,
css: css,
attr: "",
cellAttr: ""
};

meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);

if (Ext.isEmpty(meta.value)) {
meta.value = ' ';
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
meta.css += ' x-grid3-dirty-cell';
}

if (column.locked) {
lockedColBuffer[i] = cellTpl.apply(meta);
} else {
colBuffer[i] = cellTpl.apply(meta);
}
}

row = this.getRow(rowIndex);
row.className = '';
lockedRow = this.getLockedRow(rowIndex);
lockedRow.className = '';

if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
cls.push('x-grid3-row-alt');
}

if (this.getRowClass) {
rowParams.cols = colCount;
cls.push(this.getRowClass(record, rowIndex, rowParams, store));
}

// Unlocked rows
this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
rowParams.cells = colBuffer.join("");
row.innerHTML = this.templates.rowInner.apply(rowParams);

// Locked rows
this.fly(lockedRow).addClass(cls).setStyle(lockedRowParams.tstyle);
lockedRowParams.cells = lockedColBuffer.join("");
lockedRow.innerHTML = this.templates.rowInner.apply(lockedRowParams);
lockedRow.rowIndex = rowIndex;
this.syncRowHeights(row, lockedRow);
this.fireEvent('rowupdated', this, rowIndex, record);
},

syncRowHeights: function(row1, row2){
if(this.syncHeights){
var el1 = Ext.get(row1),
el2 = Ext.get(row2),
h1 = el1.getHeight(),
h2 = el2.getHeight();

if(h1 > h2){
el2.setHeight(h1);
}else if(h2 > h1){
el1.setHeight(h2);
}
}
},

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

updateLockedWidth: function()
{
var lw = this.cm.getColumnWidth(0),
tw = this.cm.getTotalWidth() - lw,
csize = this.grid.getGridEl().getSize(true),
lp = Ext.isBorderBox ? 0 : this.lockedBorderWidth,
rp = Ext.isBorderBox ? 0 : this.rowBorderWidth,
vw = (csize.width - lw - lp - rp) + 'px',
so = this.getScrollOffset();
if(!this.grid.autoHeight)
{
var vh = (csize.height - this.mainHd.getHeight()) + 'px';
this.lockedScroller.dom.style.height = vh;
this.scroller.dom.style.height = vh;
}
this.lockedWrap.dom.style.width = (lw + rp) + 'px';
this.scroller.dom.style.width = vw;
this.mainWrap.dom.style.left = (lw + lp + rp) + 'px';
if(this.innerHd){
this.lockedInnerHd.firstChild.style.width = lw + 'px';
this.lockedInnerHd.firstChild.firstChild.style.width = lw + 'px';
this.innerHd.style.width = vw;
this.innerHd.firstChild.style.width = (tw + rp + so) + 'px';
this.innerHd.firstChild.firstChild.style.width = tw + 'px';
}
if(this.mainBody){
this.lockedBody.dom.style.width = (lw + rp) + 'px';
this.mainBody.dom.style.width = (tw + rp) + 'px';
}
}
});

Ext.ux.lf.LockingTreeGrid = Ext.extend(Ext.grid.GridPanel,
{
tg_cls : 'ux-maximgb-tg-panel',

constructor: function(config) {

Ext.ux.lf.LockingTreeGrid.superclass.constructor.call(this, config);
},

initComponent : function()
{
this.initComponentPreOverride();
Ext.ux.lf.LockingTreeGrid.superclass.initComponent.call(this);
this.getSelectionModel().on('selectionchange', this.onTreeGridSelectionChange, this);
this.initComponentPostOverride();
},

initComponentPreOverride : Ext.emptyFn,

initComponentPostOverride : Ext.emptyFn,

onRender : function(ct, position)
{
Ext.ux.lf.LockingTreeGrid.superclass.onRender.call(this, ct, position);
this.el.addClass(this.tg_cls);
},

getView : function()
{
if (!this.view) {
this.view = new Ext.ux.lf.LockingTreeGridView(this.viewConfig);
}
return this.view;
},

onClick : function(e)
{

var target = e.getTarget(),
view = this.getView(),
row = view.findRowIndex(target),
store = this.getStore(),
sm = this.getSelectionModel(),
record, record_id, do_default = true;

if (row !== false) {

if (Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {

record = store.getAt(row);

if (store.isExpandedNode(record)) {
store.collapseNode(record);
}
else {
store.expandNode(record);

}
do_default = false;
}
}

if (do_default) {
Ext.ux.lf.LockingTreeGrid.superclass.onClick.call(this, e);
}
},

onMouseDown : function(e)
{
var target = e.getTarget();

if (!Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {
Ext.ux.lf.LockingTreeGrid.superclass.onMouseDown.call(this, e);
}
},

onTreeGridSelectionChange : function(sm, selection)
{
var record, ancestors, store = this.getStore();

if (sm.getSelected) {
record = sm.getSelected();
store.setActiveNode(record);
}

else if (sm.getSelectedCell && selection) {
record = selection.record;
store.setActiveNode(record);
}

if (record) {
if (!store.isVisibleNode(record)) {
ancestors = store.getNodeAncestors(record);
while (ancestors.length > 0) {
store.expandNode(ancestors.pop());
}
}
}
}

});

Ext.reg('Ext.ux.lf.LockingTreeGrid', Ext.ux.lf.LockingTreeGrid);
Ext.reg('Ext.ux.lf.LockingTreeGridStore', Ext.ux.lf.LockingTreeGridStore);


Setting up the grid and drag and drop stuff:




dashboardTabSummaryGrid = Ext.extend(Ext.ibc.DynamicColumnGridPanel, {
constructor: function(config) {
config = Ext.apply({
border : false,
trackMouseOver : false,
bodyStyle : 'border-top: 0;',
parameterType : 1,
templateID : config.queryRecord.get('TemplateID'),
enableDragDrop : true,
ddGroup :'dashboardTabSummaryGridDropZone',
contextMenu : Ext.getCmp('dashboardTabSummaryMenu')
}, config);

dashboardTabSummaryGrid.superclass.constructor.call(this, config);
},

initComponent: function() {
dashboardTabSummaryGrid.superclass.initComponent.apply(this, arguments);

this.store.grid = this;

this.on('cellclick', this.onCellClick, this);
this.on('beforecontextmenu', this.onBeforeContextMenu, this);
this.on('columnmove', this.onColumnMove, this);
this.on('columnresize', this.onColumnResize, this);
this.on('rowclick', this.onRowSelect, this);
},

onRowSelect: function(grid, row, e)
{
this.selModel.selectRow(row);
},

onColumnMove: function(oldIndex, newIndex) {

var columns = this.getColumnModel().config;
var nodes = [];
Ext.each(columns,function(column){
if (column.id != "master")
nodes.push(column.id);
});

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: {
action: 'REORDER',
nodes: nodes.join(',')
},
failure : function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onColumnResize: function(columnIndex, newSize) {
},

onCellClick: function(grid, rowIndex, columnIndex, e) {
var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

var summaryGrid = grid;
var detailTab = Ext.getCmp(grid.queryRecord.get('TemplateID') + 'DETAILTAB');

var record = this.selModel.getSelected();

if (grid.store.isLeafNode(record)) {
var tabHeight = summaryGrid.ownerCt.container.getHeight();
var newHeight = tabHeight - (summaryGrid.store.data.length * 19) - 100;

if (newHeight < 300) newHeight = 300;

detailTab.makeVisible(newHeight, record.get('Heading'));
detailTab.loadData(record.get('UserRuleName'), this.queryRecord.get('DetailTemplateID'), record, grid.queryRecord.get('TemplateID'));
}
},

onBeforeContextMenu: function(menu, record, column, rowindex) {
if (record.get('_is_leaf') === false) {
menu.enableDates();
} else {
menu.disableDates();
}

if (rowindex) {
menu.enableDeleteRow();
} else {
menu.disableDeleteRow();
}

if (column) {
menu.enableEdit();
} else {
menu.disableEdit();
}

menu.configure();
menu.doLayout();
},

setColumnAlignment: function(alignement) {
columnModel = this.getColumnModel().config;
columnModel[this.selectedColumn].align = alignement;
this.getColumnModel().setConfig(columnModel);

var column = columnModel[this.selectedColumn];
var params = {
//templateid: this._templateid,
id: column.id,
action: 'UPDATE',
number: column.number,
heading: column.header,
negativecolor: column.negativeColor,
renderer: column.renderer,
//invert: column.invert,
//calccolumn1: this._calccolumn1.getValue(),
//calcoperator: this._calcoperator.getValue(),
//calccolumn2: this._calccolumn2.getValue(),
columnalign: column.align,
//columntype: this._columntype.getValue(),
symbol: column.symbol,
ruleparameter: column.tagname
};

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: params,
scope: this,
failure: function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onRender: function(grid) {
dashboardTabSummaryGrid.superclass.onRender.apply(this, arguments);

var dropZoneOverrides = {
ddGroup : 'dashboardTabSummaryGridDropZone',
onContainerOver : function(ddSrc, evtObj, ddData) {
var destGrid = this.grid;
var tgtEl = evtObj.getTarget();
var destIndex = destGrid.getView().findRowIndex(tgtEl);
var destStore = destGrid.store;

var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
lockedBody = lockedScroller.child('div.x-grid3-body'),
scroller = mainWrap.child('div.x-grid3-scroller');

this.clearDDStyles();

if (destIndex === false) return;


// if drag before first row
if (destIndex == 0) destIndex = 1;
destIndex = (destStore.getCount() == 1 ? 0 : destIndex);

// is this a row?
if (typeof destIndex === 'number') {
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);

var tgtRowEl = Ext.get(tgtRow);
var tgtLockedRowEl = Ext.get(tgtLockedRow);
var tgtRowHeight = tgtRowEl.getHeight();
var tgtRowTop = tgtRowEl.getY();
var tgtRowCtr = tgtRowTop + Math.floor(tgtRowHeight / 2);

var tgtLockedRowHeight = tgtLockedRowEl.getHeight();
var tgtLockedRowTop = tgtLockedRowEl.getY();
var tgtLockedRowCtr = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 2);
var mouseY = evtObj.getXY()[1];

var tgtRow1 = tgtRowEl.getY();
var tgtRow2 = tgtRowTop + Math.floor(tgtRowHeight / 3);
var tgtRow3 = tgtRowTop + (Math.floor(tgtRowHeight / 3) * 2);

var tgtLockedRow1 = tgtLockedRowEl.getY();
var tgtLockedRow2 = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 3);
var tgtLockedRow3 = tgtLockedRowTop + (Math.floor(tgtLockedRowHeight / 3) * 2);

var destGrid = this.grid;
var destStore = destGrid.store;
var destRecord = destStore.getAt(destIndex);

var destPreviousRecord = destStore.getAt(destIndex-1);

if (destRecord.data._is_leaf) {
// below
if (mouseY >= tgtRowCtr) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// above
else if (mouseY < tgtRowCtr) {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');
tgtLockedRowEl.addClass('gridRowInsertTopLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}

} else {




// if root folder, insert below only
if (destIndex == 0) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');


// below
} else if (mouseY >= tgtRow3) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// middle
else if (mouseY >= tgtRow2) {
this.point = 'middle';
//destIndex ++;
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine')
}
// above
else {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');

tgtLockedRowEl.addClass('gridRowInsertTomLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}
}


this.overRow = [tgtRowEl, tgtLockedRowEl];
}
else {
destIndex = destGrid.store.getCount();
}

this.destIndex = destIndex;

//destGrid.body.addClass('gridBodyNotifyOver');

return this.dropAllowed;
},
notifyOut : function() {
this.clearDDStyles();
},
clearDDStyles : function() {
//this.grid.body.removeClass('gridBodyNotifyOver');
if (this.overRow) {
this.overRow[0].removeClass('table-drop-pin');

this.overRow[0].removeClass('gridRowInsertBottomLine');
this.overRow[0].removeClass('gridRowInsertMiddleLine');
this.overRow[0].removeClass('gridRowInsertTopLine');
this.overRow[1].removeClass('gridRowInsertBottomLine');
this.overRow[1].removeClass('gridRowInsertTopLine');
delete this.overRow;
}
},
onContainerDrop : function(ddSrc, evtObj, ddData){
if (!this.overRow) return;

var srcGrid = ddSrc.view.grid;
var srcStore = srcGrid.store;
var srcIndex = ddData.rowIndex;
var records = ddSrc.dragData.selections;
var srcRecord = records[0];

var destGrid = this.grid;
var destStore = destGrid.store;
var destIndex = this.destIndex > destStore.getCount() ? destStore.getCount() : this.destIndex;
var destRecord = destStore.getAt(destIndex);
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);


// clear grid drag styles
this.clearDDStyles();

// exit if destRecord is undefined or source and dest are the same
if (srcGrid.id == destGrid.id && srcIndex == destIndex) return false;
if (!destRecord) return false;

if (destStore.getCount() > 1) {

// set destRecord to parent folder if leaf selected
if (destRecord.data._is_leaf) {
destRecord = destStore.getNodeParent(destRecord);

if (this.point == 'above') {
destIndex--;
}

} else {
// if Top of folder, check previous sibling for expanded
if (this.point == 'above') {
var prevRecord = destStore.getNodePrevSibling(destRecord);
destRecord = destStore.getNodeParent(destRecord);
destIndex--;
}

// if middle of folder, destRecord doesnt change
if (this.point == 'middle') {
}

// if bottom of folder, check expanded
if (this.point == 'below') {
if (!destRecord.ux_maximgb_tg_expanded) {
destRecord = destStore.getNodeParent(destRecord);
}
}
}
}



if (srcGrid.type == "custom_items") {

// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
{name: 'Heading'}
]);

srcRecord = records[0];

// create Record and add to store
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:false,
Description:data.Heading,
ParentItemID:data._parent
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:false,
Heading:theRequest.data.Heading
}, x.id);

destStore.clearFieldsInRec(rc);
destStore.insert(destIndex+1, rc);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);

//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});


// ************************************************************************
// Show edit row name window
// ************************************************************************

destGrid.getSelectionModel().selectRecords([rc]);
destGrid.selectedRecord = rc;

var editRowName = Ext.getCmp('editRowName');
editRowName.edit(destGrid);
},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});




} else if (srcGrid.type == "rule_items") {
// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
'UserRuleName',
'Heading'
]);

// create Record and add to store
Ext.each(records,function(srcRecord){
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:true,
Description:data.Heading,
ParentItemID:data._parent,
UserRule:data.UserRuleName
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:theRequest.data._is_leaf,
UserRuleName:theRequest.data.UserRuleName,
Heading:theRequest.data.Heading
}, x.id);
destStore.insert(destIndex+1, rc);
destGrid.getSelectionModel().selectRecords([rc]);

destStore.applySort();
destGrid.view.refresh(true);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});



// ************************************************************************
// update rule data in realtime - dont refresh whole grid
// ************************************************************************


Ext.Ajax.request({
scope:this,
grid: destGrid,
rc: rc,
url: 'services/tree-run.exec',
params: {
userrulename : rc.get('UserRuleName'),
summary : 1,
id : destGrid.templateID
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);
x.data = x.data[0];

var ancestors = destStore.getNodeAncestors(theRequest.rc);

destStore.copyToRec(theRequest.rc, x);
destStore.addToAncestors(ancestors, theRequest.rc);

destGrid.view.refresh(true);
},
failure: function (theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});



},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});

});


} else {
// reorder rules
var record = records[0];
var ancestors = destStore.getNodeAncestors(record);

// subtract values from current ancestors
destStore.subtractFromAncestors(ancestors, record);

// move record to correct location
//if (srcIndex < destIndex) destIndex--;

// move record to new parent
//destStore.move(record,destIndex);
// set a new parent id
record.set('_parent',destRecord.get('_id'));

//sort grid and get new ancestors
//this.grid.store.applyTreeSort();
ancestors = destStore.getNodeAncestors(record);

// add values to new ancestors
destStore.addToAncestors(ancestors, record);

// Save new order and partent ids

// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************


var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: record.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
Ext.Msg.alert('Error','Error saving the changes');
}
});



// update the grid
//this.grid.store.applyTreeSort();
destStore.applySort();
destGrid.view.refresh(true);
}



return true;
}
};
// This will make sure we only drop to the view container
var leftGridDroptgtCfg = Ext.apply({}, dropZoneOverrides, {
grid : this
});
new Ext.dd.DropZone(this.el, leftGridDroptgtCfg);

}

});

Ext.reg('dashboardTabSummaryGrid', dashboardTabSummaryGrid);


dashboardTabSummaryGrid.descriptionRenderer = function(value, metadata, record, rowIndex, colIndex, store){
//if (rowIndex == 0) return '';

if (record.get('_is_leaf') === false && record.get('datefr') && record.get('datefr') != '') {

var dateStore = Ext.StoreMgr.item('dateStore');
var dateFr = record.get('datefr');
var dateTo = record.get('dateto');

var dateRec = dateStore.getById(dateFr);
if (dateRec) {
dateFr = dateRec.get('description');
} else {
dateFr = Date.parseDate(dateFr, 'Ymd').format('d/m/Y');
}

var dateRec = dateStore.getById(dateTo);
if (dateRec) {
dateTo = dateRec.get('description');
} else {
dateTo = Date.parseDate(dateTo, 'Ymd').format('d/m/Y');
}

return String.format('{0} ({1} - {2})', value, dateFr, dateTo);
} else {
return value;
}
};

THe main issue is that the drag and drop isnt working on the locked column. Also selecting the row from the locked side only works because I pretty much hacked it:

var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

I would like to row select to work normally, rather than doing this, then if it selects properly from both the locked and unlocked columns then I think the drag/drop stuff with work.

Cheers

lukefowell89
15 Dec 2010, 2:38 AM
Hmmm I have tryed to post my code twice now but I think there is too much and it wont actually post... Ill spread it over 2 posts maybe...

Locking Tree Grid Ext:



Ext.namespace('Ext.ux.lf');

Ext.ux.lf.AbstractTreeStore = Ext.extend(Ext.data.Store,
{
leaf_field_name : '_is_leaf',
page_offset : 0,
active_node : null,

constructor : function(config)
{
Ext.ux.lf.AbstractTreeStore.superclass.constructor.call(this, config);

if (!this.paramNames.active_node) {
this.paramNames.active_node = 'anode';
}

this.addEvents(
'beforeexpandnode',
'expandnode',
'expandnodefailed',
'beforecollapsenode',
'collapsenode',
'beforeactivenodechange',
'activenodechange'
);
},

remove : function(record)
{
if (record === this.active_node) {
this.setActiveNode(null);
}
this.removeNodeDescendants(record);
Ext.ux.lf.AbstractTreeStore.superclass.remove.call(this, record);
},

move : function(record, index)
{
var index = this.data.indexOf(record);
if(index > -1){
record.join(null);
this.data.removeAt(index);
}
if(index > -1){
this.fireEvent('remove', this, record, index);
}
this.insert(index, record);

},

subtractFromAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current - value).toFixed(2) + "'");
});
}
});
},

addToAncestors : function(ancestors, record)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));

Ext.each(ancestors,function(ancestor){
var current = (+ancestor.get(key));
eval("ancestor.data." + key + " = '" + (current + value).toFixed(2) + "'");
});
}
});
},

clearFieldsInRec : function(rec)
{
var keys = this.fields.keys;

Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
rec.set(key, 0.00);
}
});
},

copyToRec : function(rec, record)
{
var keys = this.fields.keys;

// copy values for all fields to rec
Ext.each(keys,function(key) {
if (key.charAt(0) == 'c') {
var value = (+eval("record.data." + key));
rec.set(key, value);
}
});
},

removeNodeDescendants : function(rc)
{
var i, len, children = this.getNodeChildren(rc);
for (i = 0, len = children.length; i < len; i++) {
this.remove(children[i]);
}
},

load : function(options)
{
if (options) {
if (options.params) {
if (options.params[this.paramNames.active_node] === undefined) {
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options.params = {};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}
}
else {
options = {params: {}};
options.params[this.paramNames.active_node] = this.active_node ? this.active_node.id : null;
}

if (options.params[this.paramNames.active_node] !== null) {
options.add = true;
}

return Ext.ux.lf.AbstractTreeStore.superclass.load.call(this, options);
},

loadRecords : function(o, options, success)
{
if (!o || success === false) {
if (success !== false) {
this.fireEvent("load", this, [], options);
}
if (options.callback) {
options.callback.call(options.scope || this, [], options, false);
}
return;
}

var r = o.records, t = o.totalRecords || r.length,
page_offset = this.getPageOffsetFromOptions(options),
loaded_node_id = this.getLoadedNodeIdFromOptions(options),
loaded_node, i, len, prev_record, record, idx, updated, self = this;

if (!options || options.add !== true/* || loaded_node_id === null*/) {
if (this.pruneModifiedRecords) {
this.modified = [];
}
for (var i = 0, len = r.length; i < len; i++) {
r[i].join(this);
}
if (this.snapshot) {
this.data = this.snapshot;
delete this.snapshot;
}
this.data.clear();
this.data.addAll(r);
this.page_offset = page_offset;
this.totalLength = t;
this.applySort();
this.fireEvent("datachanged", this);
}
else {
if (loaded_node_id) {
loaded_node = this.getById(loaded_node_id);
}
if (loaded_node) {
this.setNodeLoaded(loaded_node, true);
this.setNodeChildrenOffset(loaded_node, page_offset);
this.setNodeChildrenTotalCount(loaded_node, Math.max(t, r.length));
this.removeNodeDescendants(loaded_node);
}
this.suspendEvents();
updated = {};
for (i = 0, len = r.length; i < len; i++) {
record = r[i];
idx = this.indexOfId(record.id);
if (idx == -1) {
updated[record.id] = false;
this.add(record);
}
else {
updated[record.id] = true;
prev_record = this.getAt(idx);
prev_record.reject();
prev_record.data = record.data;
r[i] = prev_record;
}
}
this.applySort();
this.resumeEvents();

r.sort(function(r1, r2) {
var idx1 = self.data.indexOf(r1),
idx2 = self.data.indexOf(r2),
result;

if (idx1 > idx2) {
result = 1;
}
else {
result = -1;
}
return result;
});

for (i = 0, len = r.length; i < len; i++) {
record = r[i];
if (updated[record.id] == true) {
this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
}
else {
this.fireEvent("add", this, [record], this.data.indexOf(record));
}
}
}
this.fireEvent("load", this, r, options);
if (options.callback) {
options.callback.call(options.scope || this, r, options, true);
}
},

sort : function(fieldName, dir)
{
if (this.remoteSort) {
this.setActiveNode(null);
if (this.lastOptions) {
this.lastOptions.add = false;
if (this.lastOptions.params) {
this.lastOptions.params[this.paramNames.active_node] = null;
}
}
}

return Ext.ux.lf.AbstractTreeStore.superclass.sort.call(this, fieldName, dir);
},

applySort : function()
{
if(this.sortInfo && !this.remoteSort){
var s = this.sortInfo, f = s.field;
this.sortData(f, s.direction);
}
else {
this.applyTreeSort();
}
},

sortData : function(f, direction)
{
direction = direction || 'ASC';
var st = this.fields.get(f).sortType;
var fn = function(r1, r2){
var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
};
this.data.sort(direction, fn);
if(this.snapshot && this.snapshot != this.data){
this.snapshot.sort(direction, fn);
}
this.applyTreeSort();
},

applyTreeSort : function()
{
var i, len, temp,
rec, records = [],
roots = this.getRootNodes();

for (i = 0, len = roots.length; i < len; i++) {
rec = roots[i];
records.push(rec);
this.collectNodeChildrenTreeSorted(records, rec);
}

if (records.length > 0) {
this.data.clear();
this.data.addAll(records);
}

if (this.snapshot && this.snapshot !== this.data) {
temp = this.data;
this.data = this.snapshot;
this.snapshot = null;
this.applyTreeSort();
this.snapshot = this.data;
this.data = temp;
}
},

collectNodeChildrenTreeSorted : function(records, rec)
{
var i, len,
child,
children = this.getNodeChildren(rec);

for (i = 0, len = children.length; i < len; i++) {
child = children[i];
records.push(child);
this.collectNodeChildrenTreeSorted(records, child);
}
},

getActiveNode : function()
{
return this.active_node;
},

setActiveNode : function(rc)
{
if (this.active_node !== rc) {
if (rc) {
if (this.data.indexOf(rc) != -1) {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
else {
throw "Given record is not from the store.";
}
}
else {
if (this.fireEvent('beforeactivenodechange', this, this.active_node, rc) !== false) {
this.active_node = rc;
this.fireEvent('activenodechange', this, this.active_node, rc);
}
}
}
},

isExpandedNode : function(rc)
{
return rc.ux_maximgb_tg_expanded === true;
},

setNodeExpanded : function(rc, value)
{
rc.ux_maximgb_tg_expanded = value;
},

isVisibleNode : function(rc)
{
var i, len,
ancestors = this.getNodeAncestors(rc),
result = true;

for (i = 0, len = ancestors.length; i < len; i++) {
result = result && this.isExpandedNode(ancestors[i]);
if (!result) {
break;
}
}
return result;
},

isLeafNode : function(rc)
{
return rc.get(this.leaf_field_name) == true;
},

isLoadedNode : function(rc)
{
var result;

if (rc.ux_maximgb_tg_loaded !== undefined) {
result = rc.ux_maximgb_tg_loaded;
}
else if (this.isLeafNode(rc) || this.hasChildNodes(rc)) {
result = true;
}
else {
result = false;
}

return result;
},

setNodeLoaded : function(rc, value)
{
rc.ux_maximgb_tg_loaded = value;
},

getNodeChildrenOffset : function(rc)
{
return rc.ux_maximgb_tg_offset || 0;
},

setNodeChildrenOffset : function(rc, value)
{
rc.ux_maximgb_tg_offset = value;
},

getNodeChildrenTotalCount : function(rc)
{
return rc.ux_maximgb_tg_total || 0;
},

setNodeChildrenTotalCount : function(rc, value)
{
rc.ux_maximgb_tg_total = value;
},

collapseNode : function(rc)
{
if (
this.isExpandedNode(rc) &&
this.fireEvent('beforecollapsenode', this, rc) !== false
) {
this.setNodeExpanded(rc, false);
this.fireEvent('collapsenode', this, rc);
}
},

expandNode : function(rc)
{
var params;
if (!this.isExpandedNode(rc) && this.fireEvent('beforeexpandnode', this, rc) !== false)
{
if (this.isLoadedNode(rc))
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
else if(this.getNodeChildrenCount(rc) == 0)
{
this.setNodeExpanded(rc, true);
this.fireEvent('expandnode', this, rc);
}
}
},

expandAll : function()
{

var r, i, len, records = this.data.getRange();
this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (!this.isExpandedNode(r)) {
this.expandNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

collapseAll : function()
{
var r, i, len, records = this.data.getRange();

this.suspendEvents();
for (i = 0, len = records.length; i < len; i++) {
r = records[i];
if (this.isExpandedNode(r)) {
this.collapseNode(r);
}
}
this.resumeEvents();
this.fireEvent('datachanged', this);
},

getLoadedNodeIdFromOptions : function(options)
{
var result = null;
if (options && options.params && options.params[this.paramNames.active_node]) {
result = options.params[this.paramNames.active_node];
}
return result;
},

getPageOffsetFromOptions : function(options)
{
var result = 0;
if (options && options.params && options.params[this.paramNames.start]) {
result = parseInt(options.params[this.paramNames.start], 10);
if (isNaN(result)) {
result = 0;
}
}
return result;
},

hasNextSiblingNode : function(rc)
{
return this.getNodeNextSibling(rc) !== null;
},

hasPrevSiblingNode : function(rc)
{
return this.getNodePrevSibling(rc) !== null;
},

hasChildNodes : function(rc)
{
return this.getNodeChildrenCount(rc) > 0;
},

getNodeAncestors : function(rc)
{
var ancestors = [],
parent;

parent = this.getNodeParent(rc);
while (parent) {
ancestors.push(parent);
parent = this.getNodeParent(parent);
}

return ancestors;
},

getNodeChildrenCount : function(rc)
{
return this.getNodeChildren(rc).length;
},

getNodeNextSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);

if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);

if (index < siblings.length - 1) {
result = siblings[index + 1];
}

return result;
},

getNodePrevSibling : function(rc)
{
var siblings,
parent,
index,
result = null;
parent = this.getNodeParent(rc);
if (parent) {
siblings = this.getNodeChildren(parent);
}
else {
siblings = this.getRootNodes();
}

index = siblings.indexOf(rc);
if (index > 0) {
result = siblings[index - 1];
}

return result;
},

getRootNodes : function()
{
throw 'Abstract method call';
},

getNodeDepth : function(rc)
{
throw 'Abstract method call';
},

getNodeParent : function(rc)
{
throw 'Abstract method call';
},

getNodeChildren : function(rc)
{
throw 'Abstract method call';
},

addToNode : function(parent, child)
{
throw 'Abstract method call';
},

removeFromNode : function(parent, child)
{
throw 'Abstract method call';
},

getPageOffset : function()
{
return this.page_offset;
},

getActiveNodePageOffset : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenOffset(this.active_node);
}
else {
result = this.getPageOffset();
}

return result;
},

getActiveNodeCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenCount(this.active_node);
}
else {
result = this.getRootNodes().length;
}

return result;
},

getActiveNodeTotalCount : function()
{
var result;

if (this.active_node) {
result = this.getNodeChildrenTotalCount(this.active_node);
}
else {
result = this.getTotalCount();
}

return result;
}
});


Ext.ux.lf.LockingTreeGridStore = Ext.extend(Ext.ux.lf.AbstractTreeStore,
{
parent_id_field_name : '_parent',

getRootNodes : function()
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == null) {
result.push(records[i]);
}
}

return result;
},

getNodeDepth : function(rc)
{
return this.getNodeAncestors(rc).length;
},

getNodeParent : function(rc)
{
return this.getById(rc.get(this.parent_id_field_name));
},

getNodeChildren : function(rc)
{
var i,
len,
result = [],
records = this.data.getRange();

for (i = 0, len = records.length; i < len; i++) {
if (records[i].get(this.parent_id_field_name) == rc.id) {
result.push(records[i]);
}
}

return result;
},

addToNode : function(parent, child)
{
child.set(this.parent_id_field_name, parent.id);
this.addSorted(child);
},

removeFromNode : function(parent, child)
{
this.remove(child);
}
});

Ext.ux.lf.LockingTreeGridView = Ext.extend(Ext.grid.GridView,
{
expanded_icon_class : 'ux-maximgb-tg-elbow-minus',
collapsed_icon_class : 'ux-maximgb-tg-elbow-plus',

last_expanded_icon_class : 'ux-maximgb-tg-elbow-end-minus',
last_collapsed_icon_class : 'ux-maximgb-tg-elbow-end-plus',

nl_expanded_icon_class : 'ux-maximgb-tg-nl-minus',
nl_collapsed_icon_class : 'ux-maximgb-tg-nl-plus',

skip_width_update_class: 'ux-maximgb-tg-skip-width-update',

expanded_folder_class : 'ux-maximgb-tg-expanded-folder',
collapsed_folder_class : 'ux-maximgb-tg-collapsed-folder',

lockText : 'Lock',
unlockText : 'Unlock',
rowBorderWidth : 1,
lockedBorderWidth : 1,

syncHeights: false,

initTemplates : function()
{
var ts = this.templates || {};


if (!ts.masterTpl) {
ts.masterTpl = 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" style="{lstyle}">{lockedHeader}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{lstyle}">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
'</div>',
'<div class="x-grid3-viewport x-grid3-unlocked">',
'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{mainbody}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
'</div>',
'<div class="x-grid3-resize-marker">&#160;</div>',
'<div class="x-grid3-resize-proxy">&#160;</div>',
'</div>'
);
}

if (!ts.row) {
ts.row = new Ext.Template(
'<div class="x-grid3-row ux-maximgb-tg-level-{level} ux-maximgb-tg-border {alt}" style="{tstyle} {display_style}">',
'<table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
'<tbody>',
'<tr>{cells}</tr>',
(
this.enableRowBody ?
'<tr class="x-grid3-row-body-tr" style="{bodyStyle}">' +
'<td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on">'+
'<div class="x-grid3-row-body">{body}</div>'+
'</td>'+
'</tr>'
:
''
),
'</tbody>',
'</table>',
'</div>'
);
}


if (!ts.mastercell) {
ts.mastercell = new Ext.Template(
'<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
'<div class="ux-maximgb-tg-mastercell-wrap">', // This is for editor to place itself right
'{treeui}',
'<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr} style="padding-top:3px">{value}</div>',
'</div>',
'</td>'
);
}

if (!ts.treeui) {
ts.treeui = new Ext.Template(
'<div class="ux-maximgb-tg-uiwrap" style="width: {wrap_width}px">',
'{elbow_line}',
'<div style="left: {left}px" class="{cls}">&#160;</div>',
'</div>'
);
}

if (!ts.elbow_line) {
ts.elbow_line = new Ext.Template(
'<div style="left: {left}px;" class="{cls}"></div>'
);
}

this.templates = ts;
Ext.ux.lf.LockingTreeGridView.superclass.initTemplates.call(this);
},

initElements : function(){
var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
scroller = mainWrap.child('div.x-grid3-scroller');

if (this.grid.hideHeaders) {
lockedHd.setDisplayed(false);
mainHd.setDisplayed(false);
}

if(this.forceFit){
scroller.setStyle('overflow-x', 'hidden');
}

Ext.apply(this, {
el : el,
mainWrap: mainWrap,
mainHd : mainHd,
innerHd : mainHd.dom.firstChild,
scroller: scroller,
mainBody: scroller.child('div.x-grid3-body'),
focusEl : scroller.child('a'),
resizeMarker: el.child('div.x-grid3-resize-marker'),
resizeProxy : el.child('div.x-grid3-resize-proxy'),
lockedWrap: lockedWrap,
lockedHd: lockedHd,
lockedScroller: lockedScroller,
lockedBody: lockedScroller.child('div.x-grid3-body'),
lockedInnerHd: lockedHd.child('div.x-grid3-header-inner', true)
});


this.focusEl.swallowEvent('click', true);
},

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

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

getCell : function(row, col){
if(col < 1){
return this.getLockedRow(row).getElementsByTagName('td')[col];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getCell.call(this, row, col - lockedLen);
},

getHeaderCell : function(index){
var lockedLen = 1;
if(index < lockedLen){
return this.lockedHd.dom.getElementsByTagName('td')[index];
}
return Ext.ux.lf.LockingTreeGridView.superclass.getHeaderCell.call(this, index - lockedLen);
},

addRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).addClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.addRowClass.call(this, row, cls);
},

removeRowClass : function(row, cls){
var lockedRow = this.getLockedRow(row);
if(lockedRow){
this.fly(lockedRow).removeClass(cls);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRowClass.call(this, row, cls);
},

removeRow : function(row) {
Ext.removeNode(this.getLockedRow(row));
Ext.ux.lf.LockingTreeGridView.superclass.removeRow.call(this, row);
},

removeRows : function(firstRow, lastRow){
var lockedBody = this.lockedBody.dom,
rowIndex = firstRow;
for(; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(lockedBody.childNodes[firstRow]);
}
Ext.ux.lf.LockingTreeGridView.superclass.removeRows.call(this, firstRow, lastRow);
},

syncScroll : function(e){
this.lockedScroller.dom.scrollTop = this.scroller.dom.scrollTop;
Ext.ux.lf.LockingTreeGridView.superclass.syncScroll.call(this, e);
},

updateSortIcon : function(col, dir){
var sortClasses = this.sortClasses,
lockedHeaders = this.lockedHd.select('td').removeClass(sortClasses),
headers = this.mainHd.select('td').removeClass(sortClasses),
lockedLen = 1,
cls = sortClasses[dir == 'DESC' ? 1 : 0];

if(col < lockedLen){
lockedHeaders.item(col).addClass(cls);
}else{
headers.item(col - lockedLen).addClass(cls);
}
},

updateAllColumnWidths : function(){
var tw = this.getTotalWidth(),
clen = this.cm.getColumnCount(),
lw = this.getLockedWidth(),
llen = 1,
widths = [], len, i;
for(i = 0; i < clen; i++)
{
widths[i] = this.getColumnWidth(i);
var hd = this.getHeaderCell(i);
hd.style.width = widths[i];
}
var lns = this.getLockedRows(), ns = this.getRows(), row, trow, j;
for(i = 0, len = ns.length; i < len; i++)
{
row = lns[i];
row.style.width = lw;
if(row.firstChild)
{
row.firstChild.style.width = lw;
trow = row.firstChild.rows[0];
trow.childNodes[0].style.width = widths[0];

}
row = ns[i];
row.style.width = tw;
if(row.firstChild)
{
row.firstChild.style.width = tw;
trow = row.firstChild.rows[0];
for (j = llen; j < clen; j++)
{
trow.childNodes[j - llen].style.width = widths[j];
}
}
}
this.onAllColumnWidthsUpdated(widths, tw);
//this.syncHeaderHeight();
},

updateColumnWidth : function(col, width){
var w = this.getColumnWidth(col),
llen = 1,
ns, rw, c, row;
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.width = w;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.width = w;
}
}
this.onColumnWidthUpdated(col, w, this.getTotalWidth());
//this.syncHeaderHeight();
},

updateColumnHidden : function(col, hidden){
var llen = this.cm.getLockedCount(),
ns, rw, c, row,
display = hidden ? 'none' : '';
this.updateLockedWidth();
if(col < llen){
ns = this.getLockedRows();
rw = this.getLockedWidth();
c = col;
}else{
ns = this.getRows();
rw = this.getTotalWidth();
c = col - llen;
}
var hd = this.getHeaderCell(col);
hd.style.display = display;
for(var i = 0, len = ns.length; i < len; i++){
row = ns[i];
row.style.width = rw;
if(row.firstChild){
row.firstChild.style.width = rw;
row.firstChild.rows[0].childNodes[c].style.display = display;
}
}
this.onColumnHiddenUpdated(col, hidden, this.getTotalWidth());
delete this.lastViewWidth;
this.layout();
},

doRender: function(columns, records, store, startRow, colCount, stripe){

var templates = this.templates;
var cell_template = templates.mastercell;
var cell_template2 = templates.cell;
var row_template = templates.row;
var last = colCount-1;
var tstyle = 'width:'+this.getTotalWidth()+';';
var lstyle = 'width:'+this.getLockedWidth()+';';
var buffer = [];
var locked_buffer = [];
var column_buffer = [];
var locked_column_buffer = [];
var column;
var params = {};
var row_params = {};
var record;


for (var x = 0, len = records.length; x < len; x++) {
record = records[x];
column_buffer = [];
locked_column_buffer = [];

this.store.setNodeExpanded(record, true);

var rowIndex = x + startRow;
var row_render_res = this.renderRow(record, rowIndex, colCount, store, this.cm.getTotalWidth());

if (row_render_res === false) {
for (var i = 0; i < colCount; i++) {

column = columns[i];
params.id = column.id;
params.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
params.attr = params.cellAttr = "";
params.value = column.renderer.call(column.scope, record.data[column.name], params, record, rowIndex, i, store);
params.style = column.style;

if (Ext.isEmpty(params.value)) {
params.value = "&#160;";
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] !== 'undefined') {
params.css += ' x-grid3-dirty-cell';
}

if (column.id == this.grid.master_column_id) {
params.treeui = this.renderCellTreeUI(record, store);
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
else {
cell_template = templates.mastercell;
cell_template2 = templates.cell;
}
if (column.id == this.grid.master_column_id) {
locked_column_buffer[locked_column_buffer.length] = cell_template.apply(params);
}
else {
column_buffer[column_buffer.length] = cell_template2.apply(params);
}

}
}
else {
column_buffer.push(row_render_res);
}

var alt = [];
if (stripe && ((rowIndex + 1) % 2 == 0)) {
alt[0] = "x-grid3-row-alt";
}
if (record.dirty) {
alt[1] = " x-grid3-dirty-row";
}
row_params.cols = colCount;
if (this.getRowClass) {
alt[2] = this.getRowClass(r, rowIndex, rp, store);
}

row_params.alt = alt.join(" ");
row_params.cells = locked_column_buffer.join("");
row_params.lstyle = lstyle;
locked_buffer[locked_buffer.length] = row_template.apply(row_params);

row_params.cells = column_buffer.join("");
row_params.tstyle = tstyle;
buffer[buffer.length] = row_template.apply(row_params);

}
return [buffer.join(""),locked_buffer.join("")];

},



renderCellTreeUI : function(record, store)
{
var template = this.templates.treeui,
line_template = this.templates.elbow_line,
template_data = {},
rec, parent,
depth = level = store.getNodeDepth(record);
template_data.elbow_line = '';
rec = record;
left = 0;

if (store.isLeafNode(rec))
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-item'
});
}
else
{
template_data.elbow_line = line_template.apply({
left : level * 16 + 16,
cls : 'ux-maximgb-tg-elbow-active-folder ux-maximgb-tg-expanded-folder'
});
}

template_data.wrap_width = (depth + 1) * 16 + 16;
if (level > 0) {

while(level--) {
parent = store.getNodeParent(rec);
if (parent) {
if (store.hasNextSiblingNode(parent)) {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-line',
}) +
template_data.elbow_line;
}
else {
template_data.elbow_line =
line_template.apply({
left : level * 16,
cls : 'ux-maximgb-tg-elbow-empty',
}) +
template_data.elbow_line;
}
}
else {
throw [
"Tree inconsistency can't get level ",
level + 1,
" node(id=", rec.id, ") parent."
].join("");
}
rec = parent;
}
}
if (store.isLeafNode(record)) {
if (store.hasNextSiblingNode(record)) {
template_data.cls = 'ux-maximgb-tg-elbow';
}
else {
template_data.cls = 'ux-maximgb-tg-elbow-end';
}
}
else {

template_data.cls = 'ux-maximgb-tg-elbow-active ';

if (store.isExpandedNode(record)) {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.expanded_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_expanded_icon_class;
} else {
template_data.cls += this.nl_expanded_icon_class;
}
}
else {

if (store.hasNextSiblingNode(record)) {
template_data.cls += this.collapsed_icon_class;
} else if (store.hasPrevSiblingNode(record)) {
template_data.cls += this.last_collapsed_icon_class;
} else {
template_data.cls += this.nl_collapsed_icon_class;
}
}
}
template_data.left = 1 + depth * 16;
return template.apply(template_data);
},

renderRow : function(record, index, col_count, store, total_width)
{
return false;
},

afterRender : function()
{
if(!this.store || !this.cm){
return;
}
var body = this.renderRows() || ['&#160;', '&#160;'];

this.mainBody.dom.innerHTML = body[0];
this.lockedBody.dom.innerHTML = body[1];
this.processRows(0, true);
if(this.deferEmptyText !== true){
this.applyEmptyText();
}
this.grid.fireEvent('viewready', this.grid);
this.updateAllColumnWidths();
},

renderUI : function()
{
var templates = this.templates,
header = this.renderHeaders(),
body = templates.body.apply({rows:'&#160;'});


return templates.masterTpl.apply({
mainbody : body[0],
header: header[0],
ostyle: 'width:' + this.getOffsetWidth() + ';',
bstyle: 'width:' + this.getTotalWidth() + ';',
lockedBody: body[1],
lockedHeader: header[1],
lstyle: 'width:'+this.getLockedWidth()+';'
});
},

getOffsetWidth : function()
{
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0) + this.getScrollOffset()) + 'px';
},

afterRenderUI: function()
{
var grid = this.grid;
this.initElements();
Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
Ext.fly(this.lockedInnerHd).on('click', this.handleHdDown, this);
this.mainHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.lockedHd.on({
scope: this,
mouseover: this.handleHdOver,
mouseout: this.handleHdOut,
mousemove: this.handleHdMove
});
this.scroller.on('scroll', this.syncScroll, this);
if(grid.enableColumnResize !== false){
this.splitZone = new Ext.grid.GridView.SplitDragZone(grid, this.mainHd.dom);
this.splitZone2 = new Ext.grid.GridView.SplitDragZone(grid, this.lockedHd.dom);
this.splitZone2.setOuterHandleElId(Ext.id(this.lockedHd.dom));
this.splitZone.setOuterHandleElId(Ext.id(this.mainHd.dom));
}
if(grid.enableColumnMove){
this.columnDrag = new Ext.grid.GridView.ColumnDragZone(grid, this.innerHd);
this.columnDrag2 = new Ext.grid.GridView.ColumnDragZone(grid, this.lockedInnerHd);
this.columnDrag2.setOuterHandleElId(Ext.id(this.lockedInnerHd));
this.columnDrag.setOuterHandleElId(Ext.id(this.innerHd));
this.columnDrop = new Ext.grid.HeaderDropZone(grid, this.mainHd.dom);
}
if(grid.enableHdMenu !== false){
this.hmenu = new Ext.menu.Menu({id: grid.id + '-hctx'});
this.hmenu.add(
{itemId: 'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
{itemId: 'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
);

if(grid.enableColumnHide !== false){
this.colMenu = new Ext.menu.Menu({id:grid.id + '-hcols-menu'});
this.colMenu.on({
scope: this,
beforeshow: this.beforeColMenuShow,
itemclick: this.handleHdMenuClick
});
this.hmenu.add('-', {
itemId:'columns',
hideOnClick: false,
text: this.columnsText,
menu: this.colMenu,
iconCls: 'x-cols-icon'
});
}
this.hmenu.on('itemclick', this.handleHdMenuClick, this);
}
if(grid.trackMouseOver){
this.mainBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
this.lockedBody.on({
scope: this,
mouseover: this.onRowOver,
mouseout: this.onRowOut
});
}

if(grid.enableDragDrop || grid.enableDrag){
this.dragZone = new Ext.grid.GridDragZone(grid, {
ddGroup : grid.ddGroup || 'GridDD'
});
}
this.updateHeaderSortState();
},

layout : function(){
if(!this.mainBody){
return;
}
var grid = this.grid;
var grid_el = grid.getGridEl();
var cell_size = grid_el.getSize(true);
if(!grid.hideHeaders && (cell_size.width < 20 || cell_size.height < 20)){
return;
}

if(grid.autoHeight){
this.scroller.dom.style.overflow = 'visible';
this.lockedScroller.dom.style.overflow = 'visible';
if(Ext.isWebKit){
this.scroller.dom.style.position = 'static';
this.lockedScroller.dom.style.position = 'static';
}
}else{
this.el.setSize(cell_size.width, cell_size.height);
var hdHeight = this.mainHd.getHeight();
var cell_height = cell_size.height - (hdHeight);
}
this.updateLockedWidth();
if(this.forceFit){
if(this.lastViewWidth != cell_size.width){
this.fitColumns(false, false);
this.lastViewWidth = cell_size.width;
}
}else {
this.autoExpand();
this.syncHeaderScroll();
}
this.onLayout(cell_size.width, cell_height);
},

renderHeaders : function()
{
var column_model = this.cm,
templates = this.templates,
ct = templates.hcell,
cb = [], locked_cb = [],
params = {},
len = column_model.getColumnCount(),
last = len - 1;
for(var i = 0; i < len; i++)
{
params.id = column_model.getColumnId(i);
params.value = column_model.getColumnHeader(i) || '';
params.style = this.getColumnStyle(i, true);
params.tooltip = this.getColumnTooltip(i);
params.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
(column_model.config[i].headerCls ? ' ' + column_model.config[i].headerCls : '');
if(column_model.config[i].align == 'right'){
params.istyle = 'padding-right:16px';
} else {
delete params.istyle;
}
if(i == 0)
{
locked_cb[locked_cb.length] = ct.apply(params);
}
else
{
cb[cb.length] = ct.apply(params);
}
}
return [templates.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'}),
templates.header.apply({cells: locked_cb.join(''), tstyle:'width:'+this.getLockedWidth()+';'})];
},

updateHeaders : function()
{
var header = this.renderHeaders();
this.innerHd.firstChild.innerHTML = header[0];
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
this.lockedInnerHd.firstChild.innerHTML = header[1];
var locked_width = this.getLockedWidth();
this.lockedInnerHd.firstChild.style.width = locked_width;
this.lockedInnerHd.firstChild.firstChild.style.width = locked_width;
},

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

syncFocusEl : function(row, col, hscroll){
Ext.ux.lf.LockingTreeGridView.superclass.syncFocusEl.call(this, row, col, col < 1 ? false : hscroll);
},
/*
updateAllColumnWidths : function()
{
var total_width = this.getTotalWidth(),
column_length = this.cm.getColumnCount(),
widths = [],
length,
i;
for(i = 0; i < column_length; i++){
widths[i] = this.getColumnWidth(i);
}
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
for(i = 0; i < column_length; i++){
var header = this.getHeaderCell(i);
header.style.width = widths[i];
}

var rows = this.getRows(), row, trow;
for(i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
total_row = row.firstChild.rows[0];
for (var j = 0; j < column_length && j < total_row.childNodes.length; j++) {
if (!Ext.fly(total_row.childNodes[j]).hasClass(this.skip_width_update_class)) {
total_row.childNodes[j].style.width = widths[j];
}
}
}
}

this.onAllColumnWidthsUpdated(widths, total_width);
},

updateColumnWidth : function(col, width)
{
var col_width = this.getColumnWidth(col);
var total_width = this.getTotalWidth();

this.lockedInnerHd.firstChild.style.width = this.getOffsetWidth();
this.lockedInnerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var header = this.getHeaderCell(col);
header.style.width = col_width;

var rows = this.getRows(), row;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.width = col_width;
}
}
}
}

this.onColumnWidthUpdated(col, col_width, total_width);
},

updateColumnHidden : function(col, hidden)
{
var total_width = this.getTotalWidth();
this.innerHd.firstChild.style.width = this.getOffsetWidth();
this.innerHd.firstChild.firstChild.style.width = total_width;
this.mainBody.dom.style.width = total_width;
var display = hidden ? 'none' : '';

var header = this.getHeaderCell(col);
header.style.display = display;

var rows = this.getRows(), row, cell;
for(var i = 0, len = rows.length; i < len; i++){
row = rows[i];
row.style.width = total_width;
if(row.firstChild){
row.firstChild.style.width = total_width;
if (col < row.firstChild.rows[0].childNodes.length) {
if (!Ext.fly(row.firstChild.rows[0].childNodes[col]).hasClass(this.skip_width_update_class)) {
row.firstChild.rows[0].childNodes[col].style.display = display;
}
}
}
}

this.onColumnHiddenUpdated(col, hidden, total_width);
delete this.lastViewWidth; // force recalc
this.layout();
},
*/
processRows : function(startRow, skipStripe)
{
if(!this.store || this.store.getCount() < 1){
return;
}

var rows = this.getRows(),
locked_rows = this.getLockedRows(),
row, locked_row;
var processed_count = 0;

skipStripe = !this.grid.stripeRows;
startRow = startRow || 0;

for(var i = 0, len = rows.length; i < len; ++i){
row = rows[i];
locked_row = locked_rows[i];
row.rowIndex = i;
locked_row.rowIndex = i;

if(!skipStripe){
row.className = row.className.replace(this.rowClsRe, ' ');
locked_row.className = locked_row.className.replace(this.rowClsRe, ' ');
if ((i + 1) % 2 === 0){
row.className += ' x-grid3-row-alt';
locked_row.className += ' x-grid3-row-alt';
}
}
this.syncRowHeights(row, locked_row);
}

if(startRow === 0){
Ext.fly(rows[0]).addClass(this.firstRowCls);
Ext.fly(locked_rows[0]).addClass(this.firstRowCls);
}
Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
Ext.fly(locked_rows[locked_rows.length - 1]).addClass(this.lastRowCls);
},

ensureVisible : function(row, col, hscroll)
{
var ancestors, record = this.store.getAt(row);
if (!this.store.isVisibleNode(record))
{
ancestors = this.store.getNodeAncestors(record);

while (ancestors.length > 0)
{
record = ancestors.shift();

if (!this.store.isExpandedNode(record))
{
this.store.expandNode(record);
}
}
}
return Ext.ux.lf.LockingTreeGridView.superclass.ensureVisible.call(this, row, col, col < 1 ? false : hscroll);

},

expandRow : function(record, skip_process)
{
var store = this.store,
i, len, row, locked_row, pmel, lpmel, children, index, child_index;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');

if (pmel) {
pmel.removeClass(this.collapsed_icon_class);
pmel.removeClass(this.last_collapsed_icon_class);
pmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_expanded_icon_class);
} else {
pmel.addClass(this.nl_expanded_icon_class);
}
}

if (lpmel) {
lpmel.removeClass(this.collapsed_icon_class);
lpmel.removeClass(this.last_collapsed_icon_class);
lpmel.removeClass(this.nl_collapsed_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.expanded_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_expanded_icon_class);
} else {
lpmel.addClass(this.nl_expanded_icon_class);
}
}

pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');

lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');

if (pmel) {
pmel.removeClass(this.collapsed_folder_class);
pmel.addClass(this.expanded_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.collapsed_folder_class);
lpmel.addClass(this.expanded_folder_class);
}
if (store.isVisibleNode(record)) {
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
row.style.display = 'block';
locked_row.style.display = 'block';

if (store.isExpandedNode(children[i])) {
this.expandRow(child_index, true);
}
}
}
if (!skip_process) {
this.processRows(0);
}
},

collapseRow : function(record, skip_process)
{
var store = this.store,
i, len, children, row, locked_row, index, child_index, pmel, lpmel;

if (typeof record == 'number') {
index = record;
record = store.getAt(index);
}
else {
index = store.indexOf(record);
}

skip_process = skip_process || false;

row = this.getRow(index);
locked_row = this.getLockedRow(index);
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active');
if (pmel) {
pmel.removeClass(this.expanded_icon_class);
pmel.removeClass(this.last_expanded_icon_class);
pmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
pmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
pmel.addClass(this.last_collapsed_icon_class);
} else {
pmel.addClass(this.nl_collapsed_icon_class);
}
}
if (lpmel) {
lpmel.removeClass(this.expanded_icon_class);
lpmel.removeClass(this.last_expanded_icon_class);
lpmel.removeClass(this.nl_expanded_icon_class);

if (store.hasNextSiblingNode(record)) {
lpmel.addClass(this.collapsed_icon_class);
} else if (store.hasPrevSiblingNode(record)) {
lpmel.addClass(this.last_collapsed_icon_class);
} else {
lpmel.addClass(this.nl_collapsed_icon_class);
}
}
pmel = Ext.fly(row).child('.ux-maximgb-tg-elbow-active-folder');
lpmel = Ext.fly(locked_row).child('.ux-maximgb-tg-elbow-active-folder');
if (pmel) {
pmel.removeClass(this.expanded_folder_class);
pmel.addClass(this.collapsed_folder_class);
}
if (lpmel) {
lpmel.removeClass(this.expanded_folder_class);
lpmel.addClass(this.collapsed_folder_class);
}
children = store.getNodeChildren(record);
for (i = 0, len = children.length; i < len; i++) {
child_index = store.indexOf(children[i]);
row = this.getRow(child_index);
locked_row = this.getLockedRow(child_index);
if (row.style.display != 'none') {
row.style.display = 'none';
this.collapseRow(child_index, true);
}
if (locked_row.style.display != 'none') {
locked_row.style.display = 'none';
this.collapseRow(child_index, true);
}
}
if (!skip_process) {
this.processRows(0);
}
},

initData : function(store, column_model)
{
if(this.cm){
this.cm.un('columnlockchange', this.onColumnLock, this);
}
this.store = this.ds = store;
Ext.ux.lf.LockingTreeGridView.superclass.initData.call(this, store, column_model);
if (this.store) {
this.store.un('expandnode', this.onStoreExpandNode, this);
this.store.un('collapsenode', this.onStoreCollapseNode, this);
}
if (store) {
store.on('expandnode', this.onStoreExpandNode, this);
store.on('collapsenode', this.onStoreCollapseNode, this);
}
if(this.cm){
this.cm.on('columnlockchange', this.onColumnLock, this);
}
},

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

handleHdMenuClick : function(item)
{
var index = this.hdCtxIndex,
cm = this.cm,
id = item.getItemId()
switch(id){
default:
return Ext.ux.lf.LockingTreeGridView.superclass.handleHdMenuClick.call(this, item);
}
return true;
},

handleHdDown : function(e, t)
{
Ext.ux.lf.LockingTreeGridView.superclass.handleHdDown.call(this, e, t);
if(this.grid.enableColLock !== false){
if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
var hd = this.findHeaderCell(t),
index = this.getCellIndex(hd),
ms = this.hmenu.items, cm = this.cm;
}
}
},

onLoad : function(store, records, options)
{
var ridx;
if (
options &&
options.params &&
(
options.params[store.paramNames.active_node] === null ||
store.indexOfId(options.params[store.paramNames.active_node]) == -1
)
) {
Ext.ux.lf.LockingTreeGridView.superclass.onLoad.call(this, store, records, options);
}
},

onAdd : function(store, records, index)
{
Ext.ux.lf.LockingTreeGridView.superclass.onAdd.call(this, store, records, index);
if (this.mainWrap) {
this.processRows(0);
}
},

onRemove : function(store, record, index, isUpdate)
{
Ext.ux.lf.LockingTreeGridView.superclass.onRemove.call(this, store, record, index, isUpdate);
if(isUpdate !== true){
if (this.mainWrap) {
this.processRows(0);
}
}
},

onUpdate : function(store, record)
{
Ext.ux.lf.LockingTreeGridView.superclass.onUpdate.call(this, store, record);
if (this.mainWrap) {
this.processRows(0);
}
},

onStoreExpandNode : function(store, record)
{
this.expandRow(record);
},

onStoreCollapseNode : function(store, record)
{
this.collapseRow(record);
},

getColumnStyle : function(col, isHeader)
{
var style = !isHeader ? this.cm.config[col].cellStyle || this.cm.config[col].css || '' : this.cm.config[col].headerStyle || '';
style += 'width:'+this.getColumnWidth(col)+';';
if(this.cm.isHidden(col)){
style += 'display:none;';
}
var align = this.cm.config[col].align;
if(align){
style += 'text-align:'+align+';';
}
return style;
},

getLockedWidth : function() {
return this.cm.getColumnWidth(0) + 'px';
},

getTotalWidth : function() {
return (this.cm.getTotalWidth() - this.cm.getColumnWidth(0)) + 'px';
},

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 : (!Ext.isDefined(name) ? this.store.fields.get(i).name : name),
renderer : cm.getRenderer(i),
id : cm.getColumnId(i),
style : this.getColumnStyle(i),
locked : i == 0 ? true : false
};
}
return cs;
},

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

refreshRow: function(record){
var store = this.store,
colCount = this.cm.getColumnCount(),
columns = this.getColumnData(),
last = colCount - 1,
cls = ['x-grid3-row'],
rowParams = {
tstyle: String.format("width: {0};", this.getTotalWidth())
},
lockedRowParams = {
tstyle: String.format("width: {0};", this.getLockedWidth())
},
colBuffer = [],
lockedColBuffer = [],
cellTpl = this.templates.cell,
rowIndex,
row,
lockedRow,
column,
meta,
css,
i;

if (Ext.isNumber(record)) {
rowIndex = record;
record = store.getAt(rowIndex);
} else {
rowIndex = store.indexOf(record);
}

if (!record || rowIndex < 0) {
return;
}

for (i = 0; i < colCount; i++) {
column = columns[i];

if (i == 0) {
css = 'x-grid3-cell-first';
} else {
css = (i == last) ? 'x-grid3-cell-last ' : '';
}

meta = {
id: column.id,
style: column.style,
css: css,
attr: "",
cellAttr: ""
};

meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);

if (Ext.isEmpty(meta.value)) {
meta.value = ' ';
}

if (this.markDirty && record.dirty && typeof record.modified[column.name] != 'undefined') {
meta.css += ' x-grid3-dirty-cell';
}

if (column.locked) {
lockedColBuffer[i] = cellTpl.apply(meta);
} else {
colBuffer[i] = cellTpl.apply(meta);
}
}

row = this.getRow(rowIndex);
row.className = '';
lockedRow = this.getLockedRow(rowIndex);
lockedRow.className = '';

if (this.grid.stripeRows && ((rowIndex + 1) % 2 === 0)) {
cls.push('x-grid3-row-alt');
}

if (this.getRowClass) {
rowParams.cols = colCount;
cls.push(this.getRowClass(record, rowIndex, rowParams, store));
}

// Unlocked rows
this.fly(row).addClass(cls).setStyle(rowParams.tstyle);
rowParams.cells = colBuffer.join("");
row.innerHTML = this.templates.rowInner.apply(rowParams);

// Locked rows
this.fly(lockedRow).addClass(cls).setStyle(lockedRowParams.tstyle);
lockedRowParams.cells = lockedColBuffer.join("");
lockedRow.innerHTML = this.templates.rowInner.apply(lockedRowParams);
lockedRow.rowIndex = rowIndex;
this.syncRowHeights(row, lockedRow);
this.fireEvent('rowupdated', this, rowIndex, record);
},

syncRowHeights: function(row1, row2){
if(this.syncHeights){
var el1 = Ext.get(row1),
el2 = Ext.get(row2),
h1 = el1.getHeight(),
h2 = el2.getHeight();

if(h1 > h2){
el2.setHeight(h1);
}else if(h2 > h1){
el1.setHeight(h2);
}
}
},

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

updateLockedWidth: function()
{
var lw = this.cm.getColumnWidth(0),
tw = this.cm.getTotalWidth() - lw,
csize = this.grid.getGridEl().getSize(true),
lp = Ext.isBorderBox ? 0 : this.lockedBorderWidth,
rp = Ext.isBorderBox ? 0 : this.rowBorderWidth,
vw = (csize.width - lw - lp - rp) + 'px',
so = this.getScrollOffset();
if(!this.grid.autoHeight)
{
var vh = (csize.height - this.mainHd.getHeight()) + 'px';
this.lockedScroller.dom.style.height = vh;
this.scroller.dom.style.height = vh;
}
this.lockedWrap.dom.style.width = (lw + rp) + 'px';
this.scroller.dom.style.width = vw;
this.mainWrap.dom.style.left = (lw + lp + rp) + 'px';
if(this.innerHd){
this.lockedInnerHd.firstChild.style.width = lw + 'px';
this.lockedInnerHd.firstChild.firstChild.style.width = lw + 'px';
this.innerHd.style.width = vw;
this.innerHd.firstChild.style.width = (tw + rp + so) + 'px';
this.innerHd.firstChild.firstChild.style.width = tw + 'px';
}
if(this.mainBody){
this.lockedBody.dom.style.width = (lw + rp) + 'px';
this.mainBody.dom.style.width = (tw + rp) + 'px';
}
}
});

Ext.ux.lf.LockingTreeGrid = Ext.extend(Ext.grid.GridPanel,
{
tg_cls : 'ux-maximgb-tg-panel',

constructor: function(config) {

Ext.ux.lf.LockingTreeGrid.superclass.constructor.call(this, config);
},

initComponent : function()
{
this.initComponentPreOverride();
Ext.ux.lf.LockingTreeGrid.superclass.initComponent.call(this);
this.getSelectionModel().on('selectionchange', this.onTreeGridSelectionChange, this);
this.initComponentPostOverride();
},

initComponentPreOverride : Ext.emptyFn,

initComponentPostOverride : Ext.emptyFn,

onRender : function(ct, position)
{
Ext.ux.lf.LockingTreeGrid.superclass.onRender.call(this, ct, position);
this.el.addClass(this.tg_cls);
},

getView : function()
{
if (!this.view) {
this.view = new Ext.ux.lf.LockingTreeGridView(this.viewConfig);
}
return this.view;
},

onClick : function(e)
{

var target = e.getTarget(),
view = this.getView(),
row = view.findRowIndex(target),
store = this.getStore(),
sm = this.getSelectionModel(),
record, record_id, do_default = true;

if (row !== false) {

if (Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {

record = store.getAt(row);

if (store.isExpandedNode(record)) {
store.collapseNode(record);
}
else {
store.expandNode(record);

}
do_default = false;
}
}

if (do_default) {
Ext.ux.lf.LockingTreeGrid.superclass.onClick.call(this, e);
}
},

onMouseDown : function(e)
{
var target = e.getTarget();

if (!Ext.fly(target).hasClass('ux-maximgb-tg-elbow-active')) {
Ext.ux.lf.LockingTreeGrid.superclass.onMouseDown.call(this, e);
}
},

onTreeGridSelectionChange : function(sm, selection)
{
var record, ancestors, store = this.getStore();

if (sm.getSelected) {
record = sm.getSelected();
store.setActiveNode(record);
}

else if (sm.getSelectedCell && selection) {
record = selection.record;
store.setActiveNode(record);
}

if (record) {
if (!store.isVisibleNode(record)) {
ancestors = store.getNodeAncestors(record);
while (ancestors.length > 0) {
store.expandNode(ancestors.pop());
}
}
}
}

});

Ext.reg('Ext.ux.lf.LockingTreeGrid', Ext.ux.lf.LockingTreeGrid);
Ext.reg('Ext.ux.lf.LockingTreeGridStore', Ext.ux.lf.LockingTreeGridStore);

lukefowell89
15 Dec 2010, 2:41 AM
setting up the grid + DnD stuff:




dashboardTabSummaryGrid = Ext.extend(Ext.ibc.DynamicColumnGridPanel, {
constructor: function(config) {
config = Ext.apply({
border : false,
trackMouseOver : false,
bodyStyle : 'border-top: 0;',
parameterType : 1,
templateID : config.queryRecord.get('TemplateID'),
enableDragDrop : true,
ddGroup :'dashboardTabSummaryGridDropZone',
contextMenu : Ext.getCmp('dashboardTabSummaryMenu')
}, config);

dashboardTabSummaryGrid.superclass.constructor.call(this, config);
},

initComponent: function() {
dashboardTabSummaryGrid.superclass.initComponent.apply(this, arguments);

this.store.grid = this;

this.on('cellclick', this.onCellClick, this);
this.on('beforecontextmenu', this.onBeforeContextMenu, this);
this.on('columnmove', this.onColumnMove, this);
this.on('columnresize', this.onColumnResize, this);
this.on('rowclick', this.onRowSelect, this);
},

onRowSelect: function(grid, row, e)
{
this.selModel.selectRow(row);
},

onColumnMove: function(oldIndex, newIndex) {

var columns = this.getColumnModel().config;
var nodes = [];
Ext.each(columns,function(column){
if (column.id != "master")
nodes.push(column.id);
});

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: {
action: 'REORDER',
nodes: nodes.join(',')
},
failure : function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onColumnResize: function(columnIndex, newSize) {
},

onCellClick: function(grid, rowIndex, columnIndex, e) {

var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

var summaryGrid = grid;
var detailTab = Ext.getCmp(grid.queryRecord.get('TemplateID') + 'DETAILTAB');

var record = this.selModel.getSelected();

if (grid.store.isLeafNode(record)) {
var tabHeight = summaryGrid.ownerCt.container.getHeight();
var newHeight = tabHeight - (summaryGrid.store.data.length * 19) - 100;

if (newHeight < 300) newHeight = 300;

detailTab.makeVisible(newHeight, record.get('Heading'));
detailTab.loadData(record.get('UserRuleName'), this.queryRecord.get('DetailTemplateID'), record, grid.queryRecord.get('TemplateID'));
}
},

onBeforeContextMenu: function(menu, record, column, rowindex) {
if (record.get('_is_leaf') === false) {
menu.enableDates();
} else {
menu.disableDates();
}

if (rowindex) {
menu.enableDeleteRow();
} else {
menu.disableDeleteRow();
}

if (column) {
menu.enableEdit();
} else {
menu.disableEdit();
}

menu.configure();
menu.doLayout();
},

setColumnAlignment: function(alignement) {
columnModel = this.getColumnModel().config;
columnModel[this.selectedColumn].align = alignement;
this.getColumnModel().setConfig(columnModel);

var column = columnModel[this.selectedColumn];
var params = {
//templateid: this._templateid,
id: column.id,
action: 'UPDATE',
number: column.number,
heading: column.header,
negativecolor: column.negativeColor,
renderer: column.renderer,
//invert: column.invert,
//calccolumn1: this._calccolumn1.getValue(),
//calcoperator: this._calcoperator.getValue(),
//calccolumn2: this._calccolumn2.getValue(),
columnalign: column.align,
//columntype: this._columntype.getValue(),
symbol: column.symbol,
ruleparameter: column.tagname
};

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: params,
scope: this,
failure: function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onRender: function(grid) {
dashboardTabSummaryGrid.superclass.onRender.apply(this, arguments);

var dropZoneOverrides = {
ddGroup : 'dashboardTabSummaryGridDropZone',
onContainerOver : function(ddSrc, evtObj, ddData) {
var destGrid = this.grid;
var tgtEl = evtObj.getTarget();
var destIndex = destGrid.getView().findRowIndex(tgtEl);
var destStore = destGrid.store;

var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
lockedBody = lockedScroller.child('div.x-grid3-body'),
scroller = mainWrap.child('div.x-grid3-scroller');

this.clearDDStyles();

if (destIndex === false) return;


// if drag before first row
if (destIndex == 0) destIndex = 1;
destIndex = (destStore.getCount() == 1 ? 0 : destIndex);

// is this a row?
if (typeof destIndex === 'number') {
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);

var tgtRowEl = Ext.get(tgtRow);
var tgtLockedRowEl = Ext.get(tgtLockedRow);
var tgtRowHeight = tgtRowEl.getHeight();
var tgtRowTop = tgtRowEl.getY();
var tgtRowCtr = tgtRowTop + Math.floor(tgtRowHeight / 2);

var tgtLockedRowHeight = tgtLockedRowEl.getHeight();
var tgtLockedRowTop = tgtLockedRowEl.getY();
var tgtLockedRowCtr = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 2);
var mouseY = evtObj.getXY()[1];

var tgtRow1 = tgtRowEl.getY();
var tgtRow2 = tgtRowTop + Math.floor(tgtRowHeight / 3);
var tgtRow3 = tgtRowTop + (Math.floor(tgtRowHeight / 3) * 2);

var tgtLockedRow1 = tgtLockedRowEl.getY();
var tgtLockedRow2 = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 3);
var tgtLockedRow3 = tgtLockedRowTop + (Math.floor(tgtLockedRowHeight / 3) * 2);

var destGrid = this.grid;
var destStore = destGrid.store;
var destRecord = destStore.getAt(destIndex);

var destPreviousRecord = destStore.getAt(destIndex-1);

if (destRecord.data._is_leaf) {
// below
if (mouseY >= tgtRowCtr) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// above
else if (mouseY < tgtRowCtr) {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');
tgtLockedRowEl.addClass('gridRowInsertTopLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}

} else {




// if root folder, insert below only
if (destIndex == 0) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');


// below
} else if (mouseY >= tgtRow3) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// middle
else if (mouseY >= tgtRow2) {
this.point = 'middle';
//destIndex ++;
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine')
}
// above
else {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');

tgtLockedRowEl.addClass('gridRowInsertTomLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}
}


this.overRow = [tgtRowEl, tgtLockedRowEl];
}
else {
destIndex = destGrid.store.getCount();
}

this.destIndex = destIndex;

//destGrid.body.addClass('gridBodyNotifyOver');

return this.dropAllowed;
},
notifyOut : function() {
this.clearDDStyles();
},
clearDDStyles : function() {
//this.grid.body.removeClass('gridBodyNotifyOver');
if (this.overRow) {
this.overRow[0].removeClass('table-drop-pin');

this.overRow[0].removeClass('gridRowInsertBottomLine');
this.overRow[0].removeClass('gridRowInsertMiddleLine');
this.overRow[0].removeClass('gridRowInsertTopLine');
this.overRow[1].removeClass('gridRowInsertBottomLine');
this.overRow[1].removeClass('gridRowInsertTopLine');
delete this.overRow;
}
},
onContainerDrop : function(ddSrc, evtObj, ddData){
if (!this.overRow) return;

var srcGrid = ddSrc.view.grid;
var srcStore = srcGrid.store;
var srcIndex = ddData.rowIndex;
var records = ddSrc.dragData.selections;
var srcRecord = records[0];

var destGrid = this.grid;
var destStore = destGrid.store;
var destIndex = this.destIndex > destStore.getCount() ? destStore.getCount() : this.destIndex;
var destRecord = destStore.getAt(destIndex);
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);


// clear grid drag styles
this.clearDDStyles();

// exit if destRecord is undefined or source and dest are the same
if (srcGrid.id == destGrid.id && srcIndex == destIndex) return false;
if (!destRecord) return false;

if (destStore.getCount() > 1) {

// set destRecord to parent folder if leaf selected
if (destRecord.data._is_leaf) {
destRecord = destStore.getNodeParent(destRecord);

if (this.point == 'above') {
destIndex--;
}

} else {
// if Top of folder, check previous sibling for expanded
if (this.point == 'above') {
var prevRecord = destStore.getNodePrevSibling(destRecord);
destRecord = destStore.getNodeParent(destRecord);
destIndex--;
}

// if middle of folder, destRecord doesnt change
if (this.point == 'middle') {
}

// if bottom of folder, check expanded
if (this.point == 'below') {
if (!destRecord.ux_maximgb_tg_expanded) {
destRecord = destStore.getNodeParent(destRecord);
}
}
}
}



if (srcGrid.type == "custom_items") {

// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
{name: 'Heading'}
]);

srcRecord = records[0];

// create Record and add to store
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:false,
Description:data.Heading,
ParentItemID:data._parent
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:false,
Heading:theRequest.data.Heading
}, x.id);

destStore.clearFieldsInRec(rc);
destStore.insert(destIndex+1, rc);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);

//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});


// ************************************************************************
// Show edit row name window
// ************************************************************************

destGrid.getSelectionModel().selectRecords([rc]);
destGrid.selectedRecord = rc;

var editRowName = Ext.getCmp('editRowName');
editRowName.edit(destGrid);
},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});




} else if (srcGrid.type == "rule_items") {
// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
'UserRuleName',
'Heading'
]);

// create Record and add to store
Ext.each(records,function(srcRecord){
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:true,
Description:data.Heading,
ParentItemID:data._parent,
UserRule:data.UserRuleName
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:theRequest.data._is_leaf,
UserRuleName:theRequest.data.UserRuleName,
Heading:theRequest.data.Heading
}, x.id);
destStore.insert(destIndex+1, rc);
destGrid.getSelectionModel().selectRecords([rc]);

destStore.applySort();
destGrid.view.refresh(true);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});



// ************************************************************************
// update rule data in realtime - dont refresh whole grid
// ************************************************************************


Ext.Ajax.request({
scope:this,
grid: destGrid,
rc: rc,
url: 'services/tree-run.exec',
params: {
userrulename : rc.get('UserRuleName'),
summary : 1,
id : destGrid.templateID
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);
x.data = x.data[0];

var ancestors = destStore.getNodeAncestors(theRequest.rc);

destStore.copyToRec(theRequest.rc, x);
destStore.addToAncestors(ancestors, theRequest.rc);

destGrid.view.refresh(true);
},
failure: function (theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});



},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});

});


} else {
// reorder rules
var record = records[0];
var ancestors = destStore.getNodeAncestors(record);

// subtract values from current ancestors
destStore.subtractFromAncestors(ancestors, record);

// move record to correct location
//if (srcIndex < destIndex) destIndex--;

// move record to new parent
//destStore.move(record,destIndex);
// set a new parent id
record.set('_parent',destRecord.get('_id'));

//sort grid and get new ancestors
//this.grid.store.applyTreeSort();
ancestors = destStore.getNodeAncestors(record);

// add values to new ancestors
destStore.addToAncestors(ancestors, record);

// Save new order and partent ids

// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************


var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: record.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
Ext.Msg.alert('Error','Error saving the changes');
}
});



// update the grid
//this.grid.store.applyTreeSort();
destStore.applySort();
destGrid.view.refresh(true);
}



return true;
}
};
// This will make sure we only drop to the view container
var leftGridDroptgtCfg = Ext.apply({}, dropZoneOverrides, {
grid : this
});
new Ext.dd.DropZone(this.el, leftGridDroptgtCfg);

}

});

Ext.reg('dashboardTabSummaryGrid', dashboardTabSummaryGrid);


dashboardTabSummaryGrid.descriptionRenderer = function(value, metadata, record, rowIndex, colIndex, store){
//if (rowIndex == 0) return '';

if (record.get('_is_leaf') === false && record.get('datefr') && record.get('datefr') != '') {

var dateStore = Ext.StoreMgr.item('dateStore');
var dateFr = record.get('datefr');
var dateTo = record.get('dateto');

var dateRec = dateStore.getById(dateFr);
if (dateRec) {
dateFr = dateRec.get('description');
} else {
dateFr = Date.parseDate(dateFr, 'Ymd').format('d/m/Y');
}

var dateRec = dateStore.getById(dateTo);
if (dateRec) {
dateTo = dateRec.get('description');
} else {
dateTo = Date.parseDate(dateTo, 'Ymd').format('d/m/Y');
}

return String.format('{0} ({1} - {2})', value, dateFr, dateTo);
} else {
return value;
}
};

The most important part for me at the moment is getting the Drag and Drop working on the locked side of the treegrid. At the moment I can only select the row by clicking on the locked column because of a kinda hack: -

var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

I want the row to be able to select normally if you click on either locked or unlocked columns. If this is fixed then I think that the drag and drop stuff will start working too!

Thanks

lukefowell89
15 Dec 2010, 2:51 AM
Setting Up Grid + Drag/Drop Stuff:




dashboardTabSummaryGrid = Ext.extend(Ext.ibc.DynamicColumnGridPanel, {
constructor: function(config) {
config = Ext.apply({
border : false,
trackMouseOver : false,
bodyStyle : 'border-top: 0;',
parameterType : 1,
templateID : config.queryRecord.get('TemplateID'),
enableDragDrop : true,
ddGroup :'dashboardTabSummaryGridDropZone',
contextMenu : Ext.getCmp('dashboardTabSummaryMenu')
}, config);

dashboardTabSummaryGrid.superclass.constructor.call(this, config);
},

initComponent: function() {
dashboardTabSummaryGrid.superclass.initComponent.apply(this, arguments);

this.store.grid = this;

this.on('cellclick', this.onCellClick, this);
this.on('beforecontextmenu', this.onBeforeContextMenu, this);
this.on('columnmove', this.onColumnMove, this);
this.on('columnresize', this.onColumnResize, this);
this.on('rowclick', this.onRowSelect, this);
},

onRowSelect: function(grid, row, e)
{
this.selModel.selectRow(row);
},

onColumnMove: function(oldIndex, newIndex) {

var columns = this.getColumnModel().config;
var nodes = [];
Ext.each(columns,function(column){
if (column.id != "master")
nodes.push(column.id);
});

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: {
action: 'REORDER',
nodes: nodes.join(',')
},
failure : function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onColumnResize: function(columnIndex, newSize) {
},

onCellClick: function(grid, rowIndex, columnIndex, e) {

var targetIndex = this.getView().findRowIndex(e.getTarget());
this.selModel.selectRow(targetIndex);

var summaryGrid = grid;
var detailTab = Ext.getCmp(grid.queryRecord.get('TemplateID') + 'DETAILTAB');

var record = this.selModel.getSelected();

if (grid.store.isLeafNode(record)) {
var tabHeight = summaryGrid.ownerCt.container.getHeight();
var newHeight = tabHeight - (summaryGrid.store.data.length * 19) - 100;

if (newHeight < 300) newHeight = 300;

detailTab.makeVisible(newHeight, record.get('Heading'));
detailTab.loadData(record.get('UserRuleName'), this.queryRecord.get('DetailTemplateID'), record, grid.queryRecord.get('TemplateID'));
}
},

onBeforeContextMenu: function(menu, record, column, rowindex) {
if (record.get('_is_leaf') === false) {
menu.enableDates();
} else {
menu.disableDates();
}

if (rowindex) {
menu.enableDeleteRow();
} else {
menu.disableDeleteRow();
}

if (column) {
menu.enableEdit();
} else {
menu.disableEdit();
}

menu.configure();
menu.doLayout();
},

setColumnAlignment: function(alignement) {
columnModel = this.getColumnModel().config;
columnModel[this.selectedColumn].align = alignement;
this.getColumnModel().setConfig(columnModel);

var column = columnModel[this.selectedColumn];
var params = {
//templateid: this._templateid,
id: column.id,
action: 'UPDATE',
number: column.number,
heading: column.header,
negativecolor: column.negativeColor,
renderer: column.renderer,
//invert: column.invert,
//calccolumn1: this._calccolumn1.getValue(),
//calcoperator: this._calcoperator.getValue(),
//calccolumn2: this._calccolumn2.getValue(),
columnalign: column.align,
//columntype: this._columntype.getValue(),
symbol: column.symbol,
ruleparameter: column.tagname
};

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: params,
scope: this,
failure: function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onRender: function(grid) {
dashboardTabSummaryGrid.superclass.onRender.apply(this, arguments);

var dropZoneOverrides = {
ddGroup : 'dashboardTabSummaryGridDropZone',
onContainerOver : function(ddSrc, evtObj, ddData) {
var destGrid = this.grid;
var tgtEl = evtObj.getTarget();
var destIndex = destGrid.getView().findRowIndex(tgtEl);
var destStore = destGrid.store;

var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
lockedBody = lockedScroller.child('div.x-grid3-body'),
scroller = mainWrap.child('div.x-grid3-scroller');

this.clearDDStyles();

if (destIndex === false) return;


// if drag before first row
if (destIndex == 0) destIndex = 1;
destIndex = (destStore.getCount() == 1 ? 0 : destIndex);

// is this a row?
if (typeof destIndex === 'number') {
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);

var tgtRowEl = Ext.get(tgtRow);
var tgtLockedRowEl = Ext.get(tgtLockedRow);
var tgtRowHeight = tgtRowEl.getHeight();
var tgtRowTop = tgtRowEl.getY();
var tgtRowCtr = tgtRowTop + Math.floor(tgtRowHeight / 2);

var tgtLockedRowHeight = tgtLockedRowEl.getHeight();
var tgtLockedRowTop = tgtLockedRowEl.getY();
var tgtLockedRowCtr = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 2);
var mouseY = evtObj.getXY()[1];

var tgtRow1 = tgtRowEl.getY();
var tgtRow2 = tgtRowTop + Math.floor(tgtRowHeight / 3);
var tgtRow3 = tgtRowTop + (Math.floor(tgtRowHeight / 3) * 2);

var tgtLockedRow1 = tgtLockedRowEl.getY();
var tgtLockedRow2 = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 3);
var tgtLockedRow3 = tgtLockedRowTop + (Math.floor(tgtLockedRowHeight / 3) * 2);

var destGrid = this.grid;
var destStore = destGrid.store;
var destRecord = destStore.getAt(destIndex);

var destPreviousRecord = destStore.getAt(destIndex-1);

if (destRecord.data._is_leaf) {
// below
if (mouseY >= tgtRowCtr) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// above
else if (mouseY < tgtRowCtr) {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');
tgtLockedRowEl.addClass('gridRowInsertTopLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}

} else {




// if root folder, insert below only
if (destIndex == 0) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');


// below
} else if (mouseY >= tgtRow3) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// middle
else if (mouseY >= tgtRow2) {
this.point = 'middle';
//destIndex ++;
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine')
}
// above
else {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');

tgtLockedRowEl.addClass('gridRowInsertTomLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}
}


this.overRow = [tgtRowEl, tgtLockedRowEl];
}
else {
destIndex = destGrid.store.getCount();
}

this.destIndex = destIndex;

//destGrid.body.addClass('gridBodyNotifyOver');

return this.dropAllowed;
},
notifyOut : function() {
this.clearDDStyles();
},
clearDDStyles : function() {
//this.grid.body.removeClass('gridBodyNotifyOver');
if (this.overRow) {
this.overRow[0].removeClass('table-drop-pin');

this.overRow[0].removeClass('gridRowInsertBottomLine');
this.overRow[0].removeClass('gridRowInsertMiddleLine');
this.overRow[0].removeClass('gridRowInsertTopLine');
this.overRow[1].removeClass('gridRowInsertBottomLine');
this.overRow[1].removeClass('gridRowInsertTopLine');
delete this.overRow;
}
},
onContainerDrop : function(ddSrc, evtObj, ddData){
if (!this.overRow) return;

var srcGrid = ddSrc.view.grid;
var srcStore = srcGrid.store;
var srcIndex = ddData.rowIndex;
var records = ddSrc.dragData.selections;
var srcRecord = records[0];

var destGrid = this.grid;
var destStore = destGrid.store;
var destIndex = this.destIndex > destStore.getCount() ? destStore.getCount() : this.destIndex;
var destRecord = destStore.getAt(destIndex);
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);


// clear grid drag styles
this.clearDDStyles();

// exit if destRecord is undefined or source and dest are the same
if (srcGrid.id == destGrid.id && srcIndex == destIndex) return false;
if (!destRecord) return false;

if (destStore.getCount() > 1) {

// set destRecord to parent folder if leaf selected
if (destRecord.data._is_leaf) {
destRecord = destStore.getNodeParent(destRecord);

if (this.point == 'above') {
destIndex--;
}

} else {
// if Top of folder, check previous sibling for expanded
if (this.point == 'above') {
var prevRecord = destStore.getNodePrevSibling(destRecord);
destRecord = destStore.getNodeParent(destRecord);
destIndex--;
}

// if middle of folder, destRecord doesnt change
if (this.point == 'middle') {
}

// if bottom of folder, check expanded
if (this.point == 'below') {
if (!destRecord.ux_maximgb_tg_expanded) {
destRecord = destStore.getNodeParent(destRecord);
}
}
}
}



if (srcGrid.type == "custom_items") {

// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
{name: 'Heading'}
]);

srcRecord = records[0];

// create Record and add to store
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:false,
Description:data.Heading,
ParentItemID:data._parent
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:false,
Heading:theRequest.data.Heading
}, x.id);

destStore.clearFieldsInRec(rc);
destStore.insert(destIndex+1, rc);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);

//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});


// ************************************************************************
// Show edit row name window
// ************************************************************************

destGrid.getSelectionModel().selectRecords([rc]);
destGrid.selectedRecord = rc;

var editRowName = Ext.getCmp('editRowName');
editRowName.edit(destGrid);
},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});




} else if (srcGrid.type == "rule_items") {
// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
'UserRuleName',
'Heading'
]);

// create Record and add to store
Ext.each(records,function(srcRecord){
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:true,
Description:data.Heading,
ParentItemID:data._parent,
UserRule:data.UserRuleName
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:theRequest.data._is_leaf,
UserRuleName:theRequest.data.UserRuleName,
Heading:theRequest.data.Heading
}, x.id);
destStore.insert(destIndex+1, rc);
destGrid.getSelectionModel().selectRecords([rc]);

destStore.applySort();
destGrid.view.refresh(true);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});



// ************************************************************************
// update rule data in realtime - dont refresh whole grid
// ************************************************************************


Ext.Ajax.request({
scope:this,
grid: destGrid,
rc: rc,
url: 'services/tree-run.exec',
params: {
userrulename : rc.get('UserRuleName'),
summary : 1,
id : destGrid.templateID
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);
x.data = x.data[0];

var ancestors = destStore.getNodeAncestors(theRequest.rc);

destStore.copyToRec(theRequest.rc, x);
destStore.addToAncestors(ancestors, theRequest.rc);

destGrid.view.refresh(true);
},
failure: function (theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});



},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});

});


} else {
// reorder rules
var record = records[0];
var ancestors = destStore.getNodeAncestors(record);

// subtract values from current ancestors
destStore.subtractFromAncestors(ancestors, record);

// move record to correct location
//if (srcIndex < destIndex) destIndex--;

// move record to new parent
//destStore.move(record,destIndex);
// set a new parent id
record.set('_parent',destRecord.get('_id'));

//sort grid and get new ancestors
//this.grid.store.applyTreeSort();
ancestors = destStore.getNodeAncestors(record);

// add values to new ancestors
destStore.addToAncestors(ancestors, record);

// Save new order and partent ids

// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************


var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: record.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
Ext.Msg.alert('Error','Error saving the changes');
}
});



// update the grid
//this.grid.store.applyTreeSort();
destStore.applySort();
destGrid.view.refresh(true);
}



return true;
}
};
// This will make sure we only drop to the view container
var leftGridDroptgtCfg = Ext.apply({}, dropZoneOverrides, {
grid : this
});
new Ext.dd.DropZone(this.el, leftGridDroptgtCfg);

}

});

Ext.reg('dashboardTabSummaryGrid', dashboardTabSummaryGrid);


dashboardTabSummaryGrid.descriptionRenderer = function(value, metadata, record, rowIndex, colIndex, store){
//if (rowIndex == 0) return '';

if (record.get('_is_leaf') === false && record.get('datefr') && record.get('datefr') != '') {

var dateStore = Ext.StoreMgr.item('dateStore');
var dateFr = record.get('datefr');
var dateTo = record.get('dateto');

var dateRec = dateStore.getById(dateFr);
if (dateRec) {
dateFr = dateRec.get('description');
} else {
dateFr = Date.parseDate(dateFr, 'Ymd').format('d/m/Y');
}

var dateRec = dateStore.getById(dateTo);
if (dateRec) {
dateTo = dateRec.get('description');
} else {
dateTo = Date.parseDate(dateTo, 'Ymd').format('d/m/Y');
}

return String.format('{0} ({1} - {2})', value, dateFr, dateTo);
} else {
return value;
}
};

Mainly I need the drag and drop stuff to work. The problem being that I cannot drag or select anything from the locked column, which means none of my drag and drop stuff will work.

I need to be able to select the row normally, so the drag and drop stuff works, and where I have set enableDragDrop in the grid, this means that the locked column shares the same DragZone etc.

Any ideas?

lukefowell89
15 Dec 2010, 6:48 AM
Seting up Grid + Drag And Drop Stuff




dashboardTabSummaryGrid = Ext.extend(Ext.ibc.DynamicColumnGridPanel, {
constructor: function(config) {
config = Ext.apply({
border : false,
trackMouseOver : false,
bodyStyle : 'border-top: 0;',
parameterType : 1,
templateID : config.queryRecord.get('TemplateID'),
enableDragDrop : true,
ddGroup :'dashboardTabSummaryGridDropZone',
contextMenu : Ext.getCmp('dashboardTabSummaryMenu')
}, config);

dashboardTabSummaryGrid.superclass.constructor.call(this, config);
},

initComponent: function() {
dashboardTabSummaryGrid.superclass.initComponent.apply(this, arguments);

this.store.grid = this;


this.on('cellclick', this.onCellClick, this);
this.on('beforecontextmenu', this.onBeforeContextMenu, this);
this.on('columnmove', this.onColumnMove, this);
this.on('columnresize', this.onColumnResize, this);
this.on('rowclick', this.onRowSelect, this);
},

onRowSelect: function(grid, row, e)
{
this.selModel.selectRow(row);
},

onColumnMove: function(oldIndex, newIndex) {

var columns = this.getColumnModel().config;
var nodes = [];
Ext.each(columns,function(column){
if (column.id != "master")
nodes.push(column.id);
});

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: {
action: 'REORDER',
nodes: nodes.join(',')
},
failure : function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onColumnResize: function(columnIndex, newSize) {
},

onCellClick: function(grid, rowIndex, columnIndex, e) {
//var targetIndex = this.getView().findRowIndex(e.getTarget());
//this.selModel.selectRow(targetIndex);

var summaryGrid = grid;
var detailTab = Ext.getCmp(grid.queryRecord.get('TemplateID') + 'DETAILTAB');

var record = this.selModel.getSelected();
console.log(this.selModel);

if (grid.store.isLeafNode(record)) {
var tabHeight = summaryGrid.ownerCt.container.getHeight();
var newHeight = tabHeight - (summaryGrid.store.data.length * 19) - 100;

if (newHeight < 300) newHeight = 300;

detailTab.makeVisible(newHeight, record.get('Heading'));
detailTab.loadData(record.get('UserRuleName'), this.queryRecord.get('DetailTemplateID'), record, grid.queryRecord.get('TemplateID'));
}
},

onBeforeContextMenu: function(menu, record, column, rowindex) {
if (record.get('_is_leaf') === false) {
menu.enableDates();
} else {
menu.disableDates();
}

if (rowindex) {
menu.enableDeleteRow();
} else {
menu.disableDeleteRow();
}

if (column) {
menu.enableEdit();
} else {
menu.disableEdit();
}

menu.configure();
menu.doLayout();
},

setColumnAlignment: function(alignement) {
columnModel = this.getColumnModel().config;
columnModel[this.selectedColumn].align = alignement;
this.getColumnModel().setConfig(columnModel);

var column = columnModel[this.selectedColumn];
var params = {
//templateid: this._templateid,
id: column.id,
action: 'UPDATE',
number: column.number,
heading: column.header,
negativecolor: column.negativeColor,
renderer: column.renderer,
//invert: column.invert,
//calccolumn1: this._calccolumn1.getValue(),
//calcoperator: this._calcoperator.getValue(),
//calccolumn2: this._calccolumn2.getValue(),
columnalign: column.align,
//columntype: this._columntype.getValue(),
symbol: column.symbol,
ruleparameter: column.tagname
};

Ext.Ajax.request({
url: 'services/tree-column.exec',
params: params,
scope: this,
failure: function(theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});
},

onRender: function(grid) {
dashboardTabSummaryGrid.superclass.onRender.apply(this, arguments);

var dropZoneOverrides = {
ddGroup : 'dashboardTabSummaryGridDropZone',
onContainerOver : function(ddSrc, evtObj, ddData) {
var destGrid = this.grid;
var tgtEl = evtObj.getTarget();
var destIndex = destGrid.getView().findRowIndex(tgtEl);
var destStore = destGrid.store;

var el = Ext.get(this.grid.getGridEl().dom.firstChild),
lockedWrap = el.child('div.x-grid3-locked'),
lockedHd = lockedWrap.child('div.x-grid3-header'),
lockedScroller = lockedWrap.child('div.x-grid3-scroller'),
mainWrap = el.child('div.x-grid3-viewport'),
mainHd = mainWrap.child('div.x-grid3-header'),
lockedBody = lockedScroller.child('div.x-grid3-body'),
scroller = mainWrap.child('div.x-grid3-scroller');

this.clearDDStyles();

if (destIndex === false) return;


// if drag before first row
if (destIndex == 0) destIndex = 1;
destIndex = (destStore.getCount() == 1 ? 0 : destIndex);

// is this a row?
if (typeof destIndex === 'number') {
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);

var tgtRowEl = Ext.get(tgtRow);
var tgtLockedRowEl = Ext.get(tgtLockedRow);
var tgtRowHeight = tgtRowEl.getHeight();
var tgtRowTop = tgtRowEl.getY();
var tgtRowCtr = tgtRowTop + Math.floor(tgtRowHeight / 2);

var tgtLockedRowHeight = tgtLockedRowEl.getHeight();
var tgtLockedRowTop = tgtLockedRowEl.getY();
var tgtLockedRowCtr = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 2);
var mouseY = evtObj.getXY()[1];

var tgtRow1 = tgtRowEl.getY();
var tgtRow2 = tgtRowTop + Math.floor(tgtRowHeight / 3);
var tgtRow3 = tgtRowTop + (Math.floor(tgtRowHeight / 3) * 2);

var tgtLockedRow1 = tgtLockedRowEl.getY();
var tgtLockedRow2 = tgtLockedRowTop + Math.floor(tgtLockedRowHeight / 3);
var tgtLockedRow3 = tgtLockedRowTop + (Math.floor(tgtLockedRowHeight / 3) * 2);

var destGrid = this.grid;
var destStore = destGrid.store;
var destRecord = destStore.getAt(destIndex);

var destPreviousRecord = destStore.getAt(destIndex-1);

if (destRecord.data._is_leaf) {
// below
if (mouseY >= tgtRowCtr) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// above
else if (mouseY < tgtRowCtr) {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');
tgtLockedRowEl.addClass('gridRowInsertTopLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}

} else {




// if root folder, insert below only
if (destIndex == 0) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');


// below
} else if (mouseY >= tgtRow3) {
this.point = 'below';
//destIndex ++;
tgtRowEl.addClass('gridRowInsertBottomLine');
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');

tgtLockedRowEl.addClass('gridRowInsertBottomLine');
tgtLockedRowEl.removeClass('gridRowInsertTopLine');
}
// middle
else if (mouseY >= tgtRow2) {
this.point = 'middle';
//destIndex ++;
tgtRowEl.removeClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertBottomLine')
}
// above
else {
this.point = 'above';
tgtRowEl.addClass('gridRowInsertTopLine');
tgtRowEl.removeClass('gridRowInsertMiddleLine');
tgtRowEl.removeClass('gridRowInsertBottomLine');

tgtLockedRowEl.addClass('gridRowInsertTomLine');
tgtLockedRowEl.removeClass('gridRowInsertBottomLine');
}
}


this.overRow = [tgtRowEl, tgtLockedRowEl];
}
else {
destIndex = destGrid.store.getCount();
}

this.destIndex = destIndex;

//destGrid.body.addClass('gridBodyNotifyOver');

return this.dropAllowed;
},
notifyOut : function() {
this.clearDDStyles();
},
clearDDStyles : function() {
//this.grid.body.removeClass('gridBodyNotifyOver');
if (this.overRow) {
this.overRow[0].removeClass('table-drop-pin');

this.overRow[0].removeClass('gridRowInsertBottomLine');
this.overRow[0].removeClass('gridRowInsertMiddleLine');
this.overRow[0].removeClass('gridRowInsertTopLine');
this.overRow[1].removeClass('gridRowInsertBottomLine');
this.overRow[1].removeClass('gridRowInsertTopLine');
delete this.overRow;
}
},
onContainerDrop : function(ddSrc, evtObj, ddData){
if (!this.overRow) return;

var srcGrid = ddSrc.view.grid;
var srcStore = srcGrid.store;
var srcIndex = ddData.rowIndex;
var records = ddSrc.dragData.selections;
var srcRecord = records[0];

var destGrid = this.grid;
var destStore = destGrid.store;
var destIndex = this.destIndex > destStore.getCount() ? destStore.getCount() : this.destIndex;
var destRecord = destStore.getAt(destIndex);
var tgtRow = destGrid.getView().getRow(destIndex);
var tgtLockedRow = destGrid.getView().getLockedRow(destIndex);


// clear grid drag styles
this.clearDDStyles();

// exit if destRecord is undefined or source and dest are the same
if (srcGrid.id == destGrid.id && srcIndex == destIndex) return false;
if (!destRecord) return false;

if (destStore.getCount() > 1) {

// set destRecord to parent folder if leaf selected
if (destRecord.data._is_leaf) {
destRecord = destStore.getNodeParent(destRecord);

if (this.point == 'above') {
destIndex--;
}

} else {
// if Top of folder, check previous sibling for expanded
if (this.point == 'above') {
var prevRecord = destStore.getNodePrevSibling(destRecord);
destRecord = destStore.getNodeParent(destRecord);
destIndex--;
}

// if middle of folder, destRecord doesnt change
if (this.point == 'middle') {
}

// if bottom of folder, check expanded
if (this.point == 'below') {
if (!destRecord.ux_maximgb_tg_expanded) {
destRecord = destStore.getNodeParent(destRecord);
}
}
}
}



if (srcGrid.type == "custom_items") {

// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
{name: 'Heading'}
]);

srcRecord = records[0];

// create Record and add to store
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:false,
Description:data.Heading,
ParentItemID:data._parent
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:false,
Heading:theRequest.data.Heading
}, x.id);

destStore.clearFieldsInRec(rc);
destStore.insert(destIndex+1, rc);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);

//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});


// ************************************************************************
// Show edit row name window
// ************************************************************************

destGrid.getSelectionModel().selectRecords([rc]);
destGrid.selectedRecord = rc;

var editRowName = Ext.getCmp('editRowName');
editRowName.edit(destGrid);
},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});




} else if (srcGrid.type == "rule_items") {
// insert a new rule from the rules list
var rec = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_parent', type: 'auto'},
{name: '_is_leaf', type: 'bool'},
'UserRuleName',
'Heading'
]);

// create Record and add to store
Ext.each(records,function(srcRecord){
var data = {
_parent:destRecord.data._id,
_is_leaf:true,
UserRuleName:srcRecord.data.name,
Heading:srcRecord.data.description
};

Ext.Ajax.request({
scope:this,
grid: this,
data: data,
url: 'services/tree-item.exec',
params: {
Action:'INSERT',
Leaf:true,
Description:data.Heading,
ParentItemID:data._parent,
UserRule:data.UserRuleName
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);

var rc = new rec({
_id:x.id,
_parent:theRequest.data._parent,
_is_leaf:theRequest.data._is_leaf,
UserRuleName:theRequest.data.UserRuleName,
Heading:theRequest.data.Heading
}, x.id);
destStore.insert(destIndex+1, rc);
destGrid.getSelectionModel().selectRecords([rc]);

destStore.applySort();
destGrid.view.refresh(true);



// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************
var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: x.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
//Ext.Msg.alert('Error','Error saving the changes');
}
});



// ************************************************************************
// update rule data in realtime - dont refresh whole grid
// ************************************************************************


Ext.Ajax.request({
scope:this,
grid: destGrid,
rc: rc,
url: 'services/tree-run.exec',
params: {
userrulename : rc.get('UserRuleName'),
summary : 1,
id : destGrid.templateID
},
success: function (response, theRequest) {
x = Ext.decode(response.responseText);
x.data = x.data[0];

var ancestors = destStore.getNodeAncestors(theRequest.rc);

destStore.copyToRec(theRequest.rc, x);
destStore.addToAncestors(ancestors, theRequest.rc);

destGrid.view.refresh(true);
},
failure: function (theResponse, theRequest) {
throw('Failed to get response from server - ' + theResponse.responseText);
}
});



},
failure: function (theResponse, theRequest) {
this.editWindow.hide();
throw('Failed to get response from server - ' + theResponse.responseText);
}
});

});


} else {
// reorder rules
var record = records[0];
var ancestors = destStore.getNodeAncestors(record);

// subtract values from current ancestors
destStore.subtractFromAncestors(ancestors, record);

// move record to correct location
//if (srcIndex < destIndex) destIndex--;

// move record to new parent
//destStore.move(record,destIndex);
// set a new parent id
record.set('_parent',destRecord.get('_id'));

//sort grid and get new ancestors
//this.grid.store.applyTreeSort();
ancestors = destStore.getNodeAncestors(record);

// add values to new ancestors
destStore.addToAncestors(ancestors, record);

// Save new order and partent ids

// ************************************************************************
// SAVE REORDER OF NODES WITHIN FOLDER
// ************************************************************************


var childRecords = destStore.getNodeChildren(destRecord)

var nodes = [];
Ext.each(childRecords,function(record){
nodes.push(record.id);
});

//this.el.mask('Saving…', 'x-mask-loading');

Ext.Ajax.request({
url: 'services/tree-item.exec',

params: {
action: 'REORDER',
nodes: nodes.join(','),
id: record.id,
ParentItemID: destRecord.id
},

success: function(){
//tree.el.unmask();
},

failure: function(theResponse, theRequest){
throw('Failed to get response from server - ' + theResponse.responseText);
//tree.el.unmask();
Ext.Msg.alert('Error','Error saving the changes');
}
});



// update the grid
//this.grid.store.applyTreeSort();
destStore.applySort();
destGrid.view.refresh(true);
}



return true;
}
};
// This will make sure we only drop to the view container
var leftGridDroptgtCfg = Ext.apply({}, dropZoneOverrides, {
grid : this
});
new Ext.dd.DropZone(this.el, leftGridDroptgtCfg);

}

});

Ext.reg('dashboardTabSummaryGrid', dashboardTabSummaryGrid);


dashboardTabSummaryGrid.descriptionRenderer = function(value, metadata, record, rowIndex, colIndex, store){
//if (rowIndex == 0) return '';

if (record.get('_is_leaf') === false && record.get('datefr') && record.get('datefr') != '') {

var dateStore = Ext.StoreMgr.item('dateStore');
var dateFr = record.get('datefr');
var dateTo = record.get('dateto');

var dateRec = dateStore.getById(dateFr);
if (dateRec) {
dateFr = dateRec.get('description');
} else {
dateFr = Date.parseDate(dateFr, 'Ymd').format('d/m/Y');
}

var dateRec = dateStore.getById(dateTo);
if (dateRec) {
dateTo = dateRec.get('description');
} else {
dateTo = Date.parseDate(dateTo, 'Ymd').format('d/m/Y');
}

return String.format('{0} ({1} - {2})', value, dateFr, dateTo);
} else {
return value;
}
};

The main issue is the drag and drop stuff. It isnt working because the locked column doenst seem to select normally, it doesnt highlight on mouseover, or when I click on it, It doesnt do anything.

If I can get the locked column to select fine, then it should do the drag and drop stuff fine. At the moment, the unlocked columns rows select fine and can be draged.

For some reason when i show the grid on the console, it's dom is the entire grid, which is correct, but when I put the dragZone to the console, the _domRef only highlights the unlocked side? I dont understand why it does this when I cannot see it specified anywhere why that section of the grid should be selected and not the whole thing?

Thanks

lukefowell89
15 Dec 2010, 6:49 AM
Why do my posts keep saying they need to be approved by a moderator?