1.页面
//页面
<body>
<div class="gcontent" style="height:100%;padding-top :0;" id="jtk-demo-hierarchy">
<!-- table -->
//newtaskinfo 这个标签是我自用的
<input type="hidden" name="newtaskinfo" id="newtaskinfo" value="1">
<div class="miniview" id="miniview">
</div>
<div class="jtk-demo-canvas canvas-wide jtk-surface" id="jsPlumb_2_1">
</div>
</div>
</div>
</body>
//这个是他内置的方法,我看到的第一眼就觉得很神奇哈!!
//先这样,先大概看一眼咱们往下看! ↓
<script type="jtk" id="jtk-template-default">
<div class="name" title="${taskDesc?if_exists}">
<strong>
<div class="node-top">
<div class="top-left">${taskName?if_exists}</div>
<div class="top-right" style="${top_right?if_exists}">
//添加子节点的按钮,实际就是个加号
<span class="add" id="${id?if_exists},${taskLev?if_exists}" onclick="addTask('${id}','${taskLev}','${meetingId}')">+</span>
//删除子节点的按钮,同上减号
<span class="delete" id="${id?if_exists},${meetingId?if_exists}">x</span>
</div>
</div>
<div class="node-top">
<div class="user-left">${Fziduan?if_exists}</div>
<div class="user-right" style="${user_right?if_exists}" onclick="TaskRole('${id}','${taskUserId}','${meetingId}')">${username?if_exists}</div>
</div>
<div class="node-top">${SETime?if_exists}</div>
<div class="node-bow">
<div class="bow-delide" style="${bow_delide?if_exists}" onclick="updTask('${id}','${taskLev}','${meetingId}')">${Xziduan?if_exists}</div>
<div class="bow-left" style="${bow_left?if_exists}" onclick="taskWeekly('${id}','${startTime}','${endTime}','${meetingId}')">${Zziduan?if_exists}</div>
<div class="bow-right">${tasktimeType?if_exists}</div>
</div>
</strong>
</div>
</script>
2.JS
//javascript 代码
(function () {
jsPlumbToolkit.ready(function () {
var toolkit = window.toolkit = jsPlumbToolkit.newInstance({
beforeStartDetach:function() { return false; }
});
var mainElement = document.querySelector("#jtk-demo-hierarchy"),
canvasElement = mainElement.querySelector(".jtk-demo-canvas"),
miniviewElement = mainElement.querySelector(".miniview");
//删除按钮
jsPlumb.on(canvasElement, "tap", ".delete", function (e) {
//var info = toolkit.getObjectInfo(this);
//var selection = toolkit.selectDescendants(info.obj, true);
//toolkit.remove(selection);
var num = this.id;//这个this.id自己打印出来看一下,本垃圾也忘了是啥了 QAQ
var arr=num.split(",");
console.log(arr[1])
//阻止删除根节点
if(arr[0]=='00000000000000000000000000000000'){
layeropen("这里写提示信息!");
//这个方法layeropen,看我的:ajax后台传递数组的文章里面有
//这里提示之后不需要刷新,可以改一下layeropen方法 QAQ
}else{
layer.confirm('删除当前任务将同时删除子任务,请确定是否删除?', {
btn: ['确定','取消'] //按钮
}, function(){
$.ajax({
url : "${base}/meeting/delTask.action",
type : 'POST',
data:{"id":arr[0],"globalId":arr[1]},
success : function(data) {
if (data === "success") {
layeropen("删除成功!");
location.reload();//这里必须刷新
} else{
layer.msg("系统异常,请稍后尝试", {icon: 2});
}
},
error : function() {
layer.msg('系统异常', {icon: 2});
}
});
},function(){
});
}
});
//添加按钮 enmmm这个是他原带的方法,我做的东西不需要他的方法
/*jsPlumb.on(canvasElement, "tap", ".add", function (e) {
var num = this.id;
var arr=num.split(",");
var openindex = layer.open({
title:'任务添加',
type: 2,
zIndex:300,
area: ['550px', '40%'],
shadeClose: true,
shade: 0.8,
maxmin: true,
content: ['${base}/meeting/addTask.action?globalId=${globalId?if_exists}&superid='+arr[0]+'&lev='+arr[1], 'yes'],
end: function(){
layer.close(openindex);
}
});
var info = toolkit.getObjectInfo(this);
var n = jsPlumbToolkitDemoSupport.randomNode();
var newNode = toolkit.addNode(n);
toolkit.addEdge({source: info.obj, target: newNode});
});*/
//乱七八糟的设置开始。。。 最好去看一下他的源文档哈!
var renderer = toolkit.render({
container: canvasElement,
consumeRightClick: false,
layout: {
type: "Hierarchical",
parameters: {
orientation: "vertical",
padding: [160, 60],
//这个好像是根节点的id 嗯嗯!!!
rootNode:"00000000000000000000000000000000",
},
multipleRoots:false,
decorators:["Hierarchy"]
},
//enablePan:false,//禁用平移
enablePanButtons:false,//隐藏泛按钮
enableWheelZoom:false,//是否启用鼠标滚轮缩放功能。
//clampZoom:false,//缩放移动
//clamp:false,//泛运动
elementsDraggable: false,
jsPlumb:{
Anchors: ["Right", "Left"],
//Connector: [ "StateMachine", { curviness: 10 } ],
Connector:[ "Flowchart", { stub:[10, 20], gap:10, cornerRadius:2} ],
PaintStyle: { lineWidth: 1, stroke: '#89bcde' },
HoverPaintStyle: { stroke: "#FF6600", lineWidth: 3 },
Endpoints: [
[ "Dot", { radius: 2 } ],
"Blank"
],
EndpointStyle: { fill: "#89bcde" },
EndpointHoverStyle: { fill: "#FF6600" }
},
refreshLayoutOnEdgeConnect:true
});
//乱七八糟的设置结束
//surface.setMode(Surface.DISABLED);//完全禁用Surface
/* 这里这里 很关键啊!!! 这里是页面的数据
我这里是用ajax自己去弄的数据,好像是业务有一些固定的要求,
还有就是他自带的一种方法,就是下面被我注释掉的 那个。。。
url:"${base}/meeting/taskjson.action?globalId=${globalId?if_exists}"
onload: renderer.zoomToFit
*/
$.ajax({
url: "${base}/meeting/taskjson.action",
async: false,
type: "post",
dataType: 'json',
data: {globalId: '${globalId?if_exists}',jumpType :'${jumpType?if_exists}'},
success: function (data) {
/*ajax的方法需要去自己编写这个js里面的方法,js是叫...demo-support.js对这个!QAQ
再提醒一下啊,最好先去了解一下原文档!!!
jsPlumbToolkitDemoSupport.MyRandomHierarchy(data)*/
var hierarchy = jsPlumbToolkitDemoSupport.MyRandomHierarchy(data);
//console.log(hierarchy);
toolkit.load({
data: hierarchy
//url:"${base}/meeting/taskjson.action?globalId=${globalId?if_exists}"
//onload: renderer.zoomToFit
});
//这里我是动态设置了一下页面,好像是显示的东西不全屏的原因,你也可以自己想办法解决一下
$(".jtk-surface-canvas").css("top","290px");
}, error: function () {
layer.msg('系统异常', {icon: 2});
}
});
var datasetView = new jsPlumbSyntaxHighlighter(toolkit, ".jtk-demo-dataset");
});
})();
3.JS
//我们来看一下 demo-support.js 前方高能!!!
/**
* This is just a collection of utility methods used by the jsPlumb Toolkit demos to get random datasets for
* demo purposes.
*/
//json日期格式转换为正常格式
function formatDate(jsonDate) {
if(jsonDate!=null&&jsonDate!=""&&typeof(jsonDate)!="undefined"){
var year = jsonDate.year+1900;
var month = jsonDate.month+1;
var day = jsonDate.date;
month=(month>9)?(""+month):("0"+month); //如果得到的数字小于9要在前面加'0'
day=(day>9)?(""+day):("0"+day);
return year + "-" + month + "-" + day;
}
return "";
}
(function () {
window.jsPlumbToolkitDemoSupport = {
// return a random hierarchy that contains at least 10 nodes (if possible. if maxDepth * maxBreadth is less
// than 10, though, then we use that value for our desired amount). The hierarchy also contains positioning
// information for use with an absolute layout, but most layouts ignore these values.
randomHierarchy: function (maxDepth, maxBreadth, maxWidth, maxHeight) {
maxDepth = maxDepth || 6;
maxBreadth = maxBreadth || 3;
maxWidth = maxWidth || 600;
maxHeight = maxHeight || 400;
var l = 0, t = 0;
if (maxBreadth < 1) maxBreadth = 1;
var _do = function () {
var h = [ ], c = 0, pad = 80,
_node = function (depth) {
c++;
var id = "w" + c, name = "" + c,
childCount = Math.floor(Math.random() * maxBreadth) + 1,
wh = jsPlumbToolkitDemoSupport.randomSize(80, 60),
n = { id: id, name: name, w: wh[0], h: wh[1], left:l, top:t },
children = [];
l += wh[0] + pad;
if (l > maxWidth) {
l = 0;
t += wh[1] + pad;
}
if (depth < maxDepth) {
for (var i = 0; i < childCount; i++) {
children.push(_node(depth + 1));
}
}
h.unshift([n, children]);
return id;
};
_node(0);
return h;
},
_h = null;
var maxNodesDesired = Math.min(maxDepth * maxBreadth, 10);
while ((_h = _do()).length < maxNodesDesired);
var out = { nodes: [], edges: [] };
for (var i = 0; i < _h.length; i++) {
out.nodes.push(_h[i][0]);
for (var j = 0; j < _h[i][1].length; j++) {
out.edges.push({source: _h[i][0].id, target: _h[i][1][j], data:{id:jsPlumbUtil.uuid().slice(25)}});
}
}
return out;
},
//滴滴滴 看这里!!!
//这个data 就是ajax 返回的json数据,后面我会给出java 代码
MyRandomHierarchy: function (data) {
console.log(data)
_h = null;
var h = [ ];
for (var d = 0; d < data.nodes.length; d++) {
//这里就是一些业务逻辑需要用到的变量
var timeType = null ;var setime = null;
var taskUser = null;var fuzeren = null;
var zhoubao = null;var xiangqing = null;
/*看下面这些名字是不是很熟悉(啥啊!熟悉个pi啊!)
文章开头页面里面,很神奇的-内置方法里边的-元素的-id (滑稽)
发现了吧!我是这样控制style的(一些原因才这么做的,你可以不用这样)。
*/
var bow_left = "background-color:#4378d8;"
var top_right = "background-color:#4278d8;"
var bow_delide = "background-color: #4278d8;"
var user_right = "color: #f0f2f5;background-color: #4278d8;cursor: pointer;"
//这个if里面是一些逻辑判断
if(data.nodes[d].ID!="00000000000000000000000000000000"){
//console.log(formatDate(data.nodes[d].START_TIME))
if(new Date(formatDate(data.nodes[d].START_TIME))<=new Date(data.taskTime[0].taskNow)&&new Date(data.taskTime[0].taskNow)<=new Date(formatDate(data.nodes[d].END_TIME))){
if(data.nodes[d].OVER_TIME!=null&&data.nodes[d].OVER_TIME!=''&&new Date(formatDate(data.nodes[d].START_TIME))<=new Date(formatDate(data.nodes[d].OVER_TIME))&&new Date(formatDate(data.nodes[d].OVER_TIME))<=new Date(formatDate(data.nodes[d].END_TIME))){
timeType = "已完成";
}else{
timeType = "进行中";
}
}else if(new Date(formatDate(data.nodes[d].START_TIME))>new Date(data.taskTime[0].taskNow)){
timeType = "未开始";
}else if(new Date(formatDate(data.nodes[d].END_TIME))<new Date(data.taskTime[0].taskNow)){
if(data.nodes[d].OVER_TIME!=null&&data.nodes[d].OVER_TIME!=''){
timeType = "已完成";
}else{
timeType = "逾期中";
}
}
/*if(data.nodes[d].TASK_STATUS=='1'){
timeType = "已完成";
}
if(data.nodes[d].TASK_STATUS=='2'){
timeType = "逾期中";
}*/
fuzeren = "负责人:";
if(new Date(formatDate(data.nodes[d].START_TIME))>new Date(data.taskTime[0].taskNow)){
zhoubao = "";
}else{
zhoubao = "任务进展";
}
xiangqing = "详情";
setime = formatDate(data.nodes[d].START_TIME) +"~"+ formatDate(data.nodes[d].END_TIME);
if(data.nodes[d].TASK_USER_ID==null||data.nodes[d].TASK_USER_ID==""){
taskUser = "请选择负责人";
}else{
taskUser = data.nodes[d].NAME;
}
}
//逻辑结束看下面
//把data里面的数据取出来赋值,注意名字要和你页面上取的名字一样
//例子:username → ${username?if_exists}
n = { id: data.nodes[d].ID,
username : taskUser,
meetingId : data.nodes[d].MEETING_ID,
superTaskId : data.nodes[d].SUPER_TASK_ID,
taskName: data.nodes[d].TASK_NAME,
taskDesc : data.nodes[d].TASk_DESC,
taskUserId : data.nodes[d].TASK_USER_ID,
createUserId : data.nodes[d].CREATE_USER_ID,
taskStatus : data.nodes[d].TASK_STATUS,
startTime : formatDate(data.nodes[d].START_TIME),
endTime : formatDate(data.nodes[d].END_TIME),
SETime : setime,
overTime : data.nodes[d].OVER_TIME,
ifLate : data.nodes[d].IF_LATE,
ifDel : data.nodes[d].IF_DEL,
taskComment : data.nodes[d].TASK_COMMENT,
createTime : data.nodes[d].CREATE_TIME,
taskLev : data.nodes[d].TASK_LEV,
tasktimeType : timeType,
Fziduan : fuzeren,
Zziduan : zhoubao,
Xziduan : xiangqing,
user_right : user_right,
bow_delide : bow_delide,
top_right:top_right,
bow_left : bow_left
}; h.push([n]);
}
_h = h;
//下面算是固定方法了吧,应该不用做太大的改动
//这些集合或者数组的名字不要改动 例:nodes、edges、source、target、data
var out = { nodes: [], edges: [] };
for (var i = 0; i < _h.length; i++) {
out.nodes.push(_h[i][0]);
}
for (var j = 0; j < data.edges.length; j++) {
out.edges.push({source: data.edges[j].source, target: data.edges[j].target, data:{id:jsPlumbUtil.uuid().slice(25)}});
}
return out;
//把这个返回,他会自动装载到页面上 ,好啦去看java代码!!!
},
// randomizes the two given dimensions by up to +/- 20%
randomSize: function (refWidth, refHeight, factor) {
factor = factor || 0.3;
var rx = Math.floor(factor - (Math.random() * (factor * 2 * refWidth))),
ry = Math.floor(factor - (Math.random() * (factor * 2 * refHeight)));
return [ refWidth + rx, refHeight + ry ];
},
// gets a random position within the given bounds
randomLocation : function(w, h) {
return [
Math.floor(Math.random() * w),
Math.floor(Math.random() * h)
];
},
randomNode: function (name) {
var wh = jsPlumbToolkitDemoSupport.randomSize(80, 60),
xy = jsPlumbToolkitDemoSupport.randomLocation(800, 600),
id = jsPlumbToolkitUtil.uuid(),
name = name || id.substring(0, 3);
return { id: id, name: name, w: wh[0], h: wh[1], left:xy[0], top:xy[1] };
},
randomGraph:function(minimum, maximum) {
var nodeCount = minimum + Math.floor(Math.random() * (maximum - minimum));
var maybe = function() { return (Math.random() >= 0.5); };
var data = { nodes:[], edges:[] }, edgeCache = {}, edgeCount = 0;
for (var i = 0; i < nodeCount; i++) {
var sourceId = "" + (i+1);
data.nodes.push({id:sourceId, name:sourceId});
for (var j = 0; j < nodeCount; j++) {
if (i != j) {
var targetId = "" + (j+1),
key = sourceId +"_"+ targetId,
keyInv = targetId +"_"+ sourceId;
if (edgeCount < (nodeCount * 2) && !edgeCache[key] && !edgeCache[keyInv] && maybe()) {
var directed = maybe();
data.edges.push({
source:sourceId,
target: targetId,
directed:directed,
data:{type:directed? null : "bidirectional" }
});
edgeCache[key] = true;
edgeCache[keyInv] = true;
edgeCount++;
}
}
}
}
return data;
}
};
})();
我觉得js代码和java的分开写比较好,可以有个对照,而且有点写不下了,东西太多编辑器都有点卡了 QAQ
我也会在下一篇把需要的css啊js啊。。。都列出来。
看下一篇吧 关于jsPlumbToolkit的一些代码 (第二篇java篇) (嘻嘻!!!)