利用Dojo和JSON建立无限级AJAX动态加载的功能模块树


Posted in Javascript onMarch 24, 2007

 看了“使用hibernate实现树形结构无限级分类”这篇文章后,我也想将自己在所有开发的项目中使用的功能模块树的实现方法以及完整DEMO(含源码)贴出来和大家分享。其实在我的博客里是老早贴出来的,由于时间关系没好好整理。
       功能模块树是几乎在每个项目里都要用到的东西,利用Dojo的好处就是可以实现树的子节点的动态加载,这在树节点很多的情况下是很有用的。
        下载附件二dojotree.rar,解压后将dist\dojotree.war部署到应用服务器即可浏览DEMO,DEMO中内置HSQLDB数据库,启动时自动加载。DEMO运行截图见附件一。 
一、tree.jsp主要代码
1、首先在head中导入Dojo库(dojo.js)和TreeWidget
<script>"text/javascript" src="ajax/dojo/dojo.js">   
<script>"text/javascript">   
dojo.require("dojo.widget.Tree");   
dojo.require("dojo.widget.TreeNode");   
dojo.require("dojo.widget.TreeSelector");   
dojo.require("dojo.widget.TreeRPCController");   
dojo.require("dojo.widget.TreeLoadingController");   
dojo.require("dojo.widget.TreeContextMenu");   
</script>   
2、在body中放置TreeWidget,TreeLoadingController中的RPCUrl="treeServlet"为从后台获取数据的servlet名称,TreeNode中的expandLevel表示树初始张开级别
<div dojoType="TreeLoadingController" RPCUrl="treeServlet" widgetId="treeController" DNDController="create"><!--</span-->div>   
<div dojoType="TreeSelector" widgetId="treeSelector"><!--</span-->div>   
<div dojoType="Tree" DNDMode="between" selector="treeSelector" widgetId="bandTree" controller="treeController">   
<div dojoType="TreeNode" title="root" widgetId="root" objectId="root" isFolder="true" childIconSrc="images/comm.gif" expandLevel="1"/>   
3、建立TreeSelector事件处理函数
function treeSelectFired() {   
    // get a reference to the treeSelector and get the selected node    
    var treeSelector = dojo.widget.manager.getWidgetById('treeSelector');   
    var treeNode = treeSelector.selectedNode;   
    // get a reference to the songDisplay div   
    var hostDiv = document.getElementById("songDisplay");   
    var isFolder = treeNode['isFolder'];   
    //alert(isFolder);   
    if ( !isFolder) {   
       var song = treeNode['title'];   
       var url = treeNode['url'];   
       link(url);   
    } else {    
    }   
}   
4、将select事件处理函数关联到treeSelector
function init() {    
    //get a reference to the treeSelector   
    var treeSelector = dojo.widget.manager.getWidgetById('treeSelector');   
    //connect the select event to the function treeSelectFired()   
    dojo.event.connect(treeSelector,'select','treeSelectFired');    
}   
dojo.addOnLoad(init);   
二、主要java代码及数据结构
1、Gnmk.java中tree的属性
 private String id;     
 private String gnmkdm;  //功能模块代码   
private String gnmksm;  //功能模块说明   
private String gnmktb;  //功能模块图标   
 private String gnmklj;  //功能模块路径   
 private String gnmkmc;  //功能模块名称   
private String gnmksj;  //功能模块上级代码   
private String gnmkbz;  //功能模块标志(‘N'为叶节点)   
2、HSQLDB内存数据库加载SQL(db.sql)
CREATE TABLE GNMK (ID VARCHAR, GNMKDM VARCHAR, GNMKMC VARCHAR, GNMKLJ VARCHAR, GNMKTB VARCHAR, GNMKBZ VARCHAR, GNMKSJ VARCHAR);     
INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1', null, 'system.gif', 'Y', '');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830001', '0101', '二级目录1', 'cxtjAction.do', 'system.gif', 'N', '01');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830001', '0102', '二级目录2', 'cxtjAction.do', 'system.gif', 'N', '01');     
INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780002', '02', '一级目录2', null, 'system.gif', 'Y', '');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '0201', '二级目录1', 'cxtjAction.do', 'system.gif', 'N', '02');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '0202', '二级目录2', 'cxtjAction.do', 'system.gif', 'Y', '02');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '020201', '三级目录1', 'cxtjAction.do', 'system.gif', 'N', '0202');     
INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '020202', '三级目录2', 'cxtjAction.do', 'system.gif', 'N', '0202');    
3、TreeServlet .java主要代码,在getGnmkByParent(String gnmksj)方法中可以实现自己的业务,DEMO中使用GnmkDAO
public class TreeServlet extends HttpServlet {   
    private static final long serialVersionUID = 1L;   
    protected void doGet(HttpServletRequest request,   
            HttpServletResponse response) throws ServletException, IOException {   
        String action = request.getParameter("action");   
        System.out.println("action b=>" + action);   
        System.out.println("action b=>" + action);   
        String data = request.getParameter("data");   
        if (action.equalsIgnoreCase("getChildren")) {   
            JSONTokener jsonTokener = new JSONTokener(data);   
            JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();   
            JSONObject parentNodeObject = (JSONObject) jsonObject.get("node");   
            response.setContentType("text/json; charset=gb2312");   
            PrintWriter out = response.getWriter();   
            out.write(getChildren(parentNodeObject));   
        } else {   
        }   
    }   
    private String getChildren(JSONObject parentNodeObject) {   
        JSONArray result = new JSONArray();   
        String parentObjectId = parentNodeObject.getString("objectId");// id 唯一   
        // String parentWidgetId = parentNodeObject.getString("widgetId");// dm   
        parentObjectId = parentObjectId.equalsIgnoreCase("root") ? ""   
                : parentObjectId;   
        System.out.println("parentObjectId=>" + parentObjectId);   
        // 获取子功能模块   
        List listGnmk = this.getGnmkByParent(parentObjectId);   
        System.out.println("listGnmk=>" + listGnmk.size());   
        if (listGnmk != null) {   
            Iterator itGnmk = listGnmk.iterator();   
            while (itGnmk.hasNext()) {   
                Gnmk qxgnmk = (Gnmk) itGnmk.next();   
                try {   
                    JSONObject jsonGnmkObject = new JSONObject();   
                    String gnmkbz = qxgnmk.getGnmkbz();   
                    boolean isFolder = gnmkbz.equalsIgnoreCase("Y") ? true   
                            : false;   
                    jsonGnmkObject.put("title", qxgnmk.getGnmkmc());   
                    jsonGnmkObject.put("isFolder", isFolder);   
                    jsonGnmkObject.put("widgetId", qxgnmk.getGnmkdm());   
                    jsonGnmkObject.put("objectId", qxgnmk.getGnmkdm());   
                    jsonGnmkObject.put("childIconSrc", "images/"   
                            + qxgnmk.getGnmktb());   
                    jsonGnmkObject.put("url", qxgnmk.getGnmklj());   
                    result.put(jsonGnmkObject);   
                } catch (JSONException e) {   
                    e.printStackTrace();   
                }   
            }   
        }   
        return result.toString();   
    }   
    private List getGnmkByParent(String gnmksj) {   
        GnmkDAO gnmkDao = new GnmkDAO();   
        return gnmkDao.getGnmkByParent(gnmksj);   
    }   
}   
三、关于DEMO的其它配置说明
1、实现javax.servlet.ServletContextListener接口的contextInitialized方法来加载HSQLDB及其数据,ContextListener.java主要代码 
public void contextInitialized(ServletContextEvent event) {   
    try {   
        // load the driver   
        Class.forName("org.hsqldb.jdbcDriver");   
        // create the table and add sample data   
        InputStreamReader in = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("db.sql"));   
        BufferedReader reader = new BufferedReader(in);   
        DBUtils.setupDatabase(reader);   
    } catch (ClassNotFoundException e) {   
        e.printStackTrace();   
    }   
}   
2、web.xml相关配置
<listener>   
    <listener-class>   
       dojo.sample.ContextListener   
    <!--<span class="tag"--><!--</span-->listener-class>   
