Ext Tree异步树的增加修改删除的简单实现~
之前项目有个模块要求用树形解决,附带要实现checkbox,增删修改以及copy/cut/paste等等功能;
因为之前写的人用了xloadTree,其他功能都实现了,但是客户要求要有cookie功能,实现不了麻烦啊~
正巧现在在学习用Ext,发现Ext的tree本身就很强大基本的功能都可以实现。
对应的save,del,newTree方法
哦,对应tree的打开状态的cookie记录的控件
以上基本实现了树形的主要功能,右键,cookie记住打开的对象,新增新的子节点,直接修改节点名称,删除。
因为之前写的人用了xloadTree,其他功能都实现了,但是客户要求要有cookie功能,实现不了麻烦啊~
正巧现在在学习用Ext,发现Ext的tree本身就很强大基本的功能都可以实现。
Ext.onReady(
function
() {
Ext.QuickTips.init();
Ext.state.Manager.setProvider( new Ext.state.CookieProvider());
var onConfirmDelete = function (btn) {
if (btn == 'yes') {
var treePanel = Ext.getCmp('treepanel');
treePanel.el.mask('删除中
', 'x
-
mask
-
loading');
var selNode = treePanel.getSelectionModel().getSelectedNode();
Ext.Ajax.request({
url : 'organ ! del. do ',
params : {
organId : selNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext
.decode(response.responseText);
if (responseJson.success === true ) {
selNode.remove();
} else {
Ext.Msg
.alert('An error occured with the server.');
}
}
});
}
}
var onDelete = function () {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if (selNode) {
Ext.MessageBox.confirm('是否确定 ? ',
'请确定删除目录' + selNode.attributes.text, onConfirmDelete)
}
}
var onCompleteAdd = function (treeEditor, newValue, oldValue) {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if (newValue.length > 0 ) {
Ext.Ajax.request({
url : 'organ ! save. do ',
params : {
'organInfo.name' : newValue,
'organInfo.pid' : selNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext
.decode(response.responseText);
if (responseJson.success !== true ) {
Ext.Msg.alert('An error occured with the server.');
treeEditor.editNode.remove();
} else {
treeEditor.editNode.setId(responseJson.data[ 0 ].id);
}
}
});
} else {
treeEditor.editNode.remove();
}
}
var onAddNode = function () {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if ( ! this .treeEditor) {
this .treeEditor = new Ext.tree.TreeEditor(treePanel, {}, {
cancelOnEsc : true ,
completeOnEnter : true ,
selectOnFocus : true ,
allowBlank : false ,
listeners : {
complete : onCompleteAdd
}
});
}
selNode.leaf = false ;
selNode.expand( false , true , function () {
var newNodeCfg = {
text : '',
id : 'tmpNode',
leaf : (selNode.id != ' 0 '),
checked : true
}
var newNode = selNode.insertBefore(newNodeCfg,
selNode.firstChild);
this .treeEditor.editNode = newNode;
this .treeEditor.startEdit(newNode.ui.textNode);
}, this );
}
var onCompleteEdit = function (treeEditor, newValue, oldValue) {
var treePanel = Ext.getCmp('treepanel')
treePanel.el.mask('保存中
', 'x
-
mask
-
loading');
var selNode = treePanel.getSelectionModel().getSelectedNode();
var editNode = treeEditor.editNode;
var editNodeId = editNode.id;
Ext.Ajax.request({
url : 'organ ! saveC. do ',
params : {
'organInfo.id' : editNodeId,
'organInfo.name' : newValue,
'organInfo.pid' : editNode.parentNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext.decode(response.responseText);
if (responseJson.success !== true ) {
editNode.setText(oldValue);
Ext.Msg.alert('An error occured with the server.');
}
},
failure : function (response, opts) {
treePanel.el.unmask();
editNode.setText(oldValue);
Ext.Msg.alert('An error occured with the server.');
}
});
}
var onEdit = function () {
var treePanel = Ext.getCmp('treepanel');
var selectedNode = treePanel.getSelectionModel().getSelectedNode();
if ( ! this .treeEditor) {
this .treeEditor = new Ext.tree.TreeEditor(treePanel, {}, {
cancelOnEsc : true ,
completeOnEnter : true ,
selectOnFocus : true ,
allowBlank : false ,
listeners : {
complete : onCompleteEdit
}
});
}
this .treeEditor.editNode = selectedNode;
this .treeEditor.startEdit(selectedNode.ui.textNode);
}
var buildCtxMenu = function () {
return new Ext.menu.Menu({
items : [{
itemId : 'add',
handler : onAddNode
}, {
itemId : 'edit',
handler : onEdit,
scope : onEdit
}, {
itemId : ' delete ',
handler : onDelete
}]
});
}
var onCtxMenu = function (node, e) {
node.select();
e.stopEvent();
if ( ! this .ctxMenu) {
this .ctxMenu = buildCtxMenu();
}
var ctxMenu = this .ctxMenu;
var addItem = ctxMenu.getComponent('add');
var editItem = ctxMenu.getComponent('edit');
var deleteItem = ctxMenu.getComponent(' delete ');
addItem.setText('新建文件夹');
editItem.setText('重命名');
deleteItem.setText('删除');
if (node.id == ' 0 ') {
addItem.enable();
deleteItem.disable();
editItem.disable();
} else {
addItem.enable();
editItem.enable();
deleteItem.enable();
}
ctxMenu.showAt(e.getXY());
},
var tree = new Ext.tree.TreePanel({
id : 'treepanel',
autoScroll : true ,
animate : false ,
enableDD : true ,
useArrows : true ,
plugins : [ new Ext.ux.state.TreePanel()],
loader : new WithubTreeLoader({
dataUrl : 'organ ! newTree. do '
}),
root : {
nodeType : 'async',
id : ' 0 ',
text : '组织结构',
leaf : false ,
expanded : true
},
listeners : {
contextmenu : onCtxMenu,
}
});
new Ext.Window({
height : 300 ,
width : 300 ,
layout : 'fit',
border : false ,
title : 'Our first tree',
items : tree
}).show();
});
Ext.QuickTips.init();
Ext.state.Manager.setProvider( new Ext.state.CookieProvider());
var onConfirmDelete = function (btn) {
if (btn == 'yes') {
var treePanel = Ext.getCmp('treepanel');
treePanel.el.mask('删除中
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
var selNode = treePanel.getSelectionModel().getSelectedNode();
Ext.Ajax.request({
url : 'organ ! del. do ',
params : {
organId : selNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext
.decode(response.responseText);
if (responseJson.success === true ) {
selNode.remove();
} else {
Ext.Msg
.alert('An error occured with the server.');
}
}
});
}
}
var onDelete = function () {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if (selNode) {
Ext.MessageBox.confirm('是否确定 ? ',
'请确定删除目录' + selNode.attributes.text, onConfirmDelete)
}
}
var onCompleteAdd = function (treeEditor, newValue, oldValue) {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if (newValue.length > 0 ) {
Ext.Ajax.request({
url : 'organ ! save. do ',
params : {
'organInfo.name' : newValue,
'organInfo.pid' : selNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext
.decode(response.responseText);
if (responseJson.success !== true ) {
Ext.Msg.alert('An error occured with the server.');
treeEditor.editNode.remove();
} else {
treeEditor.editNode.setId(responseJson.data[ 0 ].id);
}
}
});
} else {
treeEditor.editNode.remove();
}
}
var onAddNode = function () {
var treePanel = Ext.getCmp('treepanel');
var selNode = treePanel.getSelectionModel().getSelectedNode();
if ( ! this .treeEditor) {
this .treeEditor = new Ext.tree.TreeEditor(treePanel, {}, {
cancelOnEsc : true ,
completeOnEnter : true ,
selectOnFocus : true ,
allowBlank : false ,
listeners : {
complete : onCompleteAdd
}
});
}
selNode.leaf = false ;
selNode.expand( false , true , function () {
var newNodeCfg = {
text : '',
id : 'tmpNode',
leaf : (selNode.id != ' 0 '),
checked : true
}
var newNode = selNode.insertBefore(newNodeCfg,
selNode.firstChild);
this .treeEditor.editNode = newNode;
this .treeEditor.startEdit(newNode.ui.textNode);
}, this );
}
var onCompleteEdit = function (treeEditor, newValue, oldValue) {
var treePanel = Ext.getCmp('treepanel')
treePanel.el.mask('保存中
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
var selNode = treePanel.getSelectionModel().getSelectedNode();
var editNode = treeEditor.editNode;
var editNodeId = editNode.id;
Ext.Ajax.request({
url : 'organ ! saveC. do ',
params : {
'organInfo.id' : editNodeId,
'organInfo.name' : newValue,
'organInfo.pid' : editNode.parentNode.id
},
success : function (response, opts) {
treePanel.el.unmask();
var responseJson = Ext.decode(response.responseText);
if (responseJson.success !== true ) {
editNode.setText(oldValue);
Ext.Msg.alert('An error occured with the server.');
}
},
failure : function (response, opts) {
treePanel.el.unmask();
editNode.setText(oldValue);
Ext.Msg.alert('An error occured with the server.');
}
});
}
var onEdit = function () {
var treePanel = Ext.getCmp('treepanel');
var selectedNode = treePanel.getSelectionModel().getSelectedNode();
if ( ! this .treeEditor) {
this .treeEditor = new Ext.tree.TreeEditor(treePanel, {}, {
cancelOnEsc : true ,
completeOnEnter : true ,
selectOnFocus : true ,
allowBlank : false ,
listeners : {
complete : onCompleteEdit
}
});
}
this .treeEditor.editNode = selectedNode;
this .treeEditor.startEdit(selectedNode.ui.textNode);
}
var buildCtxMenu = function () {
return new Ext.menu.Menu({
items : [{
itemId : 'add',
handler : onAddNode
}, {
itemId : 'edit',
handler : onEdit,
scope : onEdit
}, {
itemId : ' delete ',
handler : onDelete
}]
});
}
var onCtxMenu = function (node, e) {
node.select();
e.stopEvent();
if ( ! this .ctxMenu) {
this .ctxMenu = buildCtxMenu();
}
var ctxMenu = this .ctxMenu;
var addItem = ctxMenu.getComponent('add');
var editItem = ctxMenu.getComponent('edit');
var deleteItem = ctxMenu.getComponent(' delete ');
addItem.setText('新建文件夹');
editItem.setText('重命名');
deleteItem.setText('删除');
if (node.id == ' 0 ') {
addItem.enable();
deleteItem.disable();
editItem.disable();
} else {
addItem.enable();
editItem.enable();
deleteItem.enable();
}
ctxMenu.showAt(e.getXY());
},
var tree = new Ext.tree.TreePanel({
id : 'treepanel',
autoScroll : true ,
animate : false ,
enableDD : true ,
useArrows : true ,
plugins : [ new Ext.ux.state.TreePanel()],
loader : new WithubTreeLoader({
dataUrl : 'organ ! newTree. do '
}),
root : {
nodeType : 'async',
id : ' 0 ',
text : '组织结构',
leaf : false ,
expanded : true
},
listeners : {
contextmenu : onCtxMenu,
}
});
new Ext.Window({
height : 300 ,
width : 300 ,
layout : 'fit',
border : false ,
title : 'Our first tree',
items : tree
}).show();
});
对应的save,del,newTree方法
public
String save()
throws
Exception {
if (organInfo.getPid().equals( " 0 " )){
organInfo.setPid( null );
}
String id = organInfoService.saveOrganInfo(organInfo);
return json( " [{id: " + id + " }] " );
}
public String del() throws Exception {
List list = this .searchList(organId, new ArrayList());
StringBuffer sb = new StringBuffer();
sb.append(organId);
if (list.size() != 0 ) {
for ( int i = 0 ; i < list.size(); i ++ ) {
sb.append( " , " ).append(list.get(i));
}
}
organInfoService.delOrganInfo(sb.toString().split( " , " ));
return json();
}
public String newTree() throws Exception {
StringBuffer sb = new StringBuffer();
List < OrganInfo > list;
if (node.equals( " 0 " )){
list = organInfoService.getOrganInfoListByNull();
}
else {
list = organInfoService.getOrganInfoByPidList(node);
}
int i = 0 ;
sb.append( " [ " );
for (OrganInfo oi : list) {
if (i != 0 ) {
sb.append( " , " );
}
sb.append( " {text:' " ).append(oi.getName()).append( " ',id:' " ).append(oi.getId()).append( " ' " );
List < OrganInfo > listId = organInfoService.getOrganInfoByPidList(oi.getId());
if (listId.size() != 0 ) {
sb.append( " ,leaf:false " );
} else {
sb.append( " ,leaf:true " );
}
sb.append( " ,checked: true " );
sb.append( " } " );
i ++ ;
}
sb.append( " ] " );
return json(sb.toString());
}
if (organInfo.getPid().equals( " 0 " )){
organInfo.setPid( null );
}
String id = organInfoService.saveOrganInfo(organInfo);
return json( " [{id: " + id + " }] " );
}
public String del() throws Exception {
List list = this .searchList(organId, new ArrayList());
StringBuffer sb = new StringBuffer();
sb.append(organId);
if (list.size() != 0 ) {
for ( int i = 0 ; i < list.size(); i ++ ) {
sb.append( " , " ).append(list.get(i));
}
}
organInfoService.delOrganInfo(sb.toString().split( " , " ));
return json();
}
public String newTree() throws Exception {
StringBuffer sb = new StringBuffer();
List < OrganInfo > list;
if (node.equals( " 0 " )){
list = organInfoService.getOrganInfoListByNull();
}
else {
list = organInfoService.getOrganInfoByPidList(node);
}
int i = 0 ;
sb.append( " [ " );
for (OrganInfo oi : list) {
if (i != 0 ) {
sb.append( " , " );
}
sb.append( " {text:' " ).append(oi.getName()).append( " ',id:' " ).append(oi.getId()).append( " ' " );
List < OrganInfo > listId = organInfoService.getOrganInfoByPidList(oi.getId());
if (listId.size() != 0 ) {
sb.append( " ,leaf:false " );
} else {
sb.append( " ,leaf:true " );
}
sb.append( " ,checked: true " );
sb.append( " } " );
i ++ ;
}
sb.append( " ] " );
return json(sb.toString());
}
哦,对应tree的打开状态的cookie记录的控件
//
vim: ts=4:sw=4:nu:fdc=4:nospell
/* global Ext */
/* *
* @class Ext.ux.state.TreePanel
*
* Ext.tree.TreePanel State Plugin
* <br><br>
* Usage:
<pre>
var tree = new Ext.tree.TreePanel({
root:{
nodeType:'async'
,id:'root'
,text:'Root'
}
,loader: {
url:'get-tree.php'
}
<b>,plugins:[new Ext.ux.state.TreePanel()]</b>
});
</pre>
*
* @author Ing. Jozef Sakáloš
* @copyright (c) 2009, by Ing. Jozef Sakáloš
* @date <ul>
* <li>5. April 2009<li>
* </ul>
* @version 1.0
* @revision $Id: Ext.ux.state.TreePanel.js 676 2009-04-07 13:03:20Z jozo $
*
* @license Ext.ux.state.TreePanel.js is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
*
* @forum 64714
* @demo http://examples.extjs.eu/?ex=treestate
* @download <ul>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.bz2">Ext.ux.state.TreePanel.js.bz2</a></li>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.gz">Ext.ux.state.TreePanel.js.gz</a></li>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.zip">Ext.ux.state.TreePanel.js.zip</a></li>
* </ul>
*
* @donate
* <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
* <input type="hidden" name="cmd" value="_s-xclick">
* <input type="hidden" name="hosted_button_id" value="3430419">
* <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif"
* border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
* <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
* </form>
*/
Ext.ns('Ext.ux.state');
// dummy constructor
Ext.ux.state.TreePanel = function () {};
Ext.override(Ext.ux.state.TreePanel, {
/* *
* Initializes the plugin
* @param {Ext.tree.TreePanel} tree
* @private
*/
init: function (tree) {
// install event handlers on TreePanel
tree.on({
// add path of expanded node to stateHash
beforeexpandnode: function (n) {
this .stateHash[n.id] = n.getPath();
}
// delete path and all subpaths of collapsed node from stateHash
,beforecollapsenode: function (n) {
delete this .stateHash[n.id];
var cPath = n.getPath();
for ( var p in this .stateHash) {
if ( this .stateHash.hasOwnProperty(p)) {
if ( - 1 !== this .stateHash[p].indexOf(cPath)) {
delete this .stateHash[p];
}
}
}
}
});
// update state on node expand or collapse
tree.stateEvents = tree.stateEvents || [];
tree.stateEvents.push('expandnode', 'collapsenode');
// add state related props to the tree
Ext.apply(tree, {
// keeps expanded nodes paths keyed by node.ids
stateHash:{}
// apply state on tree initialization
,applyState: function (state) {
if (state) {
Ext.apply( this , state);
// it is too early to expand paths here
// so do it once on root load
this .root.on({
load:{single: true , scope: this , fn: function () {
for ( var p in this .stateHash) {
if ( this .stateHash.hasOwnProperty(p)) {
this .expandPath( this .stateHash[p]);
}
}
}}
});
}
} // eo function applyState
// returns stateHash for save by state manager
,getState: function () {
return {stateHash: this .stateHash};
} // eo function getState
});
} // eo function init
}); // eo override
// eof
/* global Ext */
/* *
* @class Ext.ux.state.TreePanel
*
* Ext.tree.TreePanel State Plugin
* <br><br>
* Usage:
<pre>
var tree = new Ext.tree.TreePanel({
root:{
nodeType:'async'
,id:'root'
,text:'Root'
}
,loader: {
url:'get-tree.php'
}
<b>,plugins:[new Ext.ux.state.TreePanel()]</b>
});
</pre>
*
* @author Ing. Jozef Sakáloš
* @copyright (c) 2009, by Ing. Jozef Sakáloš
* @date <ul>
* <li>5. April 2009<li>
* </ul>
* @version 1.0
* @revision $Id: Ext.ux.state.TreePanel.js 676 2009-04-07 13:03:20Z jozo $
*
* @license Ext.ux.state.TreePanel.js is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
* target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
*
* @forum 64714
* @demo http://examples.extjs.eu/?ex=treestate
* @download <ul>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.bz2">Ext.ux.state.TreePanel.js.bz2</a></li>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.gz">Ext.ux.state.TreePanel.js.gz</a></li>
* <li><a href="http://examples.extjs.eu/Ext.ux.state.TreePanel.js.zip">Ext.ux.state.TreePanel.js.zip</a></li>
* </ul>
*
* @donate
* <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
* <input type="hidden" name="cmd" value="_s-xclick">
* <input type="hidden" name="hosted_button_id" value="3430419">
* <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif"
* border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
* <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
* </form>
*/
Ext.ns('Ext.ux.state');
// dummy constructor
Ext.ux.state.TreePanel = function () {};
Ext.override(Ext.ux.state.TreePanel, {
/* *
* Initializes the plugin
* @param {Ext.tree.TreePanel} tree
* @private
*/
init: function (tree) {
// install event handlers on TreePanel
tree.on({
// add path of expanded node to stateHash
beforeexpandnode: function (n) {
this .stateHash[n.id] = n.getPath();
}
// delete path and all subpaths of collapsed node from stateHash
,beforecollapsenode: function (n) {
delete this .stateHash[n.id];
var cPath = n.getPath();
for ( var p in this .stateHash) {
if ( this .stateHash.hasOwnProperty(p)) {
if ( - 1 !== this .stateHash[p].indexOf(cPath)) {
delete this .stateHash[p];
}
}
}
}
});
// update state on node expand or collapse
tree.stateEvents = tree.stateEvents || [];
tree.stateEvents.push('expandnode', 'collapsenode');
// add state related props to the tree
Ext.apply(tree, {
// keeps expanded nodes paths keyed by node.ids
stateHash:{}
// apply state on tree initialization
,applyState: function (state) {
if (state) {
Ext.apply( this , state);
// it is too early to expand paths here
// so do it once on root load
this .root.on({
load:{single: true , scope: this , fn: function () {
for ( var p in this .stateHash) {
if ( this .stateHash.hasOwnProperty(p)) {
this .expandPath( this .stateHash[p]);
}
}
}}
});
}
} // eo function applyState
// returns stateHash for save by state manager
,getState: function () {
return {stateHash: this .stateHash};
} // eo function getState
});
} // eo function init
}); // eo override
// eof
以上基本实现了树形的主要功能,右键,cookie记住打开的对象,新增新的子节点,直接修改节点名称,删除。