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

所属分类: 网络编程 / JavaScript 阅读数: 1864
收藏 0 赞 0 分享
 看了“使用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-->>  
dojotree.jpg 
下载
更多精彩内容其他人还在看

Angular使用Md5加密的解决方法

这篇文章主要介绍了Angular使用Md5加密的解决方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解JS构造函数中this和return

本文通过实例代码给大家介绍了JS构造函数中this和return,需要的朋友参考下吧
收藏 0 赞 0 分享

ES6中Array.find()和findIndex()函数的用法详解

ES6为Array增加了find(),findIndex函数。find()函数用来查找目标元素,找到就返回该元素,找不到返回undefined,而findIndex()函数也是查找目标元素,找到就返回元素的位置,找不到就返回-1。下面通过实例详解,需要的朋友参考下吧
收藏 0 赞 0 分享

JS闭包的几种常见形式实例详解

本文通过实例代码给大家详细介绍了js闭包的几种常见形式,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下
收藏 0 赞 0 分享

ES6中Array.copyWithin()函数的用法实例详解

ES6为Array增加了copyWithin函数,用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。下面重点给大家介绍ES6中Array.copyWithin()函数的用法,需要的朋友参考下
收藏 0 赞 0 分享

Javascript 严格模式use strict详解

严格模式:由ECMA-262规范定义的JavaScript标准,对javascrip的限制更强。这篇文章主要介绍了Javascript 严格模式use strict详解 ,需要的朋友可以参考下
收藏 0 赞 0 分享

引入JavaScript时alert弹出框显示中文乱码问题

今天在HTML中引入JavaScript文件运行时,alert弹出的提示框中文显示为乱码,怎么解决此问题呢?下面小编给大家带来了引入JavaScript时alert弹出框显示中文乱码问题的解决方法,一起看看吧
收藏 0 赞 0 分享

AngularJs 延时器、计时器实例代码

这篇文章主要介绍了AngularJs 延时器、计时器实例代码,需要的朋友可以参考下
收藏 0 赞 0 分享

JS分页的实现(同步与异步)

这篇文章主要介绍了JS分页的实现(同步与异步),需要的朋友可以参考下
收藏 0 赞 0 分享

Angularjs自定义指令实现分页插件(DEMO)

由于最近的一个项目使用的是angularjs1.0的版本,涉及到分页查询数据的功能,后来自己就用自定义指令实现了该功能,下面小编把实例demo分享到脚本之家平台,需要的朋友参考下
收藏 0 赞 0 分享
查看更多