标题:通用的自定义菜单和动态加载的树
只看楼主
bestlife
Rank: 1
等 级:新手上路
帖 子:484
专家分:0
注 册:2005-7-8
 问题点数:0 回复次数:3 
通用的自定义菜单和动态加载的树
[Usercp=2000]
struts-menu+ibatis+少量的代码=通用的自定义菜单和动态加载的树(续)

从前面的文章我们知道,用xtree来显示树形结构(实际上也可以用其他的方式来显示,不过这个是关于struts-menu如何使用了,跟本文无关)。我们还知道xtree系列还有一个更好的树,就是xloadtree,真正的动态加载的树。下面我们就来讲怎么使用它。

xloadtree的特点是通过XML来动态加载数据。因此我们也需要开发一个能产生XML的action。通过本文大家会发现JSP输出XML是多么简单。闲话少说,进入正题。产先把xloadtree加入到我们的project中去。如果想了解xloadtree和xtree的区别,请看http://webfx.eae.net/dhtml/xloadtree/xloadtree.html

首先我们需要修改一下velocity模板,原来的模板如下。

## displayMenu is defined in WEB-INF/classes/globalMacros.vm
#macro( menuItem $menu $level )
## set title
#set ($title = $displayer.getMessage($menu.title))
#set ($node = $menu.name)
#if ($level == 0)
var $node = new WebFXTree('$title'#if($menu.url),'$!menu.url'#end);
#else
var $node = new WebFXTreeItem('$title'#if($menu.url),'$!menu.url'#end);
${menu.parent.name}.add($node);
#end
#end

#displayMenu($menu 0)
document.write($menu.name);

很简单的一个修改,把蓝色的这一行改成

var $node = new WebFXLoadTreeItem('$title'#if($menu.url),'$!menu.url'#end);

这样就生成了动态加载的树了。

然后新建一个JSP文件

<%@ page contentType="text/html; charset=GBK" %>
<%@ include file="/taglibs.jsp"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>XTree (with Velocity) Example</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<link rel="stylesheet" type="text/css" media="screen"
href="styles/global.css" />
<link rel="stylesheet" type="text/css" media="screen"
href="<html:rewrite page="/styles/xtree.css"/>" />

<script type="text/javascript" src="<html:rewrite page="/scripts/xtree.js"/>"></script>
<script type="text/javascript" src="<html:rewrite page="/scripts/xmlextras.js"/>"></script>
<script type="text/javascript" src="<html:rewrite page="/scripts/xloadtree.js"/>"></script>

</head>
<body>

<div class="container">
Simple menu with Velocity:<br />
<script type="text/javascript">
<menu:useMenuDisplayer name="Velocity" config="/templates/xloadtree.html"
bundle="org.apache.struts.action.MESSAGE">
if (document.getElementById) {
<cp:displayMenu name="com.ewuxi.champion.menu"/>
} else {
var msg = "Your browser does not support document.getElementById().\n";
msg += "You must use a modern browser for this menu.";
alert(msg);
}

</menu:useMenuDisplayer>
</script>
</div>

</body>
</html>

跟旧的文件相比。多了三个scripts文件,然后把模板文件改成新的。

下一步是增加XML文件,新建一个subMenu.jsp

<?xml version="1.0" encoding="GBK"?>
<%@ page language="java" contentType="text/xml;charset=GBK" %>
<%@ include file="/taglibs.jsp"%>
<menu:useMenuDisplayer name="Velocity" config="/templates/xloadsub.html"
bundle="org.apache.struts.action.MESSAGE">
<cp:displayMenu name="com.ewuxi.champion.menu"/>
</menu:useMenuDisplayer>

要让JSP显示XML文件。只需要变更上面两行蓝的就OK了。同样也需要一个新的模板,这个模板是组织一个XML文件。从下面文件可以看到可以看到。velocity的模板还是比较简单的。

<tree>
## displayMenu is defined in WEB-INF/classes/globalMacros.vm
#macro( menuItem $menu $level )
## set title
#set ($title = $displayer.getMessage($menu.title))
#set ($node = $menu.name)
#if ($level != 0)
<tree text="$title" #if($menu.action)src="$!menu.url" #end />
#end
#end

#displayMenu($menu 0)
</tree>

JSP部分准备完毕。然后我们需要一个新的action.在struts-config里加上一个

<action path="/loadTree"
type="com.ewuxi.champion.action.TreeLoadDemoAction"

scope="request">
<forward name="loadDemo" path="/loaddemo.jsp" redirect="false"/>
<forward name="subMenu" path="/subMenu.jsp" redirect="false"/>
</action>

然后建立TreeLoadDemoAction这个JAVA类。其代码也很简单

     Service.initSet();
DaoCommon.startTransaction();

HashMap parMap = new HashMap();
Enumeration enumeration = request.getParameterNames();
while (enumeration.hasMoreElements()) {
String element = (String) enumeration.nextElement();
if (!"type".equals(element) & !"menuName".equals(element))
parMap.put(element, request.getParameter(element));
}
TreeDemoSession session = new TreeDemoSession();
request.setAttribute(
"com.ewuxi.champion.menu",
session.getLoadMenu(request.getParameter("menuName"), parMap,request.getParameter("type")));

DaoCommon.rollBack();

return mapping.findForward(request.getParameter("type"));

第一行蓝色代码首先是去掉了一些不必要的参数。然后调用一个新的方法,这个方法可以动态生成数据。

下一步来实现getLoadMenu方法

// 通过名称和参数来得到动态树
public MenuComponent getLoadMenu(String name, Map keys, String menuType)
throws Exception {
this.menuType = menuType;
Map menuMap =
(Map) (new XmlUtils().read(Service.getPath() + "/menu.xml"));
MenuComponent menu = new MenuComponent();

if (menuMap.get(name) != null) {
MenuDefine rootMenudefine = (MenuDefine) menuMap.get(name);
menu.setTitle(rootMenudefine.getTitle());
menu.setName(rootMenudefine.getMenuName());

menu = submenuLoadAdd(menu, keys, menuMap, name);
}
return menu;
}

跟前面的代码相比,只是调用的子函数有变化。

/**组建动态加载的树。每次只加载一层
* @param menu
* @param map
* @param menuMap
* @param menuName
* @return
* @throws DaoException
* @throws Exception
*/
private MenuComponent submenuLoadAdd(
MenuComponent menu,
Map map,
final Map menuMap,
String menuName)
throws DaoException, Exception {
try {
//得到菜单定义
MenuDefine menudefine = (MenuDefine) menuMap.get(menuName);
//listfield,表示需要读取哪几个字段
map.put("listfield", menudefine.getListField());
//查询,返回列表。
List list = DaoCommon.findbyName(map, menudefine.getSqlName());

int namei = 0;
for (Iterator iter = list.iterator(); iter.hasNext();) {
Map element = (Map) iter.next();
//建立当前节点
MenuComponent submenu = new MenuComponent();
submenu.setName(menu.getName() + String.valueOf(namei++));
submenu.setTitle(
String.valueOf(element.get(menudefine.getTitleField())));
//如果不需要显示,则使用父节点作为当前节点
if (!menudefine.isNeedShow())
submenu = menu;
//如果有子菜单,则根据是否有数据决定加动态菜单
if (menudefine.getSubmenuName() != null) {

submenuUrlAdd(
submenu,
getSubMenuInfo(menudefine, element),
menuMap,
menudefine.getSubmenuName());
}
//将当前节点放到树中。(如果不需要就读取子菜单)
if (menudefine.isNeedShow())
menu.addMenuComponent(submenu);
else {
menu =
submenuLoadAdd(
submenu,
getSubMenuInfo(menudefine, element),
menuMap,
menudefine.getSubmenuName());
}

}
return menu;
} catch (DaoException e) {

throw e;
} catch (Exception e) {

throw e;
}
}

跟以前的代码相比也只是修改了很小的一部分。从而不成为递归函数了。

 /**如果子菜单有数据,则加入动态加载项
* @param submenu
* @param map
* @param menuMap
* @param string
* @return
*/
private void submenuUrlAdd(
MenuComponent submenu,
HashMap map,
Map menuMap,
String menuName)
throws Exception {
//得到菜单定义
MenuDefine menudefine = (MenuDefine) menuMap.get(menuName);
//listfield,表示需要读取哪几个字段
map.put("listfield", menudefine.getListField());
//查询,返回列表。
List list = DaoCommon.findbyName(map, menudefine.getSqlName());
if (list.size() > 0) {
map.remove("listfield");
String location = "";
String adjust = "&";
if ("subMenu".equals(menuType))
adjust = "&amp;";
location += adjust + "menuName=" + menudefine.getMenuName();
for (Iterator iterator = map.keySet().iterator();
iterator.hasNext();
) {
String lkey = (String) iterator.next();
location += adjust + lkey + "=" + map.get(lkey);
}

submenu.setAction("/loadTree.do?type=subMenu" + location);
}
}

最后多了一个函数,这个函数负责在代码中加入URL,从而能够动态加载。其中有一点要注意的就是String adjust = "&"。&在xml中要变成&amp;才能正确处理。

好了,这样就完成了动态树了(注意XML的调试好象比较麻烦,有时间需要重开一个IE)。

源码下载

[/Usercp]

[此贴子已经被作者于2006-4-10 15:54:00编辑过]

搜索更多相关主题的帖子: 动态加载 定义菜单 xtree target 
2006-04-10 08:57
a123
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2006-2-14
得分:0 
这么贵。。。
2006-04-15 15:47
water123456
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:3208
专家分:5
注 册:2006-2-21
得分:0 
太强,受不了

让我们风风火火的过一生,别平平淡淡过一年。
2006-04-16 10:50
oヤ偽妳變壞
Rank: 2
等 级:新手上路
威 望:4
帖 子:2251
专家分:0
注 册:2006-3-19
得分:0 

晕哦,没有那么多魅力,气

2006-04-23 02:47



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-56429-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.910052 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved