PDA

View Full Version : Latest code for ColumnTree



mviens
27 Oct 2008, 9:13 AM
I have taken all of the posts in this thread (http://extjs.com/forum/showthread.php?t=25076) and merged the updates into what I hope is the latest code. I am posting it here so that someone can confirm this is indeed the latest revision, and also to provide a starting point for newer users.

Ultimately, I would like to see this code get moved into the Central ux repository at: http://extjs-ux.org

code.html


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Menu Configuration</title>
<link rel="stylesheet" type="text/css" href="../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="editable-column-tree.css" />
<script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-all.js"></script>
<!--script type="text/javascript" src="ColumnModel_Hook.js"></script-->
<script type="text/javascript" src="ColumnNodeUI.js"></script>
<script type="text/javascript" src="ColumnTreeEditor.js"></script>
<script type="text/javascript" src="editor_test.js"></script>
</head>
<body>
<table border="0" width="100%" height="100%">
<tr>
<td align="center" valign="top" style="padding-top:25px;">
<div id="tree-ct" style="text-align:left"></div>
</td>
</tr>
</table>
</body>
</html>



editable-column-tree.css (adjust image paths as appropriate)


.x-column-tree.x-tree-node {
zoom: 1;
}

.x-column-tree.x-tree-node-el {
/*border-bottom:1px solid #eee; borders? */
zoom: 1;
}

.x-column-tree.x-tree-selected {
background: #d9e8fb;
}

.x-column-tree.x-tree-node a {
line-height: 18px;
vertical-align: middle;
}

.x-column-tree.x-tree-node a span { }

.x-column-tree .x-tree-node .x-tree-selected a span {
background: transparent;
color: #000;
}

.x-tree-col {
float: left;
overflow: hidden;
padding: 0 1px;
zoom: 1;
}

.x-tree-col-text, .x-tree-hd-text {
overflow: hidden;

-o-text-overflow: ellipsis;
text-overflow: ellipsis;
padding: 3px 3px 3px 5px;
white-space: nowrap;
height: 1.2em; /*height:20px;*/
font: normal 11px arial, tahoma, helvetica, sans-serif;
}

.x-tree-hd-text {
height: 1.3em; /*height:20px;*/
}

.x-tree-headers {
background: #f9f9f9 url(../resources/images/default/grid/grid3-hrow.gif) repeat-x 0 bottom;
cursor: default;
zoom: 1;
}

.x-tree-hd {
float: left;
overflow: hidden;
border-left: 1px solid #eee;
border-right: 1px solid #d0d0d0;
}

.page-icon {
background-image: url(../../icons/add.png) !important;
}

.delete-icon {
background-image: url(../../icons/delete.png) !important;
}

.folder-icon {
background-image: url(../../icons/folder_add.png) !important;
}

.save-icon {
background-image: url(../../images/disk.gif) !important;
}



ColumnEditor.js


Ext.tree.ColumnTreeEditor = function(tree, colIndex, editorConfig)
{
var field;

if (editorConfig.xtype)
{
field = new Ext.ComponentMgr.create(editorConfig);
Ext.tree.ColumnTreeEditor.superclass.constructor.call(this, field);
}
else
{
field = {};
}

this.tree = tree;
this.columnIndex = colIndex;

if (! this.tree.rendered)
{
this.tree.on('render', this.initEditor, this);
}
else
{
this.initEditor(this.tree);
}
};

Ext.extend(Ext.tree.ColumnTreeEditor, Ext.Editor,
{
onTargetBeforeClick: function(node, event)
{
var sinceLast = (this.lastClick ? this.lastClick.getElapsed() : 0);
this.lastClick = new Date();

if (sinceLast <= this.editDelay || !this.tree.getSelectionModel().isSelected(node))
{
this.completeEdit();
}
var obj = event.target;

if (Ext.select('.x-tree-node-anchor', false, obj).getCount() == 1)
{
obj = Ext.select('.x-tree-node-anchor', false, obj).elements[0].firstChild;
}

if (obj.nodeName != 'SPAN' && obj.nodeName != 'DIV')
{
return true;
}
var colIndex = 0;

if (this.tree.fireEvent('beforecelledit', this.tree, node, this.columnIndex) === false)
{
return true;
}

var elt = Ext.Element.fly(obj);
if (elt.hasClass('x-tree-col-' + this.columnIndex))
{
this.triggerEdit(node, event, this.columnIndex);
event.stopEvent();
return false;
}
else
{
return true;
}
},
alignment: 'l-l',
autoSize: false,
hideEl: false,
cls: 'x-small-editor x-tree-editor',
shim: false,
shadow: 'frame',
maxWidth: 250,
editDelay: 0,
initEditor: function(tree)
{
this.tree.on('beforeclick', this.onTargetBeforeClick, this);
this.on('complete', this.updateNode, this);
//this.on('beforestartedit', this.fitToTree, this);
this.on('startedit', this.bindScroll, this,
{
delay: 10
});

this.on('specialkey', this.onSpecialKey, this);
},
fitToTree: function(ed, el)
{
var td = this.tree.getTreeEl().dom, nd = el.dom;

if (td.scrollLeft > nd.offsetLeft)
{
td.scrollLeft = nd.offsetLeft;
}
var w = Math.min(this.maxWidth, (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft - td.scrollLeft) - 5);
this.setSize(w, '');
},
triggerEdit: function(node, e, colIndex)
{
var obj = e.target;

if (Ext.select('.x-tree-node-anchor', false, obj).getCount() == 1)
{
obj = Ext.select('.x-tree-node-anchor', false, obj).elements[0].firstChild;
}
else if (obj.nodeName == 'SPAN' || obj.nodeName == 'DIV')
{
obj = e.target;
}
else
{
return false;
}

this.completeEdit();
this.editNode = node;
this.editCol = obj;
this.editColIndex = colIndex;
this.startEdit(obj);

if (obj.nodeName == 'DIV')
{
var width = obj.offsetWidth;
this.setSize(width);
}
},
bindScroll: function()
{
this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
},
beforeNodeClick: function(node, e)
{
var sinceLast = (this.lastClick ? this.lastClick.getElapsed() : 0);
this.lastClick = new Date();

if (sinceLast > this.editDelay && this.tree.getSelectionModel().isSelected(node))
{
e.stopEvent();
this.triggerEdit(node, e);
return false;
}
else
{
this.completeEdit();
}
},
updateNode: function(ed, value)
{
if (value != '' && value != this.editCol.innerHTML)
{
value = (this.editNode.renderers[this.editColIndex].renderer ? this.editNode.renderers[this.editColIndex].renderer(value) : value);
this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
this.editNode.cols[this.editColIndex] = value; //for internal use only
this.editNode.attributes[this.editColIndex] = value; //duplicate into array of node attributes
this.editCol.innerHTML = value;
}
},

onHide: function()
{
Ext.tree.ColumnTreeEditor.superclass.onHide.call(this);
if (this.editNode)
{
this.editNode.ui.focus();
}
},
onSpecialKey: function(field, e)
{
var k = e.getKey();

if (k == e.ESC)
{
e.stopEvent();
this.cancelEdit();
}
else if (k == e.ENTER && !e.hasModifier())
{
e.stopEvent();
this.completeEdit();
}
}
});



ColumnNodeUI.js


Ext.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel,
{
lines: false,
borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
cls: 'x-column-tree',
collapsible: false,
onRender: function()
{
Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
this.headers = this.body.createChild(
{
cls: 'x-tree-headers'
}, this.innerCt.dom);

var cols = this.columns, c;
var totalWidth = 0;

for (var i = 0, len = cols.length; i < len; i++)
{
c = cols[i];
totalWidth += c.width;
this.headers.createChild(
{
cls: 'x-tree-hd ' + (c.cls ? c.cls + '-hd' : ''),
cn:
{
cls: 'x-tree-hd-text',
html: c.header
},
style: 'width:' + (c.width - this.borderWidth) + 'px;'
});
}

this.headers.createChild(
{
cls: 'x-clear'
});

// prevent floats from wrapping when clipped
this.headers.setWidth(totalWidth);
this.innerCt.setWidth(totalWidth);
},
initComponent: function()
{
Ext.tree.ColumnTree.superclass.initComponent.apply(this, arguments);
this.addEvents('beforecelledit');
for (var i = 0; i < this.columns.length; i++)
{
var col = this.columns[i];

if (col.editorField)
{
var editor = new Ext.tree.ColumnTreeEditor(this, col.dataIndex, col.editorField);
this.editor = editor;
}
}
}
});

Ext.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI,
{
focus: Ext.emptyFn, // prevent odd scrolling behavior
renderElements: function(n, a, targetNode, bulkRender)
{
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

var t = n.getOwnerTree();
var cols = t.columns;
var bw = t.borderWidth;
var c = cols[0];

n.cols = new Array();
n.renderers = new Array();

var text = n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]);
n.cols[cols[0].dataIndex] = text;

var buf =
[
'<li class="x-tree-node" unselectable="on"><div ext:tree-node-id="',
n.id,
'" class="x-tree-node-el x-tree-node-leaf ',
a.cls,
'" unselectable="on">',
'<div class="x-tree-col" style="width:',
c.width - bw,
'px;" unselectable="on">',
'<span class="x-tree-node-indent" unselectable="on">',
this.indentMarkup,
"</span>",
'<img src="',
this.emptyIcon,
'" class="x-tree-ec-icon x-tree-elbow" unselectable="on">',
'<img src="',
a.icon || this.emptyIcon,
'" class="x-tree-node-icon',
(a.icon ? ' x-tree-node-inline-icon' : ''),
(a.iconCls ? ' ' + a.iconCls : ''),
'" unselectable="on">',
'<a hidefocus="on" class="x-tree-node-anchor" href="',
a.href ? a.href : '#',
'" tabIndex="1" ',
a.hrefTarget ? ' target="' + a.hrefTarget + '"' : '',
' unselectable="on">',
'<span unselectable="on">',
text,
'</span></a>',
'</div>'
];

