|
@ -1,31 +1,45 @@
|
|
|
//公共方法
|
|
|
var GooFunc = {
|
|
|
getElCoordinate: function (dom) {
|
|
|
var t = dom.offsetTop;
|
|
|
var l = dom.offsetLeft;
|
|
|
dom = dom.offsetParent;
|
|
|
while (dom) {
|
|
|
t += dom.offsetTop;
|
|
|
l += dom.offsetLeft;
|
|
|
dom = dom.offsetParent;
|
|
|
}
|
|
|
;
|
|
|
return {top: t, left: l};
|
|
|
},
|
|
|
mousePosition: function (ev) {
|
|
|
var dom = document.getElementById('divIndexContent');
|
|
|
var domX = dom.scrollLeft;
|
|
|
var domY = dom.scrollTop;
|
|
|
//兼容各种浏览器的,获取鼠标真实位置
|
|
|
if (!ev) ev = window.event;
|
|
|
if (ev.pageX || ev.pageY) {
|
|
|
return {x: ev.pageX + domX, y: ev.pageY + domY};
|
|
|
}
|
|
|
return {
|
|
|
x: ev.clientX + document.documentElement.scrollLeft - document.body.clientLeft,
|
|
|
y: ev.clientY + document.documentElement.scrollTop - document.body.clientTop
|
|
|
};
|
|
|
}
|
|
|
getElCoordinate: function (dom) {
|
|
|
var t = dom.offsetTop;
|
|
|
var l = dom.offsetLeft;
|
|
|
dom = dom.offsetParent;
|
|
|
while (dom) {
|
|
|
t += dom.offsetTop;
|
|
|
l += dom.offsetLeft;
|
|
|
dom = dom.offsetParent;
|
|
|
};
|
|
|
return {top: t, left: l};
|
|
|
},
|
|
|
mousePosition: function (ev) {
|
|
|
var dom = document.getElementById('divIndexContent');
|
|
|
var domX = dom.scrollLeft;
|
|
|
var domY = dom.scrollTop;
|
|
|
//兼容各种浏览器的,获取鼠标真实位置
|
|
|
if (!ev) ev = window.event;
|
|
|
if (ev.pageX || ev.pageY) {
|
|
|
return {x: ev.pageX + domX, y: ev.pageY + domY};
|
|
|
}
|
|
|
return {
|
|
|
x: ev.clientX + document.documentElement.scrollLeft - document.body.clientLeft,
|
|
|
y: ev.clientY + document.documentElement.scrollTop - document.body.clientTop
|
|
|
};
|
|
|
},
|
|
|
getAjaxData: function (url, successFn, completeFn) {
|
|
|
$.ajax({
|
|
|
url: url,
|
|
|
type: 'GET',
|
|
|
async: true,
|
|
|
dataType: 'json',
|
|
|
success: successFn,
|
|
|
error: function (data, xhr, textStatus) {
|
|
|
console.log('错误')
|
|
|
console.log(xhr)
|
|
|
console.log(textStatus)
|
|
|
},
|
|
|
complete: completeFn
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
@ -34,57 +48,74 @@ var GooFunc = {
|
|
|
* Date: 2017/2/15
|
|
|
* time: 14:59
|
|
|
* */
|
|
|
function GooFlow(bgDiv, property) {
|
|
|
function GooFlow(bgDiv, property,url) {
|
|
|
/*
|
|
|
* Todo: 初始化属性设置 【初始化】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:17
|
|
|
* */
|
|
|
|
|
|
// *************************************************** 【UI相关】
|
|
|
// *************************************************** 【UI相关】
|
|
|
this.$id = property.id || bgDiv.attr("id"); // 容器id
|
|
|
this.$bgDiv = bgDiv; // 容器对象
|
|
|
this.$headBox = null; // 头部容器对象
|
|
|
this.$bgDiv = bgDiv; // 容器对象
|
|
|
this.$headBox = null; // 头部容器对象
|
|
|
this.$toolBar = null; // 工具栏操作
|
|
|
this.$flowChart = null; // 流程图工具
|
|
|
this.$contBox = null; // 主内容区
|
|
|
this.$flowChart = null; // 流程图工具
|
|
|
this.$contBox = null; // 主内容容器
|
|
|
this.$contBoxLeft = null; // 端点内容
|
|
|
this.$contBoxRight = null; // 转换器内容
|
|
|
this.$workAreaWrap = null; // 流程图区域容器
|
|
|
this.$workArea = null; // 流程图区域
|
|
|
this.$draw = null; // SVG绘制区
|
|
|
this.$fileCode = ''; // 流程图文件唯一标识
|
|
|
this.$fileName = ''; // 流程图文件名称
|
|
|
|
|
|
// *************************************************** 【线条相关】
|
|
|
this.$lineData = {}; // 数据
|
|
|
this.$lineData = {}; // 数据
|
|
|
this.$lineType = ''; // 类型
|
|
|
this.$lineCount = 0; // 数量
|
|
|
this.$lineDom = {}; // DOM
|
|
|
this.$lineMoveing = false; // 是否在移动
|
|
|
this.$deteLineId = ''; // 删除指定ID
|
|
|
this.$lineMove = null; // 线条移动镜像
|
|
|
this.$canDelLine = false; // 是否使用Delete删除线条
|
|
|
|
|
|
// *************************************************** 【结点相关】
|
|
|
this.$nodeData = {}; // 数据
|
|
|
this.$nodeCount = 0; // 数量
|
|
|
this.$nodeData = {}; // 数据
|
|
|
this.$nodeCount = 0; // 数量
|
|
|
this.$nodeDom = {}; // DOM
|
|
|
this.$newNodeValue = ''; // 值
|
|
|
this.$nodeConfig = ''; // 配置项
|
|
|
this.$nodeType = ''; // 结点类型
|
|
|
this.$deteNodeId = ''; // 删除指定ID
|
|
|
this.$ghost = null; // 结点镜像
|
|
|
|
|
|
// *************************************************** 【当前选中】
|
|
|
this.$nowType = "cursor"; // 当前操作类型
|
|
|
this.$focus = ""; // SVG操作区中选中对象
|
|
|
this.$nowType = "cursor"; // 当前操作类型
|
|
|
this.$focus = ""; // SVG操作区中选中对象
|
|
|
|
|
|
// *************************************************** 【其他】
|
|
|
this.$MainContener = property.MainContener; // 重要内容
|
|
|
this.$editable = property.editable; // 是否可编辑
|
|
|
this.$max = property.initNum; // 操作顺序
|
|
|
this.$editable = property.editable; // 是否可编辑
|
|
|
|
|
|
// *************************************************** 【公用变量】
|
|
|
var that = this;
|
|
|
|
|
|
// *************************************************** 【请求地址】
|
|
|
var getAllEndpointsURL = url + "/process/getAllEndpoints",
|
|
|
getAllProcessorsURL = url + "/process/getAllProcessors",
|
|
|
dataPostURL = URL + "/process/json";
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 初始化布局 【初始化】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:17
|
|
|
* */
|
|
|
this.$headBox = $("<div class='GooFlow_top_box'></div>");
|
|
|
this.$contBox = $("<div class='GooFlow_cont_box'></div>");
|
|
|
this.$headBox = $("<div class='GooFlow_top_box'></div>"); // 头部
|
|
|
this.$contBox = $("<div class='GooFlow_cont_box'></div>"); // 中间主体内容
|
|
|
this.$bgDiv.append(this.$headBox).append(this.$contBox);
|
|
|
|
|
|
/*
|
|
@ -93,276 +124,712 @@ function GooFlow(bgDiv, property) {
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:17
|
|
|
* */
|
|
|
if (property.haveTool) {
|
|
|
var
|
|
|
HtmlStr = "",
|
|
|
i = 0,
|
|
|
length = property.toolBtns.length;
|
|
|
|
|
|
// 工具栏UI构建
|
|
|
HtmlStr = "<div class='GooFlow_tool'>";
|
|
|
for (; i < length; ++i) {
|
|
|
HtmlStr += "<i class='ico_" + property.toolBtns[i] + "'></i>";
|
|
|
}
|
|
|
HtmlStr += "</div>";
|
|
|
this.$toolBar = $(HtmlStr);
|
|
|
this.$headBox.append(this.$toolBar);
|
|
|
|
|
|
// 工具栏功能绑定
|
|
|
this.$toolBar.children().on("click",function () {
|
|
|
var icoName = $(this).attr("class").match(/ico_\w+/g)[0];
|
|
|
switch (icoName) {
|
|
|
case "ico_save":
|
|
|
that.exportData();
|
|
|
break;
|
|
|
case "ico_undo":
|
|
|
that.undo();
|
|
|
break;
|
|
|
case "ico_redo":
|
|
|
that.redo();
|
|
|
break;
|
|
|
}
|
|
|
if (property.haveTool) {
|
|
|
var HtmlStr = "",
|
|
|
i = 0,
|
|
|
length = property.toolBtns.length;
|
|
|
|
|
|
// 工具栏UI构建
|
|
|
HtmlStr = "<div class='GooFlow_tool'>";
|
|
|
for (; i < length; ++i) {
|
|
|
HtmlStr += "<i class='ico_" + property.toolBtns[i] + "'></i>";
|
|
|
}
|
|
|
HtmlStr += "</div>";
|
|
|
this.$toolBar = $(HtmlStr);
|
|
|
this.$headBox.append(this.$toolBar);
|
|
|
|
|
|
// 工具栏功能绑定
|
|
|
this.$toolBar.children().on("click", function () {
|
|
|
var icoName = $(this).attr("class").match(/ico_\w+/g)[0];
|
|
|
switch (icoName) {
|
|
|
case "ico_save":
|
|
|
that.exportData();
|
|
|
break;
|
|
|
case "ico_undo":
|
|
|
that.undo();
|
|
|
break;
|
|
|
case "ico_redo":
|
|
|
that.redo();
|
|
|
break;
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 流程图结点构建 【UI相关--HEAD】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:17
|
|
|
* */
|
|
|
if (property.flowChart) {
|
|
|
var HtmlStr = "",
|
|
|
i = 0,
|
|
|
length = property.flowBtns.length;
|
|
|
// 流程图结点UI构建
|
|
|
HtmlStr += "<div class='GooFlow_flowChart'>"
|
|
|
// 加入用户自定义工具栏
|
|
|
for (; i < length; ++i) {
|
|
|
HtmlStr += "<i id='" + this.$id + "_btn_" + property.flowBtns[i] + "' class='ico_" + property.flowBtns[i] + "'/></i>";
|
|
|
}
|
|
|
HtmlStr += "</div>"
|
|
|
this.$flowChart = $(HtmlStr);
|
|
|
this.$headBox.append(this.$flowChart);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换器公共筛选方法
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
function itemSearchFn(obj) {
|
|
|
var $list = obj.find($('.GooFlow_app_list_item'));
|
|
|
var $input = obj.find($('.GooFlow_app_search_input'));
|
|
|
var $item = obj.find($('.GooFlow_app_item'));
|
|
|
$input.on('keyup', {inthis: that}, function () {
|
|
|
var input = $input.val()
|
|
|
if (input.length > 0) {
|
|
|
$item.hide();
|
|
|
var filterObj = $item.filter(function (index) {
|
|
|
return $(this).text().indexOf(input) >= 0;
|
|
|
})
|
|
|
if (filterObj.length > 0) {
|
|
|
filterObj.css("display", "block").parent().parent().parent().addClass('selected');
|
|
|
} else {
|
|
|
$item.show();
|
|
|
$list.removeClass('selected');
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
$item.show();
|
|
|
$list.removeClass('selected');
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换器公共HTML结构搭建 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
function renderHtml(title, className, htmlStr) {
|
|
|
var appBox = $("<div class='GooFlow_app'></div>");
|
|
|
var appHead = $("<div class='GooFlow_app_head'><h1 class='GooFlow_app_tit'></h1><div class='GooFlow_app_search'><input class='GooFlow_app_search_input' type='text' placeholder='快速搜索'><div class='GooFlow_search_btn'></div></div></div>");
|
|
|
var appCont = $("<div class='GooFlow_app_cont'><ul class='GooFlow_app_list'></ul></div>");
|
|
|
|
|
|
appHead.children('.GooFlow_app_tit').text(title);
|
|
|
appCont.children('.GooFlow_app_list').append(htmlStr);
|
|
|
appBox.prepend(appHead).append(appCont).addClass(className);
|
|
|
return appBox;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点数据渲染及事件添加 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
function getAllEndpointsFn(data) {
|
|
|
var list = $.parseJSON(data.message),
|
|
|
htmlStr = '';
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
htmlStr += "<li class='GooFlow_app_list_item'>";
|
|
|
htmlStr += "<div class='GooFlow_app_list_tit'>" + list[i].title + "</div>";
|
|
|
htmlStr += "<div class='GooFlow_app_list_box'><ul>";
|
|
|
for (var j = 0; j < list[i].list.length; j++) {
|
|
|
htmlStr += "<li class='GooFlow_app_item' data-type='" + list[i].list[j].nodeType +
|
|
|
"' data-value ='" + list[i].list[j].value + "' data-config='" + list[i].list[j].config +
|
|
|
"'><div class='app_icon'></div> <div class='app_name'>" + list[i].list[j].name + "</div></li>"
|
|
|
}
|
|
|
htmlStr += "</ul></li>";
|
|
|
}
|
|
|
if (htmlStr) {
|
|
|
that.$contBoxLeft = renderHtml('端点', 'GooFlow_left', htmlStr);
|
|
|
that.$contBox.prepend(that.$contBoxLeft)
|
|
|
|
|
|
// tab标签页
|
|
|
$('.GooFlow_app_list_tit', that.$contBoxLeft).on("click", function () {
|
|
|
$('.GooFlow_app_item', that.$contBoxLeft).show();
|
|
|
$(this).parent().toggleClass('selected').siblings().removeClass('selected');
|
|
|
});
|
|
|
// 拖拽
|
|
|
addNodeByDrag($('.GooFlow_app_item', that.$contBoxLeft), 'task');
|
|
|
// 筛选
|
|
|
itemSearchFn(that.$contBoxLeft);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 转换器数据渲染及事件添加 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
function getAllProcessorsFn(data) {
|
|
|
|
|
|
var list = $.parseJSON(data.message),
|
|
|
htmlStr = '';
|
|
|
htmlStr += "<li class='GooFlow_app_list_item'><div class='GooFlow_app_list_box'><ul>";
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
htmlStr += "<li class='GooFlow_app_item' data-type='" + list[i].nodeType +
|
|
|
"' data-value='" + list[i].value + "' data-config='" + list[i].config +
|
|
|
"'><div class='app_icon'></div> <div class='app_name'>" + list[i].name + "</div></li>"
|
|
|
}
|
|
|
htmlStr += "</ul></li>";
|
|
|
if (htmlStr) {
|
|
|
that.$contBoxRight = renderHtml('转换器', 'GooFlow_right', htmlStr);
|
|
|
that.$contBox.prepend(that.$contBoxRight)
|
|
|
|
|
|
// 拖拽
|
|
|
addNodeByDrag($('.GooFlow_app_item', that.$contBoxRight), 'plug');
|
|
|
// 筛选
|
|
|
itemSearchFn(that.$contBoxRight);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换数据加载 【ajax相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
GooFunc.getAjaxData(getAllEndpointsURL, getAllEndpointsFn);
|
|
|
GooFunc.getAjaxData(getAllProcessorsURL, getAllProcessorsFn);
|
|
|
|
|
|
/*
|
|
|
* Todo: 画布区域HTML结构搭建 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
this.initDraw("draw_" + this.$id);
|
|
|
|
|
|
// 结点镜像 & 文本框
|
|
|
this.$ghost = $("<div class='rs_ghost GooFlow_item'></div>").attr({
|
|
|
"unselectable": "on",
|
|
|
"onselectstart": 'return false',
|
|
|
"onselect": 'document.selection.empty()'
|
|
|
});
|
|
|
this.$textArea = $("<textarea class='text_input'></textarea>");
|
|
|
this.$bgDiv.append(this.$ghost).append(this.$textArea);
|
|
|
// 操作折线时的移动框 & 线条增删改操作框
|
|
|
this.$lineMove = $("<div class='GooFlow_line_move' style='display:none'></div>");
|
|
|
this.$lineOper = $("<div class='GooFlow_line_oper' style='display:none'><b class='b_l1'></b><b class='b_l2'></b><b class='b_l3'></b><b class='b_x'></b></div>");
|
|
|
this.$workArea.append(this.$lineMove).append(this.$lineOper);
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点拖拽 【增加结点触发方法】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:03
|
|
|
* */
|
|
|
var onDrag = false;
|
|
|
function addNodeByDrag(obj, type) {
|
|
|
obj.mousedown(function () {
|
|
|
that.$nowType = type;
|
|
|
if (!type) {
|
|
|
var thisType = $(this).attr("id").split("btn_")[1];
|
|
|
that.$nowType = thisType;
|
|
|
}
|
|
|
onDrag = true;
|
|
|
that.$newNodeTxt = $(this).children('.app_name').text();
|
|
|
that.$newNodeValue = $(this).attr('data-value');
|
|
|
that.$nodeType = $(this).attr('data-type');
|
|
|
that.$nodeConfig = $(this).attr('data-config');
|
|
|
});
|
|
|
$(document).mouseup(function () {
|
|
|
onDrag = false;
|
|
|
});
|
|
|
that.$workArea.mousemove(function () {
|
|
|
if (onDrag) {
|
|
|
var X, Y;
|
|
|
var ev = GooFunc.mousePosition();
|
|
|
X = ev.x - 433 + this.parentNode.scrollLeft;
|
|
|
Y = ev.y - 262 + this.parentNode.scrollTop;
|
|
|
that.$workArea.children('#node-ghost').attr({class: 'node-' + that.$nowType});
|
|
|
that.$workArea.css({cursor: 'move'}).children('#node-ghost').css({
|
|
|
display: "block",
|
|
|
top: Y + "px",
|
|
|
left: X + "px",
|
|
|
cursor: "move",
|
|
|
});
|
|
|
}
|
|
|
})
|
|
|
that.$workArea.mouseup(function () {
|
|
|
if (onDrag) {
|
|
|
addNodeOnArea();
|
|
|
onDrag = false;
|
|
|
that.$workArea.css({cursor: 'pointer'}).children('#node-ghost').remove();
|
|
|
}
|
|
|
});
|
|
|
that.$workArea.mouseenter(function () {
|
|
|
that.$workArea.append("<div id='node-ghost'></div>");
|
|
|
})
|
|
|
that.$workArea.mouseleave(function () {
|
|
|
that.$workArea.css({cursor: 'pointer'}).children('#node-ghost').remove();
|
|
|
})
|
|
|
|
|
|
function addNodeOnArea() {
|
|
|
var X, Y;
|
|
|
var ev = GooFunc.mousePosition();
|
|
|
X = ev.x - 433 + that.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - 262 + that.$workArea[0].parentNode.scrollTop;
|
|
|
that.addNode(that.$id + "_node_" + that.$nodeCount, {
|
|
|
name: "node_" + that.$nodeCount,
|
|
|
type: that.$nowType,
|
|
|
left: X,
|
|
|
top: Y
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
addNodeByDrag(this.$flowChart.children());
|
|
|
|
|
|
/*
|
|
|
* Todo: ### 画布区域功能设置 ******************************************* //
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:15
|
|
|
* */
|
|
|
if (this.$editable) {
|
|
|
// 事件添加
|
|
|
this.initEvents();
|
|
|
|
|
|
/*
|
|
|
* Todo: 取消&重做函数 【堆栈相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:12
|
|
|
* */
|
|
|
if (property.useOperStack) {
|
|
|
this.$undoStack = [];
|
|
|
this.$redoStack = [];
|
|
|
this.$isUndo = 0;
|
|
|
|
|
|
///////////////以下是构造撤销操作/重做操作的方法
|
|
|
//为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放40步操作;超过40步时,将自动删掉最旧的一个缓存
|
|
|
this.pushOper = function (funcName, paras) {
|
|
|
var len = this.$undoStack.length;
|
|
|
if (this.$isUndo == 1) {
|
|
|
this.$redoStack.push([funcName, paras]);
|
|
|
this.$isUndo = false;
|
|
|
if (this.$redoStack.length > 40) this.$redoStack.shift();
|
|
|
} else {
|
|
|
this.$undoStack.push([funcName, paras]);
|
|
|
if (this.$undoStack.length > 40) this.$undoStack.shift();
|
|
|
if (this.$isUndo == 0) {
|
|
|
this.$redoStack.splice(0, this.$redoStack.length);
|
|
|
}
|
|
|
this.$isUndo = 0;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
this.pushExternalOper = function (func, jsonPara) {
|
|
|
this.pushOper("externalFunc", [func, jsonPara]);
|
|
|
};
|
|
|
|
|
|
//撤销上一步操作
|
|
|
this.undo = function () {
|
|
|
if (this.$undoStack.length == 0) return;
|
|
|
var tmp = this.$undoStack.pop();
|
|
|
this.$isUndo = 1;
|
|
|
if (tmp[0] == "externalFunc") {
|
|
|
tmp[1][0](tmp[1][1]);
|
|
|
}
|
|
|
else {
|
|
|
//传参的数量,最多支持5个.
|
|
|
switch (tmp[1].length) {
|
|
|
case 0:
|
|
|
this[tmp[0]]();
|
|
|
break;
|
|
|
case 1:
|
|
|
this[tmp[0]](tmp[1][0]);
|
|
|
break;
|
|
|
case 2:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1]);
|
|
|
break;
|
|
|
case 3:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]);
|
|
|
break;
|
|
|
case 4:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]);
|
|
|
break;
|
|
|
case 5:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//重做最近一次被撤销的操作
|
|
|
this.redo = function () {
|
|
|
if (this.$redoStack.length == 0) return;
|
|
|
var tmp = this.$redoStack.pop();
|
|
|
this.$isUndo = 2;
|
|
|
if (tmp[0] == "externalFunc") {
|
|
|
tmp[1][0](tmp[1][1]);
|
|
|
}
|
|
|
else {
|
|
|
//传参的数量,最多支持5个.
|
|
|
switch (tmp[1].length) {
|
|
|
case 0:
|
|
|
this[tmp[0]]();
|
|
|
break;
|
|
|
case 1:
|
|
|
this[tmp[0]](tmp[1][0]);
|
|
|
break;
|
|
|
case 2:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1]);
|
|
|
break;
|
|
|
case 3:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]);
|
|
|
break;
|
|
|
case 4:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]);
|
|
|
break;
|
|
|
case 5:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: ## 原型方法 ***************************************************************************************
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 14:59
|
|
|
* */
|
|
|
GooFlow.prototype = {
|
|
|
useSVG: true,
|
|
|
/*
|
|
|
* Todo: 初始化画布 【SVG & 箭头 UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:51
|
|
|
* */
|
|
|
initDraw: function (id) {
|
|
|
this.$workAreaWrap = $("<div class='GooFlow_work'></div>");
|
|
|
this.$workArea = $("<div class='GooFlow_work_inner'></div>").attr({
|
|
|
"unselectable": "on",
|
|
|
"onselectstart": 'return false',
|
|
|
"onselect": 'document.selection.empty()'
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 流程图结点构建 【UI相关--HEAD】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:17
|
|
|
* */
|
|
|
if (property.flowChart) {
|
|
|
var
|
|
|
HtmlStr = "",
|
|
|
i = 0,
|
|
|
length = property.flowBtns.length;
|
|
|
// 流程图结点UI构建
|
|
|
HtmlStr += "<div class='GooFlow_flowChart'>"
|
|
|
// 加入用户自定义工具栏
|
|
|
for (; i < length; ++i) {
|
|
|
HtmlStr += "<i id='" + this.$id + "_btn_" + property.flowBtns[i] + "' class='ico_" + property.flowBtns[i] + "'/></i>";
|
|
|
this.$workAreaWrap.append(this.$workArea);
|
|
|
this.$contBox.append(this.$workAreaWrap);
|
|
|
|
|
|
this.$draw = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
|
this.$workArea.prepend(this.$draw);
|
|
|
this.$workArea.prepend("<div class='file-box'>编码:<input id='fileCode' value='" + this.$fileCode +
|
|
|
"'>流程名称:<input id='fileName' value='" + this.$fileName +
|
|
|
"'></div>")
|
|
|
// 设置画布属性
|
|
|
this.$draw.id = id;
|
|
|
this.$draw.style.width = '100%';
|
|
|
this.$draw.style.height = '100%';
|
|
|
|
|
|
// 定义可以重复利用的元素
|
|
|
var defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
|
this.$draw.appendChild(defs);
|
|
|
defs.appendChild(getSvgMarker("arrow1", "#323232"));
|
|
|
defs.appendChild(getSvgMarker("arrow2", "#00b7ee"));
|
|
|
defs.appendChild(getSvgMarker("arrow3", "#f00"));
|
|
|
|
|
|
function getSvgMarker(id, color) {
|
|
|
var m = document.createElementNS("http://www.w3.org/2000/svg", "marker");
|
|
|
m.setAttribute("id", id);
|
|
|
m.setAttribute("viewBox", "0 0 6 6");
|
|
|
m.setAttribute("refX", 5);
|
|
|
m.setAttribute("refY", 3);
|
|
|
m.setAttribute("markerUnits", "strokeWidth");
|
|
|
m.setAttribute("markerWidth", 8);
|
|
|
m.setAttribute("markerHeight", 8);
|
|
|
m.setAttribute("orient", "auto");
|
|
|
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
|
path.setAttribute("d", "M 0 0 L 6 3 L 0 6 L 2 3 z");
|
|
|
path.setAttribute("fill", color);
|
|
|
path.setAttribute("stroke-width", 2);
|
|
|
m.appendChild(path);
|
|
|
return m;
|
|
|
}
|
|
|
HtmlStr += "</div>"
|
|
|
this.$flowChart = $(HtmlStr);
|
|
|
this.$headBox.append(this.$flowChart);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 初始化工作区 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:18
|
|
|
* */
|
|
|
var width = ( property.width == 'auto' ) ? (this.$bgDiv.parent().width()) : property.width;
|
|
|
var height = property.height;
|
|
|
var workWidth = workWidth ? property.workWidth : width;
|
|
|
var workHeight = workHeight ? property.workHeight : height;
|
|
|
|
|
|
// 创建工作区JQ对象
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换数据加载 【ajax相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
|
|
|
function getAppData(url, className, title) {
|
|
|
$.ajax({
|
|
|
url: url,
|
|
|
type: 'GET',
|
|
|
async: true,
|
|
|
dataType: 'json',
|
|
|
success: function (data) {
|
|
|
var contData = $.parseJSON(data.message);
|
|
|
appHtml(contData, className, title);
|
|
|
},
|
|
|
error: function (data, xhr, textStatus) {
|
|
|
console.log('错误')
|
|
|
console.log(xhr)
|
|
|
console.log(textStatus)
|
|
|
},
|
|
|
complete: function () {
|
|
|
// 数据加载完成后添加端点或转换器点击函数
|
|
|
completeFn();
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: ### 初始化事件绑定********************************--开始
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:09
|
|
|
* */
|
|
|
initEvents: function () {
|
|
|
// 防止回调函数里this偏移
|
|
|
var that = this;
|
|
|
var timeId = null;
|
|
|
|
|
|
/*
|
|
|
* Todo: 空白区域点击事件 【单击事件】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:05
|
|
|
* */
|
|
|
$(this.$draw).on("click", function (e) {
|
|
|
that.$canDelLine = false;
|
|
|
var n = $(e.target).prop("tagName");
|
|
|
if (n == "svg") {
|
|
|
that.blurItem();
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
});
|
|
|
|
|
|
getAppData('http://192.168.131.110:8080/esb/process/getAllEndpoints', 'GooFlow_left', '端点');
|
|
|
getAppData('http://192.168.131.110:8080/esb/process/getAllProcessors', 'GooFlow_right', '转换器');
|
|
|
/*
|
|
|
* Todo: 结点事件绑定 【@@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:22
|
|
|
* */
|
|
|
this.$workArea.on({
|
|
|
// 选中
|
|
|
click: function () {
|
|
|
clearTimeout(timeId);
|
|
|
var Dom = $(this);
|
|
|
var id = Dom.attr("id");
|
|
|
that.focusItem(id, true);
|
|
|
},
|
|
|
// 编辑
|
|
|
dblclick: function () {
|
|
|
var id = $(this).attr('id'),
|
|
|
objPosition = $(this).position(),
|
|
|
objLeft = objPosition.left,
|
|
|
objTop = objPosition.top,
|
|
|
oldTxt = that.$nodeData[id].config;
|
|
|
console.log(that.$nodeData[id]);
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换器事件添加 【端点&转换器--事件】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
// 编辑的时候禁止delete键删除
|
|
|
that.$canDelLine = false;
|
|
|
that.$deteNodeId = '';
|
|
|
that.$deteLineId = '';
|
|
|
|
|
|
function completeFn() {
|
|
|
clearTimeout(timeId);
|
|
|
that.$textArea.val(oldTxt).css({
|
|
|
display: "block",
|
|
|
left: objLeft + 170,
|
|
|
top: objTop + 50
|
|
|
}).data("id", that.$focus).focus();
|
|
|
|
|
|
addNodeByDrag($('.GooFlow_left .GooFlow_app_item'), 'task');
|
|
|
addNodeByDrag($('.GooFlow_right .GooFlow_app_item'), 'plug');
|
|
|
that.$workArea.parent().one("mousedown", function () {
|
|
|
that.setName(that.$textArea.data("id"), that.$textArea.val(), "node");
|
|
|
that.$textArea.val("").removeData("id").hide();
|
|
|
});
|
|
|
|
|
|
$('.GooFlow_left .GooFlow_app_list_tit').on("click", {inthis: that}, function () {
|
|
|
$('.GooFlow_left .GooFlow_app_item').show();
|
|
|
$(this).parent().toggleClass('selected').siblings().removeClass('selected');
|
|
|
});
|
|
|
},
|
|
|
// 移动
|
|
|
mousedown: function (e) {
|
|
|
if (!e) e = window.event;
|
|
|
var Dom = $(this);
|
|
|
var id = Dom.attr("id");
|
|
|
clearTimeout(timeId);
|
|
|
timeId = setTimeout(function () {
|
|
|
that.focusItem(id, true);
|
|
|
var ev = GooFunc.mousePosition(e),
|
|
|
t = GooFunc.getElCoordinate(that.$workArea[0]),
|
|
|
c = GooFunc.getElCoordinate(that.$MainContener);
|
|
|
|
|
|
that.$ghost.css({
|
|
|
display: "block",
|
|
|
top: that.$nodeData[id].top + 133 - that.$workArea[0].parentNode.scrollTop + "px",
|
|
|
left: that.$nodeData[id].left + 200 - that.$workArea[0].parentNode.scrollLeft + "px",
|
|
|
cursor: "move"
|
|
|
});
|
|
|
|
|
|
function itemSearchFn(obj) {
|
|
|
var $list = obj.find($('.GooFlow_app_list_item'));
|
|
|
var $input = obj.find($('.GooFlow_app_search_input'));
|
|
|
var $item = obj.find($('.GooFlow_app_item'));
|
|
|
$input.on('keyup', {inthis: that}, function (e) {
|
|
|
var input = $input.val()
|
|
|
if (input.length > 0) {
|
|
|
$item.hide();
|
|
|
var filterObj = $item.filter(function (index) {
|
|
|
return $(this).text().indexOf(input) >= 0;
|
|
|
})
|
|
|
if (filterObj.length > 0) {
|
|
|
filterObj.css("display", "block").parent().parent().parent().addClass('selected');
|
|
|
} else {
|
|
|
$item.show();
|
|
|
$list.removeClass('selected');
|
|
|
var X, Y;
|
|
|
X = ev.x - t.left + that.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + that.$workArea[0].parentNode.scrollTop;
|
|
|
var vX = X - that.$nodeData[id].left, vY = Y - that.$nodeData[id].top;
|
|
|
var isMove = false;
|
|
|
|
|
|
document.onmousemove = function (e) {
|
|
|
if (!e) {
|
|
|
e = window.event;
|
|
|
}
|
|
|
var ev = GooFunc.mousePosition(e);
|
|
|
X = ev.x - vX - c.left;
|
|
|
Y = ev.y - vY - c.top;
|
|
|
if (X < t.left - c.left - that.$workArea[0].parentNode.scrollLeft) {
|
|
|
X = t.left - c.left - that.$workArea[0].parentNode.scrollLeft;
|
|
|
}
|
|
|
else if (X + that.$workArea[0].parentNode.scrollLeft + that.$nodeData[id].width > t.left - c.left + that.$workArea.width()) {
|
|
|
X = t.left - c.left + that.$workArea.width() - that.$workArea[0].parentNode.scrollLeft - that.$nodeData[id].width;
|
|
|
}
|
|
|
if (Y < t.top - c.top - that.$workArea[0].parentNode.scrollTop) {
|
|
|
Y = t.top - c.top - that.$workArea[0].parentNode.scrollTop;
|
|
|
}
|
|
|
else if (Y + that.$workArea[0].parentNode.scrollTop + that.$nodeData[id].height > t.top - c.top + that.$workArea.height()) {
|
|
|
Y = t.top - c.top + that.$workArea.height() - that.$workArea[0].parentNode.scrollTop - that.$nodeData[id].height;
|
|
|
}
|
|
|
that.$ghost.css({left: X - 230 + "px", top: Y - 133 + "px"});
|
|
|
isMove = true;
|
|
|
}
|
|
|
document.onmouseup = function () {
|
|
|
if (isMove) that.moveNode(id, X + that.$workArea[0].parentNode.scrollLeft - t.left + c.left, Y + that.$workArea[0].parentNode.scrollTop - t.top + c.top);
|
|
|
{
|
|
|
that.$ghost.empty().hide();
|
|
|
}
|
|
|
document.onmousemove = null;
|
|
|
document.onmouseup = null;
|
|
|
}
|
|
|
}, 150);
|
|
|
},
|
|
|
// 显示连线图标
|
|
|
mouseenter: function () {
|
|
|
var moving = that.$lineMoveing;
|
|
|
if (!moving) {
|
|
|
var w = $(this).width() + 60 + 'px';
|
|
|
var h = $(this).height() + 30 + 'px';
|
|
|
$(this).append("<div class='line-begin' style='width:" + w + ";height:" + h + "'><div class='line-begin-icon top'></div><div class='line-begin-icon left'></div><div class='line-begin-icon right'></div><div class='line-begin-icon bottom'></div></div>")
|
|
|
}
|
|
|
else {
|
|
|
$item.show();
|
|
|
$list.removeClass('selected');
|
|
|
if (moving) {
|
|
|
$(this).addClass('item-mark');
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
},
|
|
|
mouseleave: function () {
|
|
|
$(this).children('.line-begin').remove();
|
|
|
$(this).removeClass('item-mark');
|
|
|
},
|
|
|
// 结束连线
|
|
|
mouseup: function () {
|
|
|
clearTimeout(timeId);
|
|
|
if (that.$lineMoveing) {
|
|
|
var type = $(this).children('.GooFlow_item_cont').children('.GooFlow_item_txt').attr("id").split("type-")[1]
|
|
|
var obj = $(this);
|
|
|
if (that.$nowType != "cursor") {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
itemSearchFn($('.GooFlow_left'));
|
|
|
itemSearchFn($('.GooFlow_right'));
|
|
|
}
|
|
|
var lineT, lineM;
|
|
|
var lineType = that.$lineType;
|
|
|
|
|
|
switch (lineType) {
|
|
|
case 'top':
|
|
|
case 'bottom':
|
|
|
lineT = 'tb';
|
|
|
break;
|
|
|
case 'left':
|
|
|
case 'right':
|
|
|
lineT = 'lr';
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 端点及转换器HTML结构搭建 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
function appHtml(data, className, title) {
|
|
|
var list = data, htmlStr;
|
|
|
htmlStr = "<div class='GooFlow_app " +
|
|
|
className +
|
|
|
"'><div class='GooFlow_app_head'><h1 class='GooFlow_app_tit'>"
|
|
|
+ title +
|
|
|
"</h1><div class='GooFlow_app_search'><input class='GooFlow_app_search_input' type='text' placeholder='搜索"
|
|
|
+ title +
|
|
|
"'><div class='GooFlow_search_btn'></div></div></div><div class='GooFlow_app_cont'><ul" +
|
|
|
" class='GooFlow_app_list'>"
|
|
|
|
|
|
if (title == '端点') {
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
htmlStr += "<li class='GooFlow_app_list_item'>";
|
|
|
htmlStr += "<div class='GooFlow_app_list_tit'>" + list[i].title + "</div>";
|
|
|
htmlStr += "<div class='GooFlow_app_list_box'><ul>";
|
|
|
for (var j = 0; j < list[i].list.length; j++) {
|
|
|
htmlStr += "<li class='GooFlow_app_item'data ='" + list[i].list[j].value +
|
|
|
"'><div class='app_icon'></div> <div class='app_name'>" + list[i].list[j].name + "</div></li>"
|
|
|
var lineStart = that.$workArea.data("lineStart");
|
|
|
console.log("lineStart" + lineStart);
|
|
|
var n1 = that.$nodeData[lineStart.id], n2 = that.$nodeData[obj[0].id];
|
|
|
|
|
|
//To结点中心点位置判断
|
|
|
var sLeft = n1.left;
|
|
|
var sRight = sLeft + n1.width;
|
|
|
var sTop = n1.top;
|
|
|
var sBottom = sTop + n1.height;
|
|
|
|
|
|
var EXcenter = n2.left + n2.width / 2;
|
|
|
var EYcenter = n2.top + n2.height / 2;
|
|
|
|
|
|
// 当To结点中心点在From结点内时,用直线
|
|
|
if ((EXcenter >= sLeft && EXcenter <= sRight) || (EYcenter >= sTop && EYcenter <= sBottom)) {
|
|
|
lineT = 'sl';
|
|
|
lineM = '';
|
|
|
}
|
|
|
|
|
|
var lineM = GooFlow.prototype.getMValue(n1, n2, lineT);
|
|
|
|
|
|
if (lineStart) {
|
|
|
that.addLine(that.$id + "_line_" + that.$lineCount, {
|
|
|
from: lineStart.id,
|
|
|
to: obj[0].id,
|
|
|
name: "",
|
|
|
x: lineStart.x,
|
|
|
y: lineStart.y,
|
|
|
typeFrom: lineStart.typeFrom,
|
|
|
typeTo: type,
|
|
|
type: lineT,
|
|
|
M: lineM
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
htmlStr += "</ul></li>";
|
|
|
}
|
|
|
} else if (title == '转换器'){
|
|
|
htmlStr += "<li class='GooFlow_app_list_item'><div class='GooFlow_app_list_box'><ul>";
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
htmlStr += "<li class='GooFlow_app_item' data='" + list[i].value +
|
|
|
"'><div class='app_icon'></div> <div class='app_name'>" + list[i].name + "</div></li>"
|
|
|
}
|
|
|
htmlStr += "</ul></li></ul></div></div>";
|
|
|
}
|
|
|
that.$contBox.prepend(htmlStr);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: 画布区域 【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:09
|
|
|
* */
|
|
|
this.$contBox.append("<div class='GooFlow_work'></div>");
|
|
|
this.$workArea = $("<div class='GooFlow_work_inner'></div>").attr({
|
|
|
"unselectable": "on",
|
|
|
"onselectstart": 'return false',
|
|
|
"onselect": 'document.selection.empty()'
|
|
|
});
|
|
|
this.$contBox.children(".GooFlow_work").append(this.$workArea);
|
|
|
|
|
|
this.$draw = null;
|
|
|
this.initDraw("draw_" + this.$id, width, height, workWidth, workHeight);
|
|
|
|
|
|
/*
|
|
|
* Todo: ### 画布区域功能设置 ******************************************* //
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:15
|
|
|
* */
|
|
|
if (this.$editable) {
|
|
|
|
|
|
/*
|
|
|
* Todo: 空白区域点击事件 【画布--click事件】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:05
|
|
|
* */
|
|
|
this.$workArea.on("click", {inthis: this}, function (e) {
|
|
|
// 获取事件对象
|
|
|
var This = e.data.inthis;
|
|
|
This.$canDelLine = false;
|
|
|
|
|
|
if (!e) {
|
|
|
e = window.event;
|
|
|
}
|
|
|
if (!e.data.inthis.$editable) {
|
|
|
return;
|
|
|
}
|
|
|
// 获取当前工具类型
|
|
|
var type = e.data.inthis.$nowType;
|
|
|
// 如果当前所选工具类型为指针时
|
|
|
if (type == "cursor") {
|
|
|
var t = $(e.target);
|
|
|
var n = t.prop("tagName");
|
|
|
if (n == "svg" || (n == "DIV" && t.prop("class").indexOf("GooFlow_work") > -1) || n == "LABEL") {
|
|
|
// 点击空白处取消所有结点/连线被选定的状态
|
|
|
e.data.inthis.blurItem();
|
|
|
}
|
|
|
return;
|
|
|
}, ".GooFlow_item").on({
|
|
|
// 删除
|
|
|
mousedown: function () {
|
|
|
that.delNode(that.$focus);
|
|
|
return false;
|
|
|
}
|
|
|
});
|
|
|
}, ".rs_close")
|
|
|
|
|
|
// 对结点进行移动或者RESIZE时用来显示的遮罩层
|
|
|
this.$ghost = $("<div class='rs_ghost GooFlow_item'></div>").attr({
|
|
|
"unselectable": "on",
|
|
|
"onselectstart": 'return false',
|
|
|
"onselect": 'document.selection.empty()'
|
|
|
});
|
|
|
this.$bgDiv.append(this.$ghost);
|
|
|
|
|
|
/*
|
|
|
* Todo: 线条绘制 【线条--mousemove & mouseup事件】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:04
|
|
|
* */
|
|
|
this.$workArea.mousemove({inthis: this}, function (e) {
|
|
|
|
|
|
var This = e.data.inthis;
|
|
|
if (This.$nowType == "cursor") {
|
|
|
var lineStart = $(this).data("lineStart");
|
|
|
if (!lineStart)return;
|
|
|
|
|
|
var ev = GooFunc.mousePosition(e), t = GooFunc.getElCoordinate(this);
|
|
|
var X, Y;
|
|
|
X = ev.x - t.left + this.parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + this.parentNode.scrollTop;
|
|
|
|
|
|
var line = document.getElementById("GooFlow_tmp_line");
|
|
|
$('.file-box input').click(function () {
|
|
|
// 编辑的时候禁止delete键删除
|
|
|
that.blurItem();
|
|
|
})
|
|
|
/*
|
|
|
* Todo: 连线链接 【 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:23
|
|
|
* */
|
|
|
this.$workArea.on({
|
|
|
// 连线开始
|
|
|
mousedown: function () {
|
|
|
var cs = $(this).attr("class").split(/\s+/);
|
|
|
that.$lineMoveing = true;
|
|
|
that.$lineType = cs[1];
|
|
|
var obj = $(this).parent().parent();
|
|
|
that.$nowType = "cursor";
|
|
|
|
|
|
var type = obj.children('.GooFlow_item_cont').children('.GooFlow_item_txt').attr("id").split("type-")[1]
|
|
|
// 将划线开始点定为元素中心点
|
|
|
var X, Y;
|
|
|
var objPosition = obj.position();
|
|
|
var objLeft = objPosition.left;
|
|
|
var objTop = objPosition.top;
|
|
|
var w = (obj.width()) / 2;
|
|
|
var h = (obj.height()) / 2;
|
|
|
X = objLeft + w;
|
|
|
Y = objTop + h;
|
|
|
|
|
|
that.$workArea.data("lineStart", {
|
|
|
"x": X,
|
|
|
"y": Y,
|
|
|
"id": obj[0].id,
|
|
|
"typeFrom": type
|
|
|
}).css("cursor", "crosshair");
|
|
|
|
|
|
var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [X, Y], [X, Y], true, true);
|
|
|
that.$draw.appendChild(line);
|
|
|
|
|
|
$(document).mouseup(function () {
|
|
|
$('.GooFlow_item').removeClass('item-mark');
|
|
|
that.$lineMoveing = false;
|
|
|
})
|
|
|
return false;
|
|
|
}
|
|
|
}, ".GooFlow_item .line-begin > *").on({
|
|
|
// 连线中
|
|
|
mousemove: function (e) {
|
|
|
if (that.$nowType == "cursor") {
|
|
|
var lineStart = $(this).data("lineStart");
|
|
|
if (!lineStart)return;
|
|
|
var ev = GooFunc.mousePosition(e), t = GooFunc.getElCoordinate(this);
|
|
|
var X, Y;
|
|
|
X = ev.x - t.left + this.parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + this.parentNode.scrollTop;
|
|
|
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
var line = document.getElementById("GooFlow_tmp_line");
|
|
|
line.childNodes[0].setAttribute("d", "M " + lineStart.x + " " + lineStart.y + " L " + X + " " + Y);
|
|
|
line.childNodes[1].setAttribute("d", "M " + lineStart.x + " " + lineStart.y + " L " + X + " " + Y);
|
|
|
|
|
@ -373,701 +840,274 @@ function GooFlow(bgDiv, property) {
|
|
|
line.childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
line.points.value = lineStart.x + "," + lineStart.y + " " + X + "," + Y;
|
|
|
},
|
|
|
// 连线结束
|
|
|
mouseup: function () {
|
|
|
if (that.$nowType != "cursor") {
|
|
|
return;
|
|
|
}
|
|
|
$(this).css("cursor", "auto").removeData("lineStart");
|
|
|
var HtmlStr = document.getElementById("GooFlow_tmp_line");
|
|
|
if (HtmlStr) {
|
|
|
that.$draw.removeChild(HtmlStr);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
this.$workArea.mouseup({inthis: this}, function (e) {
|
|
|
if (e.data.inthis.$nowType != "cursor") {
|
|
|
return;
|
|
|
}
|
|
|
$(this).css("cursor", "auto").removeData("lineStart");
|
|
|
var HtmlStr = document.getElementById("GooFlow_tmp_line");
|
|
|
if (HtmlStr) {
|
|
|
e.data.inthis.$draw.removeChild(HtmlStr);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点拖拽 【结点- document.mousemove@@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:03
|
|
|
* */
|
|
|
var onDrag = false;
|
|
|
function addNodeByDrag(obj, type) {
|
|
|
obj.mousedown(function () {
|
|
|
that.$nowType = type;
|
|
|
if (!type) {
|
|
|
var thisType = $(this).attr("id").split("btn_")[1];
|
|
|
that.$nowType = thisType;
|
|
|
})
|
|
|
|
|
|
/*
|
|
|
* Todo: 线条文字编辑 【 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:23
|
|
|
* */
|
|
|
$(this.$draw).on({
|
|
|
click: function () {
|
|
|
that.focusItem(this.id, true);
|
|
|
},
|
|
|
dblclick: function () {
|
|
|
var oldTxt, x, y, from, to;
|
|
|
// 编辑的时候禁止delete键删除
|
|
|
that.$canDelLine = false;
|
|
|
that.$deteNodeId = '';
|
|
|
that.$deteLineId = '';
|
|
|
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
oldTxt = this.childNodes[2].textContent;
|
|
|
from = this.getAttribute("from").split(",");
|
|
|
to = this.getAttribute("to").split(",");
|
|
|
}
|
|
|
onDrag = true;
|
|
|
that.$newNodeTxt = $(this).children('.app_name').text();
|
|
|
that.$newNodeValue = $(this).attr('data');
|
|
|
console.log( $(this));
|
|
|
});
|
|
|
$(document).mouseup(function () {
|
|
|
onDrag = false;
|
|
|
});
|
|
|
that.$workArea.mousemove(function () {
|
|
|
if (onDrag) {
|
|
|
var X, Y;
|
|
|
var ev = GooFunc.mousePosition();
|
|
|
X = ev.x - 433 + this.parentNode.scrollLeft;
|
|
|
Y = ev.y - 262 + this.parentNode.scrollTop;
|
|
|
that.$workArea.children('#node-ghost').attr({class: 'node-' + that.$nowType});
|
|
|
that.$workArea.css({cursor: 'move'}).children('#node-ghost').css({
|
|
|
display: "block",
|
|
|
top: Y + "px",
|
|
|
left: X + "px",
|
|
|
cursor: "move",
|
|
|
});
|
|
|
|
|
|
if (that.$lineData[this.id].type == "lr") {
|
|
|
from[0] = that.$lineData[this.id].M;
|
|
|
to[0] = from[0];
|
|
|
}
|
|
|
})
|
|
|
that.$workArea.mouseup(function () {
|
|
|
if (onDrag) {
|
|
|
addNodeOnArea();
|
|
|
onDrag = false;
|
|
|
that.$workArea.css({cursor: 'pointer'}).children('#node-ghost').remove();
|
|
|
else if (that.$lineData[this.id].type == "tb") {
|
|
|
from[1] = that.$lineData[this.id].M;
|
|
|
to[1] = from[1];
|
|
|
}
|
|
|
});
|
|
|
that.$workArea.mouseenter(function () {
|
|
|
that.$workArea.append("<div id='node-ghost'></div>");
|
|
|
})
|
|
|
that.$workArea.mouseleave(function () {
|
|
|
that.$workArea.css({cursor: 'pointer'}).children('#node-ghost').remove();
|
|
|
})
|
|
|
|
|
|
function addNodeOnArea() {
|
|
|
var X, Y;
|
|
|
var ev = GooFunc.mousePosition();
|
|
|
X = ev.x - 433 + that.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - 262 + that.$workArea[0].parentNode.scrollTop;
|
|
|
that.addNode(that.$id + "_node_" + that.$nodeCount, {
|
|
|
name: "node_" + that.$nodeCount,
|
|
|
left: X,
|
|
|
top: Y,
|
|
|
type: that.$nowType
|
|
|
x = (parseInt(from[0], 10) + parseInt(to[0], 10)) / 2 + 230;
|
|
|
y = (parseInt(from[1], 10) + parseInt(to[1], 10)) / 2 + 60;
|
|
|
|
|
|
that.$textArea.val(oldTxt).css({
|
|
|
display: "block",
|
|
|
left: x,
|
|
|
top: y
|
|
|
}).data("id", that.$focus).focus();
|
|
|
|
|
|
that.$workArea.parent().one("mousedown", function () {
|
|
|
that.setName(that.$textArea.data("id"), that.$textArea.val(), "line");
|
|
|
that.$textArea.val("").removeData("id").hide();
|
|
|
});
|
|
|
that.$max++;
|
|
|
}
|
|
|
}
|
|
|
addNodeByDrag(that.$flowChart.children());
|
|
|
|
|
|
// 为了结点而增加的一些集体delegate绑定
|
|
|
this.initWorkForNode();
|
|
|
|
|
|
// 文本框
|
|
|
this.$textArea = $("<textarea class='text_input'></textarea>");
|
|
|
this.$bgDiv.append(this.$textArea);
|
|
|
|
|
|
// 操作折线时的移动框
|
|
|
this.$lineMove = $("<div class='GooFlow_line_move' style='display:none'></div>");
|
|
|
this.$workArea.append(this.$lineMove);
|
|
|
|
|
|
/*
|
|
|
* Todo: 线条移动事件 【线条编辑相关 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:33
|
|
|
* */
|
|
|
this.$lineMove.on("mousedown", {inthis: this}, function (e) {
|
|
|
}, 'g');
|
|
|
|
|
|
/*
|
|
|
* Todo: 线条移动 【 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:33
|
|
|
* */
|
|
|
this.$lineMove.on("mousedown", function (e) {
|
|
|
var lm = $(this);
|
|
|
lm.css({"background-color": "#333"});
|
|
|
var This = e.data.inthis;
|
|
|
var ev = GooFunc.mousePosition(e), t = GooFunc.getElCoordinate(This.$workArea[0]);
|
|
|
var ev = GooFunc.mousePosition(e), t = GooFunc.getElCoordinate(that.$workArea[0]);
|
|
|
var X, Y;
|
|
|
X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop;
|
|
|
var p = This.$lineMove.position();
|
|
|
X = ev.x - t.left + that.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + that.$workArea[0].parentNode.scrollTop;
|
|
|
var p = that.$lineMove.position();
|
|
|
var vX = X - p.left, vY = Y - p.top;
|
|
|
var isMove = false;
|
|
|
|
|
|
document.onmousemove = function (e) {
|
|
|
if (!e) e = window.event;
|
|
|
var ev = GooFunc.mousePosition(e);
|
|
|
var ps = This.$lineMove.position();
|
|
|
X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop;
|
|
|
if (This.$lineMove.data("type") == "lr") {
|
|
|
var ps = that.$lineMove.position();
|
|
|
X = ev.x - t.left + that.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + that.$workArea[0].parentNode.scrollTop;
|
|
|
if (that.$lineMove.data("type") == "lr") {
|
|
|
X = X - vX;
|
|
|
if (X < 0) X = 0;
|
|
|
else if (X > This.$workArea.width())
|
|
|
X = This.$workArea.width();
|
|
|
This.$lineMove.css({left: X + "px"});
|
|
|
else if (X > that.$workArea.width())
|
|
|
X = that.$workArea.width();
|
|
|
that.$lineMove.css({left: X + "px"});
|
|
|
}
|
|
|
else if (This.$lineMove.data("type") == "tb") {
|
|
|
else if (that.$lineMove.data("type") == "tb") {
|
|
|
Y = Y - vY;
|
|
|
if (Y < 0) Y = 0;
|
|
|
else if (Y > This.$workArea.height())
|
|
|
Y = This.$workArea.height();
|
|
|
This.$lineMove.css({top: Y + "px"});
|
|
|
else if (Y > that.$workArea.height())
|
|
|
Y = that.$workArea.height();
|
|
|
that.$lineMove.css({top: Y + "px"});
|
|
|
}
|
|
|
isMove = true;
|
|
|
}
|
|
|
|
|
|
document.onmouseup = function (e) {
|
|
|
if (isMove) {
|
|
|
var p = This.$lineMove.position();
|
|
|
if (This.$lineMove.data("type") == "lr")
|
|
|
This.setLineM(This.$lineMove.data("tid"), p.left + 3);
|
|
|
else if (This.$lineMove.data("type") == "tb")
|
|
|
This.setLineM(This.$lineMove.data("tid"), p.top + 3);
|
|
|
var p = that.$lineMove.position();
|
|
|
if (that.$lineMove.data("type") == "lr")
|
|
|
that.setLineM(that.$lineMove.data("tid"), p.left + 3);
|
|
|
else if (that.$lineMove.data("type") == "tb")
|
|
|
that.setLineM(that.$lineMove.data("tid"), p.top + 3);
|
|
|
}
|
|
|
This.$lineMove.css({"background-color": "transparent"});
|
|
|
if (This.$focus == This.$lineMove.data("tid")) {
|
|
|
This.focusItem(This.$lineMove.data("tid"));
|
|
|
that.$lineMove.css({"background-color": "transparent"});
|
|
|
if (that.$focus == that.$lineMove.data("tid")) {
|
|
|
that.focusItem(that.$lineMove.data("tid"));
|
|
|
}
|
|
|
document.onmousemove = null;
|
|
|
document.onmouseup = null;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 生成线条修改框 【线条编辑UI相关 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:02
|
|
|
* */
|
|
|
this.$lineOper = $("<div class='GooFlow_line_oper' style='display:none'><b class='b_l1'></b><b class='b_l2'></b><b class='b_l3'></b><b class='b_x'></b></div>");
|
|
|
this.$workArea.append(this.$lineOper);
|
|
|
this.$lineOper.on("click", {inthis: this}, function (e) {
|
|
|
if (!e) e = window.event;
|
|
|
this.$lineOper.on("click", function (e) {
|
|
|
if (e.target.tagName != "B") return;
|
|
|
var This = e.data.inthis;
|
|
|
var id = $(this).data("tid");
|
|
|
switch ($(e.target).attr("class")) {
|
|
|
case "b_x":
|
|
|
This.delLine(id);
|
|
|
that.delLine(id);
|
|
|
this.style.display = "none";
|
|
|
break;
|
|
|
case "b_l1":
|
|
|
This.setLineType(id, "lr");
|
|
|
that.setLineType(id, "lr");
|
|
|
break;
|
|
|
case "b_l2":
|
|
|
This.setLineType(id, "tb");
|
|
|
that.setLineType(id, "tb");
|
|
|
break;
|
|
|
case "b_l3":
|
|
|
This.setLineType(id, "sl");
|
|
|
that.setLineType(id, "sl");
|
|
|
break;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
//下面绑定当结点/线/分组块的一些操作事件,这些事件可直接通过this访问对象本身
|
|
|
//当操作某个单元(结点/线/分组块)被添加时, 触发的方法, 返回FALSE可阻止添加事件的发生
|
|
|
//格式function(id, type,json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json.
|
|
|
this.onItemAdd = property.onItemAdd;
|
|
|
|
|
|
//当操作某个单元(结点/线/分组块)被删除时, 触发的方法, 返回FALSE可阻止删除事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值
|
|
|
this.onItemDel = property.onItemDel;
|
|
|
|
|
|
//当操作某个单元(结点/分组块)被移动时, 触发的方法, 返回FALSE可阻止移动事件的发生
|
|
|
//格式function(id, type,left,top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值, 线line不支持移动,left是新的左边距坐标, top是新的顶边距坐标
|
|
|
this.onItemMove = property.onItemMove;
|
|
|
|
|
|
//当操作某个单元(结点/线/分组块)被重命名时, 触发的方法, 返回FALSE可阻止重命名事件的发生
|
|
|
//格式function(id,name,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称
|
|
|
this.onItemRename = property.onItemRename;
|
|
|
|
|
|
//当操作某个单元(结点/线)被由不选中变成选中时, 触发的方法, 返回FALSE可阻止选中事件的发生
|
|
|
//格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中
|
|
|
this.onItemFocus = property.onItemFocus;
|
|
|
|
|
|
//当操作某个单元(结点/线)被由选中变成不选中时, 触发的方法, 返回FALSE可阻止取消选中事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中
|
|
|
this.onItemBlur = property.onItemBlur;
|
|
|
|
|
|
//当操作某个单元(结点/分组块)被重定义大小或造型时, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type,width,height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值;width是新的宽度,height是新的高度
|
|
|
this.onItemResize = property.onItemResize;
|
|
|
|
|
|
//当移动某条折线中段的位置, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标
|
|
|
this.onLineMove = property.onLineMove;
|
|
|
|
|
|
//当变换某条连接线的类型, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线
|
|
|
this.onLineSetType = property.onLineSetType;
|
|
|
|
|
|
//当用重色标注某个结点/转换线时触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type, mark):id是单元的唯一标识ID,type是单元类型("node"结点,"line"转换线), mark为布尔值,表示是要标注TRUE还是取消标注FALSE
|
|
|
this.onItemMark = property.onItemMark;
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 取消&重做函数 【堆栈相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:12
|
|
|
* */
|
|
|
|
|
|
//如果要使用堆栈记录操作并提供“撤销/重做”的功能
|
|
|
if (property.useOperStack) {
|
|
|
this.$undoStack = [];
|
|
|
this.$redoStack = [];
|
|
|
this.$isUndo = 0;
|
|
|
|
|
|
///////////////以下是构造撤销操作/重做操作的方法
|
|
|
//为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放40步操作;超过40步时,将自动删掉最旧的一个缓存
|
|
|
this.pushOper = function (funcName, paras) {
|
|
|
var len = this.$undoStack.length;
|
|
|
if (this.$isUndo == 1) {
|
|
|
this.$redoStack.push([funcName, paras]);
|
|
|
this.$isUndo = false;
|
|
|
if (this.$redoStack.length > 40) this.$redoStack.shift();
|
|
|
} else {
|
|
|
this.$undoStack.push([funcName, paras]);
|
|
|
if (this.$undoStack.length > 40) this.$undoStack.shift();
|
|
|
if (this.$isUndo == 0) {
|
|
|
this.$redoStack.splice(0, this.$redoStack.length);
|
|
|
}
|
|
|
this.$isUndo = 0;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//将外部的方法加入到GooFlow对象的事务操作堆栈中,在过后的undo/redo操作中可以进行控制, 一般用于对流程图以外的附加信息进行编辑的事务撤销/重做控制;
|
|
|
//传参func为要执行方法对象,jsonPara为外部方法仅有的一个面向字面的JSON传参,由JSON对象带入所有要传的信息;
|
|
|
//提示:为了让外部方法能够被UNDO/REDO,需要在编写这些外部方法实现时,加入对该方法执行后效果回退的另一个执行方法的pushExternalOper
|
|
|
this.pushExternalOper = function (func, jsonPara) {
|
|
|
this.pushOper("externalFunc", [func, jsonPara]);
|
|
|
};
|
|
|
|
|
|
//撤销上一步操作
|
|
|
this.undo = function () {
|
|
|
if (this.$undoStack.length == 0) return;
|
|
|
var tmp = this.$undoStack.pop();
|
|
|
this.$isUndo = 1;
|
|
|
if (tmp[0] == "externalFunc") {
|
|
|
tmp[1][0](tmp[1][1]);
|
|
|
}
|
|
|
else {
|
|
|
//传参的数量,最多支持5个.
|
|
|
switch (tmp[1].length) {
|
|
|
case 0:
|
|
|
this[tmp[0]]();
|
|
|
break;
|
|
|
case 1:
|
|
|
this[tmp[0]](tmp[1][0]);
|
|
|
break;
|
|
|
case 2:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1]);
|
|
|
break;
|
|
|
case 3:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]);
|
|
|
break;
|
|
|
case 4:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]);
|
|
|
break;
|
|
|
case 5:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]);
|
|
|
break;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: ### 初始化事件绑定******************************--结束
|
|
|
* */
|
|
|
|
|
|
/*
|
|
|
* Todo: 取消选定状态 【取消聚焦公共方法】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:53
|
|
|
* */
|
|
|
blurItem: function () {
|
|
|
this.$canDelLine = false;
|
|
|
this.$deteNodeId = '';
|
|
|
this.$deteLineId = '';
|
|
|
if (this.$focus != "") {
|
|
|
// 获取被选中对象
|
|
|
var jq = $("#" + this.$focus);
|
|
|
if (jq.prop("tagName") == "DIV") {
|
|
|
if (this.onItemBlur != null && !this.onItemBlur(id, "node")) return false;
|
|
|
jq.removeClass("item_focus").children(".rs-box").css("display", "none");
|
|
|
}
|
|
|
else {
|
|
|
if (this.onItemBlur != null && !this.onItemBlur(id, "line")) return false;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
if (!this.$lineData[this.$focus].marked) {
|
|
|
jq[0].childNodes[1].setAttribute("stroke", "#323232");
|
|
|
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow1)");
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
|
|
|
//重做最近一次被撤销的操作
|
|
|
this.redo = function () {
|
|
|
if (this.$redoStack.length == 0) return;
|
|
|
var tmp = this.$redoStack.pop();
|
|
|
this.$isUndo = 2;
|
|
|
if (tmp[0] == "externalFunc") {
|
|
|
tmp[1][0](tmp[1][1]);
|
|
|
}
|
|
|
else {
|
|
|
//传参的数量,最多支持5个.
|
|
|
switch (tmp[1].length) {
|
|
|
case 0:
|
|
|
this[tmp[0]]();
|
|
|
break;
|
|
|
case 1:
|
|
|
this[tmp[0]](tmp[1][0]);
|
|
|
break;
|
|
|
case 2:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1]);
|
|
|
break;
|
|
|
case 3:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]);
|
|
|
break;
|
|
|
case 4:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]);
|
|
|
break;
|
|
|
case 5:
|
|
|
this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]);
|
|
|
break;
|
|
|
}
|
|
|
if (!this.$lineData[this.$focus].marked) jq[0].strokeColor = "#323232";
|
|
|
}
|
|
|
};
|
|
|
|
|
|
this.$lineMove.hide().removeData("type").removeData("tid");
|
|
|
if (this.$editable) this.$lineOper.hide().removeData("tid");
|
|
|
}
|
|
|
}
|
|
|
this.$focus = "";
|
|
|
return true;
|
|
|
},
|
|
|
|
|
|
}
|
|
|
/*
|
|
|
* Todo: 选定状态 【聚焦公共方法】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:53
|
|
|
* */
|
|
|
focusItem: function (id, bool) {
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Todo: ## 原型方法 ***************************************************************************************
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 14:59
|
|
|
* */
|
|
|
GooFlow.prototype = {
|
|
|
useSVG: true,
|
|
|
/*
|
|
|
* Todo: SVG箭头相关【UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:11
|
|
|
* */
|
|
|
|
|
|
getSvgMarker: function (id, color) {
|
|
|
var m = document.createElementNS("http://www.w3.org/2000/svg", "marker");
|
|
|
m.setAttribute("id", id);
|
|
|
m.setAttribute("viewBox", "0 0 6 6");
|
|
|
m.setAttribute("refX", 5);
|
|
|
m.setAttribute("refY", 3);
|
|
|
m.setAttribute("markerUnits", "strokeWidth");
|
|
|
m.setAttribute("markerWidth", 8);
|
|
|
m.setAttribute("markerHeight", 8);
|
|
|
m.setAttribute("orient", "auto");
|
|
|
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
|
path.setAttribute("d", "M 0 0 L 6 3 L 0 6 L 2 3 z");
|
|
|
path.setAttribute("fill", color);
|
|
|
path.setAttribute("stroke-width", 2);
|
|
|
m.appendChild(path);
|
|
|
return m;
|
|
|
},
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 初始化画布 【SVG & 箭头 UI相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:51
|
|
|
* */
|
|
|
initDraw: function (id, width, height, workWidth, workHeight) {
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
this.$draw = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
|
//可创建带有指定命名空间的元素节点
|
|
|
this.$workArea.prepend(this.$draw);
|
|
|
// 定义可以重复利用的元素
|
|
|
var defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
|
this.$draw.appendChild(defs);
|
|
|
defs.appendChild(GooFlow.prototype.getSvgMarker("arrow1", "#323232"));
|
|
|
defs.appendChild(GooFlow.prototype.getSvgMarker("arrow2", "#00b7ee"));
|
|
|
defs.appendChild(GooFlow.prototype.getSvgMarker("arrow3", "#f00"));
|
|
|
}
|
|
|
else {
|
|
|
this.$draw = document.createElement("v:group");
|
|
|
this.$draw.coordsize = workWidth + "," + workHeight;
|
|
|
this.$workArea.prepend("<div class='GooFlow_work_vml'" +
|
|
|
" style='position:relative;width:100%;height:100%'></div>");
|
|
|
this.$workArea.children("div")[0].insertBefore(this.$draw, null);
|
|
|
}
|
|
|
|
|
|
// 设置画布属性
|
|
|
this.$draw.id = id;
|
|
|
this.$draw.style.width = '100%';
|
|
|
this.$draw.style.height = '100%';
|
|
|
|
|
|
//绑定连线的点击选中以及双击编辑事件
|
|
|
var tmpClk = (GooFlow.prototype.useSVG != "") ? 'g' : 'PolyLine';
|
|
|
|
|
|
// 对连线绑定单击事件
|
|
|
$(this.$draw).delegate(tmpClk, "click", {inthis: this}, function (e) {
|
|
|
e.data.inthis.focusItem(this.id, true);
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 双击线条编辑事件 【SVG- 双击事件 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:50
|
|
|
* */
|
|
|
if (this.$editable) {
|
|
|
$(this.$draw).delegate(tmpClk, "dblclick", {inthis: this}, function (e) {
|
|
|
var oldTxt, x, y, from, to;
|
|
|
var This = e.data.inthis;
|
|
|
// 编辑的时候禁止delete键删除
|
|
|
This.$canDelLine = false;
|
|
|
This.$deteNodeId = '';
|
|
|
This.$deteLineId = '';
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
oldTxt = this.childNodes[2].textContent;
|
|
|
from = this.getAttribute("from").split(",");
|
|
|
to = this.getAttribute("to").split(",");
|
|
|
} else {
|
|
|
oldTxt = this.childNodes[1].innerHTML;
|
|
|
var n = this.getAttribute("fromTo").split(",");
|
|
|
from = [n[0], n[1]];
|
|
|
to = [n[2], n[3]];
|
|
|
}
|
|
|
|
|
|
if (This.$lineData[this.id].type == "lr") {
|
|
|
from[0] = This.$lineData[this.id].M;
|
|
|
to[0] = from[0];
|
|
|
}
|
|
|
else if (This.$lineData[this.id].type == "tb") {
|
|
|
from[1] = This.$lineData[this.id].M;
|
|
|
to[1] = from[1];
|
|
|
var jq = $("#" + id);
|
|
|
var that = this;
|
|
|
this.$ghost.attr({'class': 'rs_ghost ' + jq.attr('class')});
|
|
|
if (jq.length == 0) return;
|
|
|
if (!this.blurItem()) return;//先执行"取消选中",如果返回FLASE,则也会阻止选定事件继续进行.
|
|
|
if (jq.prop("tagName") == "DIV") {
|
|
|
if (bool && this.onItemFocus != null && !this.onItemFocus(id, "node")) return;
|
|
|
jq.addClass("item_focus");
|
|
|
if (this.$editable) jq.children(".rs-box").css("display", "block");
|
|
|
this.$workArea.append(jq);
|
|
|
that.$canDelLine = false;
|
|
|
that.$deteLineId = '';
|
|
|
that.$deteNodeId = id;
|
|
|
$(document).keydown(function (e) {
|
|
|
if (e.keyCode != 8 && that.$deteNodeId) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
x = (parseInt(from[0], 10) + parseInt(to[0], 10)) / 2 + 230;
|
|
|
y = (parseInt(from[1], 10) + parseInt(to[1], 10)) / 2 + 60;
|
|
|
|
|
|
This.$textArea.val(oldTxt).css({
|
|
|
display: "block",
|
|
|
left: x,
|
|
|
top: y
|
|
|
}).data("id", This.$focus).focus();
|
|
|
|
|
|
This.$workArea.parent().one("mousedown", function (e) {
|
|
|
This.setName(This.$textArea.data("id"), This.$textArea.val(), "line");
|
|
|
This.$textArea.val("").removeData("id").hide();
|
|
|
});
|
|
|
that.delNode(that.$deteNodeId);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: ### 工作区事件绑定 ***************************************************************
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:09
|
|
|
* */
|
|
|
initWorkForNode: function () {
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点选中事件 【结点--click 事件 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:21
|
|
|
* */
|
|
|
this.$workArea.delegate(".GooFlow_item", "click", {inthis: this}, function (e) {
|
|
|
e.data.inthis.focusItem(this.id, true);
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点删除事件 【删除按钮-mousedown事件 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:22
|
|
|
* */
|
|
|
this.$workArea.on("mousedown", ".rs_close", {inthis: this}, function (e) {
|
|
|
if (!e) e = window.event;
|
|
|
e.data.inthis.delNode(e.data.inthis.$focus);
|
|
|
return false;
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点移动事件 【结点--mousedown 事件 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:22
|
|
|
* */
|
|
|
this.$workArea.on("mousedown", ".GooFlow_item", {inthis: this}, function (e) {
|
|
|
if (!e) e = window.event;
|
|
|
var This = e.data.inthis;
|
|
|
var Dom = $(this);
|
|
|
var id = Dom.attr("id");
|
|
|
This.focusItem(id, true);
|
|
|
var ev = GooFunc.mousePosition(e),
|
|
|
t = GooFunc.getElCoordinate(This.$workArea[0]),
|
|
|
c = GooFunc.getElCoordinate(This.$MainContener);
|
|
|
|
|
|
This.$ghost.css({
|
|
|
display: "block",
|
|
|
top: This.$nodeData[id].top + 133 - This.$workArea[0].parentNode.scrollTop + "px",
|
|
|
left: This.$nodeData[id].left + 200 - This.$workArea[0].parentNode.scrollLeft + "px",
|
|
|
cursor: "move"
|
|
|
});
|
|
|
|
|
|
var X, Y;
|
|
|
X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft;
|
|
|
Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop;
|
|
|
var vX = X - This.$nodeData[id].left, vY = Y - This.$nodeData[id].top;
|
|
|
var isMove = false;
|
|
|
|
|
|
document.onmousemove = function (e) {
|
|
|
if (!e) {
|
|
|
e = window.event;
|
|
|
}
|
|
|
var ev = GooFunc.mousePosition(e);
|
|
|
X = ev.x - vX - c.left;
|
|
|
Y = ev.y - vY - c.top;
|
|
|
if (X < t.left - c.left - This.$workArea[0].parentNode.scrollLeft) {
|
|
|
X = t.left - c.left - This.$workArea[0].parentNode.scrollLeft;
|
|
|
}
|
|
|
else if (X + This.$workArea[0].parentNode.scrollLeft + This.$nodeData[id].width > t.left - c.left + This.$workArea.width()) {
|
|
|
X = t.left - c.left + This.$workArea.width() - This.$workArea[0].parentNode.scrollLeft - This.$nodeData[id].width;
|
|
|
}
|
|
|
if (Y < t.top - c.top - This.$workArea[0].parentNode.scrollTop) {
|
|
|
Y = t.top - c.top - This.$workArea[0].parentNode.scrollTop;
|
|
|
}
|
|
|
else if (Y + This.$workArea[0].parentNode.scrollTop + This.$nodeData[id].height > t.top - c.top + This.$workArea.height()) {
|
|
|
Y = t.top - c.top + This.$workArea.height() - This.$workArea[0].parentNode.scrollTop - This.$nodeData[id].height;
|
|
|
}
|
|
|
This.$ghost.css({left: X - 230 + "px", top: Y - 133 + "px"});
|
|
|
isMove = true;
|
|
|
}
|
|
|
document.onmouseup = function (e) {
|
|
|
if (isMove) This.moveNode(id, X + This.$workArea[0].parentNode.scrollLeft - t.left + c.left, Y + This.$workArea[0].parentNode.scrollTop - t.top + c.top);
|
|
|
{
|
|
|
This.$ghost.empty().hide();
|
|
|
else {//如果是连接线
|
|
|
if (this.onItemFocus != null && !this.onItemFocus(id, "line")) return;
|
|
|
that.$canDelLine = true;
|
|
|
that.$deteNodeId = '';
|
|
|
that.$deteLineId = id;
|
|
|
$(document).keydown(function (e) {
|
|
|
if (e.keyCode == 8 && that.$deteLineId) {
|
|
|
that.delLine(that.$deteLineId);
|
|
|
$('.GooFlow_line_oper').hide();
|
|
|
}
|
|
|
document.onmousemove = null;
|
|
|
document.onmouseup = null;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 鼠标移入结点 【结点--mouseenter 事件 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:22
|
|
|
* */
|
|
|
this.$workArea.delegate(".GooFlow_item", "mouseenter", {inthis: this}, function (e) {
|
|
|
var This = e.data.inthis;
|
|
|
var moving = This.$lineMoveing;
|
|
|
|
|
|
if (!moving) {
|
|
|
var w = $(this).width() + 60 + 'px';
|
|
|
var h = $(this).height() + 30 + 'px';
|
|
|
|
|
|
$(this).append("<div class='line-begin' style='width:" + w + ";height:" + h + "'><div class='line-begin-icon top'></div><div class='line-begin-icon left'></div><div class='line-begin-icon right'></div><div class='line-begin-icon bottom'></div></div>")
|
|
|
}
|
|
|
|
|
|
if (moving) {
|
|
|
$(this).addClass('item-mark');
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 鼠标移出结点 【结点--mouseleave 事件 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:22
|
|
|
* */
|
|
|
this.$workArea.delegate(".GooFlow_item", "mouseleave", {inthis: this}, function (e) {
|
|
|
$(this).children('.line-begin').remove();
|
|
|
$(this).removeClass('item-mark');
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 连线事件 【连线按钮--mousedown 事件 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:23
|
|
|
* */
|
|
|
this.$workArea.delegate(".GooFlow_item .line-begin > *", "mousedown", {inthis: this}, function (e) {
|
|
|
var cs = $(this).attr("class").split(/\s+/);
|
|
|
var This = e.data.inthis;
|
|
|
This.$lineMoveing = true;
|
|
|
This.$lineType = cs[1];
|
|
|
|
|
|
var obj = $(this).parent().parent();
|
|
|
This.$nowType = "cursor";
|
|
|
|
|
|
var type = obj.children('.GooFlow_item_cont').children('.GooFlow_item_txt').attr("id").split("type-")[1]
|
|
|
// 将划线开始点定为元素中心点
|
|
|
var X, Y;
|
|
|
var objPosition = obj.position();
|
|
|
var objLeft = objPosition.left;
|
|
|
var objTop = objPosition.top;
|
|
|
var w = (obj.width()) / 2;
|
|
|
var h = (obj.height()) / 2;
|
|
|
X = objLeft + w;
|
|
|
Y = objTop + h;
|
|
|
|
|
|
This.$workArea.data("lineStart", {
|
|
|
"x": X,
|
|
|
"y": Y,
|
|
|
"id": obj[0].id,
|
|
|
"typeFrom": type
|
|
|
}).css("cursor", "crosshair");
|
|
|
|
|
|
var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [X, Y], [X, Y], true, true);
|
|
|
This.$draw.appendChild(line);
|
|
|
|
|
|
$(document).mouseup(function () {
|
|
|
$('.GooFlow_item').removeClass('item-mark');
|
|
|
This.$lineMoveing = false;
|
|
|
})
|
|
|
return false;
|
|
|
});
|
|
|
|
|
|
/*
|
|
|
* Todo: 连线结束事件 【连线按钮--mousedown 事件 $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:24
|
|
|
* */
|
|
|
this.$workArea.delegate(".GooFlow_item", "mouseup", {inthis: this}, function (e) {
|
|
|
var type = $(this).children('.GooFlow_item_cont').children('.GooFlow_item_txt').attr("id").split("type-")[1]
|
|
|
var This = e.data.inthis;
|
|
|
var obj = $(this);
|
|
|
if (This.$nowType != "cursor") {
|
|
|
return;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
jq[0].childNodes[1].setAttribute("stroke", "#00b7ee");
|
|
|
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
|
|
}
|
|
|
|
|
|
var lineT,lineM;
|
|
|
var lineType = This.$lineType;
|
|
|
|
|
|
switch (lineType){
|
|
|
case 'top':
|
|
|
case 'bottom':
|
|
|
lineT = 'tb';
|
|
|
break;
|
|
|
case 'left':
|
|
|
case 'right':
|
|
|
lineT = 'lr';
|
|
|
break;
|
|
|
else jq[0].strokeColor = "#00b7ee";
|
|
|
if (!this.$editable) return;
|
|
|
var x, y, from, to;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
from = jq.attr("from").split(",");
|
|
|
to = jq.attr("to").split(",");
|
|
|
} else {
|
|
|
var n = jq[0].getAttribute("fromTo").split(",");
|
|
|
from = [n[0], n[1]];
|
|
|
to = [n[2], n[3]];
|
|
|
}
|
|
|
from[0] = parseInt(from[0], 10);
|
|
|
from[1] = parseInt(from[1], 10);
|
|
|
to[0] = parseInt(to[0], 10);
|
|
|
to[1] = parseInt(to[1], 10);
|
|
|
|
|
|
var lineStart = This.$workArea.data("lineStart");
|
|
|
console.log("lineStart"+lineStart);
|
|
|
var n1 = This.$nodeData[lineStart.id], n2 = This.$nodeData[obj[0].id];
|
|
|
|
|
|
//To结点中心点位置判断
|
|
|
var sLeft = n1.left;
|
|
|
var sRight = sLeft + n1.width;
|
|
|
var sTop = n1.top;
|
|
|
var sBottom = sTop + n1.height;
|
|
|
|
|
|
var EXcenter = n2.left+n2.width/2;
|
|
|
var EYcenter = n2.top+n2.height/2;
|
|
|
if (this.$lineData[id].type == "lr") {
|
|
|
from[0] = this.$lineData[id].M;
|
|
|
to[0] = from[0];
|
|
|
|
|
|
// 当To结点中心点在From结点内时,用直线
|
|
|
if ((EXcenter >= sLeft && EXcenter <= sRight)||(EYcenter >= sTop && EYcenter <= sBottom)) {
|
|
|
lineT = 'sl';
|
|
|
lineM = '';
|
|
|
this.$lineMove.css({
|
|
|
width: "5px", height: (to[1] - from[1]) * (to[1] > from[1] ? 1 : -1) + "px",
|
|
|
left: from[0] - 3 + "px",
|
|
|
top: (to[1] > from[1] ? from[1] : to[1]) + 1 + "px",
|
|
|
cursor: "e-resize", display: "block"
|
|
|
}).data({"type": "lr", "tid": id});
|
|
|
}
|
|
|
|
|
|
var lineM = GooFlow.prototype.getMValue(n1,n2,lineT);
|
|
|
|
|
|
if (lineStart) {
|
|
|
This.addLine(This.$id + "_line_" + This.$lineCount, {
|
|
|
from: lineStart.id,
|
|
|
to: obj[0].id,
|
|
|
name: "",
|
|
|
x: lineStart.x,
|
|
|
y: lineStart.y,
|
|
|
typeFrom: lineStart.typeFrom,
|
|
|
typeTo: type,
|
|
|
type: lineT,
|
|
|
M: lineM
|
|
|
});
|
|
|
else if (this.$lineData[id].type == "tb") {
|
|
|
from[1] = this.$lineData[id].M;
|
|
|
to[1] = from[1];
|
|
|
this.$lineMove.css({
|
|
|
width: (to[0] - from[0]) * (to[0] > from[0] ? 1 : -1) + "px", height: "5px",
|
|
|
left: (to[0] > from[0] ? from[0] : to[0]) + 1 + "px",
|
|
|
top: from[1] - 3 + "px",
|
|
|
cursor: "s-resize", display: "block"
|
|
|
}).data({"type": "tb", "tid": id});
|
|
|
}
|
|
|
});
|
|
|
|
|
|
x = (from[0] + to[0]) / 2 - 35;
|
|
|
y = (from[1] + to[1]) / 2 + 6;
|
|
|
this.$lineOper.css({display: "block", left: x + "px", top: y + "px"}).data("tid", id);
|
|
|
}
|
|
|
this.$focus = id;
|
|
|
this.$nowType = "cursor";
|
|
|
},
|
|
|
/*
|
|
|
* Todo: ### 工作区事件绑定结束 ************************************************
|
|
|
* */
|
|
|
|
|
|
/*
|
|
|
* Todo: 增加结点 【结点公共方法 @@】
|
|
@ -1075,7 +1115,7 @@ GooFlow.prototype = {
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:53
|
|
|
* */
|
|
|
addNode: function (id, json,isDataLoad) {
|
|
|
addNode: function (id, json) {
|
|
|
if (this.onItemAdd != null && !this.onItemAdd(id, "node", json))return;
|
|
|
if (this.$undoStack) {
|
|
|
this.pushOper("delNode", [id]);
|
|
@ -1084,45 +1124,46 @@ GooFlow.prototype = {
|
|
|
if (json.type != "start" && json.type != "end") {
|
|
|
if (json.top < 0) json.top = 0;
|
|
|
if (json.left < 0) json.left = 0;
|
|
|
var hack = 0;
|
|
|
if (navigator.userAgent.indexOf("8.0") != -1) hack = 2;
|
|
|
|
|
|
switch (json.type) {
|
|
|
case "state":
|
|
|
json.name = '判断';
|
|
|
json.config = '';
|
|
|
json.nodeType = 'judgement'
|
|
|
break;
|
|
|
case "complex":
|
|
|
json.name = '循环';
|
|
|
json.config = 'splitJsonArray';
|
|
|
json.nodeType = 'circle'
|
|
|
break;
|
|
|
case "join":
|
|
|
json.name = '聚合';
|
|
|
json.config = '';
|
|
|
json.nodeType = 'aggregate'
|
|
|
break;
|
|
|
case "fork":
|
|
|
json.name = '分流';
|
|
|
json.config = '';
|
|
|
json.nodeType = 'multicast'
|
|
|
break;
|
|
|
case "task":
|
|
|
json.name = this.$newNodeTxt || json.name;
|
|
|
json.value = this.$newNodeValue || json.value;
|
|
|
json.nodeType = 'service'
|
|
|
json.config = this.$nodeConfig || json.config;
|
|
|
json.nodeType = this.$nodeType || json.nodeType;
|
|
|
break;
|
|
|
case "plug":
|
|
|
json.name = this.$newNodeTxt || json.name;
|
|
|
json.value = this.$newNodeValue || json.value;
|
|
|
json.nodeType = 'processor'
|
|
|
json.config = this.$nodeConfig || json.config;
|
|
|
json.nodeType = this.$nodeType || json.nodeType;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
this.$nodeDom[id] = $(" <div class='GooFlow_item node-" + json.type + "' id='" + id + "' style='top:" + json.top + "px;left:" + json.left + "px'> <div class='GooFlow_item_cont'> <i class='fa ico_" + json.type + "'></i> <span class='GooFlow_item_txt' id='type-" + json.type + "'>" + json.name + "</span></div> <div class='rs-box' style='display:none'> <div class='rs_close'><i class='fa fa-close' aria-hidden='true'></i></div> </div> </div>");
|
|
|
this.$nodeDom[id] = $("<div class='GooFlow_item node-" + json.type + "' id='" + id + "' style='top:" + json.top + "px;left:" + json.left + "px'><div class='GooFlow_item_cont'> <i class='fa ico_" + json.type + "'></i><span class='GooFlow_item_txt' id='type-" + json.type + "'>" + json.name + "</span></div> <div class='rs-box' style='display:none'><div class='rs_close'><i class='fa fa-close' aria-hidden='true'></i></div></div></div>");
|
|
|
|
|
|
}
|
|
|
var ua = navigator.userAgent.toLowerCase();
|
|
|
if (ua.indexOf('msie') != -1 && ua.indexOf('8.0') != -1) {
|
|
|
this.$nodeDom[id].css("filter", "progid:DXImageTransform.Microsoft.Shadow(color=#94AAC2,direction=135,strength=2)");
|
|
|
}
|
|
|
|
|
|
this.$workArea.append(this.$nodeDom[id]);
|
|
|
json.width = this.$nodeDom[id].width();
|
|
|
json.height = this.$nodeDom[id].height();
|
|
@ -1130,252 +1171,240 @@ GooFlow.prototype = {
|
|
|
++this.$nodeCount;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 取消选定状态 【取消聚焦公共方法】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:53
|
|
|
* */
|
|
|
blurItem: function () {
|
|
|
this.$deteLineId = '';
|
|
|
this.$deteNodeId = '';
|
|
|
if (this.$focus != "") {
|
|
|
// 获取被选中对象
|
|
|
var jq = $("#" + this.$focus);
|
|
|
if (jq.prop("tagName") == "DIV") {
|
|
|
if (this.onItemBlur != null && !this.onItemBlur(id, "node")) return false;
|
|
|
jq.removeClass("item_focus").children(".rs-box").css("display", "none");
|
|
|
}
|
|
|
else {
|
|
|
if (this.onItemBlur != null && !this.onItemBlur(id, "line")) return false;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
if (!this.$lineData[this.$focus].marked) {
|
|
|
jq[0].childNodes[1].setAttribute("stroke", "#323232");
|
|
|
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow1)");
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
if (!this.$lineData[this.$focus].marked) jq[0].strokeColor = "#323232";
|
|
|
}
|
|
|
this.$lineMove.hide().removeData("type").removeData("tid");
|
|
|
if (this.$editable) this.$lineOper.hide().removeData("tid");
|
|
|
/*
|
|
|
* Todo: 删除结点 【结点公共方法 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:55
|
|
|
* */
|
|
|
delNode: function (id) {
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$nodeData[id]];
|
|
|
this.pushOper("addNode", paras);
|
|
|
}
|
|
|
if (this.onItemDel != null && !this.onItemDel(id, "node")) return;
|
|
|
delete this.$nodeData[id];
|
|
|
this.$nodeDom[id].remove();
|
|
|
delete this.$nodeDom[id];
|
|
|
if (this.$focus == id) this.$focus = "";
|
|
|
for (var k in this.$lineData) {
|
|
|
if (this.$lineData[k].from == id || this.$lineData[k].to == id) {
|
|
|
this.$draw.removeChild(this.$lineDom[k]);
|
|
|
delete this.$lineData[k];
|
|
|
delete this.$lineDom[k];
|
|
|
}
|
|
|
}
|
|
|
this.$focus = "";
|
|
|
return true;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点或线条选中事件 【聚焦公共方法】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:53
|
|
|
* */
|
|
|
focusItem: function (id, bool) {
|
|
|
/*
|
|
|
* Todo: 结点移动 【结点移动方法 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:54
|
|
|
* */
|
|
|
moveNode: function (id, left, top) {
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
if (this.onItemMove != null && !this.onItemMove(id, "node", left, top)) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$nodeData[id].left, this.$nodeData[id].top];
|
|
|
this.pushOper("moveNode", paras);
|
|
|
}
|
|
|
if (left < 0) left = 0;
|
|
|
if (top < 0) top = 0;
|
|
|
$("#" + id).css({left: left + "px", top: top + "px"});
|
|
|
this.$nodeData[id].left = left;
|
|
|
this.$nodeData[id].top = top;
|
|
|
//重画转换线
|
|
|
this.resetLines(id, this.$nodeData[id]);
|
|
|
},
|
|
|
|
|
|
var jq = $("#" + id);
|
|
|
var that = this;
|
|
|
this.$ghost.attr({'class': 'rs_ghost ' + jq.attr('class')});
|
|
|
if (jq.length == 0) return;
|
|
|
if (!this.blurItem()) return;//先执行"取消选中",如果返回FLASE,则也会阻止选定事件继续进行.
|
|
|
if (jq.prop("tagName") == "DIV") {
|
|
|
if (bool && this.onItemFocus != null && !this.onItemFocus(id, "node")) return;
|
|
|
jq.addClass("item_focus");
|
|
|
if (this.$editable) jq.children(".rs-box").css("display", "block");
|
|
|
this.$workArea.append(jq);
|
|
|
that.$canDelLine = false;
|
|
|
that.$deteLineId = '';
|
|
|
that.$deteNodeId = id;
|
|
|
$(document).keydown(function (e) {
|
|
|
if (e.keyCode != 8 && that.$deteNodeId) {return}
|
|
|
that.delNode(that.$deteNodeId);
|
|
|
});
|
|
|
/*
|
|
|
* Todo: 设置结点线等内容 【内容设置公共方法 @@ $$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:54
|
|
|
* */
|
|
|
setName: function (id, config, type) {
|
|
|
var oldName;
|
|
|
|
|
|
if (type == "node") {//如果是结点
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
this.$nodeData[id].config = config;
|
|
|
}
|
|
|
else if (type == "line") {//如果是线
|
|
|
if (!this.$lineData[id]) return;
|
|
|
if (this.$lineData[id].config == config) return;
|
|
|
oldName = this.$lineData[id].value;
|
|
|
this.$lineData[id].config = config;
|
|
|
this.$lineDom[id].childNodes[2].textContent = config;
|
|
|
}
|
|
|
else {//如果是连接线
|
|
|
if (this.onItemFocus != null && !this.onItemFocus(id, "line")) return;
|
|
|
that.$canDelLine = true;
|
|
|
that.$deteNodeId = '';
|
|
|
that.$deteLineId = id;
|
|
|
|
|
|
$(document).keydown(function (e) {
|
|
|
if (e.keyCode == 8 && that.$deteLineId){
|
|
|
that.delLine(that.$deteLineId);
|
|
|
$('.GooFlow_line_oper').hide();
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
jq[0].childNodes[1].setAttribute("stroke", "#00b7ee");
|
|
|
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
|
|
/*
|
|
|
* Todo: 增加线条 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 16:46
|
|
|
* */
|
|
|
addLine: function (id, json, isDataLoad) {
|
|
|
|
|
|
if (!isDataLoad) {
|
|
|
if (this.$undoStack) {
|
|
|
this.pushOper("delLine", [id]);
|
|
|
}
|
|
|
else jq[0].strokeColor = "#00b7ee";
|
|
|
if (!this.$editable) return;
|
|
|
var x, y, from, to;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
from = jq.attr("from").split(",");
|
|
|
to = jq.attr("to").split(",");
|
|
|
} else {
|
|
|
var n = jq[0].getAttribute("fromTo").split(",");
|
|
|
from = [n[0], n[1]];
|
|
|
to = [n[2], n[3]];
|
|
|
|
|
|
if (json.from == json.to) {
|
|
|
return;
|
|
|
}
|
|
|
from[0] = parseInt(from[0], 10);
|
|
|
from[1] = parseInt(from[1], 10);
|
|
|
to[0] = parseInt(to[0], 10);
|
|
|
to[1] = parseInt(to[1], 10);
|
|
|
|
|
|
if (this.$lineData[id].type == "lr") {
|
|
|
from[0] = this.$lineData[id].M;
|
|
|
to[0] = from[0];
|
|
|
var typeF = json.typeFrom || json.type;
|
|
|
var typeT = json.typeTo || json.type;
|
|
|
|
|
|
for (var k in this.$lineData) {
|
|
|
// 单出
|
|
|
var onlyOut = (json.from == this.$lineData[k].from);
|
|
|
// 单进
|
|
|
var onlyIn = (json.to == this.$lineData[k].to);
|
|
|
// 来源等于去向
|
|
|
var formEto = (json.from == this.$lineData[k].to);
|
|
|
// 去向等于来源
|
|
|
var tofrom = (json.to == this.$lineData[k].from);
|
|
|
|
|
|
// 不能反向
|
|
|
if (tofrom && formEto) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 设置除了聚合其余都默认单进
|
|
|
if (typeT != 'join') {
|
|
|
if (onlyIn) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
switch (typeF) {
|
|
|
case 'task':
|
|
|
case 'plug':
|
|
|
if (onlyOut) {
|
|
|
return;
|
|
|
}
|
|
|
break;
|
|
|
case 'state':
|
|
|
case 'complex':
|
|
|
if (json.from == this.$lineData[k].from) {
|
|
|
var i = 0;
|
|
|
for (var j in this.$lineData) {
|
|
|
if (json.from == this.$lineData[j].from) {
|
|
|
i++
|
|
|
}
|
|
|
}
|
|
|
if (i >= 2) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
this.$lineMove.css({
|
|
|
width: "5px", height: (to[1] - from[1]) * (to[1] > from[1] ? 1 : -1) + "px",
|
|
|
left: from[0] - 3 + "px",
|
|
|
top: (to[1] > from[1] ? from[1] : to[1]) + 1 + "px",
|
|
|
cursor: "e-resize", display: "block"
|
|
|
}).data({"type": "lr", "tid": id});
|
|
|
}
|
|
|
else if (this.$lineData[id].type == "tb") {
|
|
|
from[1] = this.$lineData[id].M;
|
|
|
to[1] = from[1];
|
|
|
this.$lineMove.css({
|
|
|
width: (to[0] - from[0]) * (to[0] > from[0] ? 1 : -1) + "px", height: "5px",
|
|
|
left: (to[0] > from[0] ? from[0] : to[0]) + 1 + "px",
|
|
|
top: from[1] - 3 + "px",
|
|
|
cursor: "s-resize", display: "block"
|
|
|
}).data({"type": "tb", "tid": id});
|
|
|
}
|
|
|
x = (from[0] + to[0]) / 2 - 35;
|
|
|
y = (from[1] + to[1]) / 2 + 6;
|
|
|
this.$lineOper.css({display: "block", left: x + "px", top: y + "px"}).data("tid", id);
|
|
|
}
|
|
|
this.$focus = id;
|
|
|
this.$nowType = "cursor";
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 结点移动 【结点移动方法 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:54
|
|
|
* */
|
|
|
moveNode: function (id, left, top) {
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
if (this.onItemMove != null && !this.onItemMove(id, "node", left, top)) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$nodeData[id].left, this.$nodeData[id].top];
|
|
|
this.pushOper("moveNode", paras);
|
|
|
//获取开始/结束结点的数据
|
|
|
var n1 = this.$nodeData[json.from], n2 = this.$nodeData[json.to];
|
|
|
if (!n1 || !n2) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 划线函数以及线条类型处理
|
|
|
var res;
|
|
|
if (json.type && json.type != "sl") {
|
|
|
res = GooFlow.prototype.calcPolyPoints(n1, n2, json.type, json.M);
|
|
|
}
|
|
|
else {
|
|
|
res = GooFlow.prototype.calcStartEnd(n1, n2);// 刚开始连线时,默认为直线
|
|
|
}
|
|
|
|
|
|
if (!res) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 存储线条
|
|
|
this.$lineData[id] = {};
|
|
|
if (json.type) {
|
|
|
this.$lineData[id].type = json.type;
|
|
|
this.$lineData[id].M = json.M;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineData[id].type = "sl";//默认为直线
|
|
|
}
|
|
|
|
|
|
this.$lineData[id].from = json.from;
|
|
|
this.$lineData[id].to = json.to;
|
|
|
this.$lineData[id].config = json.name;
|
|
|
|
|
|
if (json.mark) {
|
|
|
this.$lineData[id].marked = json.mark;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineData[id].marked = false;
|
|
|
}
|
|
|
if (left < 0) left = 0;
|
|
|
if (top < 0) top = 0;
|
|
|
$("#" + id).css({left: left + "px", top: top + "px"});
|
|
|
this.$nodeData[id].left = left;
|
|
|
this.$nodeData[id].top = top;
|
|
|
//重画转换线
|
|
|
this.resetLines(id, this.$nodeData[id]);
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 设置结点线等内容 【内容设置公共方法 @@ $$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:54
|
|
|
* */
|
|
|
setName: function (id, name, type) {
|
|
|
var oldName;
|
|
|
if (type == "node") {//如果是结点
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
if (this.$nodeData[id].name == name) return;
|
|
|
if (this.onItemRename != null && !this.onItemRename(id, name, "node")) return;
|
|
|
oldName = this.$nodeData[id].name;
|
|
|
this.$nodeData[id].name = name;
|
|
|
if (this.$nodeData[id].type == "start" || this.$nodeData[id].type == "end") {
|
|
|
this.$nodeDom[id].children(".span").text(name);
|
|
|
}
|
|
|
else {
|
|
|
this.$nodeDom[id].find("td:eq(1)").text(name);
|
|
|
var hack = 0;
|
|
|
if (navigator.userAgent.indexOf("8.0") != -1) hack = 2;
|
|
|
var width = this.$nodeDom[id].outerWidth();
|
|
|
var height = this.$nodeDom[id].outerHeight();
|
|
|
this.$nodeDom[id].children("table").css({width: width - 2 + "px", height: height - 2 + "px"});
|
|
|
this.$nodeData[id].width = width;
|
|
|
this.$nodeData[id].height = height;
|
|
|
}
|
|
|
//重画转换线
|
|
|
this.resetLines(id, this.$nodeData[id]);
|
|
|
if (this.$lineData[id].type == "sl") {
|
|
|
this.$lineDom[id] = GooFlow.prototype.drawLine(id, res.start, res.end, json.mark);
|
|
|
}
|
|
|
else if (type == "line") {//如果是线
|
|
|
if (!this.$lineData[id]) return;
|
|
|
if (this.$lineData[id].name == name) return;
|
|
|
if (this.onItemRename != null && !this.onItemRename(id, name, "line")) return;
|
|
|
oldName = this.$lineData[id].name;
|
|
|
this.$lineData[id].name = name;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
this.$lineDom[id].childNodes[2].textContent = name;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineDom[id].childNodes[1].innerHTML = name;
|
|
|
var n = this.$lineDom[id].getAttribute("fromTo").split(",");
|
|
|
var x;
|
|
|
if (this.$lineData[id].type != "lr") {
|
|
|
x = (n[2] - n[0]) / 2;
|
|
|
}
|
|
|
else {
|
|
|
var Min = n[2] > n[0] ? n[0] : n[2];
|
|
|
if (Min > this.$lineData[id].M) Min = this.$lineData[id].M;
|
|
|
x = this.$lineData[id].M - Min;
|
|
|
}
|
|
|
if (x < 0) x = x * -1;
|
|
|
this.$lineDom[id].childNodes[1].style.left = x - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4 + "px";
|
|
|
}
|
|
|
else {
|
|
|
this.$lineDom[id] = GooFlow.prototype.drawPoly(id, res.start, res.m1, res.m2, res.end, json.mark);
|
|
|
}
|
|
|
else if (type == "area") {//如果是分组区域
|
|
|
if (!this.$areaData[id]) return;
|
|
|
if (this.$areaData[id].name == name) return;
|
|
|
if (this.onItemRename != null && !this.onItemRename(id, name, "area")) return;
|
|
|
oldName = this.$areaData[id].name;
|
|
|
this.$areaData[id].name = name;
|
|
|
this.$areaDom[id].children("label").text(name);
|
|
|
|
|
|
this.$draw.appendChild(this.$lineDom[id]);
|
|
|
|
|
|
if (GooFlow.prototype.useSVG == "") {
|
|
|
this.$lineDom[id].childNodes[1].innerHTML = json.name;
|
|
|
if (this.$lineData[id].type != "sl") {
|
|
|
var Min = (res.start[0] > res.end[0] ? res.end[0] : res.start[0]);
|
|
|
if (Min > res.m2[0]) Min = res.m2[0];
|
|
|
if (Min > res.m1[0]) Min = res.m1[0];
|
|
|
this.$lineDom[i].childNodes[1].style.left = (res.m2[0] + res.m1[0]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4;
|
|
|
Min = (res.start[1] > res.end[1] ? res.end[1] : res.start[1]);
|
|
|
if (Min > res.m2[1]) Min = res.m2[1];
|
|
|
if (Min > res.m1[1]) Min = res.m1[1];
|
|
|
this.$lineDom[id].childNodes[1].style.top = (res.m2[1] + res.m1[1]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetHeight / 2;
|
|
|
} else
|
|
|
this.$lineDom[id].childNodes[1].style.left =
|
|
|
((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[id].childNodes[1].offsetWidth) / 2 + 4;
|
|
|
}
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, oldName, type];
|
|
|
this.pushOper("setName", paras);
|
|
|
else {
|
|
|
this.$lineDom[id].childNodes[2].textContent = json.name;
|
|
|
}
|
|
|
|
|
|
++this.$lineCount;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 删除结点 【结点公共方法 @@】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:55
|
|
|
* */
|
|
|
delNode: function (id) {
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
/*
|
|
|
* Todo: 线条删除 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:57
|
|
|
* */
|
|
|
delLine: function (id) {
|
|
|
if (!this.$lineData[id]) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$nodeData[id]];
|
|
|
this.pushOper("addNode", paras);
|
|
|
var paras = [id, this.$lineData[id]];
|
|
|
this.pushOper("addLine", paras);
|
|
|
}
|
|
|
if (this.onItemDel != null && !this.onItemDel(id, "node")) return;
|
|
|
delete this.$nodeData[id];
|
|
|
this.$nodeDom[id].remove();
|
|
|
delete this.$nodeDom[id];
|
|
|
this.$draw.removeChild(this.$lineDom[id]);
|
|
|
delete this.$lineData[id];
|
|
|
delete this.$lineDom[id];
|
|
|
if (this.$focus == id) this.$focus = "";
|
|
|
for (var k in this.$lineData) {
|
|
|
if (this.$lineData[k].from == id || this.$lineData[k].to == id) {
|
|
|
this.$draw.removeChild(this.$lineDom[k]);
|
|
|
delete this.$lineData[k];
|
|
|
delete this.$lineDom[k];
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 直线绘制 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 14:57
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 直线生成 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 14:57
|
|
|
* */
|
|
|
drawLine: function (id, sp, ep, mark, dash) {
|
|
|
var line;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
@ -1448,12 +1477,12 @@ GooFlow.prototype = {
|
|
|
return line;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 折线绘制 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:26
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 折线生成 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:26
|
|
|
* */
|
|
|
drawPoly: function (id, sp, m1, m2, ep, mark) {
|
|
|
var poly, strPath;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
@ -1530,12 +1559,12 @@ GooFlow.prototype = {
|
|
|
return poly;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 直线坐标计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:26
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 直线坐标计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:26
|
|
|
* */
|
|
|
calcStartEnd: function (n1, n2) {
|
|
|
if (!n1 || !n2) {
|
|
|
return {"start": [], "end": []};
|
|
@ -1584,12 +1613,12 @@ GooFlow.prototype = {
|
|
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 折线坐标计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:27
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 折线坐标计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:27
|
|
|
* */
|
|
|
calcPolyPoints: function (n1, n2, type, M) {
|
|
|
|
|
|
//开始/结束两个结点的中心
|
|
@ -1651,12 +1680,12 @@ GooFlow.prototype = {
|
|
|
return {start: sp, m1: m1, m2: m2, end: ep};
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 折线固定中线计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:27
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 折线固定中线计算 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:27
|
|
|
* */
|
|
|
getMValue: function (n1, n2, mType) {
|
|
|
if (mType == "lr") {
|
|
|
return (n1.left + n1.width / 2 + n2.left + n2.width / 2) / 2;
|
|
@ -1666,154 +1695,12 @@ GooFlow.prototype = {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 增加线条 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 16:46
|
|
|
* */
|
|
|
addLine: function (id, json,isDataLoad) {
|
|
|
|
|
|
if (!isDataLoad) {
|
|
|
if (this.onItemAdd != null && !this.onItemAdd(id, "line", json)) {
|
|
|
return;
|
|
|
}
|
|
|
if (this.$undoStack) {
|
|
|
this.pushOper("delLine", [id]);
|
|
|
}
|
|
|
|
|
|
if (json.from == json.to) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var typeF = json.typeFrom || json.type;
|
|
|
var typeT = json.typeTo || json.type;
|
|
|
|
|
|
for (var k in this.$lineData) {
|
|
|
// 单出
|
|
|
var onlyOut = (json.from == this.$lineData[k].from);
|
|
|
// 单进
|
|
|
var onlyIn = (json.to == this.$lineData[k].to);
|
|
|
// 来源等于去向
|
|
|
var formEto = (json.from == this.$lineData[k].to);
|
|
|
// 去向等于来源
|
|
|
var tofrom = (json.to == this.$lineData[k].from);
|
|
|
|
|
|
// 不能反向
|
|
|
if (tofrom && formEto) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 设置除了聚合其余都默认单进
|
|
|
if (typeT != 'join') {
|
|
|
if (onlyIn) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
switch (typeF) {
|
|
|
case 'task':
|
|
|
case 'plug':
|
|
|
if (onlyOut) {
|
|
|
return;
|
|
|
}
|
|
|
break;
|
|
|
case 'state':
|
|
|
case 'complex':
|
|
|
if (json.from == this.$lineData[k].from) {
|
|
|
var i = 0;
|
|
|
for (var j in this.$lineData) {
|
|
|
if (json.from == this.$lineData[j].from) {
|
|
|
i++
|
|
|
}
|
|
|
}
|
|
|
if (i >= 2) {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//获取开始/结束结点的数据
|
|
|
var n1 = this.$nodeData[json.from], n2 = this.$nodeData[json.to];
|
|
|
if (!n1 || !n2) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 划线函数以及线条类型处理
|
|
|
var res;
|
|
|
if (json.type && json.type != "sl") {
|
|
|
res = GooFlow.prototype.calcPolyPoints(n1, n2, json.type,json.M);
|
|
|
}
|
|
|
else {
|
|
|
res = GooFlow.prototype.calcStartEnd(n1, n2);// 刚开始连线时,默认为直线
|
|
|
}
|
|
|
|
|
|
if (!res) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 存储线条
|
|
|
this.$lineData[id] = {};
|
|
|
if (json.type) {
|
|
|
this.$lineData[id].type = json.type;
|
|
|
this.$lineData[id].M = json.M;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineData[id].type = "sl";//默认为直线
|
|
|
}
|
|
|
|
|
|
this.$lineData[id].from = json.from;
|
|
|
this.$lineData[id].to = json.to;
|
|
|
this.$lineData[id].name = json.name;
|
|
|
|
|
|
if (json.mark) {
|
|
|
this.$lineData[id].marked = json.mark;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineData[id].marked = false;
|
|
|
}
|
|
|
|
|
|
if (this.$lineData[id].type == "sl") {
|
|
|
this.$lineDom[id] = GooFlow.prototype.drawLine(id, res.start, res.end, json.mark);
|
|
|
}
|
|
|
else {
|
|
|
this.$lineDom[id] = GooFlow.prototype.drawPoly(id, res.start, res.m1, res.m2, res.end, json.mark);
|
|
|
}
|
|
|
|
|
|
this.$draw.appendChild(this.$lineDom[id]);
|
|
|
|
|
|
if (GooFlow.prototype.useSVG == "") {
|
|
|
this.$lineDom[id].childNodes[1].innerHTML = json.name;
|
|
|
if (this.$lineData[id].type != "sl") {
|
|
|
var Min = (res.start[0] > res.end[0] ? res.end[0] : res.start[0]);
|
|
|
if (Min > res.m2[0]) Min = res.m2[0];
|
|
|
if (Min > res.m1[0]) Min = res.m1[0];
|
|
|
this.$lineDom[i].childNodes[1].style.left = (res.m2[0] + res.m1[0]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4;
|
|
|
Min = (res.start[1] > res.end[1] ? res.end[1] : res.start[1]);
|
|
|
if (Min > res.m2[1]) Min = res.m2[1];
|
|
|
if (Min > res.m1[1]) Min = res.m1[1];
|
|
|
this.$lineDom[id].childNodes[1].style.top = (res.m2[1] + res.m1[1]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetHeight / 2;
|
|
|
} else
|
|
|
this.$lineDom[id].childNodes[1].style.left =
|
|
|
((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[id].childNodes[1].offsetWidth) / 2 + 4;
|
|
|
}
|
|
|
else {
|
|
|
this.$lineDom[id].childNodes[2].textContent = json.name;
|
|
|
}
|
|
|
|
|
|
++this.$lineCount;
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 重置线条 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:56
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 重置线条 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:56
|
|
|
* */
|
|
|
resetLines: function (id, node) {
|
|
|
for (var i in this.$lineData) {
|
|
|
var other = null;//获取结束/开始结点的数据
|
|
@ -1864,15 +1751,14 @@ GooFlow.prototype = {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 重置线条类型 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:56
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 重置线条类型 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:56
|
|
|
* */
|
|
|
setLineType: function (id, newType) {
|
|
|
if (!newType || newType == null || newType == "" || newType == this.$lineData[id].type) return false;
|
|
|
if (this.onLineSetType != null && !this.onLineSetType(id, newType)) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$lineData[id].type];
|
|
|
this.pushOper("setLineType", paras);
|
|
@ -1912,15 +1798,14 @@ GooFlow.prototype = {
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 重置折线中点 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:57
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 重置折线中点 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:57
|
|
|
* */
|
|
|
setLineM: function (id, M, noStack) {
|
|
|
if (!this.$lineData[id] || M < 0 || !this.$lineData[id].type || this.$lineData[id].type == "sl") return false;
|
|
|
if (this.onLineMove != null && !this.onLineMove(id, M)) return false;
|
|
|
if (this.$undoStack && !noStack) {
|
|
|
var paras = [id, this.$lineData[id].M];
|
|
|
this.pushOper("setLineM", paras);
|
|
@ -1947,282 +1832,228 @@ GooFlow.prototype = {
|
|
|
},
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 线条删除 【$$】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:57
|
|
|
* */
|
|
|
delLine: function (id) {
|
|
|
if (!this.$lineData[id]) return;
|
|
|
if (this.onItemDel != null && !this.onItemDel(id, "line")) return;
|
|
|
if (this.$undoStack) {
|
|
|
var paras = [id, this.$lineData[id]];
|
|
|
this.pushOper("addLine", paras);
|
|
|
}
|
|
|
this.$draw.removeChild(this.$lineDom[id]);
|
|
|
delete this.$lineData[id];
|
|
|
delete this.$lineDom[id];
|
|
|
if (this.$focus == id) this.$focus = "";
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 初始化数据加载 【AJAX相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:02
|
|
|
* */
|
|
|
loadData: function (data) {
|
|
|
for (var i in data.nodes) {
|
|
|
this.addNode(i, data.nodes[i]);
|
|
|
}
|
|
|
for (var j in data.lines) {
|
|
|
this.addLine(j, data.lines[j],true);
|
|
|
}
|
|
|
/*
|
|
|
* Todo: 初始化数据加载 【AJAX相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:02
|
|
|
* */
|
|
|
loadData: function (url) {
|
|
|
var that = this;
|
|
|
$.ajax({
|
|
|
url: url,
|
|
|
type: 'GET',
|
|
|
async: true,
|
|
|
dataType: 'json',
|
|
|
success: function (data) {
|
|
|
var data = $.parseJSON(data.message);
|
|
|
that.fileMsg(data.code,data.name);
|
|
|
for (var i in data.result.nodes) {
|
|
|
that.addNode(i, data.result.nodes[i]);
|
|
|
}
|
|
|
for (var j in data.result.lines) {
|
|
|
that.addLine(j, data.result.lines[j], true);
|
|
|
}
|
|
|
},
|
|
|
error: function (data, xhr, textStatus) {
|
|
|
console.log('错误')
|
|
|
console.log(xhr)
|
|
|
console.log(textStatus)
|
|
|
},
|
|
|
})
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: AJAX数据加载 【AJAX相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:02
|
|
|
* */
|
|
|
loadDataAjax: function (para) {
|
|
|
var This = this;
|
|
|
$.ajax({
|
|
|
type: para.type,
|
|
|
url: para.url,
|
|
|
dataType: "json",
|
|
|
data: para.data,
|
|
|
success: function (msg) {
|
|
|
if (para.dataFilter) para.dataFilter(msg, "json");
|
|
|
This.loadData(msg);
|
|
|
if (para.success) para.success(msg);
|
|
|
},
|
|
|
error: function (XMLHttpRequest, textStatus, errorThrown) {
|
|
|
if (para.error) para.error(textStatus, errorThrown);
|
|
|
}
|
|
|
})
|
|
|
fileMsg:function (code,name) {
|
|
|
$('#fileCode').val(code);
|
|
|
$('#fileName').val(name);
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 导出数据 【AJAX相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:58
|
|
|
* */
|
|
|
/*
|
|
|
* Todo: 导出数据 【AJAX相关】
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:58
|
|
|
* */
|
|
|
exportData: function () {
|
|
|
var that = this;
|
|
|
var data = {
|
|
|
nodes:{},
|
|
|
lines:{}
|
|
|
}
|
|
|
this.$fileCode = $('#fileCode').val();
|
|
|
this.$fileName = $('#fileName').val();
|
|
|
var data = {
|
|
|
nodes: {},
|
|
|
lines: {}
|
|
|
}
|
|
|
var nodes = data.nodes;
|
|
|
var lines = data.lines;
|
|
|
|
|
|
var nodes = data.nodes;
|
|
|
var lines = data.lines;
|
|
|
function keyJson(obj, target, args) {
|
|
|
for (var k in obj) {
|
|
|
var jsonstr = JSON.stringify(obj[k], args);
|
|
|
$.parseJSON(jsonstr);
|
|
|
target[k] = $.parseJSON(jsonstr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function keyJson(obj,target,args) {
|
|
|
for (var k in obj) {
|
|
|
var jsonstr = JSON.stringify(obj[k],args);
|
|
|
$.parseJSON(jsonstr);
|
|
|
target[k] = $.parseJSON(jsonstr)
|
|
|
}
|
|
|
}
|
|
|
keyJson(this.$nodeData, nodes, ['name', 'value', 'nodeType', 'config']);
|
|
|
keyJson(this.$lineData, lines, ['from', 'to', 'config']);
|
|
|
|
|
|
keyJson(this.$nodeData,nodes,['name','value','nodeType']);
|
|
|
keyJson(this.$lineData,lines,['from','to','name']);
|
|
|
console.log(this.$lineData);
|
|
|
|
|
|
var positionData = {
|
|
|
nodes: this.$nodeData,
|
|
|
lines: this.$lineData
|
|
|
}
|
|
|
|
|
|
var nodeArr = [];
|
|
|
var specialArr = [];
|
|
|
for (var i in nodes) {
|
|
|
nodeArr.push(i);
|
|
|
if (nodes[i].nodeType === 'judgement' || nodes[i].nodeType === 'circle'){
|
|
|
specialArr.push(i)
|
|
|
}
|
|
|
postData = {
|
|
|
code: this.$fileCode,
|
|
|
name: this.$fileName,
|
|
|
positionJson: JSON.stringify(positionData),
|
|
|
flowJson: JSON.stringify(data)
|
|
|
}
|
|
|
|
|
|
console.log(postData);
|
|
|
|
|
|
var fromArr = [];
|
|
|
var toArr = [];
|
|
|
for (var j in lines) {
|
|
|
fromArr.push(lines[j].from);
|
|
|
toArr.push(lines[j].to);
|
|
|
}
|
|
|
var nodeArr = [];
|
|
|
var specialArr = [];
|
|
|
var fromArr = [];
|
|
|
var toArr = [];
|
|
|
var noError = true;
|
|
|
|
|
|
|
|
|
// 如果存在没有连线的结点则报错
|
|
|
var noError = true;
|
|
|
nodeArr.forEach(function (elem) {
|
|
|
var nodeWithoutLines = (fromArr.indexOf(elem) === -1) && (toArr.indexOf(elem)===-1)
|
|
|
if (nodeWithoutLines) {
|
|
|
noError = false;
|
|
|
$('#'+elem).addClass('node-error');
|
|
|
}else{
|
|
|
$('#'+elem).removeClass('node-error');
|
|
|
}
|
|
|
});
|
|
|
// 存储所有结点名,并将判断和循环结点单独存储
|
|
|
for (var i in nodes) {
|
|
|
nodeArr.push(i);
|
|
|
if (nodes[i].nodeType === 'judgement') {
|
|
|
specialArr.push(i)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 判断和循环必须有两条线
|
|
|
specialArr.forEach(function (elem) {
|
|
|
var i = 0;
|
|
|
fromArr.forEach(function(el){
|
|
|
if (elem === el){
|
|
|
i++
|
|
|
}
|
|
|
})
|
|
|
if (i<2) {
|
|
|
noError = false;
|
|
|
$('#'+elem).addClass('node-error');
|
|
|
}else{
|
|
|
$('#'+elem).removeClass('node-error');
|
|
|
for (var e in lines) {
|
|
|
console.log('lines[e].name:'+lines[e].name);
|
|
|
if (lines[e].from === elem){
|
|
|
if (lines[e].name == '') {
|
|
|
noError = false;
|
|
|
$('#' + e + ' path').addClass('line-error').attr("marker-end", "url(#arrow3)");
|
|
|
$('#'+elem).addClass('node-error');
|
|
|
}else{
|
|
|
$('#' + e + ' path').removeClass('line-error').attr("marker-end", "url(#arrow1)");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
// 存储所有的线条的开始结点和结束结点
|
|
|
|
|
|
if (noError){
|
|
|
saveConfirm();
|
|
|
for (var j in lines) {
|
|
|
fromArr.push(lines[j].from);
|
|
|
toArr.push(lines[j].to);
|
|
|
}
|
|
|
|
|
|
// 如果存在没有连线的结点则报错
|
|
|
nodeArr.forEach(function (elem) {
|
|
|
var nodeWithoutLines = (fromArr.indexOf(elem) === -1) && (toArr.indexOf(elem) === -1) || (nodes[elem].config === '')
|
|
|
if (nodeWithoutLines) {
|
|
|
noError = false;
|
|
|
$('#' + elem).addClass('node-error');
|
|
|
} else {
|
|
|
$('#' + elem).removeClass('node-error');
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 判断和循环必须有两条线
|
|
|
// 每个节点都必须有配置项
|
|
|
specialArr.forEach(function (elem) {
|
|
|
var i = 0;
|
|
|
fromArr.forEach(function (el) {
|
|
|
if (elem === el) {
|
|
|
i++
|
|
|
}
|
|
|
})
|
|
|
if (i < 2) {
|
|
|
noError = false;
|
|
|
$('#' + elem).addClass('special-error');
|
|
|
} else {
|
|
|
$('#' + elem).removeClass('special-error');
|
|
|
for (var e in lines) {
|
|
|
if (lines[e].from === elem) {
|
|
|
console.log(lines[e]);
|
|
|
if (lines[e].config === '') {
|
|
|
noError = false;
|
|
|
$('#' + e + ' path').attr({"marker-end":"url(#arrow3)","stroke":"#f00"});
|
|
|
$('#' + elem).addClass('special-error');
|
|
|
} else {
|
|
|
$('#' + e + ' path').attr({"marker-end":"url(#arrow1)","stroke":"#323232"});
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
|
|
|
// 标题code和name不能为空
|
|
|
if (this.$fileCode === '' || this.$fileName === ''){
|
|
|
noError = false;
|
|
|
$('.file-box').addClass('node-error');
|
|
|
}else{
|
|
|
$.ligerDialog.alert('<p style="padding: 10px;">您还有未编排完成的对象,无法保存。</p>')
|
|
|
}
|
|
|
|
|
|
function saveConfirm () {
|
|
|
var callback = function () {
|
|
|
|
|
|
}
|
|
|
|
|
|
$.ligerDialog.confirm2 = function (content, title, callback)
|
|
|
{
|
|
|
if (typeof (title) == "function")
|
|
|
{
|
|
|
callback = title;
|
|
|
type = null;
|
|
|
}
|
|
|
var btnclick = function (item, Dialog)
|
|
|
{
|
|
|
Dialog.close();
|
|
|
if (callback)
|
|
|
{
|
|
|
callback(item.type == 'ok');
|
|
|
}
|
|
|
};
|
|
|
p = {
|
|
|
type: 'question',
|
|
|
content: content,
|
|
|
buttons: [
|
|
|
{
|
|
|
text: $.ligerDefaults.DialogString.yes, onclick: btnclick, type: 'ok', cls: 'l-dialog-btn-ok'
|
|
|
}, {
|
|
|
text: $.ligerDefaults.DialogString.no, onclick: btnclick, type: 'no', cls: 'l-dialog-btn-no'
|
|
|
}
|
|
|
]
|
|
|
};
|
|
|
if (typeof (title) == "string" && title != "") p.title = title;
|
|
|
$.extend(p, {
|
|
|
width:350,
|
|
|
showMax: false,
|
|
|
showToggle: false,
|
|
|
showMin: false
|
|
|
});
|
|
|
return $.ligerDialog(p);
|
|
|
};
|
|
|
|
|
|
$.ligerDialog.confirm2('<p style="font-size: 15px;font-weight: bold;text-align: center;line-height: 20px">是否确认保存为正式流程,确认后流程将立即生效?</p><p style="margin-top: 10px;color: #999;text-align: center;line-height: 20px;">如果是请按确认,如果不是请按取消</p>', '保存流程', callback)
|
|
|
|
|
|
$('.l-dialog-content').css({ "padding": "0 40px 20px 40px"});
|
|
|
$('.file-box').removeClass('node-error');
|
|
|
}
|
|
|
|
|
|
console.log(data);
|
|
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 清空数据
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 10:28
|
|
|
* */
|
|
|
clearData: function () {
|
|
|
for (var key in this.$nodeData) {
|
|
|
this.delNode(key);
|
|
|
}
|
|
|
for (var key in this.$lineData) {
|
|
|
this.delLine(key);
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/*
|
|
|
* Todo: 工具函数
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/15
|
|
|
* time: 15:02
|
|
|
* */
|
|
|
destrory: function () {
|
|
|
this.$bgDiv.empty();
|
|
|
this.$lineData = null;
|
|
|
this.$nodeData = null;
|
|
|
this.$lineDom = null;
|
|
|
this.$nodeDom = null;
|
|
|
this.$areaDom = null;
|
|
|
this.$areaData = null;
|
|
|
this.$nodeCount = 0;
|
|
|
},
|
|
|
|
|
|
//获取结点/连线/分组区域的详细信息
|
|
|
getItemInfo: function (id, type) {
|
|
|
switch (type) {
|
|
|
case "node":
|
|
|
return this.$nodeData[id] || null;
|
|
|
case "line":
|
|
|
return this.$lineData[id] || null;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
//用颜色标注/取消标注一个结点或转换线, 常用于显示重点或流程的进度。
|
|
|
//这是一个在编辑模式中无用,但是在纯浏览模式中非常有用的方法, 实际运用中可用于跟踪流程的进度。
|
|
|
markItem: function (id, type, mark) {
|
|
|
if (type == "node") {
|
|
|
if (!this.$nodeData[id]) return;
|
|
|
if (this.onItemMark != null && !this.onItemMark(id, "node", mark)) return;
|
|
|
this.$nodeData[id].marked = mark || false;
|
|
|
if (mark) this.$nodeDom[id].addClass("item_mark");
|
|
|
else this.$nodeDom[id].removeClass("item_mark");
|
|
|
// 如果没有错误则弹出保存菜单
|
|
|
if (noError) {
|
|
|
saveConfirm();
|
|
|
} else {
|
|
|
$.ligerDialog.alert('<p style="padding: 10px;">您还有未编排完成的对象,无法保存。</p>')
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Todo: 保存发送请求
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/22
|
|
|
* time: 18:59
|
|
|
* */
|
|
|
function saveConfirm() {
|
|
|
var callback = function (yes) {
|
|
|
if (yes) {
|
|
|
$.ajax({
|
|
|
type: "POST",
|
|
|
url: dataPostURL,
|
|
|
data: postData,
|
|
|
success: function () {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$.ligerDialog.confirm2 = function (content, title, callback) {
|
|
|
if (typeof (title) == "function") {
|
|
|
callback = title;
|
|
|
type = null;
|
|
|
}
|
|
|
var btnclick = function (item, Dialog) {
|
|
|
Dialog.close();
|
|
|
if (callback) {
|
|
|
callback(item.type == 'ok');
|
|
|
}
|
|
|
};
|
|
|
p = {
|
|
|
type: 'question',
|
|
|
content: content,
|
|
|
buttons: [
|
|
|
{
|
|
|
text: $.ligerDefaults.DialogString.yes,
|
|
|
onclick: btnclick,
|
|
|
type: 'ok',
|
|
|
cls: 'l-dialog-btn-ok'
|
|
|
}, {
|
|
|
text: $.ligerDefaults.DialogString.no,
|
|
|
onclick: btnclick,
|
|
|
type: 'no',
|
|
|
cls: 'l-dialog-btn-no'
|
|
|
}
|
|
|
]
|
|
|
};
|
|
|
if (typeof (title) == "string" && title != "") p.title = title;
|
|
|
$.extend(p, {
|
|
|
width: 350,
|
|
|
showMax: false,
|
|
|
showToggle: false,
|
|
|
showMin: false
|
|
|
});
|
|
|
return $.ligerDialog(p);
|
|
|
};
|
|
|
|
|
|
$.ligerDialog.confirm2('<p style="font-size: 15px;font-weight: bold;text-align: center;line-height: 20px">是否确认保存为正式流程,确认后流程将立即生效?</p><p style="margin-top: 10px;color: #999;text-align: center;line-height: 20px;">如果是请按确认,如果不是请按取消</p>', '保存流程', callback)
|
|
|
|
|
|
$('.l-dialog-content').css({"padding": "0 40px 20px 40px"});
|
|
|
}
|
|
|
|
|
|
} else if (type == "line") {
|
|
|
if (!this.$lineData[id]) return;
|
|
|
if (this.onItemMark != null && !this.onItemMark(id, "line", mark)) return;
|
|
|
this.$lineData[id].marked = mark || false;
|
|
|
if (GooFlow.prototype.useSVG != "") {
|
|
|
if (mark) {
|
|
|
this.$nodeDom[id].childNodes[1].setAttribute("stroke", "#00b7ee");
|
|
|
this.$nodeDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
|
|
} else {
|
|
|
this.$nodeDom[id].childNodes[1].setAttribute("stroke", "#323232");
|
|
|
this.$nodeDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow1)");
|
|
|
}
|
|
|
} else {
|
|
|
if (mark) this.$nodeDom[id].strokeColor = "#00b7ee";
|
|
|
else this.$nodeDom[id].strokeColor = "#323232"
|
|
|
}
|
|
|
}
|
|
|
if (this.$undoStatck) {
|
|
|
var paras = [id, type, !mark];
|
|
|
this.pushOper("markItem", paras);
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
|
|
|
}
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
* Todo: ## 注册JQ插件 ****************************************************************************
|
|
@ -2231,84 +2062,33 @@ GooFlow.prototype = {
|
|
|
* time: 14:59
|
|
|
* */
|
|
|
$.fn.extend({
|
|
|
createGooFlow: function (property) {
|
|
|
|
|
|
/*
|
|
|
* Todo: 初始化配置参数
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:59
|
|
|
* */
|
|
|
|
|
|
var defaultOption = {
|
|
|
// ******************************************************* UI相关
|
|
|
id: '',
|
|
|
MainContener: $('body')[0],
|
|
|
width: 1400,
|
|
|
height: 600,
|
|
|
workWidth: null,
|
|
|
workHeight: null,
|
|
|
initNum: 1,
|
|
|
|
|
|
// ******************************************************* 工具栏
|
|
|
haveTool: true,
|
|
|
toolBtns: ["save", "undo", "redo"],
|
|
|
toolBtnRemarks: ['保存', '撤销', '重做'],
|
|
|
|
|
|
// ******************************************************* 流程图工具
|
|
|
flowChart: true,
|
|
|
flowBtns: ["state", "complex", "join", "fork"],
|
|
|
useOperStack: true, // 是否启用回滚栈, 如否, 头部工具栏的回滚和重做按钮都将失效
|
|
|
editable: true, // 是否可编辑
|
|
|
|
|
|
// 工具栏回调函数:
|
|
|
onBtnNewClick: null, // 新建流程图按钮被点中
|
|
|
onBtnOpenClick: null, // 打开流程图按钮定义
|
|
|
onBtnSaveClick: null, // 保存流程图按钮定义
|
|
|
onFreshClick: null, // 重载流程图按钮定义
|
|
|
onExpandClick: null, // 扩大画布按钮定义
|
|
|
|
|
|
//当操作某个单元(结点/线/分组块)被添加时, 触发的方法, 返回FALSE可阻止添加事件的发生
|
|
|
//格式function(id, type, json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json.
|
|
|
onItemAdd: null,
|
|
|
|
|
|
//当操作某个单元(结点/线/分组块)被删除时, 触发的方法, 返回FALSE可阻止删除事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值
|
|
|
onItemDel: null,
|
|
|
|
|
|
//当操作某个单元(结点/分组块)被移动时, 触发的方法, 返回FALSE可阻止移动事件的发生
|
|
|
//格式function(id, type, left, top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值, 线line不支持移动,left是新的左边距坐标, top是新的顶边距坐标
|
|
|
onItemMove: null,
|
|
|
|
|
|
//当操作某个单元(结点/线/分组块)被重命名时, 触发的方法, 返回FALSE可阻止重命名事件的发生
|
|
|
//格式function(id, name, type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称
|
|
|
onItemRename: null,
|
|
|
|
|
|
//当操作某个单元(结点/线)被由不选中变成选中时, 触发的方法, 返回FALSE可阻止选中事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中
|
|
|
onItemFocus: null,
|
|
|
|
|
|
//当操作某个单元(结点/线)被由选中变成不选中时, 触发的方法, 返回FALSE可阻止取消选中事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中
|
|
|
onItemBlur: null,
|
|
|
|
|
|
//当操作某个单元(结点/分组块)被重定义大小或造型时, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type, width, height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,width是新的宽度,height是新的高度
|
|
|
onItemResize: null,
|
|
|
|
|
|
//当移动某条折线中段的位置, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标
|
|
|
onLineMove: null,
|
|
|
|
|
|
//当变换某条连接线的类型, 触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线
|
|
|
onLineSetType: null,
|
|
|
//当用重色标注某个结点/转换线时触发的方法, 返回FALSE可阻止重定大小/造型事件的发生
|
|
|
//格式function(id, type, mark):id是单元的唯一标识ID,type是单元类型("node"结点,"line"转换线), mark为布尔值,表示是要标注TRUE还是取消标注FALSE
|
|
|
|
|
|
onItemMark: null,
|
|
|
};
|
|
|
var options = $.extend({}, defaultOption, property);
|
|
|
return new GooFlow(this, options);
|
|
|
}
|
|
|
createGooFlow: function (property,url) {
|
|
|
/*
|
|
|
* Todo: 初始化配置参数
|
|
|
* Author: LE
|
|
|
* Date: 2017/2/20
|
|
|
* time: 9:59
|
|
|
* */
|
|
|
var defaultOption = {
|
|
|
// ******************************************************* UI相关
|
|
|
id: '',
|
|
|
MainContener: $('body')[0],
|
|
|
width: '100%',
|
|
|
height: '100%',
|
|
|
|
|
|
// ******************************************************* 工具栏
|
|
|
haveTool: true,
|
|
|
toolBtns: ["save", "undo", "redo"],
|
|
|
toolBtnRemarks: ['保存', '撤销', '重做'],
|
|
|
|
|
|
// ******************************************************* 流程图工具
|
|
|
flowChart: true,
|
|
|
flowBtns: ["state", "complex", "join", "fork"],
|
|
|
useOperStack: true, // 是否启用回滚栈, 如否, 头部工具栏的回滚和重做按钮都将失效
|
|
|
editable: true, // 是否可编辑
|
|
|
|
|
|
};
|
|
|
var options = $.extend({}, defaultOption, property);
|
|
|
return new GooFlow(this, options,url);
|
|
|
}
|
|
|
});
|