我是为了实现树的拖动才开始学习extjs的,它也让我感到了extjs的强大,我就直接贴代码了。
一、实现树的jsp页面,我是直接将extjs写到jsp页面的,格式有点乱,呵。。。。。
<%@ page language="java" import="java.util.*,java.lang.*"
contentType="text/html; charset=GBK" isErrorPage="true"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title></title>
<link rel="stylesheet" href="../resources/css/ext-all.css" />
<link rel="stylesheet" href="../resources/css/xtheme-default.css" />
<script language="javascript" src="../js/ext/ext-base.js"></script>
<script language="javascript" src="../js/ext/ext-all.js"></script>
<script language="javascript" src="<c:url value='/js/xmlHttpHelper.js'/>"></script>
<script type="text/javascript">
var Tree = Ext.tree;
var tree = null;
Ext.onReady(function(){
tree = new Tree.TreePanel({
el:'tree-div',
onlyLeafCheckable:false,
rootVisible: true,
autoScroll:true,
animate:false,//是否动画
enableDD:true,// 是否支持拖放
containerScroll:true,
lines:true,
checkModel:'cascade',
loader:new Tree.TreeLoader({dataUrl:'../info/rss.do?method=getJsonArray',
baseAttrs: {uiProvider: Ext.tree.TreeCheckNodeUI}
})
});
// set the root node
var root = new Tree.AsyncTreeNode(
{
"text":"我的网摘",
"id":"01",
"allowDrag":false //false表示不能被拖动
}
);
//绑定节点加载之前事件
tree.on('beforeload',function(node){
if(node.id!='01'){
tree.loader.dataUrl = '../info/rss.do?method=getChildJsonArray&nodeid='+node.id;
}
});
//绑定节点点击事件
/*
tree.on('click', function(node){
if(node.id!='root'){
alert(node.id);
alert(node.text);
alert(node.href);
}
});
*/
//绑定节点拖动事件,找了很久树节点拖动的实现,终于在老外的帖子发现上了这个实现,拖动以后所需的信息已经捕获,与后台联动的函数 加上即可实现TREE的拖拽
tree.on('nodedrop',
function(e){
if(e.point=='append'){
alert('当前"【'+e.dropNode.text+'】"被放到目录"【'+e.target.text+'】"下!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=append";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}
else if(e.point=='above'){
//alert('当前"'+e.dropNode.text+'"放在了"'+e.target.text+'"上面!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=above";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}else if(e.point=='below'){
//alert('当前"'+e.dropNode.text+'"放在了"'+e.target.text+'"下面!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=below";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}
}
);
//绑定节点右键菜单功能
tree.on('contextmenu',function(node,event){
// alert("node.id="+ node.id);
event.preventDefault(); //这行是必须的
rightClick.showAt(event.getXY());//取得鼠标点击坐标,展示菜单
//alert(node.id);
document.getElementById('rootid').value=node.id;
});
//定义右键菜单
var rightClick = new Ext.menu.Menu({
id :'rightClickCont',
items : [{
id:'rMenu1',
text : '编辑',
//增加菜单点击事件
handler:function (node){
//alert(node.dropNode.id);
}
}, {
id:'rMenu2',
text : '删除'
}, {
id:'rMenu3',
text : '菜单3'
}]
});
tree.setRootNode(root);
// render the tree
tree.render();
root.expand();
});
</script>
</head>
<body>
<div id="tree-div" style="overflow:auto;width:98%;"></div>
</body>
</html>
contentType="text/html; charset=GBK" isErrorPage="true"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title></title>
<link rel="stylesheet" href="../resources/css/ext-all.css" />
<link rel="stylesheet" href="../resources/css/xtheme-default.css" />
<script language="javascript" src="../js/ext/ext-base.js"></script>
<script language="javascript" src="../js/ext/ext-all.js"></script>
<script language="javascript" src="<c:url value='/js/xmlHttpHelper.js'/>"></script>
<script type="text/javascript">
var Tree = Ext.tree;
var tree = null;
Ext.onReady(function(){
tree = new Tree.TreePanel({
el:'tree-div',
onlyLeafCheckable:false,
rootVisible: true,
autoScroll:true,
animate:false,//是否动画
enableDD:true,// 是否支持拖放
containerScroll:true,
lines:true,
checkModel:'cascade',
loader:new Tree.TreeLoader({dataUrl:'../info/rss.do?method=getJsonArray',
baseAttrs: {uiProvider: Ext.tree.TreeCheckNodeUI}
})
});
// set the root node
var root = new Tree.AsyncTreeNode(
{
"text":"我的网摘",
"id":"01",
"allowDrag":false //false表示不能被拖动
}
);
//绑定节点加载之前事件
tree.on('beforeload',function(node){
if(node.id!='01'){
tree.loader.dataUrl = '../info/rss.do?method=getChildJsonArray&nodeid='+node.id;
}
});
//绑定节点点击事件
/*
tree.on('click', function(node){
if(node.id!='root'){
alert(node.id);
alert(node.text);
alert(node.href);
}
});
*/
//绑定节点拖动事件,找了很久树节点拖动的实现,终于在老外的帖子发现上了这个实现,拖动以后所需的信息已经捕获,与后台联动的函数 加上即可实现TREE的拖拽
tree.on('nodedrop',
function(e){
if(e.point=='append'){
alert('当前"【'+e.dropNode.text+'】"被放到目录"【'+e.target.text+'】"下!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=append";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}
else if(e.point=='above'){
//alert('当前"'+e.dropNode.text+'"放在了"'+e.target.text+'"上面!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=above";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}else if(e.point=='below'){
//alert('当前"'+e.dropNode.text+'"放在了"'+e.target.text+'"下面!');
var resultUrl = "../info/rss.do?method=treeNodeTuoDong¤RootId="+e.dropNode.id+"&parentRootId="+e.target.id+"&type=below";
var resulthtml = XmlHttpHelper.transmit(false, "get", "text", resultUrl, null, null);
}
}
);
//绑定节点右键菜单功能
tree.on('contextmenu',function(node,event){
// alert("node.id="+ node.id);
event.preventDefault(); //这行是必须的
rightClick.showAt(event.getXY());//取得鼠标点击坐标,展示菜单
//alert(node.id);
document.getElementById('rootid').value=node.id;
});
//定义右键菜单
var rightClick = new Ext.menu.Menu({
id :'rightClickCont',
items : [{
id:'rMenu1',
text : '编辑',
//增加菜单点击事件
handler:function (node){
//alert(node.dropNode.id);
}
}, {
id:'rMenu2',
text : '删除'
}, {
id:'rMenu3',
text : '菜单3'
}]
});
tree.setRootNode(root);
// render the tree
tree.render();
root.expand();
});
</script>
</head>
<body>
<div id="tree-div" style="overflow:auto;width:98%;"></div>
</body>
</html>
注意dataUrl的值,那个action就是动态读取json数据的action,如下:
public ActionForward getJsonArray(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
FndUser user = (FndUser) request.getSession().getAttribute(
HASConstants.SESSION_USER);
JSONArray jsonArray=this.getJson(user);
response.setContentType("text/json; charset=GBK");
try {
response.getWriter().print(jsonArray);
} catch (Exception e) {
log.error("输出json失败"+e.getMessage());
return null;
}
return null;
}
HttpServletRequest request, HttpServletResponse response){
FndUser user = (FndUser) request.getSession().getAttribute(
HASConstants.SESSION_USER);
JSONArray jsonArray=this.getJson(user);
response.setContentType("text/json; charset=GBK");
try {
response.getWriter().print(jsonArray);
} catch (Exception e) {
log.error("输出json失败"+e.getMessage());
return null;
}
return null;
}
我读取的json数据是第一层节点
public JSONArray getJson(FndUser user)
{
List list = new ArrayList();
List userContentslist = getUserRssContents(user);
for(Iterator iter=userContentslist.iterator();iter.hasNext();)
{
String[] userContent=(String[])iter.next();
Map tree = new HashMap();
tree.put("text", userContent[1]);
tree.put("id", userContent[0]);
list.add(tree);
}
JSONArray jsonArray = JSONArray.fromObject(list);
return jsonArray;
}
二、当点击第一层节点时,会异步绑定下级节点,在绑定下级节点前,会调用beforeload函数
tree.loader.dataUrl = '../info/rss.do?method=getChildJsonArray&nodeid='+node.id
根据传入的上级节点的节点ID,得到其下级节点的json格式的数据
这样,就实现了异步加载,看起来真是很简单哦
对于拖动事件,也是一样的,调用action,来更改文件夹之间的上下级关系,并实现后台的更新数据库,由于处于学习阶段,代码不尽合理。
xmlHttpHelper.js
{
List list = new ArrayList();
List userContentslist = getUserRssContents(user);
for(Iterator iter=userContentslist.iterator();iter.hasNext();)
{
String[] userContent=(String[])iter.next();
Map tree = new HashMap();
tree.put("text", userContent[1]);
tree.put("id", userContent[0]);
list.add(tree);
}
JSONArray jsonArray = JSONArray.fromObject(list);
return jsonArray;
}
二、当点击第一层节点时,会异步绑定下级节点,在绑定下级节点前,会调用beforeload函数
tree.loader.dataUrl = '../info/rss.do?method=getChildJsonArray&nodeid='+node.id
根据传入的上级节点的节点ID,得到其下级节点的json格式的数据
public ActionForward getChildJsonArray(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
FndUser user = (FndUser) request.getSession().getAttribute(
HASConstants.SESSION_USER);
String nodeid=request.getParameter("nodeid");
List list = new ArrayList();
List urllisttree = getUserRssUrl(user,nodeid);
for(Iterator iterurl=urllisttree.iterator();iterurl.hasNext();)
{
String[] userUrl=(String[])iterurl.next();;
Map url = new HashMap();
url.put("text", userUrl[2]);
url.put("id", userUrl[0]);
url.put("href", "../info/rss.do?method=getRssComent&rssurl="+userUrl[1]);
url.put("hrefTarget", "rssiframe");
url.put("allowDrag", Boolean.TRUE);
url.put("leaf", Boolean.TRUE);
list.add(url);
}
JSONArray jsonArray = JSONArray.fromObject(list);
response.setContentType("text/json; charset=GBK");
try {
response.getWriter().print(jsonArray);
} catch (Exception e) {
log.error("输出json失败"+e.getMessage());
return null;
}
return null;
}
HttpServletRequest request, HttpServletResponse response){
FndUser user = (FndUser) request.getSession().getAttribute(
HASConstants.SESSION_USER);
String nodeid=request.getParameter("nodeid");
List list = new ArrayList();
List urllisttree = getUserRssUrl(user,nodeid);
for(Iterator iterurl=urllisttree.iterator();iterurl.hasNext();)
{
String[] userUrl=(String[])iterurl.next();;
Map url = new HashMap();
url.put("text", userUrl[2]);
url.put("id", userUrl[0]);
url.put("href", "../info/rss.do?method=getRssComent&rssurl="+userUrl[1]);
url.put("hrefTarget", "rssiframe");
url.put("allowDrag", Boolean.TRUE);
url.put("leaf", Boolean.TRUE);
list.add(url);
}
JSONArray jsonArray = JSONArray.fromObject(list);
response.setContentType("text/json; charset=GBK");
try {
response.getWriter().print(jsonArray);
} catch (Exception e) {
log.error("输出json失败"+e.getMessage());
return null;
}
return null;
}
这样,就实现了异步加载,看起来真是很简单哦
对于拖动事件,也是一样的,调用action,来更改文件夹之间的上下级关系,并实现后台的更新数据库,由于处于学习阶段,代码不尽合理。
xmlHttpHelper.js
function XmlHttpHelper(){}
XmlHttpHelper.__getXmlHttpObj = function()
{
try
{
return new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e)
{
try
{
return new XMLHttpRequest();
}
catch(ee)
{
throw(new Error(-1, "无法创建XMLHTTP对象。"));
}
}
};
//
// 使用XMLHTTP和远程服务器通信。
//
// async 是否为异步方式:true/false
// httpMethod http方法:"post"/"get"
// responseType 返回数据的类型:"text"/"xml"/null
// url 请求的URL地址
// callback 异步操作完成时执行的回调函数
// postData post方式时发送的数据
//
XmlHttpHelper.transmit = function(async, httpMethod, responseType, url, callback, postData)
{
var xmlhttp = this.__getXmlHttpObj();
xmlhttp.open(httpMethod, url, async);
if(!async && httpMethod.toLowerCase() == "post")
{
xmlhttp.setRequestHeader('Content-Length', postData.length);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
}
if(async)
{
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4)
{
try
{
if(responseType != null)
{
if(responseType.toLowerCase() == "text")
callback(xmlhttp.responseText);
else if(responseType.toLowerCase() == "xml")
callback(xmlhttp.responseXML);
}
else
{
callback(null);
}
}
finally
{
xmlhttp = null;
}
}
}
xmlhttp.send(postData);
}
else
{
xmlhttp.send(postData);
if(xmlhttp.status == 200)
{
if(responseType != null)
{
if(responseType.toLowerCase() == "text")
return xmlhttp.responseText;
else if(responseType.toLowerCase() == "xml")
return xmlhttp.responseXML;
}
else
{
return null;
}
}
return null;
}
};
XmlHttpHelper.__getXmlHttpObj = function()
{
try
{
return new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e)
{
try
{
return new XMLHttpRequest();
}
catch(ee)
{
throw(new Error(-1, "无法创建XMLHTTP对象。"));
}
}
};
//
// 使用XMLHTTP和远程服务器通信。
//
// async 是否为异步方式:true/false
// httpMethod http方法:"post"/"get"
// responseType 返回数据的类型:"text"/"xml"/null
// url 请求的URL地址
// callback 异步操作完成时执行的回调函数
// postData post方式时发送的数据
//
XmlHttpHelper.transmit = function(async, httpMethod, responseType, url, callback, postData)
{
var xmlhttp = this.__getXmlHttpObj();
xmlhttp.open(httpMethod, url, async);
if(!async && httpMethod.toLowerCase() == "post")
{
xmlhttp.setRequestHeader('Content-Length', postData.length);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
}
if(async)
{
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4)
{
try
{
if(responseType != null)
{
if(responseType.toLowerCase() == "text")
callback(xmlhttp.responseText);
else if(responseType.toLowerCase() == "xml")
callback(xmlhttp.responseXML);
}
else
{
callback(null);
}
}
finally
{
xmlhttp = null;
}
}
}
xmlhttp.send(postData);
}
else
{
xmlhttp.send(postData);
if(xmlhttp.status == 200)
{
if(responseType != null)
{
if(responseType.toLowerCase() == "text")
return xmlhttp.responseText;
else if(responseType.toLowerCase() == "xml")
return xmlhttp.responseXML;
}
else
{
return null;
}
}
return null;
}
};