1. 首先还是主要的显示页面tree.html,这里有两个地方要注意一下,一个是我们引用的JS如果采用GBK的默认编码,浏览器会显示未结束的字符串常量的错误,所以我们一般会修改JS文件的编码方式为UTF-8,或者在导入JS时加上编码字符集。第二个是我们要定义一个显示TreePanel的DIV。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css" />
<script type="text/javascript" src="resources/js/ext-base.js"></script>
<script type="text/javascript" src="resources/js/ext-all.js"></script>
<script type="text/javascript" src="resources/js/tree.js" charset="gbk"></script>
</head>
<body>
<div id="tree-panel" style="overflow:auto; height:300px;width:200px;border:2px solid #c3daf9;"></div>
</body>
</html>
2. 然后是我们的主体JS文件,tree.js
Ext.onReady(function() {
Ext.QuickTips.init();// 浮动信息提示
Ext.BLANK_IMAGE_URL = 'resources/images/default/s.gif';// 替换图片文件地址为本地
// 创建一个简写
var Tree = Ext.tree;
// 定义根节点的Loader
var treeloader = new Tree.TreeLoader({
// dataUrl : 'tree.jsp'//这里可以不需要指定URL,在加载前事件响应里面设置
});
// 添加一个树形面板
var treepanel = new Tree.TreePanel({
// renderTo:"tree_div",//如果使用renderTo,则不能使用setRootNode()方法,需要在TreePanel中设置root属性。
el : 'tree-panel',// 将树形添加到一个指定的div中,非常重要!
region : 'west',
title : '功能菜单',
width : 200,
minSize : 180,
maxSize : 250,
split : true,
autoHeight : false,
frame : true,// 美化界面
// width : 200,//面板宽度
// title : '可编辑和拖动的异步树',//标题
// autoScroll : true, // 自动滚动
enableDD : true,// 是否支持拖拽效果
containerScroll : true,// 是否支持滚动条
rootVisible : true, // 是否隐藏根节点,很多情况下,我们选择隐藏根节点增加美观性
border : true, // 边框
animate : true, // 动画效果
loader : treeloader
// 树加载
});
// 异步加载根节点
var rootnode = new Tree.AsyncTreeNode({
id : '0',
text : '家电品牌总类',
draggable : false,// 根节点不容许拖动
expanded : true
});
// 为tree设置根节点
treepanel.setRootNode(rootnode);
// 响应加载前事件,传递node参数
treepanel.on('beforeload', function(node) {
treepanel.loader.dataUrl = 'tree.jsp?parentId=' + node.id; // 定义子节点的Loader
});
// 渲染树形
treepanel.render();
// 展开节点,第一个参数表示是否级联展开子节点
rootnode.expand(true);
// 设置树的点击事件
function treeClick(node, e) {
if (node.isLeaf()) {
e.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) {
var n = contentPanel.add({
'id' : node.id,
'title' : node.text,
closable : true,
autoLoad : {
url : 'tabFrame.jsp?url=grid.html',
scripts : true
} // 通过autoLoad属性载入目标页,如果要用到脚本,必须加上scripts属性
});
}
contentPanel.setActiveTab(n);
}
}
// 增加鼠标单击事件
treepanel.on('click', treeClick);
// 定义右键菜单
var rightClick = new Ext.menu.Menu({
id : 'rightClickCont',
items : [{
id : 'rMenu1',
text : '添加节点',
// 增加菜单点击事件
handler : function() {
alert('添加节点的实现!');
}
}, {
id : 'rMenu2',
text : '编辑节点'
}, {
id : 'rMenu3',
text : '删除节点'
}]
});
// 增加右键点击事件
treepanel.on('contextmenu', function(node, event) {// 声明菜单类型
event.preventDefault();// 阻止浏览器默认右键菜单显示
rightClick.showAt(event.getXY());// 取得鼠标点击坐标,展示菜单
});
/*
* 设置tree的节点放置函数此函数有一个很重要的参数对象e e对象有三个重要的属性,分别为dropNode,target,point
* 1.dropNode为在拖动时鼠标抓住的节点 2.target为将要放置在某处的节点
* 3.point为被放置的状态,分别有append表示添加,above节点的上方,below节点的下方。
*
*/
treepanel.on('nodedrop', function(e) {
if (e.point == 'append') {
alert('当前"' + e.dropNode.text + '"划到"' + e.target.text
+ '"里面!');
} else if (e.point == 'above') {
alert('当前"' + e.dropNode.text + '"放在了"' + e.target.text
+ '"上面!');
} else if (e.point == 'below') {
alert('当前"' + e.dropNode.text + '"放在了"' + e.target.text
+ '"下面!');
}
});
// 在原有的树形添加一个TreeEditor
var treeEditer = new Tree.TreeEditor(treepanel, {
allowBlank : false
});
/*
* 为创建的treeEditer添加事件 有两个事件最为常用,一个为beforestartedit另一个为complete
* 从名字就可以看出,beforestartedit事件是在编辑前的事件,因此可以通过它来判断那些节点可以编辑那些不可以。
* complete为编辑之后的事件,在这里面可以添加很多事件,比如添加一个Ext.Ajax向后台传送修改的值等等。
*/
treeEditer.on("beforestartedit", function(treeEditer) {
var tempNode = treeEditer.editNode;// 将要编辑的节点
if (tempNode.isLeaf()) {// 这里设定叶子节点才容许编辑
return true;
} else {
return false;
}
});
treeEditer.on("complete", function(treeEditer) {
alert("被修改为" + treeEditer.editNode.text);
});
// (1)通过TabPanel控件的html属性配合<iframe>实现。该方法是利用
// html属性中包含<iframe>的语法来调用另一个页面,具体见代码。
// (2)通过TabPanel控件的autoLoad属性实现。该方法是利用autoLoad属性,它有很多参数,
// 其中有两个比较重要,url表示要载入的文件,scripts表示载入的文件是否含有脚本,该属性相当重要,
// 如果在新的页面中要创建Ext控件,必须指定该参数。该方法实现较前一个复杂,因为引入的文件不是一个完整的html文件,
// 有可能只是内容的一部分,但是资源占用较少,而且载入速度较快(它有一个载入指示)
// 添加第一个节点(html)
treepanel.root.appendChild(new Ext.tree.TreeNode({
id : 'htmlPanel',
text : '通过html打开',
listeners : {
'click' : function(node, event) {
event.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) { // 判断是否已经打开该面板
n = contentPanel.add({
'id' : node.id,
'title' : node.text,
closable : true, // 通过html载入目标页
html : '<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="grid.html"></iframe>'
});
}
contentPanel.setActiveTab(n);
}
}
}));
// 添加第二个节点(autoLoad)
treepanel.root.appendChild(new Ext.tree.TreeNode({
id : 'autoLoadPanel',
text : '通过autoLoad打开',
listeners : {
'click' : function(node, event) {
event.stopEvent();
var n = contentPanel.getComponent(node.id);
if (!n) { // //判断是否已经打开该面板
n = contentPanel.add({
'id' : node.id,
'title' : node.text,
closable : true,
autoLoad : {
url : 'tabFrame.jsp?url=grid.html',
scripts : true
} // 通过autoLoad属性载入目标页,如果要用到脚本,必须加上scripts属性
});
}
contentPanel.setActiveTab(n);
}
}
}));
// 右边具体功能面板区
var contentPanel = new Ext.TabPanel({
region : 'center',
enableTabScroll : true,
activeTab : 0,
items : [{
id : 'homePage',
title : '首页',
autoScroll : true,
html : '<div style="position:absolute;color:#ff0000;top:40%;left:40%;">Tree控件和TabPanel控件结合功能演示</div>'
}]
});
new Ext.Viewport({
layout : 'border', // 使用border布局
defaults : {
activeItem : 0
},
items : [treepanel, contentPanel]
});
});
3. 再接着是tree.js中ExtJS的TreeLoader调用的tree.jsp,在目录树上点击TreeNode后会加载下一级节点。tree.jsp负责TreeNode点击后,传回由下一级节点构造的JSON数据,也就是前台树异步请求访问的后台WEB组件。它会调用JAVABEAN操作数据库,得到每个节点的子节点数据。这里由于我们后台需要返回给客户端JSON格式的数据,也就是需要操作JSON数据格式。所以我们首先要下载JSON-lib,地址:http://json-lib.sourceforge.net/打开网址后,首页上有一段话:
Json-lib requires (at least) the following dependencies in your classpath:
jakarta commons-lang 2.3
jakarta commons-beanutils 1.7.0
jakarta commons-collections 3.2
jakarta commons-logging 1.1.1
ezmorph 1.0.4
需要下载上述jar文件,配合JSON-lib 一起使用。
commons 下载地址:http://commons.apache.org/
ezmorph 下载地址:http://ezmorph.sourceforge.net
或者,到 http://www.docjar.com 搜索下载。
JSON的用法,我们已经提过多次,大家可参考相关文档。看看tree.jsp的代码:
<%@ page language="java" pageEncoding="utf-8"%>
<jsp:useBean class="org.leno.javabean.JSONTree" id="JSONTree"></jsp:useBean>
<%
String parentId = "";
if (request.getParameter("parentId") != null) {
parentId = request.getParameter("parentId").toString();
}
JSONTree.setparentId(parentId);
%>
<%=JSONTree.getJSONString()%>
4. 后台用到的JAVA类,这里包括访问数据库的数据源工厂类DataSourceFactory(这里用到了DBCP连接池,大家要记得导入连接sqlserver 2000数据库和dbcp连接池的相关JAR包!),定义树节点的属性,包括节点ID、Text、图标、是否为叶子节点、是否展开等的类JSONTreeNode,还有类似DAO能够封装数据访问和格式转换细节的JSONTree。
package org.leno.javabean;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
public class DataSourceFactory {
/**
* @param args
*/
private static BasicDataSource ds;
public static BasicDataSource getDataSource() {
if (ds == null) {
ds = new BasicDataSource();
ds.setDriverClassName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
ds.setUrl("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=java28");
ds.setUsername("sa");
ds.setPassword("123");
ds.setMaxActive(5);
}
return ds;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
System.out.println(DataSourceFactory.getDataSource()
.getConnection());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package org.leno.javabean;
/**
* @author leno
*定义树节点的属性,包括节点ID、Text、图标、是否为叶子节点、是否展开等。
*/
public class JSONTreeNode {
private String id; //ID
private String text; //节点显示
private String cls; //图标
private boolean leaf; //是否叶子
private String href; //链接
private String hrefTarget; //链接指向
private boolean expandable; //是否展开
private String description; //描述信息
get/set……
}
package org.leno.javabean;
import java.sql.*;
import java.util.*;
import net.sf.json.JSONArray;
public class JSONTree {
private String parentId;
public String getJSONString(){
Connection con =null;
Statement st = null;
ResultSet rs = null;
List<JSONTreeNode> treeNodeArray = null;
String SQLString = "SELECT * FROM Categories WHERE parentId="+this.parentId+" ORDER BY categoryId";
try
{
con = DataSourceFactory.getDataSource().getConnection();
st = con.createStatement();
//查找所有拥有下级类别的类别ID
rs = st.executeQuery("SELECT parentId FROM Categories WHERE parentId>0 Group By parentId Order By parentId");
StringBuffer parentIDBuffer =new StringBuffer();
parentIDBuffer.append("|");
while(rs.next())
{
parentIDBuffer.append(rs.getString("parentId"));
parentIDBuffer.append("|");
}
//得到所有的parentcategoryId列表
String parentIDString = parentIDBuffer.toString();
rs = st.executeQuery(SQLString);
treeNodeArray = new ArrayList<JSONTreeNode>();
while(rs.next())
{
JSONTreeNode treeNode = new JSONTreeNode();
String categoryId = rs.getString("categoryId");
treeNode.setId(categoryId);
treeNode.setText(rs.getString("categoryName"));
treeNode.setDescription(rs.getString("description"));
// treeNode.setHref("rightframe.jsp?categoryId="
// + rs.getString("categoryId").toString());
// treeNode.setHrefTarget("rightFrame");
if (parentIDString.indexOf("|"+categoryId+"|")>=0) //父节点
{
treeNode.setCls("folder");
treeNode.setLeaf(false);
treeNode.setExpandable(false);
}
else //子节点
{
treeNode.setCls("file");
treeNode.setLeaf(true);
treeNode.setExpandable(false);
}
treeNodeArray.add(treeNode);
}
JSONArray JsonArray = JSONArray.fromObject(treeNodeArray); //得到JSON数组
return JsonArray.toString();//返回JSON数据
}
catch(Exception e)
{
System.out.println("getJSONString() of JSONTree.java throws : "+e.toString());
return "";
}
finally
{
try {
if(con!=null&&!con.isClosed()){
con.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String getparentId() {
return parentId;
}
public void setparentId(String parentId) {
this.parentId = parentId;
}
}
5. 最后是我们的数据库脚本script.sql,大家用SQLServer 2000数据库创建一个java28的database,然后执行下列脚本即可。
create table Categories
(
categoryId int identity(1,1) primary key,
categoryName varchar(30),
description varchar(100),
parentId int
)
insert into Categories values('电脑','关于电脑',0);
insert into Categories values('电视机','关于电视机',0);
insert into Categories values('数码相机','关于数码相机',0);
insert into Categories values('冰箱','关于冰箱',0);
insert into Categories values('联想电脑','关于联想电脑',1);
insert into Categories values('创维电视机','关于创维电视机',2);
insert into Categories values('索尼相机','关于索尼相机',3);
insert into Categories values('海尔冰箱','关于海尔冰箱',4);
insert into Categories values('旭日电脑','关于旭日电脑',5);
insert into Categories values('天逸电脑','关于天逸电脑',5);
insert into Categories values('创维液晶电视','关于创维液晶电视机',6);
insert into Categories values('索尼M23相机','关于索尼M23相机',7);
insert into Categories values('海尔G1冰箱','关于海尔G1冰箱',8);
select * from Categories
SELECT parentId FROM Categories WHERE parentId>0 Group By parentId Order By parentId
ExtJS只要求返回的数据格式类似下面这样即可:
[{'text':'welcome.html','id':'welcome.html','cls':'file',myPara:'myValue'},
{'text':'welcome2.html','id':'welcome2.html','leaf':true,'cls':'file','href':'welcome2.html'}]
这些数据是存储到一个数组中的,数组中的每一项代表一个节点,每一个节点都包含以下几个主要属性:
text:定义该节点显示的名称;
id:定义该节点的页面ID,便于document.getElementById方法获取该节点;
leaf:true或者false,定义该节点是否是叶子节点;
cls:定义该节点的class(显示的样式);
href:定义点击该节点后链接的页面;
另外你还可以为节点增加自定义的属性,方法如上面的myPara:'myValue'一样。ExtJS会自动将返回的数据解析成节点并正确显示到页面上。
分享到:
相关推荐
在IT领域,特别是前端开发中,`Ext JS`是一个广泛使用的JavaScript库,它提供了一整套组件和工具,用于构建富交互式的Web应用程序。`TreePanel`是`Ext JS`中的一个关键组件,用于展示层次结构的数据,就像操作系统中...
TreePanel可以与Ext.data.TreeStore配合使用,TreeStore负责加载和管理树形数据。TreePanel中的每个节点通常表示为一个条目,这些条目可以通过配置不同的列来进行展示和编辑。 在描述中提到的`Ext.grid....
- 在权限管理中,可以使用这样的TreePanel来让用户选择不同的权限角色或功能。 - 文件管理系统中,可以展示文件夹和文件的层级结构,并通过Checkbox选择需要操作的项目。 - 在组织架构展示中,可以方便地勾选以...
Ext.NET的TreePanel还支持异步加载,这样在处理大量数据时可以提高性能。 结合使用Menu和TreePanel,开发者可以创建复杂的导航结构。例如,Menu可以作为主导航,包含多个顶级菜单项,每个菜单项可以关联到一个...
完美的Extjs4 treePanel节点刷新,函数为自动刷新选中的节点.API看得头疼才别出来的代码.截止我发之前,好像没有谁共享这个功能的函数吧.
在EXTJS这个强大的JavaScript框架中,`Ext.Panel`和`TreePanel`是两个非常重要的组件,它们被广泛用于构建复杂的用户界面。这篇文章将探讨如何在这些组件中动态加载本地页面数据,以提升用户体验并实现灵活的数据...
当我们谈论“DWR方式动态加载EXT TreePanel”时,意味着我们需要使用DWR来获取服务器端的数据,并将其动态地填充到EXT TreePanel中,以实现数据的实时更新和交互性。这种技术的应用场景可能包括:当用户需要查看或...
在本文中,我们将深入探讨`TreePanel`和`TabPanel`这两个重要的Ext JS组件,并讨论如何将它们结合在一起,以创建功能丰富的用户界面。`TreePanel`用于展示层次结构的数据,而`TabPanel`则提供了多标签页的功能,两者...
6. **页面布局**:整个页面可能使用了ExtJS 的布局管理器,如`border`布局,将页面分为左侧和右侧两部分,左侧是TreePanel,右侧是可折叠的TabPanel。 7. **URL 链接处理**:`嘉瑞传播.url`可能是一个树节点的`href...
通过以上步骤,我们就能在VS环境下搭建一个使用Ext4.2 TreePanel的简单应用,并与数据库进行交互。这只是一个基础的框架,实际开发中可能需要根据业务需求进行更多的定制和优化,例如增加拖放功能、节点展开动画、...
在EXT.NET框架中,TreePanel是一个非常重要的组件,它用于展示层次结构的数据,例如文件系统、组织结构等。本文将详细讲解如何实现TreePanel中的Checkbox操作以及父子节点间的联动效果,特别是针对之前存在的Bug进行...
在ASP.NET环境中,使用Ext JS的TreePanel组件展示数据时,你可能会遇到一个问题,即尝试直接从服务器加载XML文件,但树形结构无法正确显示或数据加载失败。这个问题通常是由于跨域限制、数据格式不正确或者服务器端...
博文链接:https://jfp.iteye.com/blog/178889
环境:Windows XP sp3、IE 7.0、MS SQL Server 2000、MyEclipse5.5、 Ext 3.2、Tomcat 6.0 使用步骤: 1、下载解压之后,使用IDE...阅读对象:本中心需要使用Ext框架开发的人员 阅读条件:熟悉JavaScript的DOM编程技术
在"struts2中用ext框架显示树(tree)形菜单"这个主题中,我们主要关注如何在Struts2应用中使用EXT框架来展示树形结构数据。EXT框架的TreePanel组件非常适合用来展示层次化的数据,如组织结构、文件系统或导航菜单。...
默认情况下,TreePanel使用SingleSelectionModel,但可以通过配置项`selModel`设置为`Ext.selection.TreeModel`来启用多选模式。 问题的根源可能有以下几点: 1. **配置问题**:确保在创建TreePanel时正确配置了...
在EXT中,我们通常会使用Store来存储和管理数据,然后将Store与Treepanel关联,从而在界面上显示数据。在这个例子中,“简单的EXT加载数据的例子”可能是指如何动态地从服务器获取数据并加载到Treepanel中。 1. **...
- 使用`Ext.data.TreeStore`可以更灵活地管理树的数据源,支持远程数据加载和实时更新。 8. **示例代码**: 示例代码中,`treePanel.html`定义了HTML结构,`treePanel.js`包含了`TreePanel`的创建和配置。`...