1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%
3 String path = request.getContextPath();
4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
5 %>
6
7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
8 <html>
9 <head>
10 <base href="<%=basePath%>">
11
12 <title>js Tree Test</title>
13
14 <meta http-equiv="pragma" content="no-cache">
15 <meta http-equiv="cache-control" content="no-cache">
16 <meta http-equiv="expires" content="0">
17 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
18 <meta http-equiv="description" content="This is my page">
19 <!--
20 <link rel="stylesheet" type="text/css" href="styles.css">
21 -->
22 <!-- CSS for js tree -->
23 <link rel="stylesheet" type="text/css" href="static/jstree/dist/themes/default/style.min.css">
24 <link rel="stylesheet" type="text/css" href="static/jstree/dist/themes/default-dark/style.min.css">
25 <!-- CSS for bootstrap -->
26 <link rel="stylesheet" type="text/css" href="static/bootstrap4.0/css/bootstrap.min.css">
27
28 <!-- JS for jQuery -->
29 <script type="text/javascript" src="static/js/jquery.min.js"></script>
30 <!-- JS for js tree -->
31 <script type="text/javascript" src="static/jstree/dist/jstree.min.js"></script>
32 <!-- JS for bootstrap -->
33 <script type="text/javascript" src="static/bootstrap4.0/js/bootstrap.min.js"></script>
34 </head>
35
36 <body>
37 <div>
38 <ul class="nav nav-tabs" role="tablist">
39 <li role="presentation" class="active"><a href="#">Home</a></li>
40 <li role="presentation"><a href="#">Profile</a></li>
41 <li role="presentation"><a href="#">Messages</a></li>
42 </ul>
43 </div>
44 <div class="panel panel-default">
45 <div class="panel-body">
46 <div class="tree" id="jstree"></div>
47 </div>
48 </div>
49
50
51 <script>
52 $(function(){
53 $('#jstree').jstree({
54 core : {
55 check_callback : true,
56 data : [
57 { "id" : "1", "parent" : "#", "text" : "root"},
58 { "id" : "2", "parent" : "1", "text" : "child 1" },
59 { "id" : "3", "parent" : "1", "text" : "child 2"},
60 { "id" : "4", "parent" : "1", "text" : "child 3" },
61 { "id" : "5", "parent" : "1", "text" : "child 4" },
62 { "id" : "6", "parent" : "1", "text" : "child 5" },
63 { "id" : "7", "parent" : "1", "text" : "child 6"},
64 { "id" : "8", "parent" : "3", "text" : "child 3-1" },
65 { "id" : "9", "parent" : "3", "text" : "child 3-2" },
66 { "id" : "10", "parent" : "3", "text" : "child 3-3"}
67 ],
68 },
69 plugins : ["wholerow","checkbox"]
70 }).on("ready.jstree", function (e, data) {
71 //data.instance.open_all();
72 }).bind("loaded.jstree",function(e,data){
73 var checkId=[9];
74 jQuery('#jstree').jstree("open_all");
75 jQuery('#jstree').find("li").each(function(){
76 if(checkId == 'all'){
77 jQuery('#jstree').jstree("check_node",jQuery(this));
78 }else if(checkId instanceof Array){
79 for(var i=0;i<checkId.length;i++){
80 if(jQuery(this).attr("id") == checkId[i]){
81 jQuery('#jstree').jstree("check_node",jQuery(this));
82 }
83 }
84 }
85 });
86 });
87 });
88 </script>
89 </body>
90 </html>
一丶
1.该checkbox并不是真正的input-type='checkbox',而是图片,可以在jstree的包中看到这个图片,这也是比较通用的方式。
2.该页面放在SSM架构中实现的显示,在配置静态文件的时候遇到了一个问题:无法加载32.png和.gif文件
于是在web.xml文件分发器的前面加入了如下的配置:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
网上有几种关于静态文件的加入方法,这种配置方法看起来有一些麻烦。把常用的后缀配置出来也还行。不想要的直接过滤掉。
二丶构建树的两种方式:
方式1:使用id,parent,text,icon等给出树的列表,parent节点将id设置为#
缺点:id和parent均必须唯一,不能有重复的key出现,如果重复,在使用plugins-checkbox时会出现错误勾选的情况。
方式2:使用text,children{}显示的把树形结构给出来,可以不设置id和parent,自动根据children的关系生成树。
缺点:需要根据数据库中的id和parent关系,在后台自己写嵌套方法或者递归将树形结构生成
结构如下:
为何不和方式1冲突,此处id和parent的命名不要出现
1 package com.ws.poi.user;
2
3 /**
4 * @author Administrator
5 *
6 */
7 public class JsTreeVo {
8 private int keyId;
9 private int pId;
10 private String text;
11 private String icon;
12 private JsTreeVo children;
13 private LiAttr liattr;
14 // private TreeState{opened:true,selected:true,disabled,true} TODO
15 public int getKeyId() {
16 return keyId;
17 }
18 public void setKeyId(int keyId) {
19 this.keyId = keyId;
20 }
21 public int getpId() {
22 return pId;
23 }
24 public void setpId(int pId) {
25 this.pId = pId;
26 }
27 public String getText() {
28 return text;
29 }
30 public void setText(String text) {
31 this.text = text;
32 }
33 public String getIcon() {
34 return icon;
35 }
36 public void setIcon(String icon) {
37 this.icon = icon;
38 }
39 public JsTreeVo getChildren() {
40 return children;
41 }
42 public void setChildren(JsTreeVo children) {
43 this.children = children;
44 }
45 public LiAttr getLiattr() {
46 return liattr;
47 }
48 public void setLiattr(LiAttr liattr) {
49 this.liattr = liattr;
50 }
51
52
53 }
54 class LiAttr{
55 private int pId;
56 // TODO 其他 li的自定义属性 -同理 a_li属性也可以定义一个类来管理
57 }
生成List<JsTreeVo> treeList即可:结构需要自己写方法生成。
PS:checkbox已经占用了click_node.jstree,dbclick_node.jstree,change_node事件
如果需要处理checkbox被勾选和反选,可以使用这两个事件:
select_node.jstree(e,data)和deselect_node.jstree(e,data)来获取被选中和反选的节点
e.树对象,可以拿到这棵树的所有内容
data.树数据,也可以拿到树的内容
可以通过data.instance.get_selected();获取到当前被选中的行的id,然后做进一步的处理,这些只要有一定jquery和js基础的都能做到。
三丶一些技巧
1.使用浏览器的console.log打印树的结构
2.open_all方法有弊端,如果数据量比较大,树形结构比较大的时候不建议使用这个方法。这个方法效率不高。
可以使用get_selected和get_node(node)方法拿到这个节点写一个递归方法来展开需要展开的节点:open_node(node);
3.关闭树可以直接使用close_all
4.使用checkbox-plugins时,一方面是事件的冲突性,另外一方面是数据回显时比较搞笑:如果last_child_node没有被展开是无法通过get_checked()方法来获取这个选中节点的
此时就需要借助1.2.的建议写方法来展开指定节点再抓取选中的值,不要直接使用open_all方法。
5.其他的一些常用操作,多学习js和jquery类似的插件都可以很好的解决。
6.树形结构是有层次的,4.中无法直接通过get_checked方法获取勾选的节点的根本原因就如此。使用open_node的时候也是需要递归展开节点,从root到末尾children。
7.通过get_bottom_checked()方法获取未展开却被勾选了的子末尾节点。
8.是否可以通过,get_parent和get_children回显数据呢?
没有get_children方法,可以使用:
$("#jstree2").jstree(true).get_node("j2_3"),该方法可以获取到未展开的节点。
$("#jstree2").jstree(true).get_node("j2_2").children_d,该方法能拿到该节点下的所有子节点,不区分层级。
由于树形结构未展开,所以是无法从children_d中直接获取到html的dom对象。
但是,可以拿到每一层的文本内容,可以先将这部分文本内容保存起来,找到需要勾选的节点,在open操作的时候把这些id选中。
下面成功绕过了手动调用open_node、open_all方法:
1 $('#jstree2').jstree({
2 core : {
3 check_callback : true,
4 data : [
5 { "text" : "root"},
6 { "text" : "A","children":[{ "text" : "A-1","children":[{ "text" : "A-1-1" },{ "text" : "A-1-2"}]},{ "text" : "A-2","children":[{ "text" : "A-2-1" },{ "text" : "A-2-2"}]}] },
7 { "text" : "child 2"},
8 { "text" : "child 3","children":[{ "text" : "child 5" },{ "text" : "child 6"}]},
9 { "text" : "child 4","children":[{ "text" : "child 5" },{ "text" : "child 6"}]},
10 { "text" : "child 5" },
11 { "text" : "child 6"},
12 { "text" : "child 3-1" },
13 { "text" : "child 3-2" },
14 { "text" : "child 3-3"}
15 ],
16 },
17 plugins : ["wholerow","checkbox"]
18 }).on("ready.jstree", function (e, data) {
19 //data.instance.open_all();
20 }).bind("loaded.jstree",function(e,data){
21
22 /** 以下操作成功避开了手动调用open_node方法*/
23
24 // 测试数据 - 需要回显的数据结构
25 var check = ['A/A-1/A-1-2','A/A-2/A-2-1'];
26
27 // 所有节点id列表
28 var nodes = data.instance._model.data;
29 //console.log(nodes);
30
31 var $tree = $("#jstree2").jstree(true);
32 var p_length = 0;
33 var rv = "";
34 var val = "";
35 var node_id = "";
36
37 for(var i in check){
38
39 val = check[i];
40
41 $.each(nodes,function(index,element){
42
43 node_id = index;
44 p_length = $tree.get_node(node_id).parents.length;
45
46 // 过滤掉不足3层的节点
47 if(p_length==3){
48
49 var p_2 = $tree.get_parent(node_id);
50 var p_1 = $tree.get_parent(p_2);
51
52 // 1.2.3层文本
53 rv = $tree.get_node(p_1).text
54 + "/" + $tree.get_node(p_2).text
55 + "/" + $tree.get_node(node_id).text;
56
57 // 过滤掉不满足条件的文本
58 if(rv==val){
59 //console.log(rv);
60 // TODO 以下操作能选上,但是却无法将父节点半选
61 //$tree.get_node(node_id).state.selected=true;
62
63 // 调用check_node方法勾选满足条件的文本
64 $("#jstree2").jstree("check_node",node_id);
65 }
66 }
67 });
68 }
69
70 });
下面是两种实现的效果图:
四丶关于异步
后续补充
五丶关于添加菜单操作
后续补充
本文代码量太少,工作性质约束,没办法把代码搬迁过来,如有疑问,欢迎评论交流。