最近参与了一个jsp项目,其间要处理一个用户对权限的关系,权限列表用带checkbox的树型结构来展示,于是到网上找“js 树形结构”,很快便找到了dtree,找到连接,下载了一个带checkbox的dtree,又找到一篇动态构建树形结构的文章(http://zc4530.blog.51cto.com/96735/29722 ), 三下五除二,根据自己使用的数据库写了一个符合例子数据库要求的sql,往数据库中插入三十几条数据,中间遇到几个小问题,但很快就解决了,最后打开页 面,一颗带有checkbox的树形菜单展示出来了,心里兴奋了一阵,大赞dtree的轻便易用,就接着做下面的事情了。
过了几天版本发布,交付测试,很快测试找到了我,我过去一看,页面上只有一个小窗口:“stack overflow at line:。。。”,晕倒!!
我立刻意识到性能问题,于是很快找到了dtree的致命递归(http://tech.ddvip.com/2009-03/1237891234112143.html ),我们的实际库数据量上几千,看来dtree是无能为力了,前功尽弃!唉,这就是开发人员的命运,继续找资料,于是找到了被称为大虾的梅花雪,以及他的成名作:MzTreeView!我找到了救星,事不宜迟,时间不多了!
首先还是下载控件,构建动态树形结构,循环结果集的代码:
String tree = "";
tree += "var data={}; ";
while (rs.next()) {
String id = String.valueOf(rs.getString("id"));
String pid = String.valueOf(rs.getString("parentId"));
String text = rs.getString("text");
String hint = rs.getString("hint");
String url = rs.getString("url");
String target = rs.getString("target");
tree += "/n" + "data" + "[/'" + pid + "_" + id
+ "/']= /'";
if (text != null && text.trim() != "") {
tree += "text:" + text + ";";
}
if (hint != null && !hint.trim().equals("")) {
tree += "hint:" + hint + ";";
}
//tree += "checked:false;";
if (url != null && !url.trim().equals("")) {
tree += "url:" + url + ";";
}
if (target != null && !target.trim().equals("")) {
tree += "target:" + target + ";";
}
tree += "/';";
}
我兴奋地输入网址,空白!立刻查看源文件,文本显示类似:
data['1_9001'] = 'text: 我感兴趣的社区;'; //JSData: myselect.aspx
data['1_9002'] = 'text: 我的技术社区 xml; XMLData: mycommunity.xml ';
data['1_9009'] = 'text: 开发语言; url:/Expert/ForumsList.asp?typenum=1&roomid=1 ; JSData: scripts/csdn/community/treedata/language.js ';
data['1_54'] = 'text: Java 技术; url:/Expert/ForumsList.asp?typenum=1&roomid=54 ; JSData: scripts/csdn/community/treedata/java.js ';
有什么问题吗?我又找到了梅花雪的例子,一步一步对比,原来问题出在这里,根节点!这个错误有点幼稚,但不注意还是真困惑,根节点必须以-1作为父结点id,于是修改代码:
String tree = "";
tree += "var data={}; data['-1_0']='text:预算单位';";
刷新页面,可爱的梅花雪数终于出来了!
文章写到这里才开始进入主题,相信用不到的人是看不下去的, ,仅以上述文字,纪念我悲惨的经历, ,好,第一个问题,如何获取选中值?这个网上资料较多:
var nodes = Tree.nodes;
for(var i in nodes) {
if(nodes[i].checked){
text = nodes[i].text ;
}
}
当然,也可通过nodes.parentId nodes.id获取父节点id,节点id,这里注意,梅花雪树节点是没有length属性的,所以不能通过for(var i=0;i<nodes.length;i++)来循环。第二个问题,如何设置默认值?有人给出了一个解决方案,就是在创建节点时添加属性:
data['1_9001'] = 'text: 我感兴趣的社区;checked:true';
经验证,确实是可以的,但是不能满足我们的需求,我的项目需要动态选中checkbox,如选择一个用户,动态显示用户对应的权限,到网上查了很多 资料,很多人都有类似需求,但却没有人给出有效的解决方案,有人说节点的checkbox是图片,要想办法改变图片之类,真是越看越困惑,无意中看到了梅 花雪大虾的qq:梅花雪(112889082);我满怀兴奋,添加了好友,但是。。。。。没有反应!
估计大虾也很忙啊,我给出自己一个解释,可是我的问题怎么办?时间越来越近了
问题的解决很多时候都是一时的灵感,拿着梅花雪的例子点来点去,我突然想到,既然可以通过选中父级来选中子节点,一定可以通过事件来选中了,接下来只有一个办法,阅读源码,找到单击事件!
最为java开发人员,估计大多数都不愿意阅读js的代码的,不是逼到这步田地,我也不会耐下心来的
//private: attachEvent tree onClick
MzTreeView.prototype.clickHandle = function(e)
{
e = window.event || e; var B;
e = e.srcElement || e.target;
if(B=(e.id && 0==e.id.indexOf(this.index +"_")))
{
var n=this.currentNode=this.nodes[e.id.substr(e.id.lastIndexOf("_")+1)];
}
switch(e.tagName)
{
case "IMG" :
if(B)
{
if(e.id.indexOf(this.index +"_expand_")==0){
n.expanded ? n.collapse() : n.expand();}
else if(e.id.indexOf(this.index +"_icon_")==0){
n.focus();}
else if(e.id.indexOf(this.index +"_checkbox_")==0){
n.check(!n.checked); n.upCheck();}
}
break;
case "A":
if(B){ n.focus(); this.dispatchEvent(new System.Event("onclick"));}
break;
default :
if(System.ns) e = e.parentNode;
break;
}
};
看到这里估计你已经很清楚了, n.check(!n.checked); n.upCheck();,就是这里,是通过函数check(true);来实现的,终于可以尽快结束这段噩梦了