for (var i = 1, len = cols.length; i < len; i++)
{
c = cols[i];
var text = (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]);
n.cols[c.dataIndex] = text;
n.renderers[c.dataIndex] = { renderer: ( c.renderer ? c.renderer : false ) }
buf.push('<div class="x-tree-col ', (c.cls ? c.cls : ''), '" style="width:', c.width - bw,
'px;" unselectable="on">', '<div class="x-tree-col-text x-tree-col-', c.dataIndex, '" unselectable="on">', text, '</div>', '</div>');
}
buf.push('<div class="x-clear" unselectable="on"></div></div>',
'<ul class="x-tree-node-ct" style="display:none;" unselectable="on"></ul>', '</li>');

if (bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl())
{
this.wrap = Ext.DomHelper.insertHtml('beforeBegin', n.nextSibling.ui.getEl(), buf.join(''));
}
else
{
this.wrap = Ext.DomHelper.insertHtml('beforeEnd', targetNode, buf.join(''));
}

this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.firstChild.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
this.anchor = cs[3];
this.textNode = cs[3].firstChild;
}
});



editor_test.js


Ext.BLANK_IMAGE_URL = '../resources/images/default/s.gif';
Ext.onReady(function()
{
var store = new Ext.data.SimpleStore(
{
fields:
[
'chart_report'
],
data:
[
[
'Password Reset Summary'
],
[
'Password Reset By Agents'
]
]
});

var store2 = new Ext.data.SimpleStore(
{
fields:
[
'report'
],
data:
[
[
'Pasry'
],
[
'Pasents'
]
]
});

var combo_config =
{
id: 'chart_combo_list',
store: store,
displayField: 'chart_report',
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
width: 100,
emptyText: 'Please select report type...',
selectOnFocus: true
};

var combo_config2 =
{
id: 'chart_combo_list2',
store: store2,
displayField: 'report',
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
width: 100,
emptyText: 'Please select report type..',
selectOnFocus: true
};

var tree = new Ext.tree.ColumnTree(
{
el: 'tree-ct',
width: 700,
autoHeight: true,
rootVisible: false,
autoScroll: true,
expandable: false,
enableDD: true,
title: 'Menu Configuration',
tbar:
[
{
text: 'Save Menu',
tooltip: 'Save Menu',
iconCls: 'save-icon',
listeners:
{
'click': function()
{
var json = tree.toJsonString(null, function(key, val)
{
return (key == 'leaf' || key == 'id' || key == 'menu_item' || key == 'menu_url');
},
{
menu_item: 'text',
menu_url: 'href'
});
alert(json);
},
scope: this
}
},
{
xtype: 'tbseparator'
},
{
text: 'Add Folder Item',
tooltip: 'Add Folder Item',
iconCls: 'folder-icon',
listeners:
{
'click': function()
{
var selectedItem = tree.getSelectionModel().getSelectedNode();
if (! selectedItem)
{
selectedItem = tree.getRootNode();
}
handleCreate = function (btn, text, cBoxes)
{
if (btn == 'ok' && text)
{
var newNode = new Ext.tree.TreeNode(
{
menu_item: text,
menu_url: '',
leaf: false,
expandable: true,
uiProvider: Ext.tree.ColumnNodeUI
});
if (selectedItem.isLeaf())
{
selectedItem.parentNode.insertBefore(newNode, selectedItem.nextSibling);
}
else
{
selectedItem.insertBefore(newNode, selectedItem.firstChild);
}
}
}
Ext.MessageBox.show(
{
title: 'Add new Folder Item',
msg: 'Name of Folder Item:',
buttons: Ext.MessageBox.OKCANCEL,
prompt: true,
fn: handleCreate
});
}
}
},
{
xtype: 'tbseparator'
},
{
text: 'Add Page Item',
tooltip: 'Add Page Item',
iconCls: 'page-icon',
listeners:
{
'click': function()
{
var selectedItem = tree.getSelectionModel().getSelectedNode();
if (!selectedItem)
{
Ext.Msg.alert('Warning', 'Please select an Item after which you want to add a new one.');
return false;
}
handleCreate = function (btn, text, cBoxes)
{
if (btn == 'ok' && text)
{
var newNode = new Ext.tree.TreeNode(
{
menu_item: text,
menu_url: '',
leaf: true,
allowChildren: false,
uiProvider: Ext.tree.ColumnNodeUI
});
if (selectedItem.isLeaf())
{
selectedItem.parentNode.insertBefore(newNode, selectedItem.nextSibling);
}
else
{
selectedItem.insertBefore(newNode, selectedItem.firstChild);
}
}
}
Ext.MessageBox.show(
{
title: 'Add new Page Item',
msg: 'Name of Page Item:',
buttons: Ext.MessageBox.OKCANCEL,
prompt: true,
fn: handleCreate
});
}
}
},
{
xtype: 'tbseparator'
},
{
text: 'Delete Item',
tooltip: 'Delete Item',
iconCls: 'delete-icon',
listeners:
{
'click': function()
{
var selectedItem = tree.getSelectionModel().getSelectedNode();
if (!selectedItem)
{
Ext.Msg.alert('Warning', 'Please select an Item to delete.');
return false;
}
handleDelete = function (btn)
{
if (btn == 'ok')
{
selectedItem.remove();
}
}
Ext.MessageBox.show(
{
title: 'Confirm your action',
msg: 'Are you sure you want to delete this item and its children?',
buttons: Ext.MessageBox.OKCANCEL,
fn: handleDelete
});
}
}
},
{
xtype: 'tbseparator'
}
],
columns:
[
{
header: 'Menu Item',
width: 200,
dataIndex: 'menu_item'
// editorField: combo_config
},
{
header: 'URL',
width: 150,
dataIndex: 'menu_url',
editorField:
{
xtype: 'textfield',
editable: true
}
},
{
header: 'Approval Status',
width: 120,
dataIndex: 'approval',
editorField: combo_config2
}
],
loader: new Ext.tree.TreeLoader(
{
preloadChildren: true,
uiProviders:
{
'col': Ext.tree.ColumnNodeUI
}
}),
root: new Ext.tree.AsyncTreeNode(
{
allowChildren: true,
children:
[
{
menu_item: 'Current State',
menu_url: 'blah blah',
uiProvider: 'col',
approval: 'text',
children:
[
{
menu_item: 'Executive Summary',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability Scorecard',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability Distribution',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
}
]
},
{
menu_item: 'Trends',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
children:
[
{
menu_item: 'Host Changes',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Hosts and Vulnerability',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Application and Vulnerability',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability by Operation System',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability by Networks',
menu_url: 'blah blah',
approval: 'text',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability by Application Group',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
}
]
},
{
menu_item: 'Technical',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
children:
[
{
menu_item: 'Risk Matrix',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Host Inventory',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Application Inventory',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Vulnerability Inventory',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Most Common Vulnerabilites',
menu_url: 'blah blah',
uiProvider: 'col',
approval: '',
leaf: true
},
{
menu_item: 'Most Common SANS Vulnerabilities',
menu_url: 'blah blah',
uiProvider: 'col',
approval: '',
leaf: true
},
{
menu_item: 'Most Vulnerable Applications',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'Most Vulnerable Hosts',
menu_url: 'blah blah',
approval: '',
uiProvider: 'col',
leaf: true
},
{
menu_item: 'PCI Compliance',
menu_url: 'blah blah',
uiProvider: 'col',
approval: '',
leaf: true
}
]
}
]
})
});
tree.render();
tree.expandAll();

});