<!--</span-->>  
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树 
下载

Javascript 相关文章推荐
[原创]提供复制本站内容时出现,该文章转自脚本之家等字样的js代码
Mar 27 Javascript
扩展jquery实现客户端表格的分页、排序功能代码
Mar 16 Javascript
javascript之querySelector和querySelectorAll使用说明
Oct 09 Javascript
关于jQuery新的事件绑定机制on()的使用技巧
Apr 26 Javascript
js父页面与子页面不同时显示的方法
Oct 16 Javascript
JavaScript中的Math.E属性使用详解
Jun 12 Javascript
js获取当前周、上一周、下一周日期
Mar 19 Javascript
vue中全局路由守卫中替代this操作(this.$store/this.$vux)
Jul 24 Javascript
vue 导航菜单刷新状态不消失,显示对应的路由界面操作
Aug 06 Javascript
JavaScript实现简单动态表格
Dec 02 Javascript
详解Vue的异步更新实现原理
Dec 22 Vue.js
Vue ​v-model相关知识总结
Jan 28 Vue.js
tbody元素支持嵌套的注意方法
Mar 24 #Javascript
xml 与javascript结合的问题解决方法
Mar 24 #Javascript
用prototype实现的简单小巧的多级联动菜单
Mar 24 #Javascript
this[] 指的是什么内容 讨论
Mar 24 #Javascript
javascript对象的property和prototype是这样一种关系
Mar 24 #Javascript
Ajax一统天下之Dojo整合篇
Mar 24 #Javascript
dojo 之基础篇(三)之向服务器发送数据
Mar 24 #Javascript
You might like
php解析xml提示Invalid byte 1 of 1-byte UTF-8 sequence错误的处理方法
2013/11/14 PHP
php提取字符串中网站url地址的方法
2014/12/03 PHP
全面解读PHP的人气开发框架Laravel
2015/10/15 PHP
基于PHP实现等比压缩图片大小
2016/03/04 PHP
Some tips of wmi scripting in jscript (1)
2007/04/03 Javascript
js 获取中文拼音,Select自动匹配字母获取值的代码
2009/09/23 Javascript
js获取select标签的值且兼容IE与firefox
2013/12/30 Javascript
js闭包实例汇总
2014/11/09 Javascript
使用jQuery仿苹果官网焦点图特效
2014/12/23 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
JavaScript中exec函数用法实例分析
2015/06/08 Javascript
js调出上下文菜单的实例
2015/12/17 Javascript
详解在AngularJS的controller外部直接获取$scope
2017/06/02 Javascript
vue中组件的3种使用方式详解
2019/03/23 Javascript
详解vue 路由跳转四种方式 (带参数)
2019/04/28 Javascript
解决Vue-cli3没有vue.config.js文件夹及配置vue项目域名的问题
2020/12/04 Vue.js
JavaScript实现滚动加载更多
2020/12/27 Javascript
[01:35]辉夜杯战队访谈宣传片—iG.V
2015/12/25 DOTA
python append、extend与insert的区别
2016/10/13 Python
Ubuntu下创建虚拟独立的Python环境全过程
2017/02/10 Python
python 实现将字典dict、列表list中的中文正常显示方法
2018/07/06 Python
Python3 修改默认环境的方法
2019/02/16 Python
python求平均数、方差、中位数的例子
2019/08/22 Python
Django 返回json数据的实现示例
2020/03/05 Python
jupyter使用自动补全和切换默认浏览器的方法
2020/11/18 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
CSS3模拟IOS滑动开关效果
2016/09/28 HTML / CSS
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
美国战术品牌:5.11 Tactical
2019/05/01 全球购物
环境科学毕业生自荐信
2013/11/21 职场文书
求职信模板标准格式范文
2014/02/23 职场文书
大学生应聘导游自荐信
2014/06/02 职场文书
春节超市活动方案
2014/08/14 职场文书
教师政风行风自查自纠报告
2014/10/21 职场文书
升职感谢领导的话语及升职感谢信
2019/06/24 职场文书
Python并发编程实例教程之线程的玩法
2021/06/20 Python