前段時間,因爲工作很忙,所以一直都沒有寫了。
最近因爲工作上的一個任務需要用到Extjs的Tree,所以現在把我在任務中用到的方法,和遇到的問題,在這裏寫一下。
任務平臺是asp.net 2003 + sqlserver 2005
任務需求是這樣的:界面上方左右兩個tree,然後通過URL地址欄傳入一個參數corpcode,並在右邊的tree加載該公司和與該公司有關係的公司(上下級關係和平級關係),然後通過一個文本框,查詢一些公司加載到左邊的tree,然後通過左右tree的拖動,來調整右邊tree公司的關係,最後保存。
這裏,我們先建2個頁面,其中一個名爲CorpGroupRelation,用於加載tree,另一頁面爲CorpGroupAjax,用於傳遞ajax。
這裏我先把兩個文件的代碼貼出來:
CorpGroupRelation.aspx
<%...@ Register TagPrefix="eventapproval" Namespace="CECERP.IE.Libraries.Controls.EventApproval" Assembly="CECERP.IE.Libraries" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title></title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="C#" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
<LINK href="../../../../Libraries/Scripts/extjs-2.0/resources/css/ext-all.css" type="text/css"
rel="stylesheet">
<script language="javascript" src="../../../../Libraries/Scripts/extjs-2.0/adapter/ext/ext-base.js"
type="text/javascript"></script>
<script language="javascript" src="../../../../Libraries/Scripts/extjs-2.0/ext-all.js" type="text/javascript"></script>
<style type="text/css">... HR {...}{ clear: both; visibility: hidden }
</style>
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<input id="html_TxtB_corpcode" type="hidden" name="html_TxtB_corpcode"> <input id="html_TxtB_OldID" type="hidden" name="html_TxtB_OldID" runat="server">
<input id="html_TxtB_New" type="hidden" name="html_TxtB_New" runat="server"> <input id="html_TxtB_Root" type="hidden" name="html_TxtB_Root" runat="server">
<TABLE id="html_tableHead" cellSpacing="0" cellPadding="0" width="100%" border="0">
<TR>
<TD>
<P align="center"><INPUT id="TxtB_Query" type="text" size="31" name="TxtB_Query">
<INPUT id="html_btnSearch" type="button" name="html_btnSearch"></P>
</TD>
</TR>
<TR>
<TD>
<TABLE id="html_tabletree" cellSpacing="0" cellPadding="0" width="100%" border="0">
<TR>
<TD width="50%">
<div id="list1" style="HEIGHT: 300px">
<hr>
</div>
<div id="list" style="DISPLAY: none; HEIGHT: 300px">
<hr>
</div>
</TD>
<TD vAlign="top">
<div id="tree" style="HEIGHT: 300px">
<hr>
</div>
</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
</form>
<script language="javascript">...
<asp:Literal Runat="server" ID="LiteralScript"></asp:Literal>
</script>
<script type="text/javascript">...
Ext.onReady(function()...{
//輸入框樣式
var textquery = new Ext.form.TextField(...{
allowBlank:false,
applyTo: 'TxtB_Query'
});
//搜尋事件
Ext.get('html_btnSearch').on('click', function()...{
if(Ext.get('TxtB_Query').dom.value=="")
...{
alert( Checktext );
Ext.get('TxtB_Query').focus();
}
else
...{
Ext.get('list1').dom.style.display="none";
Ext.get('list').dom.style.display="";
var msg = Ext.get('list');
msg.load(...{
url: 'CorpGroupAjax.aspx', // <-- change if necessary
params: 'param1=1',
text: 'Updating...',
scripts: true
});
msg.show();
SaveList();
}
});
//初始化左側樣式
var listree1 = new Ext.tree.TreePanel(...{
el:'list1',
animate:true,
autoScroll:true,
enableDD:true,
containerScroll: true,
lines:false,
rootVisible:false,
dropConfig: ...{appendOnly:true}
});
new Ext.tree.TreeSorter(listree1, ...{folderSort:true});
var root = new Ext.tree.AsyncTreeNode(...{
draggable:false,
id:'source'
});
listree1.setRootNode(root);
listree1.render();
root.expand(true, /**//*no anim*/ false);
});
var tree;
var RightTreeLoad = function()...{
var Tree = Ext.tree;
return ...{
init : function()...{
tree = new Tree.TreePanel(...{
el:'tree',
animate:true,
autoScroll:true,
loader: new Tree.TreeLoader(...{dataUrl:'CorpGroupAjax.aspx?corpcode='+Ext.get('html_TxtB_corpcode').dom.value}),
enableDD:true,
containerScroll: true,
dropConfig: ...{appendOnly:true}
});
new Tree.TreeSorter(tree, ...{folderSort:true});
var root = new Tree.AsyncTreeNode(...{
text: corpName,
draggable:false,
id:'source'
});
tree.setRootNode(root);
tree.render();
root.expand(true, /**//*no anim*/ false);
tree.on('click',function(e)...{
SaveList();
});
tree.on('enddrag',function(Node,e)...{
SaveList();
FindList();
});
}
};
}();
//右側菜單加載
Ext.EventManager.onDocumentReady(RightTreeLoad.init, RightTreeLoad, true);
//左側列表加載
TreeShow = function()...{
return ...{
init : function()...{
var listree = new Ext.tree.TreePanel(...{
el:'list',
animate:true,
autoScroll:true,
loader: new Ext.tree.TreeLoader(...{dataUrl:'CorpGroupAjax.aspx?Search='+escape(Ext.get('TxtB_Query').dom.value)}),
enableDD:true,
containerScroll: true,
lines:false,
title:corpName,
rootVisible:false
});
new Ext.tree.TreeSorter(listree, ...{folderSort:true});
var root = new Ext.tree.AsyncTreeNode(...{
draggable:false,
id:'source'
});
listree.setRootNode(root);
listree.render();
root.expand(true, /**//*no anim*/ false);
listree.on('enddrag',function(Node,e)...{
FindList();
});
}
};
}();
</script>
<script language="javascript">...
result="";
function SaveList()
...{
if( Ext.get('html_TxtB_OldID').dom.value == "" )
...{
tradeNode(tree.getRootNode());
Ext.get('html_TxtB_OldID').dom.value=result;
result="";
}
}
function tradeNode(node)
...{
if (node.childNodes && node.childNodes.length>0)
...{
var child;
for (var i=0;i<node.childNodes.length;i++)
...{
child = node.childNodes[i];
if (child!=null && child.text.length>0 )
...{
tradeList(child,child.text);
}
}
}
}
function tradeList(prant,children)
...{
if(prant.childNodes && prant.childNodes.length>0)
...{
var list;
for (var i=0;i<prant.childNodes.length;i++)
...{
list = prant.childNodes[i];
if (list!=null && list.text.length>0 )
...{
result+= list.id +"|";
tradeList(list,list.text);
}
}
}
}
var Newlvl = "";
var NewRoot = "";
function FindList()
...{
FindNew(tree.getRootNode());
Ext.get('html_TxtB_New').dom.value=Newlvl;
Ext.get('html_TxtB_Root').dom.value=NewRoot;
Newlvl="";
NewRoot=""
}
function FindNew(node)
...{
if (node.childNodes && node.childNodes.length>0)
...{
var child;
for (var i=0;i<node.childNodes.length;i++)
...{
child = node.childNodes[i];
if (child!=null && child.text.length>0 )
...{
NewRoot += child.text + "|";
Newlvl += "$";
FindNewList(child,child.text);
}
}
}
}
function FindNewList(prant,children)
...{
if(prant.childNodes && prant.childNodes.length>0)
...{
var list;
for (var i=0;i<prant.childNodes.length;i++)
...{
list = prant.childNodes[i];
if (list!=null && list.text.length>0 )
...{
Newlvl+= list.text+":"+children +"|";
FindNewList(list,list.text);
}
}
}
}
</script>
</body>
</HTML>
在這裏我只把前臺代碼貼出來了,因爲後臺代碼畢竟業務很複雜,而且沒有必要全部貼出,所以就不貼了。只是這個ajax頁面用於返還tree加載時候的字符串。
現在我來具體說明一下里面的代碼。
Extjs加載時候 是在 Ext.onReady進行的。
從
這句話開始 則是加載右邊的tree。先是設定右邊tree的屬性。
animate:true,
autoScroll:true,
enableDD:true,
containerScroll: true,
lines:false,
rootVisible:false,
dropConfig: ...{appendOnly:true}
然後在這裏給這個tree加載一個默認的根
draggable:false,
id:'source'
});
然後就是加載樹了(關鍵地方我加了註釋):
var RightTreeLoad = function()...{
var Tree = Ext.tree;
return ...{
init : function()...{
tree = new Tree.TreePanel(...{
el:'tree',
animate:true,
autoScroll:true,
loader: new Tree.TreeLoader(...{dataUrl:'CorpGroupAjax.aspx?corpcode='+Ext.get('html_TxtB_corpcode').dom.value}),//Ext.get('html_TxtB_corpcode').dom.value是搜尋的文本框的值
enableDD:true,
containerScroll: true,
dropConfig: ...{appendOnly:true}
});
new Tree.TreeSorter(tree, ...{folderSort:true});
var root = new Tree.AsyncTreeNode(...{
text: corpName, //加載公司名稱
draggable:false,
id:'source'
});
tree.setRootNode(root);
tree.render();
root.expand(true, false); //加載並展開節點
tree.on('click',function(e)...{//在點擊事件時觸發的JS
SaveList();
});
tree.on('enddrag',function(Node,e)...{//當拖動結束後觸發的JS
SaveList();
FindList();
});
//凡是tree的時間都寫在這裏。
}
};
下面這句話就是當頁面加載的時候,並執行
下面是點擊搜尋按鈕後,在左邊加載的方法:
TreeShow = function()...{
return ...{
init : function()...{
var listree = new Ext.tree.TreePanel(...{
el:'list',
animate:true,
autoScroll:true,
loader: new Ext.tree.TreeLoader(...{dataUrl:'CorpGroupAjax.aspx?Search='+escape(Ext.get('TxtB_Query').dom.value)}),
enableDD:true,
containerScroll: true,
lines:false,
title:corpName,
rootVisible:false
});
new Ext.tree.TreeSorter(listree, ...{folderSort:true});
var root = new Ext.tree.AsyncTreeNode(...{
draggable:false,
id:'source'
});
listree.setRootNode(root);
listree.render();
root.expand(true, false);
listree.on('enddrag',function(Node,e)...{
FindList();
});
}
};
下面的JS則是在保存前取出對應的ID和文本。
result="";
function SaveList()
...{
if( Ext.get('html_TxtB_OldID').dom.value == "" )
...{
tradeNode(tree.getRootNode());
Ext.get('html_TxtB_OldID').dom.value=result;
result="";
}
}
function tradeNode(node)
...{
if (node.childNodes && node.childNodes.length>0)
...{
var child;
for (var i=0;i<node.childNodes.length;i++)
...{
child = node.childNodes[i];
if (child!=null && child.text.length>0 )
...{
tradeList(child,child.text);
}
}
}
}
function tradeList(prant,children)
...{
if(prant.childNodes && prant.childNodes.length>0)
...{
var list;
for (var i=0;i<prant.childNodes.length;i++)
...{
list = prant.childNodes[i];
if (list!=null && list.text.length>0 )
...{
result+= list.id +"|";
tradeList(list,list.text);
}
}
}
}
var Newlvl = "";
var NewRoot = "";
function FindList()
...{
FindNew(tree.getRootNode());
Ext.get('html_TxtB_New').dom.value=Newlvl;
Ext.get('html_TxtB_Root').dom.value=NewRoot;
Newlvl="";
NewRoot=""
}
function FindNew(node)
...{
if (node.childNodes && node.childNodes.length>0)
...{
var child;
for (var i=0;i<node.childNodes.length;i++)
...{
child = node.childNodes[i];
if (child!=null && child.text.length>0 )
...{
NewRoot += child.text + "|";
Newlvl += "$";//得到所有第二層的根節點
FindNewList(child,child.text);
}
}
}
}
function FindNewList(prant,children)
...{
if(prant.childNodes && prant.childNodes.length>0)
...{
var list;
for (var i=0;i<prant.childNodes.length;i++)
...{
list = prant.childNodes[i];
if (list!=null && list.text.length>0 )
...{
Newlvl+= list.text+":"+children +"|"; //循環加載節點的文本
FindNewList(list,list.text);
}
}
}
}
</script>
其中值得注意到是:
1、葉子節點的屬性中設置爲children:[],則可以在葉子節點下面添加節點了
2、無論在加載或者取值的時候,都需要遞歸遍歷。
3、在網上有一種方式是通過一個json的dll,實現了DataSet與tree之間互相轉換,這個dll可以到json的官方網站去下載,這個要方便得多。