Mike V.

mjlecomte
27 Oct 2008, 11:02 AM
Hi. What are you waiting on to "move" it to the repo?

mviens
27 Oct 2008, 2:40 PM
To make sure that the code is working and updated.

Since posting it, I have found a couple of issues. I am hoping someone who has a good working copy (ie: one or more of the authors from the original thread) will post their version of the code, so I can make any final adjustments.

Mike V.

eseguin3
2 Dec 2008, 11:45 AM
I was wondering if any progress had been made with this. Is the above posted code in working, usable order?

Thanks

moegal
19 Jun 2009, 7:49 AM
how and where do I add a listener to see it an item has been edited? I would like to get the old and new value and the node id. I have been playing around a while but cannot figure out where to add the event(or is there is already one available) and then where to add the listener.

Any ideas?

Thanks, Marty

leeyesong
2 Mar 2010, 10:26 PM
how and where do I add a listener to see it an item has been edited? I would like to get the old and new value and the node id. I have been playing around a while but cannot figure out where to add the event(or is there is already one available) and then where to add the listener.

Any ideas?

Thanks, Marty

I want to know that, too.

manasaguli
5 Mar 2010, 3:28 PM
Any updates on the Latest code? I am looking for a stable code which i can use.
Please help.

moegal
5 Mar 2010, 7:03 PM
Here is what I am using and it seems to work with 3.1.1



/*
* Ext JS Library 2.0 RC 1
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/

Ext.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
lines:false,
borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
cls:'x-column-tree',
collapsible: false,

onRender : function(){
Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
this.headers = this.body.createChild(
{cls:'x-tree-headers'},this.innerCt.dom);

var cols = this.columns, c;
var totalWidth = 0;

for(var i = 0, len = cols.length; i < len; i++){
c = cols[i];
totalWidth += c.width;
this.headers.createChild({
cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
cn: {
cls:'x-tree-hd-text',
html: c.header
},
style:'width:'+(c.width-this.borderWidth)+'px;'
});
}
this.headers.createChild({cls:'x-clear'});
// prevent floats from wrapping when clipped
this.headers.setWidth(totalWidth);
this.innerCt.setWidth(totalWidth);
}
});


Ext.tree.ColumnNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
focus: Ext.emptyFn, // prevent odd scrolling behavior

renderElements : function(n, a, targetNode, bulkRender){
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

var t = n.getOwnerTree();
var cols = t.columns;
var bw = t.borderWidth;
var c = cols[0];

n.cols = new Array();

var text = n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]);
n.cols[cols[0].dataIndex] = text;

var buf = [
'<li class="x-tree-node" unselectable="on"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf ', a.cls,'" unselectable="on">',
'<div class="x-tree-col" style="width:',c.width-bw,'px;" unselectable="on">',
'<span class="x-tree-node-indent" unselectable="on">',this.indentMarkup,"</span>",
'<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" unselectable="on">',
'<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
'<a hidefocus="on" class="x-tree-node-anchor" href="',a.href ? a.href : "#",'" tabIndex="1" ',
a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", ' unselectable="on">',
'<span unselectable="on">', text,"</span></a>",
"</div>"];
for(var i = 1, len = cols.length; i < len; i++){
c = cols[i];
var text = (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]);
n.cols[cols[i].dataIndex] = text;
buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;" unselectable="on">',
'<div class="x-tree-col-text" unselectable="on">',text,"</div>",
"</div>");
}
buf.push(
'<div class="x-clear" unselectable="on"></div></div>',
'<ul class="x-tree-node-ct" style="display:none;" unselectable="on"></ul>',
"</li>");

if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
this.wrap = Ext.DomHelper.insertHtml("beforeBegin",
n.nextSibling.ui.getEl(), buf.join(""));
}else{
this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
}

this.elNode = this.wrap.childNodes[0];
this.ctNode = this.wrap.childNodes[1];
var cs = this.elNode.firstChild.childNodes;
this.indentNode = cs[0];
this.ecNode = cs[1];
this.iconNode = cs[2];
this.anchor = cs[3];
this.textNode = cs[3].firstChild;
}
});
Ext.tree.ColumnTreeEditor = function(tree, config){
config = config || {};
var field = config.events ? config : new Ext.form.TextField(config);
//var field = config.events ? config : new Ext.form.TriggerField(config);
Ext.tree.TreeEditor.superclass.constructor.call(this, field);

this.tree = tree;

if(!tree.rendered){
tree.on('render', this.initEditor, this);
}else{
this.initEditor(tree);
}
};

Ext.extend(Ext.tree.ColumnTreeEditor, Ext.Editor, {

alignment: "l-l",
autoSize: false,

hideEl : false,

cls: "x-small-editor x-tree-editor",

shim:false,
shadow:"frame",

maxWidth: 250,

editDelay: 0,

initEditor : function(tree){
tree.on('beforeclick', this.beforeNodeClick, this);
this.on('complete', this.updateNode, this);
this.on('beforestartedit', this.fitToTree, this);
this.on('startedit', this.bindScroll, this, {delay:10});
this.on('specialkey', this.onSpecialKey, this);
this.addEvents(
'updatedNode'
);
},

fitToTree : function(ed, el){
var td = this.tree.getTreeEl().dom, nd = el.dom;
if(td.scrollLeft > nd.offsetLeft){ td.scrollLeft = nd.offsetLeft;
}
var w = Math.min(
this.maxWidth,
(td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
this.setSize(w, '');
},

triggerEdit : function(node, e){
var obj = e.target;
if (Ext.select(".x-tree-node-anchor", false, obj).getCount() == 1) {
obj = Ext.select(".x-tree-node-anchor", false, obj).elements[0].firstChild;
} else if (obj.nodeName == 'SPAN' || obj.nodeName == 'DIV'){
obj = e.target;
} else {
return false;
}

var colIndex = 0;
for (var i in node.cols) {
if (node.cols[i] == obj.innerHTML) {
colIndex = i;
}
}
this.completeEdit();
this.editNode = node;
this.editCol = obj;
this.editColIndex = colIndex;
this.startEdit(obj);
if (obj.nodeName == 'DIV') {
var width = obj.offsetWidth;
this.setSize(width);
}
},

bindScroll : function(){
this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
},

beforeNodeClick : function(node, e){
var sinceLast = (this.lastClick ? this.lastClick.getElapsed() : 0);
this.lastClick = new Date();
if(sinceLast > this.editDelay && this.tree.getSelectionModel().isSelected(node)){
e.stopEvent();
this.triggerEdit(node, e);
return false;
} else {
this.completeEdit();
}
},

updateNode : function(ed, value){
this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
this.editNode.cols[this.editColIndex] = value; //for internal use only
this.editNode.attributes[this.editColIndex] = value;//duplicate into array of node attributes
var oldValue = this.editCol.innerHTML;
this.editCol.innerHTML = value;
this.tree.fireEvent('updatedNode', ed, value, oldValue);
},

onHide : function(){
Ext.tree.TreeEditor.superclass.onHide.call(this);
if(this.editNode){
this.editNode.ui.focus();
}
},

onSpecialKey : function(field, e){
var k = e.getKey();
if(k == e.ESC){
e.stopEvent();
this.cancelEdit();
}else if(k == e.ENTER && !e.hasModifier()){
e.stopEvent();
this.completeEdit();
}
}
})/*;edi*/

manasaguli
5 Mar 2010, 7:11 PM
@moegal, thanks for responding back.

I do have similar code with me But the main problems comes up if i have multiple editable columns.

The issue is in triggeredit and updatenode methods.

The triggeredit method does not give the right edited column index if we have multiple editable columns and their values are not changed.

I think this is a known bug, but i am trying find a solution.
Do you know any solution for this issue.

Thanks.

moegal
5 Mar 2010, 7:20 PM
sorry I don't. Wish I could help.

Marty