mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-05-16 21:19:37 +08:00
1909 lines
93 KiB
JavaScript
1909 lines
93 KiB
JavaScript
//定义一个区域图类:
|
||
function GooFlow(bgDiv, property) {
|
||
if (navigator.userAgent.indexOf("MSIE 8.0") > 0 || navigator.userAgent.indexOf("MSIE 7.0") > 0 || navigator.userAgent.indexOf("MSIE 6.0") > 0)
|
||
GooFlow.prototype.useSVG = "";
|
||
else GooFlow.prototype.useSVG = "1";
|
||
//初始化区域图的对象
|
||
this.$id = bgDiv.attr("id");
|
||
this.$bgDiv = bgDiv;//最父框架的DIV
|
||
this.$bgDiv.addClass("GooFlow");
|
||
var width = (property.width || 800) - 2;
|
||
var height = (property.height || 500) - 2;
|
||
this.$bgDiv.css({ width: width + "px", height: height + "px" });
|
||
this.$tool = null;//左侧工具栏对象
|
||
this.$head = null;//顶部标签及工具栏按钮
|
||
this.$title = "newFlow_1";//流程图的名称
|
||
this.$nodeRemark = {};//每一种结点或按钮的说明文字,JSON格式,key为类名,value为用户自定义文字说明
|
||
this.$nowType = "cursor";//当前要绘制的对象类型
|
||
this.$lineData = {};
|
||
this.$lineCount = 0;
|
||
this.$nodeData = {};
|
||
this.$nodeCount = 0;
|
||
this.$areaData = {};
|
||
this.$areaCount = 0;
|
||
this.$lineDom = {};
|
||
this.$nodeDom = {};
|
||
this.$areaDom = {};
|
||
this.$max = property.initNum || 1;//计算默认ID值的起始SEQUENCE
|
||
this.$focus = "";//当前被选定的结点/转换线ID,如果没选中或者工作区被清空,则为""
|
||
this.$cursor = "default";//鼠标指针在工作区内的样式
|
||
this.$editable = false;//工作区是否可编辑
|
||
this.$deletedItem = {};//在流程图的编辑操作中被删除掉的元素ID集合,元素ID为KEY,元素类型(node,line.area)为VALUE
|
||
var headHeight = 0;
|
||
var tmp = "";
|
||
if (property.haveHead) {
|
||
tmp = "<div class='GooFlow_head'><label title='" + (property.initLabelText || "newFlow_1") + "'>" + (property.initLabelText || "newFlow_1") + "</label>";
|
||
for (var x = 0; x < property.headBtns.length; ++x) {
|
||
tmp += "<a class='GooFlow_head_btn'><b class='ico_" + property.headBtns[x] + "'></b></a>"
|
||
}
|
||
tmp += "</div>";
|
||
this.$head = $(tmp);
|
||
this.$bgDiv.append(this.$head);
|
||
headHeight = 24;
|
||
//以下是当工具栏按钮被点击时触发的事件自定义(虚函数),格式为function(),因为可直接用THIS操作对象本身,不用传参;用户可自行重定义:
|
||
this.onBtnNewClick = null;//新建流程图按钮被点中
|
||
this.onBtnOpenClick = null;//打开流程图按钮定义
|
||
this.onBtnSaveClick = null;//保存流程图按钮定义
|
||
this.onFreshClick = null;//重载流程图按钮定义
|
||
if (property.headBtns)
|
||
this.$head.on("click", { inthis: this }, function (e) {
|
||
if (!e) e = window.event;
|
||
var tar = e.target;
|
||
if (tar.tagName == "DIV" || tar.tagName == "SPAN") return;
|
||
else if (tar.tagName == "a") tar = tar.childNode[0];
|
||
var This = e.data.inthis;
|
||
//定义顶部操作栏按钮的事件
|
||
switch ($(tar).attr("class")) {
|
||
case "ico_new": if (This.onBtnNewClick != null) This.onBtnNewClick(); break;
|
||
case "ico_open": if (This.onBtnOpenClick != null) This.onBtnOpenClick(); break;
|
||
case "ico_save": if (This.onBtnSaveClick != null) This.onBtnSaveClick(); break;
|
||
case "ico_undo": This.undo(); break;
|
||
case "ico_redo": This.redo(); break;
|
||
case "ico_reload": if (This.onFreshClick != null) This.onFreshClick(); break;
|
||
}
|
||
});
|
||
}
|
||
var toolWidth = 0;
|
||
if (property.haveTool) {
|
||
this.$bgDiv.append("<div class='GooFlow_tool'" + (property.haveHead ? "" : " style='margin-top:1px'") + "><div style='height:" + (height - headHeight - (property.haveHead ? 7 : 10)) + "px' class='GooFlow_tool_div'></div></div>");
|
||
this.$tool = this.$bgDiv.find(".GooFlow_tool div");
|
||
//未加代码:加入绘图工具按钮
|
||
this.$tool.append("<a type='cursor' class='GooFlow_tool_btndown' id='" + this.$id + "_btn_cursor'><b class='ico_cursor'/></a><a type='direct' class='GooFlow_tool_btn' id='" + this.$id + "_btn_direct'><b class='ico_direct'/></a>");
|
||
if (property.toolBtns && property.toolBtns.length > 0) {
|
||
tmp = "<span/>";
|
||
for (var i = 0; i < property.toolBtns.length; ++i) {
|
||
tmp += "<a type='" + property.toolBtns[i] + "' id='" + this.$id + "_btn_" + property.toolBtns[i].split(" ")[0] + "' class='GooFlow_tool_btn'><b class='ico_" + property.toolBtns[i] + "'/></a>";//加入自定义按钮
|
||
}
|
||
this.$tool.append(tmp);
|
||
}
|
||
//加入区域划分框工具开关按钮
|
||
if (property.haveGroup)
|
||
this.$tool.append("<span/><a type='group' class='GooFlow_tool_btn' id='" + this.$id + "_btn_group'><b class='ico_group'/></a>");
|
||
toolWidth = 31;
|
||
this.$nowType = "cursor";
|
||
//绑定各个按钮的点击事件
|
||
this.$tool.on("click", { inthis: this }, function (e) {
|
||
if (!e) e = window.event;
|
||
var tar;
|
||
switch (e.target.tagName) {
|
||
case "SPAN": return false;
|
||
case "DIV": return false;
|
||
case "B": tar = e.target.parentNode; break;
|
||
case "A": tar = e.target;
|
||
};
|
||
var type = $(tar).attr("type");
|
||
e.data.inthis.switchToolBtn(type);
|
||
return false;
|
||
});
|
||
this.$editable = true;//只有具有工具栏时可编辑
|
||
}
|
||
width = width - toolWidth - 8;
|
||
height = height;
|
||
this.$bgDiv.append("<div class='GooFlow_work' style='width:" + (width - (property.haveTool == true?20:-8)) + "px;height:" + (height) + "px;" + (property.haveHead ? "" : "margin-top:0px") + "'></div>");
|
||
this.$workArea = $("<div class='GooFlow_work_inner' style='width:" + width * 3 + "px;height:" + height * 3 + "px'></div>")
|
||
.attr({ "unselectable": "on", "onselectstart": 'return false', "onselect": 'document.selection.empty()' });
|
||
this.$bgDiv.children(".GooFlow_work").append(this.$workArea);
|
||
this.$draw = null;//画矢量线条的容器
|
||
this.initDraw("draw_" + this.$id, width, height);
|
||
this.$group = null;
|
||
if (property.haveGroup)
|
||
this.initGroup(width, height);
|
||
if (this.$editable) {
|
||
this.$workArea.on("click", { inthis: this }, function (e) {
|
||
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;
|
||
}
|
||
else if (type == "direct" || type == "group") return;
|
||
var X, Y;
|
||
var ev = mousePosition(e), t = getElCoordinate(this);
|
||
X = ev.x - t.left + this.parentNode.scrollLeft - 1;
|
||
Y = ev.y - t.top + this.parentNode.scrollTop - 1;
|
||
|
||
var name = "新建节点" + e.data.inthis.$max;
|
||
var type = e.data.inthis.$nowType;
|
||
if (type == 'startround') {
|
||
name = "开始";
|
||
}
|
||
if (type == 'endround') {
|
||
name = "结束";
|
||
}
|
||
var executeadd = true;
|
||
var _nodeData = e.data.inthis.$nodeData;
|
||
$.each(_nodeData, function (i) {
|
||
if (_nodeData[i].name == name) {
|
||
alert(name + '节点不能重复');
|
||
executeadd = false;
|
||
return false;
|
||
}
|
||
})
|
||
if (executeadd) {
|
||
e.data.inthis.addNode(e.data.inthis.$id + "_node_" + e.data.inthis.$max, { name: name, left: X, top: Y, type: e.data.inthis.$nowType, css: '', img: '', });
|
||
e.data.inthis.$max++;
|
||
}
|
||
});
|
||
//划线时用的绑定
|
||
this.$workArea.mousemove({ inthis: this }, function (e) {
|
||
if (e.data.inthis.$nowType != "direct") return;
|
||
var lineStart = $(this).data("lineStart");
|
||
if (!lineStart) return;
|
||
var ev = mousePosition(e), t = 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");
|
||
if (GooFlow.prototype.useSVG != "") {
|
||
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);
|
||
if (line.childNodes[1].getAttribute("marker-end") == "url(\"#arrow2\")")
|
||
line.childNodes[1].setAttribute("marker-end", "url(#arrow3)");
|
||
else line.childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
||
}
|
||
else line.points.value = lineStart.x + "," + lineStart.y + " " + X + "," + Y;
|
||
});
|
||
this.$workArea.mouseup({ inthis: this }, function (e) {
|
||
if (e.data.inthis.$nowType != "direct") return;
|
||
$(this).css("cursor", "auto").removeData("lineStart");
|
||
var tmp = document.getElementById("GooFlow_tmp_line");
|
||
if (tmp) e.data.inthis.$draw.removeChild(tmp);
|
||
});
|
||
//为了结点而增加的一些集体delegate绑定
|
||
this.initWorkForNode();
|
||
//对结点进行移动或者RESIZE时用来显示的遮罩层
|
||
this.$ghost = $("<div class='rs_ghost'></div>").attr({ "unselectable": "on", "onselectstart": 'return false', "onselect": 'document.selection.empty()' });
|
||
this.$bgDiv.append(this.$ghost);
|
||
this.$textArea = $("<textarea></textarea>");
|
||
this.$bgDiv.append(this.$textArea);
|
||
this.$lineMove = $("<div class='GooFlow_line_move' style='display:none'></div>");//操作折线时的移动框
|
||
this.$workArea.append(this.$lineMove);
|
||
this.$lineMove.on("mousedown", { inthis: this }, function (e) {
|
||
if (e.button == 2) return false;
|
||
var lm = $(this);
|
||
lm.css({ "background-color": "#333" });
|
||
var This = e.data.inthis;
|
||
var ev = mousePosition(e), t = getElCoordinate(This.$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();
|
||
var vX = X - p.left, vY = Y - p.top;
|
||
var isMove = false;
|
||
document.onmousemove = function (e) {
|
||
if (!e) e = window.event;
|
||
var ev = 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") {
|
||
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 (This.$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" });
|
||
}
|
||
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);
|
||
}
|
||
This.$lineMove.css({ "background-color": "transparent" });
|
||
if (This.$focus == This.$lineMove.data("tid")) {
|
||
This.focusItem(This.$lineMove.data("tid"));
|
||
}
|
||
document.onmousemove = null;
|
||
document.onmouseup = null;
|
||
}
|
||
});
|
||
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;
|
||
if (e.target.tagName != "A" && 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);
|
||
this.style.display = "none"; break;
|
||
case "b_l1":
|
||
This.setLineType(id, "lr"); break;
|
||
case "b_l2":
|
||
This.setLineType(id, "tb"); break;
|
||
case "b_l3":
|
||
This.setLineType(id, "sl"); break;
|
||
break;
|
||
}
|
||
});
|
||
|
||
//下面绑定当结点/线/分组块的一些操作事件,这些事件可直接通过this访问对象本身
|
||
//当操作某个单元(结点/线/分组块)被添加时,触发的方法,返回FALSE可阻止添加事件的发生
|
||
//格式function(id,type,json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json.
|
||
this.onItemAdd = null;
|
||
//当操作某个单元(结点/线/分组块)被删除时,触发的方法,返回FALSE可阻止删除事件的发生
|
||
//格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值
|
||
this.onItemDel = null;
|
||
//当操作某个单元(结点/分组块)被移动时,触发的方法,返回FALSE可阻止移动事件的发生
|
||
//格式function(id,type,left,top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值,线line不支持移动,left是新的左边距坐标,top是新的顶边距坐标
|
||
this.onItemMove = null;
|
||
//当操作某个单元(结点/线/分组块)被重命名时,触发的方法,返回FALSE可阻止重命名事件的发生
|
||
//格式function(id,name,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称
|
||
this.onItemRename = null;
|
||
//当操作某个单元(结点/线)被由不选中变成选中时,触发的方法,返回FALSE可阻止选中事件的发生
|
||
//格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中
|
||
this.onItemFocus = null;
|
||
//当操作某个单元(结点/线)被由选中变成不选中时,触发的方法,返回FALSE可阻止取消选中事件的发生
|
||
//格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中
|
||
this.onItemBlur = null;
|
||
//当操作某个单元(结点/分组块)被重定义大小或造型时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生
|
||
//格式function(id,type,width,height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值;width是新的宽度,height是新的高度
|
||
this.onItemResize = null;
|
||
//当移动某条折线中段的位置,触发的方法,返回FALSE可阻止重定大小/造型事件的发生
|
||
//格式function(id,M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标
|
||
this.onLineMove = null;
|
||
//当变换某条连接线的类型,触发的方法,返回FALSE可阻止重定大小/造型事件的发生
|
||
//格式function(id,type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线
|
||
this.onLineSetType = null;
|
||
//当用重色标注某个结点/转换线时触发的方法,返回FALSE可阻止重定大小/造型事件的发生
|
||
//格式function(id,type,mark):id是单元的唯一标识ID,type是单元类型("node"结点,"line"转换线),mark为布尔值,表示是要标注TRUE还是取消标注FALSE
|
||
this.onItemMark = null;
|
||
|
||
if (property.useOperStack && this.$editable) {//如果要使用堆栈记录操作并提供“撤销/重做”的功能,只在编辑状态下有效
|
||
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 {
|
||
//传参的数量,最多支持6个.
|
||
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;
|
||
case 6: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4], tmp[1][5]); 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 {
|
||
//传参的数量,最多支持6个.
|
||
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;
|
||
case 6: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4], tmp[1][5]); break;
|
||
}
|
||
}
|
||
};
|
||
}
|
||
$(document).keydown({ inthis: this }, function (e) {
|
||
//绑定键盘操作
|
||
var This = e.data.inthis;
|
||
if (This.$focus == "") return;
|
||
switch (e.keyCode) {
|
||
case 46://删除
|
||
This.delNode(This.$focus, true);
|
||
This.delLine(This.$focus);
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
GooFlow.prototype = {
|
||
useSVG: "",
|
||
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", 6);
|
||
m.setAttribute("markerHeight", 6);
|
||
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 z");
|
||
path.setAttribute("fill", color);
|
||
path.setAttribute("stroke-width", 0);
|
||
m.appendChild(path);
|
||
return m;
|
||
},
|
||
initDraw: function (id, width, height) {
|
||
var elem;
|
||
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", "gray"));
|
||
defs.appendChild(GooFlow.prototype.getSvgMarker("arrow2", "#ff3300"));
|
||
defs.appendChild(GooFlow.prototype.getSvgMarker("arrow3", "#ff3300"));
|
||
}
|
||
else {
|
||
this.$draw = document.createElement("v:group");
|
||
this.$draw.coordsize = width * 3 + "," + height * 3;
|
||
this.$workArea.prepend("<div class='GooFlow_work_vml' style='position:relative;width:" + width * 3 + "px;height:" + height * 3 + "px'></div>");
|
||
this.$workArea.children("div")[0].insertBefore(this.$draw, null);
|
||
}
|
||
this.$draw.id = id;
|
||
this.$draw.style.width = width * 3 + "px";
|
||
this.$draw.style.height = +height * 3 + "px";
|
||
//绑定连线的点击选中以及双击编辑事件
|
||
var tmpClk = null;
|
||
if (GooFlow.prototype.useSVG != "") tmpClk = "g";
|
||
else tmpClk = "PolyLine";
|
||
if (this.$editable) {
|
||
$(this.$draw).delegate(tmpClk, "click", { inthis: this }, function (e) {
|
||
e.data.inthis.focusItem(this.id, true);
|
||
});
|
||
$(this.$draw).delegate(tmpClk, "dblclick", { inthis: this }, function (e) {
|
||
var This = e.data.inthis;
|
||
OpenLine(this.id, This);
|
||
//var oldTxt, x, y, from, to;
|
||
//var This = e.data.inthis;
|
||
//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];
|
||
//}
|
||
//x = (parseInt(from[0], 10) + parseInt(to[0], 10)) / 2 - 60;
|
||
//y = (parseInt(from[1], 10) + parseInt(to[1], 10)) / 2 - 12;
|
||
//var t = getElCoordinate(This.$workArea[0]);
|
||
//This.$textArea.val(oldTxt).css({
|
||
// display: "block", width: 120, height: 14,
|
||
// left: t.left + x - This.$workArea[0].parentNode.scrollLeft,
|
||
// top: t.top + y - This.$workArea[0].parentNode.scrollTop
|
||
//}).data("id", This.$focus).focus();
|
||
//This.$workArea.parent().one("mousedown", function (e) {
|
||
// if (e.button == 2) return false;
|
||
// This.setName(This.$textArea.data("id"), This.$textArea.val(), "line");
|
||
// This.$textArea.val("").removeData("id").hide();
|
||
//});
|
||
});
|
||
}
|
||
},
|
||
initGroup: function (width, height) {
|
||
this.$group = $("<div class='GooFlow_work_group' style='width:" + width * 3 + "px;height:" + height * 3 + "px'></div>");//存放背景区域的容器
|
||
this.$workArea.prepend(this.$group);
|
||
if (!this.$editable) return;
|
||
//区域划分框操作区的事件绑定
|
||
this.$group.on("mousedown", { inthis: this }, function (e) {//绑定RESIZE功能以及移动功能
|
||
if (e.button == 2) return false;
|
||
var This = e.data.inthis;
|
||
if (This.$nowType != "group") return;
|
||
if (This.$textArea.css("display") == "block") {
|
||
This.setName(This.$textArea.data("id"), This.$textArea.val(), "area");
|
||
This.$textArea.val("").removeData("id").hide();
|
||
return false;
|
||
};
|
||
if (!e) e = window.event;
|
||
var cursor = $(e.target).css("cursor");
|
||
var id = e.target.parentNode;
|
||
switch (cursor) {
|
||
case "nw-resize": id = id.parentNode; break;
|
||
case "w-resize": id = id.parentNode; break;
|
||
case "n-resize": id = id.parentNode; break;
|
||
case "move": break;
|
||
default: return;
|
||
}
|
||
id = id.id;
|
||
var hack = 1;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 0;
|
||
var ev = mousePosition(e), t = getElCoordinate(This.$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;
|
||
if (cursor != "move") {
|
||
This.$ghost.css({
|
||
display: "block",
|
||
width: This.$areaData[id].width - 2 + "px", height: This.$areaData[id].height - 2 + "px",
|
||
top: This.$areaData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px",
|
||
left: This.$areaData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor
|
||
});
|
||
var vX = (This.$areaData[id].left + This.$areaData[id].width) - X;
|
||
var vY = (This.$areaData[id].top + This.$areaData[id].height) - Y;
|
||
}
|
||
else {
|
||
var vX = X - This.$areaData[id].left;
|
||
var vY = Y - This.$areaData[id].top;
|
||
}
|
||
var isMove = false;
|
||
This.$ghost.css("cursor", cursor);
|
||
document.onmousemove = function (e) {
|
||
if (!e) e = window.event;
|
||
var ev = mousePosition(e);
|
||
if (cursor != "move") {
|
||
X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft - This.$areaData[id].left + vX;
|
||
Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop - This.$areaData[id].top + vY;
|
||
if (X < 200) X = 200;
|
||
if (Y < 100) Y = 100;
|
||
switch (cursor) {
|
||
case "nw-resize": This.$ghost.css({ width: X - 2 + "px", height: Y - 2 + "px" }); break;
|
||
case "w-resize": This.$ghost.css({ width: X - 2 + "px" }); break;
|
||
case "n-resize": This.$ghost.css({ height: Y - 2 + "px" }); break;
|
||
}
|
||
}
|
||
else {
|
||
if (This.$ghost.css("display") == "none") {
|
||
This.$ghost.css({
|
||
display: "block",
|
||
width: This.$areaData[id].width - 2 + "px", height: This.$areaData[id].height - 2 + "px",
|
||
top: This.$areaData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px",
|
||
left: This.$areaData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor
|
||
});
|
||
}
|
||
X = ev.x - vX; Y = ev.y - vY;
|
||
if (X < t.left - This.$workArea[0].parentNode.scrollLeft)
|
||
X = t.left - This.$workArea[0].parentNode.scrollLeft;
|
||
else if (X + This.$workArea[0].parentNode.scrollLeft + This.$areaData[id].width > t.left + This.$workArea.width())
|
||
X = t.left + This.$workArea.width() - This.$workArea[0].parentNode.scrollLeft - This.$areaData[id].width;
|
||
if (Y < t.top - This.$workArea[0].parentNode.scrollTop)
|
||
Y = t.top - This.$workArea[0].parentNode.scrollTop;
|
||
else if (Y + This.$workArea[0].parentNode.scrollTop + This.$areaData[id].height > t.top + This.$workArea.height())
|
||
Y = t.top + This.$workArea.height() - This.$workArea[0].parentNode.scrollTop - This.$areaData[id].height;
|
||
This.$ghost.css({ left: X + hack + "px", top: Y + hack + "px" });
|
||
}
|
||
isMove = true;
|
||
}
|
||
document.onmouseup = function (e) {
|
||
This.$ghost.empty().hide();
|
||
document.onmousemove = null;
|
||
document.onmouseup = null;
|
||
if (!isMove) return;
|
||
if (cursor != "move")
|
||
This.resizeArea(id, This.$ghost.outerWidth(), This.$ghost.outerHeight());
|
||
else
|
||
This.moveArea(id, X + This.$workArea[0].parentNode.scrollLeft - t.left, Y + This.$workArea[0].parentNode.scrollTop - t.top);
|
||
return false;
|
||
}
|
||
});
|
||
//绑定修改文字说明功能
|
||
this.$group.on("dblclick", { inthis: this }, function (e) {
|
||
var This = e.data.inthis;
|
||
if (This.$nowType != "group") return;
|
||
if (!e) e = window.event;
|
||
if (e.target.tagName != "LABEL") return false;
|
||
var oldTxt = e.target.innerHTML;
|
||
var p = e.target.parentNode;
|
||
var x = parseInt(p.style.left, 10) + 18, y = parseInt(p.style.top, 10) + 1;
|
||
var t = getElCoordinate(This.$workArea[0]);
|
||
This.$textArea.val(oldTxt).css({
|
||
display: "block", width: 100, height: 14,
|
||
left: t.left + x - This.$workArea[0].parentNode.scrollLeft,
|
||
top: t.top + y - This.$workArea[0].parentNode.scrollTop
|
||
}).data("id", p.id).focus();
|
||
This.$workArea.parent().one("mousedown", function (e) {
|
||
if (e.button == 2) return false;
|
||
if (This.$textArea.css("display") == "block") {
|
||
This.setName(This.$textArea.data("id"), This.$textArea.val(), "area");
|
||
This.$textArea.val("").removeData("id").hide();
|
||
}
|
||
});
|
||
return false;
|
||
});
|
||
//绑定点击事件
|
||
this.$group.mouseup({ inthis: this }, function (e) {
|
||
|
||
var This = e.data.inthis;
|
||
if (This.$nowType != "group") return;
|
||
if (!e) e = window.event;
|
||
switch ($(e.target).attr("class")) {
|
||
case "rs_close": This.delArea(e.target.parentNode.parentNode.id); return false;//删除该分组区域
|
||
case "bg": return;
|
||
}
|
||
switch (e.target.tagName) {
|
||
case "LABEL": return false;
|
||
case "B"://绑定变色功能
|
||
var id = e.target.parentNode.id;
|
||
switch (This.$areaData[id].color) {
|
||
case "red": This.setAreaColor(id, "yellow"); break;
|
||
case "yellow": This.setAreaColor(id, "blue"); break;
|
||
case "blue": This.setAreaColor(id, "green"); break;
|
||
case "green": This.setAreaColor(id, "red"); break;
|
||
}
|
||
return false;
|
||
}
|
||
if (e.data.inthis.$ghost.css("display") == "none") {
|
||
var X, Y;
|
||
var ev = mousePosition(e), t = getElCoordinate(this);
|
||
X = ev.x - t.left + this.parentNode.parentNode.scrollLeft - 1;
|
||
Y = ev.y - t.top + this.parentNode.parentNode.scrollTop - 1;
|
||
var color = ["red", "yellow", "blue", "green"];
|
||
e.data.inthis.addArea(e.data.inthis.$id + "_area_" + e.data.inthis.$max, { name: "area_" + e.data.inthis.$max, left: X, top: Y, color: color[e.data.inthis.$max % 4], width: 200, height: 100 });
|
||
e.data.inthis.$max++;
|
||
return false;
|
||
}
|
||
});
|
||
},
|
||
//每一种类型结点及其按钮的说明文字
|
||
setNodeRemarks: function (remark) {
|
||
if (this.$tool != null)
|
||
{
|
||
this.$tool.children("a").each(function () {
|
||
this.title = remark[$(this).attr("id").split("btn_")[1]];
|
||
});
|
||
this.$nodeRemark = remark;
|
||
}
|
||
},
|
||
|
||
//切换左边工具栏按钮,传参TYPE表示切换成哪种类型的按钮
|
||
switchToolBtn: function (type) {
|
||
this.$tool.children("#" + this.$id + "_btn_" + this.$nowType.split(" ")[0]).attr("class", "GooFlow_tool_btn");
|
||
if (this.$nowType == "group") {
|
||
this.$workArea.prepend(this.$group);
|
||
for (var key in this.$areaDom) this.$areaDom[key].addClass("lock").children("div:eq(1)").css("display", "none");
|
||
}
|
||
this.$nowType = type;
|
||
this.$tool.children("#" + this.$id + "_btn_" + type.split(" ")[0]).attr("class", "GooFlow_tool_btndown");
|
||
if (this.$nowType == "group") {
|
||
this.blurItem();
|
||
this.$workArea.append(this.$group);
|
||
for (var key in this.$areaDom) this.$areaDom[key].removeClass("lock").children("div:eq(1)").css("display", "");
|
||
}
|
||
if (this.$textArea.css("display") == "none") this.$textArea.removeData("id").val("").hide();
|
||
},
|
||
//增加一个流程结点,传参为一个JSON,有id,name,top,left,width,height,type(结点类型)等属性
|
||
addNode: function (id, json) {
|
||
if (this.onItemAdd != null && !this.onItemAdd(id, "node", json)) return;
|
||
if (this.$undoStack && this.$editable) {
|
||
this.pushOper("delNode", [id]);
|
||
}
|
||
var mark = json.type;
|
||
if (json.type != "startround" && json.type != "endround") {
|
||
if (!json.width || json.width < 86) json.width = 150;
|
||
if (!json.height || json.height < 24) json.height = 65;
|
||
if (!json.top || json.top < 0) json.top = 0;
|
||
if (!json.left || json.left < 0) json.left = 0;
|
||
var hack = 0;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 2;
|
||
this.$nodeDom[id] = $("<div class='GooFlow_item " + mark + "' id='" + id + "' style='top:" + json.top + "px;left:" + json.left + "px'><table cellspacing='1' style='width:" + (json.width) + "px;height:" + (json.height) + "px;'><tr><td class='ico'><b class='ico_" + json.type + "'></b></td><td>" + json.name + "</td></tr></table><div style='display:none'><div class='rs_bottom'></div><div class='rs_right'></div><div class='rs_rb'></div><div class='rs_close'></div></div></div>");
|
||
if (json.type.indexOf(" mix") > -1) this.$nodeDom[id].addClass(mark);
|
||
//json.css = mark;
|
||
//json.img = mark;
|
||
}
|
||
else {
|
||
json.width = 24; json.height = 24;
|
||
var name = json.name;
|
||
if (json.type == 'startround') {
|
||
name = "开始";
|
||
}
|
||
if (json.type == 'endround') {
|
||
name = "结束";
|
||
}
|
||
this.$nodeDom[id] = $("<div class='GooFlow_item item_" + json.type + "' id='" + id + "' style='top:" + json.top + "px;left:" + json.left + "px'><table cellspacing='0'><tr><td class='ico'></td></tr></table><div style='display:none'><div class='rs_close'></div></div><div class='span'>" + name + "</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]);
|
||
this.$nodeData[id] = json;
|
||
++this.$nodeCount;
|
||
if (this.$editable) {
|
||
this.$nodeData[id].alt = true;
|
||
if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录
|
||
}
|
||
},
|
||
initWorkForNode: function () {
|
||
//绑定点击事件
|
||
this.$workArea.delegate(".GooFlow_item", "click", { inthis: this }, function (e) {
|
||
e.data.inthis.focusItem(this.id, true);
|
||
$(this).removeClass("item_mark");
|
||
//if (!$(this).hasClass("item_startround")) {
|
||
// LoadrightMenu("#" + this.id);
|
||
//}
|
||
//if (!$(this).hasClass("item_endround")) {
|
||
// LoadrightMenu("#" + this.id);
|
||
//}
|
||
});
|
||
//绑定右击事件
|
||
this.$workArea.delegate(".GooFlow_item", "contextmenu", { inthis: this }, function (e) {
|
||
e.data.inthis.focusItem(this.id, true);
|
||
$(this).removeClass("item_mark");
|
||
return false;
|
||
});
|
||
//绑定用鼠标移动事件
|
||
this.$workArea.delegate(".ico", "mousedown", { inthis: this }, function (e) {
|
||
if (!e) e = window.event;
|
||
if (e.button == 2) return false;
|
||
var This = e.data.inthis;
|
||
if (This.$nowType == "direct") return;
|
||
var Dom = $(this).parents(".GooFlow_item");
|
||
var id = Dom.attr("id");
|
||
This.focusItem(id, true);
|
||
var hack = 1;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 0;
|
||
var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]);
|
||
|
||
Dom.children("table").clone().prependTo(This.$ghost);
|
||
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 = mousePosition(e);
|
||
if (X == ev.x - vX && Y == ev.y - vY) return false;
|
||
X = ev.x - vX; Y = ev.y - vY;
|
||
|
||
if (isMove && This.$ghost.css("display") == "none") {
|
||
This.$ghost.css({
|
||
display: "block",
|
||
width: $('#' + id).width() - 2 + "px", height: $('#' + id).height() - 2 + "px",
|
||
top: This.$nodeData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px",
|
||
left: This.$nodeData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: "move"
|
||
});
|
||
}
|
||
|
||
if (X < t.left - This.$workArea[0].parentNode.scrollLeft)
|
||
X = t.left - This.$workArea[0].parentNode.scrollLeft;
|
||
else if (X + This.$workArea[0].parentNode.scrollLeft + This.$nodeData[id].width > t.left + This.$workArea.width())
|
||
X = t.left + This.$workArea.width() - This.$workArea[0].parentNode.scrollLeft - This.$nodeData[id].width;
|
||
if (Y < t.top - This.$workArea[0].parentNode.scrollTop)
|
||
Y = t.top - This.$workArea[0].parentNode.scrollTop;
|
||
else if (Y + This.$workArea[0].parentNode.scrollTop + This.$nodeData[id].height > t.top + This.$workArea.height())
|
||
Y = t.top + This.$workArea.height() - This.$workArea[0].parentNode.scrollTop - This.$nodeData[id].height;
|
||
This.$ghost.css({ left: X + hack + "px", top: Y + hack + "px" });
|
||
isMove = true;
|
||
}
|
||
document.onmouseup = function (e) {
|
||
if (isMove) This.moveNode(id, X + This.$workArea[0].parentNode.scrollLeft - t.left, Y + This.$workArea[0].parentNode.scrollTop - t.top);
|
||
This.$ghost.empty().hide();
|
||
document.onmousemove = null;
|
||
document.onmouseup = null;
|
||
}
|
||
});
|
||
if (!this.$editable) return;
|
||
//绑定鼠标覆盖/移出事件
|
||
this.$workArea.delegate(".GooFlow_item", "mouseenter", { inthis: this }, function (e) {
|
||
if (e.data.inthis.$nowType != "direct") return;
|
||
$(this).addClass("item_mark");
|
||
});
|
||
this.$workArea.delegate(".GooFlow_item", "mouseleave", { inthis: this }, function (e) {
|
||
if (e.data.inthis.$nowType != "direct") return;
|
||
$(this).removeClass("item_mark");
|
||
});
|
||
//绑定连线时确定初始点
|
||
this.$workArea.delegate(".GooFlow_item", "mousedown", { inthis: this }, function (e) {
|
||
if (e.button == 2) return false;
|
||
var This = e.data.inthis;
|
||
if (This.$nowType != "direct") return;
|
||
var ev = mousePosition(e), t = getElCoordinate(This.$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;
|
||
This.$workArea.data("lineStart", { "x": X, "y": Y, "id": this.id }).css("cursor", "crosshair");
|
||
var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [X, Y], [X, Y], true, true);
|
||
This.$draw.appendChild(line);
|
||
});
|
||
//绑定连线时确定结束点
|
||
this.$workArea.delegate(".GooFlow_item", "mouseup", { inthis: this }, function (e) {
|
||
var This = e.data.inthis;
|
||
if (This.$nowType != "direct") return;
|
||
var lineStart = This.$workArea.data("lineStart");
|
||
if (lineStart) This.addLine(This.$id + "_line_" + This.$max, { from: lineStart.id, to: this.id, name: "" });
|
||
This.$max++;
|
||
});
|
||
//绑定双击编辑事件
|
||
this.$workArea.delegate(".GooFlow_item > .span", "dblclick", { inthis: this }, function (e) {
|
||
var This = e.data.inthis;
|
||
var type = $('.item_focus').hasClass('item_startround');
|
||
if (type) {
|
||
OpenNode(This);
|
||
}
|
||
//var oldTxt = this.innerHTML;
|
||
//var This = e.data.inthis;
|
||
//var id = this.parentNode.id;
|
||
//var t = getElCoordinate(This.$workArea[0]);
|
||
//This.$textArea.val(oldTxt).css({
|
||
// display: "block", height: $(this).height(), width: 100,
|
||
// left: t.left + This.$nodeData[id].left - This.$workArea[0].parentNode.scrollLeft - 24,
|
||
// top: t.top + This.$nodeData[id].top - This.$workArea[0].parentNode.scrollTop + 26
|
||
//})
|
||
// .data("id", This.$focus).focus();
|
||
//This.$workArea.parent().one("mousedown", function (e) {
|
||
// if (e.button == 2) return false;
|
||
// This.setName(This.$textArea.data("id"), This.$textArea.val(), "node");
|
||
// This.$textArea.val("").removeData("id").hide();
|
||
//});
|
||
});
|
||
//节点双击事件
|
||
this.$workArea.delegate(".ico + td", "dblclick", { inthis: this }, function (e) {
|
||
var This = e.data.inthis;
|
||
OpenNode(This);
|
||
//var oldTxt = this.innerHTML;
|
||
//var This = e.data.inthis;
|
||
//var id = $(this).parents(".GooFlow_item").attr("id");
|
||
//var t = getElCoordinate(This.$workArea[0]);
|
||
//This.$textArea.val(oldTxt).css({
|
||
// display: "block", width: $(this).width() + 24, height: $(this).height(),
|
||
// left: t.left + 24 + This.$nodeData[id].left - This.$workArea[0].parentNode.scrollLeft,
|
||
// top: t.top + 2 + This.$nodeData[id].top - This.$workArea[0].parentNode.scrollTop
|
||
//})
|
||
// .data("id", This.$focus).focus();
|
||
//This.$workArea.parent().one("mousedown", function (e) {
|
||
// if (e.button == 2) return false;
|
||
// This.setName(This.$textArea.data("id"), This.$textArea.val(), "node");
|
||
// This.$textArea.val("").removeData("id").hide();
|
||
//});
|
||
});
|
||
//绑定结点的删除功能
|
||
this.$workArea.delegate(".rs_close", "click", { inthis: this }, function (e) {
|
||
if (!e) e = window.event;
|
||
e.data.inthis.delNode(e.data.inthis.$focus);
|
||
return false;
|
||
});
|
||
//绑定结点的RESIZE功能
|
||
this.$workArea.delegate(".GooFlow_item > div > div[class!=rs_close]", "mousedown", { inthis: this }, function (e) {
|
||
if (!e) e = window.event;
|
||
if (e.button == 2) return false;
|
||
var cursor = $(this).css("cursor");
|
||
if (cursor == "pointer") { return; }
|
||
var This = e.data.inthis;
|
||
var id = This.$focus;
|
||
This.switchToolBtn("cursor");
|
||
e.cancelBubble = true;
|
||
e.stopPropagation();
|
||
var hack = 1;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 0;
|
||
var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]);
|
||
This.$ghost.css({
|
||
display: "block",
|
||
width: This.$nodeData[id].width - 2 + "px", height: This.$nodeData[id].height - 2 + "px",
|
||
top: This.$nodeData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px",
|
||
left: This.$nodeData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor
|
||
});
|
||
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 = (This.$nodeData[id].left + This.$nodeData[id].width) - X;
|
||
var vY = (This.$nodeData[id].top + This.$nodeData[id].height) - Y;
|
||
var isMove = false;
|
||
This.$ghost.css("cursor", cursor);
|
||
document.onmousemove = function (e) {
|
||
if (!e) e = window.event;
|
||
var ev = mousePosition(e);
|
||
X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft - This.$nodeData[id].left + vX;
|
||
Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop - This.$nodeData[id].top + vY;
|
||
if (X < 86) X = 86;
|
||
if (Y < 24) Y = 24;
|
||
isMove = true;
|
||
switch (cursor) {
|
||
case "nw-resize": This.$ghost.css({ width: X - 2 + "px", height: Y - 2 + "px" }); break;
|
||
case "w-resize": This.$ghost.css({ width: X - 2 + "px" }); break;
|
||
case "n-resize": This.$ghost.css({ height: Y - 2 + "px" }); break;
|
||
}
|
||
}
|
||
document.onmouseup = function (e) {
|
||
This.$ghost.hide();
|
||
if (!isMove) return;
|
||
if (!e) e = window.event;
|
||
This.resizeNode(id, This.$ghost.outerWidth(), This.$ghost.outerHeight());
|
||
document.onmousemove = null;
|
||
document.onmouseup = null;
|
||
}
|
||
});
|
||
},
|
||
//获取结点/连线/分组区域的详细信息
|
||
getItemInfo: function (id, type) {
|
||
switch (type) {
|
||
case "node": return this.$nodeData[id] || null;
|
||
case "line": return this.$lineData[id] || null;
|
||
case "area": return this.$areaData[id] || null;
|
||
}
|
||
},
|
||
//取消所有结点/连线被选定的状态
|
||
blurItem: function () {
|
||
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("div:eq(0)").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", "gray");
|
||
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow1)");
|
||
}
|
||
}
|
||
else {
|
||
if (!this.$lineData[this.$focus].marked) jq[0].strokeColor = "gray";
|
||
}
|
||
this.$lineMove.hide().removeData("type").removeData("tid");
|
||
if (this.$editable) this.$lineOper.hide().removeData("tid");
|
||
}
|
||
}
|
||
this.$focus = "";
|
||
return true;
|
||
},
|
||
//选定某个结点/转换线 bool:TRUE决定了要触发选中事件,FALSE则不触发选中事件,多用在程序内部调用。
|
||
focusItem: function (id, bool) {
|
||
var jq = $("#" + id);
|
||
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("div:eq(0)").css("display", "block");
|
||
this.$workArea.append(jq);
|
||
}
|
||
else {//如果是连接线
|
||
if (this.onItemFocus != null && !this.onItemFocus(id, "line")) return;
|
||
if (GooFlow.prototype.useSVG != "") {
|
||
jq[0].childNodes[1].setAttribute("stroke", "#ff3300");
|
||
jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
||
}
|
||
else jq[0].strokeColor = "#ff3300";
|
||
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 t=getElCoordinate(this.$workArea[0]);
|
||
if (this.$lineData[id].type == "lr") {
|
||
from[0] = this.$lineData[id].M;
|
||
to[0] = from[0];
|
||
|
||
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.switchToolBtn("cursor");
|
||
},
|
||
//移动结点到一个新的位置
|
||
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]);
|
||
if (this.$editable) {
|
||
this.$nodeData[id].alt = true;
|
||
}
|
||
},
|
||
//设置结点/连线/分组区域的文字信息
|
||
setName: function (id, name, type,setinfo) {
|
||
var oldName;
|
||
if (type == "node") {//如果是结点
|
||
this.$nodeData[id].setInfo = setinfo;
|
||
if (!this.$nodeData[id])
|
||
if (this.$nodeData[id].name == name)
|
||
if (this.onItemRename != null && !this.onItemRename(id, name, "node"))
|
||
oldName = this.$nodeData[id].name;
|
||
this.$nodeData[id].name = name;
|
||
if (this.$nodeData[id].type.indexOf("round") > 1) {
|
||
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;
|
||
}
|
||
if (this.$editable) {
|
||
this.$nodeData[id].alt = true;
|
||
}
|
||
//重画转换线
|
||
this.resetLines(id, this.$nodeData[id]);
|
||
}
|
||
else if (type == "line") {//如果是线
|
||
this.$lineData[id].setInfo = setinfo;
|
||
if (!this.$lineData[id])
|
||
if (this.$lineData[id].name == name)
|
||
if (this.onItemRename != null && !this.onItemRename(id, name, "line"))
|
||
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";
|
||
}
|
||
if (this.$editable) {
|
||
this.$lineData[id].alt = true;
|
||
}
|
||
}
|
||
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);
|
||
if (this.$editable) {
|
||
this.$areaData[id].alt = true;
|
||
}
|
||
}
|
||
if (this.$undoStack) {
|
||
var paras = [id, oldName, type];
|
||
this.pushOper("setName", paras);
|
||
}
|
||
},
|
||
//设置结点的尺寸,仅支持非开始/结束结点
|
||
resizeNode: function (id, width, height) {
|
||
if (!this.$nodeData[id]) return;
|
||
if (this.onItemResize != null && !this.onItemResize(id, "node", width, height)) return;
|
||
if (this.$nodeData[id].type == "start" || this.$nodeData[id].type == "end") return;
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$nodeData[id].width, this.$nodeData[id].height];
|
||
this.pushOper("resizeNode", paras);
|
||
}
|
||
var hack = 0;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 2;
|
||
this.$nodeDom[id].children("table").css({ width: width - 2 + "px", height: height - 2 + "px" });
|
||
width = this.$nodeDom[id].outerWidth() - hack;
|
||
height = this.$nodeDom[id].outerHeight() - hack;
|
||
this.$nodeDom[id].children("table").css({ width: width - 2 + "px", height: height - 2 + "px" });
|
||
this.$nodeData[id].width = width;
|
||
this.$nodeData[id].height = height;
|
||
if (this.$editable) {
|
||
this.$nodeData[id].alt = true;
|
||
}
|
||
//重画转换线
|
||
this.resetLines(id, this.$nodeData[id]);
|
||
},
|
||
//删除结点
|
||
delNode: function (id) {
|
||
if (!this.$nodeData[id]) return;
|
||
if (this.onItemDel != null && !this.onItemDel(id, "node")) return;
|
||
//先删除可能的连线
|
||
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.delLine(k);
|
||
}
|
||
}
|
||
//再删除结点本身
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$nodeData[id]];
|
||
this.pushOper("addNode", paras);
|
||
}
|
||
delete this.$nodeData[id];
|
||
this.$nodeDom[id].remove();
|
||
delete this.$nodeDom[id];
|
||
--this.$nodeCount;
|
||
if (this.$focus == id) this.$focus = "";
|
||
|
||
if (this.$editable) {
|
||
//在回退新增操作时,如果节点ID以this.$id+"_node_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中
|
||
if (id.indexOf(this.$id + "_node_") < 0)
|
||
this.$deletedItem[id] = "node";
|
||
}
|
||
},
|
||
//设置流程图的名称
|
||
setTitle: function (text) {
|
||
this.$title = text;
|
||
if (this.$head) this.$head.children("label").attr("title", text).text(text);
|
||
},
|
||
//载入一组数据
|
||
loadData: function (data) {
|
||
if (data == undefined)
|
||
{
|
||
data = "";
|
||
}
|
||
var t = this.$editable;
|
||
this.$editable = false;
|
||
if (data.title) this.setTitle(data.title);
|
||
if (data.initNum) this.$max = data.initNum;
|
||
for (var i in data.nodes)
|
||
this.addNode(data.nodes[i].id, data.nodes[i]);
|
||
for (var j in data.lines)
|
||
this.addLine(data.lines[j].id, data.lines[j]);
|
||
for (var k in data.areas)
|
||
this.addArea(data.areas[k].id, data.areas[k]);
|
||
this.$editable = t;
|
||
this.$deletedItem = {};
|
||
},
|
||
//用AJAX方式,远程读取一组数据
|
||
//参数para为JSON结构,与JQUERY中$.ajax()方法的传参一样
|
||
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);
|
||
}
|
||
})
|
||
},
|
||
//把画好的整个流程图导出到一个变量中(其实也可以直接访问GooFlow对象的$nodeData,$lineData,$areaData这三个JSON属性)
|
||
exportData: function () {
|
||
var ret = { title: this.$title, nodes: this.$nodeData, lines: this.$lineData, areas: this.$areaData, initNum: this.$max };
|
||
|
||
var _nodeobject = [],_lineobject = [];
|
||
for (var k1 in ret.nodes) {
|
||
if (!ret.nodes[k1].marked) {
|
||
delete ret.nodes[k1]["marked"];
|
||
}
|
||
ret.nodes[k1]["id"] = k1;
|
||
_nodeobject.push(ret.nodes[k1]);
|
||
}
|
||
ret.nodes = _nodeobject;
|
||
for (var k2 in ret.lines) {
|
||
if (!ret.lines[k2].marked) {
|
||
delete ret.lines[k2]["marked"];
|
||
}
|
||
ret.lines[k2]["id"] = k2;
|
||
_lineobject.push(ret.lines[k2]);
|
||
}
|
||
ret.lines = _lineobject;
|
||
return ret;
|
||
},
|
||
//只把本次编辑流程图中作了变更(包括增删改)的元素导出到一个变量中,以方便用户每次编辑载入的流程图后只获取变更过的数据
|
||
exportAlter: function () {
|
||
var ret = { nodes: {}, lines: {}, areas: {} };
|
||
for (var k1 in this.$nodeData) {
|
||
if (this.$nodeData[k1].alt) {
|
||
ret.nodes[k1] = this.$nodeData[k1];
|
||
}
|
||
}
|
||
for (var k2 in this.$lineData) {
|
||
if (this.$lineData[k2].alt) {
|
||
ret.lines[k2] = this.$lineData[k2];
|
||
}
|
||
}
|
||
for (var k3 in this.$areaData) {
|
||
if (this.$areaData[k3].alt) {
|
||
ret.areas[k3] = this.$areaData[k3];
|
||
}
|
||
}
|
||
ret.deletedItem = this.$deletedItem;
|
||
return ret;
|
||
},
|
||
//变更元素的ID,一般用于快速保存后,将后台返回新元素的ID更新到页面中;type为元素类型(节点,连线,区块)
|
||
transNewId: function (oldId, newId, type) {
|
||
var tmp;
|
||
switch (type) {
|
||
case "node":
|
||
if (this.$nodeData[oldId]) {
|
||
tmp = this.$nodeData[oldId];
|
||
delete this.$nodeData[oldId];
|
||
this.$nodeData[newId] = tmp;
|
||
}
|
||
break;
|
||
case "line":
|
||
if (this.$lineData[oldId]) {
|
||
tmp = this.$lineData[oldId];
|
||
delete this.$lineData[oldId];
|
||
this.$lineData[newId] = tmp;
|
||
}
|
||
break;
|
||
case "area":
|
||
if (this.$areaData[oldId]) {
|
||
tmp = this.$areaData[oldId];
|
||
delete this.$areaData[oldId];
|
||
this.$areaData[newId] = tmp;
|
||
}
|
||
break;
|
||
}
|
||
},
|
||
//清空工作区及已载入的数据
|
||
clearData: function () {
|
||
for (var key in this.$nodeData) {
|
||
this.delNode(key);
|
||
}
|
||
for (var key in this.$lineData) {
|
||
this.delLine(key);
|
||
}
|
||
for (var key in this.$areaData) {
|
||
this.delArea(key);
|
||
}
|
||
this.$deletedItem = {};
|
||
},
|
||
//销毁自己
|
||
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;
|
||
this.$areaCount = 0;
|
||
this.$areaCount = 0;
|
||
this.$deletedItem = {};
|
||
},
|
||
///////////以下为有关画线的方法
|
||
//绘制一条箭头线,并返回线的DOM
|
||
drawLine: function (id, sp, ep, mark, dash) {
|
||
var line;
|
||
if (GooFlow.prototype.useSVG != "") {
|
||
line = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||
var hi = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||
|
||
if (id != "") line.setAttribute("id", id);
|
||
line.setAttribute("from", sp[0] + "," + sp[1]);
|
||
line.setAttribute("to", ep[0] + "," + ep[1]);
|
||
hi.setAttribute("visibility", "hidden");
|
||
hi.setAttribute("stroke-width", 9);
|
||
hi.setAttribute("fill", "none");
|
||
hi.setAttribute("stroke", "white");
|
||
hi.setAttribute("d", "M " + sp[0] + " " + sp[1] + " L " + ep[0] + " " + ep[1]);
|
||
hi.setAttribute("pointer-events", "stroke");
|
||
path.setAttribute("d", "M " + sp[0] + " " + sp[1] + " L " + ep[0] + " " + ep[1]);
|
||
path.setAttribute("stroke-width", 2.0);
|
||
path.setAttribute("stroke-linecap", "round");
|
||
path.setAttribute("fill", "none");
|
||
if (dash) path.setAttribute("style", "stroke-dasharray:6,5");
|
||
if (mark) {
|
||
path.setAttribute("stroke", "#ff3300");
|
||
path.setAttribute("marker-end", "url(#arrow2)");
|
||
}
|
||
else {
|
||
path.setAttribute("stroke", "gray");
|
||
path.setAttribute("marker-end", "url(#arrow1)");
|
||
}
|
||
line.appendChild(hi);
|
||
line.appendChild(path);
|
||
line.style.cursor = "crosshair";
|
||
if (id != "" && id != "GooFlow_tmp_line") {
|
||
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||
//text.textContent=id;
|
||
line.appendChild(text);
|
||
var x = (ep[0] + sp[0]) / 2;
|
||
var y = (ep[1] + sp[1]) / 2;
|
||
text.setAttribute("text-anchor", "middle");
|
||
text.setAttribute("x", x);
|
||
text.setAttribute("y", y - 5);
|
||
line.style.cursor = "pointer";
|
||
text.style.cursor = "text";
|
||
}
|
||
} else {
|
||
line = document.createElement("v:polyline");
|
||
if (id != "") line.id = id;
|
||
//line.style.position="absolute";
|
||
line.points.value = sp[0] + "," + sp[1] + " " + ep[0] + "," + ep[1];
|
||
line.setAttribute("fromTo", sp[0] + "," + sp[1] + "," + ep[0] + "," + ep[1]);
|
||
line.strokeWeight = "1.2";
|
||
line.stroke.EndArrow = "Block";
|
||
line.style.cursor = "crosshair";
|
||
if (id != "" && id != "GooFlow_tmp_line") {
|
||
var text = document.createElement("div");
|
||
//text.innerHTML=id;
|
||
line.appendChild(text);
|
||
var x = (ep[0] - sp[0]) / 2;
|
||
var y = (ep[1] - sp[1]) / 2;
|
||
if (x < 0) x = x * -1;
|
||
if (y < 0) y = y * -1;
|
||
text.style.left = x + "px";
|
||
text.style.top = y - 6 + "px";
|
||
line.style.cursor = "pointer";
|
||
}
|
||
if (dash) line.stroke.dashstyle = "Dash";
|
||
if (mark) line.strokeColor = "#ff3300";
|
||
else line.strokeColor = "gray";
|
||
}
|
||
return line;
|
||
},
|
||
//画一条只有两个中点的折线
|
||
drawPoly: function (id, sp, m1, m2, ep, mark) {
|
||
var poly, strPath;
|
||
if (GooFlow.prototype.useSVG != "") {
|
||
poly = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
||
var hi = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||
if (id != "") poly.setAttribute("id", id);
|
||
poly.setAttribute("from", sp[0] + "," + sp[1]);
|
||
poly.setAttribute("to", ep[0] + "," + ep[1]);
|
||
hi.setAttribute("visibility", "hidden");
|
||
hi.setAttribute("stroke-width", 9);
|
||
hi.setAttribute("fill", "none");
|
||
hi.setAttribute("stroke", "white");
|
||
strPath = "M " + sp[0] + " " + sp[1];
|
||
if (m1[0] != sp[0] || m1[1] != sp[1])
|
||
strPath += " L " + m1[0] + " " + m1[1];
|
||
if (m2[0] != ep[0] || m2[1] != ep[1])
|
||
strPath += " L " + m2[0] + " " + m2[1];
|
||
strPath += " L " + ep[0] + " " + ep[1];
|
||
hi.setAttribute("d", strPath);
|
||
hi.setAttribute("pointer-events", "stroke");
|
||
path.setAttribute("d", strPath);
|
||
path.setAttribute("stroke-width", 2.0);
|
||
path.setAttribute("stroke-linecap", "round");
|
||
path.setAttribute("fill", "none");
|
||
if (mark) {
|
||
path.setAttribute("stroke", "#ff3300");
|
||
path.setAttribute("marker-end", "url(#arrow2)");
|
||
}
|
||
else {
|
||
path.setAttribute("stroke", "gray");
|
||
path.setAttribute("marker-end", "url(#arrow1)");
|
||
}
|
||
poly.appendChild(hi);
|
||
poly.appendChild(path);
|
||
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||
//text.textContent=id;
|
||
poly.appendChild(text);
|
||
var x = (m2[0] + m1[0]) / 2;
|
||
var y = (m2[1] + m1[1]) / 2;
|
||
text.setAttribute("text-anchor", "middle");
|
||
text.setAttribute("x", x);
|
||
text.setAttribute("y", y - 5);
|
||
text.style.cursor = "text";
|
||
poly.style.cursor = "pointer";
|
||
}
|
||
else {
|
||
poly = document.createElement("v:Polyline");
|
||
if (id != "") poly.id = id;
|
||
poly.filled = "false";
|
||
strPath = sp[0] + "," + sp[1];
|
||
if (m1[0] != sp[0] || m1[1] != sp[1])
|
||
strPath += " " + m1[0] + "," + m1[1];
|
||
if (m2[0] != ep[0] || m2[1] != ep[1])
|
||
strPath += " " + m2[0] + "," + m2[1];
|
||
strPath += " " + ep[0] + "," + ep[1];
|
||
poly.points.value = strPath;
|
||
poly.setAttribute("fromTo", sp[0] + "," + sp[1] + "," + ep[0] + "," + ep[1]);
|
||
poly.strokeWeight = "1.2";
|
||
poly.stroke.EndArrow = "Block";
|
||
var text = document.createElement("div");
|
||
//text.innerHTML=id;
|
||
poly.appendChild(text);
|
||
var x = (m2[0] - m1[0]) / 2;
|
||
var y = (m2[1] - m1[1]) / 2;
|
||
if (x < 0) x = x * -1;
|
||
if (y < 0) y = y * -1;
|
||
text.style.left = x + "px";
|
||
text.style.top = y - 4 + "px";
|
||
poly.style.cursor = "pointer";
|
||
if (mark) poly.strokeColor = "#ff3300";
|
||
else poly.strokeColor = "gray";
|
||
}
|
||
return poly;
|
||
},
|
||
//计算两个结点间要连直线的话,连线的开始坐标和结束坐标
|
||
calcStartEnd: function (n1, n2) {
|
||
var X_1, Y_1, X_2, Y_2;
|
||
//X判断:
|
||
var x11 = n1.left, x12 = n1.left + n1.width, x21 = n2.left, x22 = n2.left + n2.width;
|
||
//结点2在结点1左边
|
||
if (x11 >= x22) {
|
||
X_1 = x11; X_2 = x22;
|
||
}
|
||
//结点2在结点1右边
|
||
else if (x12 <= x21) {
|
||
X_1 = x12; X_2 = x21;
|
||
}
|
||
//结点2在结点1水平部分重合
|
||
else if (x11 <= x21 && x12 >= x21 && x12 <= x22) {
|
||
X_1 = (x12 + x21) / 2; X_2 = X_1;
|
||
}
|
||
else if (x11 >= x21 && x12 <= x22) {
|
||
X_1 = (x11 + x12) / 2; X_2 = X_1;
|
||
}
|
||
else if (x21 >= x11 && x22 <= x12) {
|
||
X_1 = (x21 + x22) / 2; X_2 = X_1;
|
||
}
|
||
else if (x11 <= x22 && x12 >= x22) {
|
||
X_1 = (x11 + x22) / 2; X_2 = X_1;
|
||
}
|
||
|
||
//Y判断:
|
||
var y11 = n1.top, y12 = n1.top + n1.height, y21 = n2.top, y22 = n2.top + n2.height;
|
||
//结点2在结点1上边
|
||
if (y11 >= y22) {
|
||
Y_1 = y11; Y_2 = y22;
|
||
}
|
||
//结点2在结点1下边
|
||
else if (y12 <= y21) {
|
||
Y_1 = y12; Y_2 = y21;
|
||
}
|
||
//结点2在结点1垂直部分重合
|
||
else if (y11 <= y21 && y12 >= y21 && y12 <= y22) {
|
||
Y_1 = (y12 + y21) / 2; Y_2 = Y_1;
|
||
}
|
||
else if (y11 >= y21 && y12 <= y22) {
|
||
Y_1 = (y11 + y12) / 2; Y_2 = Y_1;
|
||
}
|
||
else if (y21 >= y11 && y22 <= y12) {
|
||
Y_1 = (y21 + y22) / 2; Y_2 = Y_1;
|
||
}
|
||
else if (y11 <= y22 && y12 >= y22) {
|
||
Y_1 = (y11 + y22) / 2; Y_2 = Y_1;
|
||
}
|
||
return { "start": [X_1, Y_1], "end": [X_2, Y_2] };
|
||
},
|
||
//计算两个结点间要连折线的话,连线的所有坐标
|
||
calcPolyPoints: function (n1, n2, type, M) {
|
||
//开始/结束两个结点的中心
|
||
var SP = { x: n1.left + n1.width / 2, y: n1.top + n1.height / 2 };
|
||
var EP = { x: n2.left + n2.width / 2, y: n2.top + n2.height / 2 };
|
||
var sp = [], m1 = [], m2 = [], ep = [];
|
||
//如果是允许中段可左右移动的折线,则参数M为可移动中段线的X坐标
|
||
//粗略计算起始点
|
||
sp = [SP.x, SP.y];
|
||
ep = [EP.x, EP.y];
|
||
if (type == "lr") {
|
||
//粗略计算2个中点
|
||
m1 = [M, SP.y];
|
||
m2 = [M, EP.y];
|
||
//再具体分析修改开始点和中点1
|
||
if (m1[0] > n1.left && m1[0] < n1.left + n1.width) {
|
||
m1[1] = (SP.y > EP.y ? n1.top : n1.top + n1.height);
|
||
sp[0] = m1[0]; sp[1] = m1[1];
|
||
}
|
||
else {
|
||
sp[0] = (m1[0] < n1.left ? n1.left : n1.left + n1.width)
|
||
}
|
||
//再具体分析中点2和结束点
|
||
if (m2[0] > n2.left && m2[0] < n2.left + n2.width) {
|
||
m2[1] = (SP.y > EP.y ? n2.top + n2.height : n2.top);
|
||
ep[0] = m2[0]; ep[1] = m2[1];
|
||
}
|
||
else {
|
||
ep[0] = (m2[0] < n2.left ? n2.left : n2.left + n2.width)
|
||
}
|
||
}
|
||
//如果是允许中段可上下移动的折线,则参数M为可移动中段线的Y坐标
|
||
else if (type == "tb") {
|
||
//粗略计算2个中点
|
||
m1 = [SP.x, M];
|
||
m2 = [EP.x, M];
|
||
//再具体分析修改开始点和中点1
|
||
if (m1[1] > n1.top && m1[1] < n1.top + n1.height) {
|
||
m1[0] = (SP.x > EP.x ? n1.left : n1.left + n1.width);
|
||
sp[0] = m1[0]; sp[1] = m1[1];
|
||
}
|
||
else {
|
||
sp[1] = (m1[1] < n1.top ? n1.top : n1.top + n1.height)
|
||
}
|
||
//再具体分析中点2和结束点
|
||
if (m2[1] > n2.top && m2[1] < n2.top + n2.height) {
|
||
m2[0] = (SP.x > EP.x ? n2.left + n2.width : n2.left);
|
||
ep[0] = m2[0]; ep[1] = m2[1];
|
||
}
|
||
else {
|
||
ep[1] = (m2[1] < n2.top ? n2.top : n2.top + n2.height);
|
||
}
|
||
}
|
||
return { start: sp, m1: m1, m2: m2, end: ep };
|
||
},
|
||
//初始化折线中段的X/Y坐标,mType='rb'时为X坐标,mType='tb'时为Y坐标
|
||
getMValue: function (n1, n2, mType) {
|
||
if (mType == "lr") {
|
||
return (n1.left + n1.width / 2 + n2.left + n2.width / 2) / 2;
|
||
}
|
||
else if (mType == "tb") {
|
||
return (n1.top + n1.height / 2 + n2.top + n2.height / 2) / 2;
|
||
}
|
||
},
|
||
//增加一条线
|
||
addLine: function (id, json) {
|
||
if (this.onItemAdd != null && !this.onItemAdd(id, "line", json)) return;
|
||
if (this.$undoStack && this.$editable) {
|
||
this.pushOper("delLine", [id]);
|
||
}
|
||
var n1 = null, n2 = null;//获取开始/结束结点的数据
|
||
if (json.from == json.to) return;
|
||
//避免两个节点间不能有一条以上同向接连线
|
||
for (var k in this.$lineData) {
|
||
if ((json.from == this.$lineData[k].from && json.to == this.$lineData[k].to))
|
||
return;
|
||
}
|
||
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] = {};
|
||
this.$lineData[id].setInfo = json.setInfo;
|
||
this.$lineData[id].id = json.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[id].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;
|
||
if (this.$editable) {
|
||
this.$lineData[id].alt = true;
|
||
if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录
|
||
}
|
||
},
|
||
//重构所有连向某个结点的线的显示,传参结构为$nodeData数组的一个单元结构
|
||
resetLines: function (id, node) {
|
||
for (var i in this.$lineData) {
|
||
var other = null;//获取结束/开始结点的数据
|
||
var res;
|
||
if (this.$lineData[i].from == id) {//找结束点
|
||
other = this.$nodeData[this.$lineData[i].to] || null;
|
||
if (other == null) continue;
|
||
if (this.$lineData[i].type == "sl")
|
||
res = GooFlow.prototype.calcStartEnd(node, other);
|
||
else
|
||
res = GooFlow.prototype.calcPolyPoints(node, other, this.$lineData[i].type, this.$lineData[i].M)
|
||
if (!res) break;
|
||
}
|
||
else if (this.$lineData[i].to == id) {//找开始点
|
||
other = this.$nodeData[this.$lineData[i].from] || null;
|
||
if (other == null) continue;
|
||
if (this.$lineData[i].type == "sl")
|
||
res = GooFlow.prototype.calcStartEnd(other, node);
|
||
else
|
||
res = GooFlow.prototype.calcPolyPoints(other, node, this.$lineData[i].type, this.$lineData[i].M);
|
||
if (!res) break;
|
||
}
|
||
if (other == null) continue;
|
||
this.$draw.removeChild(this.$lineDom[i]);
|
||
if (this.$lineData[i].type == "sl") {
|
||
this.$lineDom[i] = GooFlow.prototype.drawLine(i, res.start, res.end, this.$lineData[i].marked);
|
||
}
|
||
else {
|
||
this.$lineDom[i] = GooFlow.prototype.drawPoly(i, res.start, res.m1, res.m2, res.end, this.$lineData[i].marked);
|
||
}
|
||
this.$draw.appendChild(this.$lineDom[i]);
|
||
if (GooFlow.prototype.useSVG == "") {
|
||
this.$lineDom[i].childNodes[1].innerHTML = this.$lineData[i].name;
|
||
if (this.$lineData[i].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[i].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[i].childNodes[1].style.top = (res.m2[1] + res.m1[1]) / 2 - Min - this.$lineDom[i].childNodes[1].offsetHeight / 2 - 4;
|
||
} else
|
||
this.$lineDom[i].childNodes[1].style.left =
|
||
((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[i].childNodes[1].offsetWidth) / 2 + 4;
|
||
}
|
||
else this.$lineDom[i].childNodes[2].textContent = this.$lineData[i].name;
|
||
}
|
||
},
|
||
//重新设置连线的样式 newType= "sl":直线, "lr":中段可左右移动型折线, "tb":中段可上下移动型折线
|
||
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);
|
||
if (this.$lineData[id].type != "sl") {
|
||
var para2 = [id, this.$lineData[id].M];
|
||
this.pushOper("setLineM", para2);
|
||
}
|
||
}
|
||
var from = this.$lineData[id].from;
|
||
var to = this.$lineData[id].to;
|
||
this.$lineData[id].type = newType;
|
||
var res;
|
||
//如果是变成折线
|
||
if (newType != "sl") {
|
||
var res = GooFlow.prototype.calcPolyPoints(this.$nodeData[from], this.$nodeData[to], this.$lineData[id].type, this.$lineData[id].M);
|
||
this.setLineM(id, this.getMValue(this.$nodeData[from], this.$nodeData[to], newType), true);
|
||
}
|
||
//如果是变回直线
|
||
else {
|
||
delete this.$lineData[id].M;
|
||
this.$lineMove.hide().removeData("type").removeData("tid");
|
||
res = GooFlow.prototype.calcStartEnd(this.$nodeData[from], this.$nodeData[to]);
|
||
if (!res) return;
|
||
this.$draw.removeChild(this.$lineDom[id]);
|
||
this.$lineDom[id] = GooFlow.prototype.drawLine(id, res.start, res.end, this.$lineData[id].marked || this.$focus == id);
|
||
this.$draw.appendChild(this.$lineDom[id]);
|
||
if (GooFlow.prototype.useSVG == "") {
|
||
this.$lineDom[id].childNodes[1].innerHTML = this.$lineData[id].name;
|
||
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 = this.$lineData[id].name;
|
||
}
|
||
if (this.$focus == id) {
|
||
this.focusItem(id);
|
||
}
|
||
if (this.$editable) {
|
||
this.$lineData[id].alt = true;
|
||
}
|
||
},
|
||
//设置折线中段的X坐标值(可左右移动时)或Y坐标值(可上下移动时)
|
||
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);
|
||
}
|
||
var from = this.$lineData[id].from;
|
||
var to = this.$lineData[id].to;
|
||
this.$lineData[id].M = M;
|
||
var ps = GooFlow.prototype.calcPolyPoints(this.$nodeData[from], this.$nodeData[to], this.$lineData[id].type, this.$lineData[id].M);
|
||
this.$draw.removeChild(this.$lineDom[id]);
|
||
this.$lineDom[id] = GooFlow.prototype.drawPoly(id, ps.start, ps.m1, ps.m2, ps.end, this.$lineData[id].marked || this.$focus == id);
|
||
this.$draw.appendChild(this.$lineDom[id]);
|
||
if (GooFlow.prototype.useSVG == "") {
|
||
this.$lineDom[id].childNodes[1].innerHTML = this.$lineData[id].name;
|
||
var Min = (ps.start[0] > ps.end[0] ? ps.end[0] : ps.start[0]);
|
||
if (Min > ps.m2[0]) Min = ps.m2[0];
|
||
if (Min > ps.m1[0]) Min = ps.m1[0];
|
||
this.$lineDom[id].childNodes[1].style.left = (ps.m2[0] + ps.m1[0]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4;
|
||
Min = (ps.start[1] > ps.end[1] ? ps.end[1] : ps.start[1]);
|
||
if (Min > ps.m2[1]) Min = ps.m2[1];
|
||
if (Min > ps.m1[1]) Min = ps.m1[1];
|
||
this.$lineDom[id].childNodes[1].style.top = (ps.m2[1] + ps.m1[1]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetHeight / 2 - 4;
|
||
}
|
||
else this.$lineDom[id].childNodes[2].textContent = this.$lineData[id].name;
|
||
if (this.$editable) {
|
||
this.$lineData[id].alt = true;
|
||
}
|
||
},
|
||
//删除转换线
|
||
delLine: function (id) {
|
||
if (!this.$lineData[id]) return;
|
||
if (this.onItemDel != null && !this.onItemDel(id, "node")) 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 = "";
|
||
--this.$lineCount;
|
||
if (this.$editable) {
|
||
//在回退新增操作时,如果节点ID以this.$id+"_line_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中
|
||
if (id.indexOf(this.$id + "_line_") < 0)
|
||
this.$deletedItem[id] = "line";
|
||
}
|
||
this.$lineOper.hide();
|
||
},
|
||
//用颜色标注/取消标注一个结点或转换线,常用于显示重点或流程的进度。
|
||
//这是一个在编辑模式中无用,但是在纯浏览模式中非常有用的方法,实际运用中可用于跟踪流程的进度。
|
||
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");
|
||
|
||
} 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", "#ff3300");
|
||
this.$nodeDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow2)");
|
||
} else {
|
||
this.$nodeDom[id].childNodes[1].setAttribute("stroke", "gray");
|
||
this.$nodeDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow1)");
|
||
}
|
||
} else {
|
||
if (mark) this.$nodeDom[id].strokeColor = "#ff3300";
|
||
else this.$nodeDom[id].strokeColor = "gray"
|
||
}
|
||
}
|
||
if (this.$undoStatck) {
|
||
var paras = [id, type, !mark];
|
||
this.pushOper("markItem", paras);
|
||
}
|
||
},
|
||
////////////////////////以下为区域分组块操作
|
||
moveArea: function (id, left, top) {
|
||
if (!this.$areaData[id]) return;
|
||
if (this.onItemMove != null && !this.onItemMove(id, "area", left, top)) return;
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$areaData[id].left, this.$areaData[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.$areaData[id].left = left;
|
||
this.$areaData[id].top = top;
|
||
if (this.$editable) {
|
||
this.$areaData[id].alt = true;
|
||
}
|
||
},
|
||
//删除区域分组
|
||
delArea: function (id) {
|
||
if (!this.$areaData[id]) return;
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$areaData[id]];
|
||
this.pushOper("addArea", paras);
|
||
}
|
||
if (this.onItemDel != null && !this.onItemDel(id, "node")) return;
|
||
delete this.$areaData[id];
|
||
this.$areaDom[id].remove();
|
||
delete this.$areaDom[id];
|
||
--this.$areaCount;
|
||
if (this.$editable) {
|
||
//在回退新增操作时,如果节点ID以this.$id+"_area_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中
|
||
if (id.indexOf(this.$id + "_area_") < 0)
|
||
this.$deletedItem[id] = "area";
|
||
}
|
||
},
|
||
//设置区域分组的颜色
|
||
setAreaColor: function (id, color) {
|
||
if (!this.$areaData[id]) return;
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$areaData[id].color];
|
||
this.pushOper("setAreaColor", paras);
|
||
}
|
||
if (color == "red" || color == "yellow" || color == "blue" || color == "green") {
|
||
this.$areaDom[id].removeClass("area_" + this.$areaData[id].color).addClass("area_" + color);
|
||
this.$areaData[id].color = color;
|
||
}
|
||
if (this.$editable) {
|
||
this.$areaData[id].alt = true;
|
||
}
|
||
},
|
||
//设置区域分块的尺寸
|
||
resizeArea: function (id, width, height) {
|
||
if (!this.$areaData[id]) return;
|
||
if (this.onItemResize != null && !this.onItemResize(id, "area", width, height)) return;
|
||
if (this.$undoStack) {
|
||
var paras = [id, this.$areaData[id].width, this.$areaData[id].height];
|
||
this.pushOper("resizeArea", paras);
|
||
}
|
||
var hack = 0;
|
||
if (navigator.userAgent.indexOf("8.0") != -1) hack = 2;
|
||
this.$areaDom[id].children(".bg").css({ width: width - 2 + "px", height: height - 2 + "px" });
|
||
width = this.$areaDom[id].outerWidth();
|
||
height = this.$areaDom[id].outerHeight();
|
||
this.$areaDom[id].children("bg").css({ width: width - 2 + "px", height: height - 2 + "px" });
|
||
this.$areaData[id].width = width;
|
||
this.$areaData[id].height = height;
|
||
if (this.$editable) {
|
||
this.$areaData[id].alt = true;
|
||
}
|
||
},
|
||
addArea: function (id, json) {
|
||
if (this.onItemAdd != null && !this.onItemAdd(id, "area", json)) return;
|
||
if (this.$undoStack && this.$editable) {
|
||
this.pushOper("delArea", [id]);
|
||
}
|
||
this.$areaDom[id] = $("<div id='" + id + "' class='GooFlow_area area_" + json.color + "' style='top:" + json.top + "px;left:" + json.left + "px'><div class='bg' style='width:" + (json.width - 2) + "px;height:" + (json.height - 2) + "px'></div>"
|
||
+ "<label>" + json.name + "</label><b></b><div><div class='rs_bottom'></div><div class='rs_right'></div><div class='rs_rb'></div><div class='rs_close'></div></div></div>");
|
||
this.$areaData[id] = json;
|
||
this.$group.append(this.$areaDom[id]);
|
||
if (this.$nowType != "group") this.$areaDom[id].children("div:eq(1)").css("display", "none");
|
||
++this.$areaCount;
|
||
if (this.$editable) {
|
||
this.$areaData[id].alt = true;
|
||
if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录
|
||
}
|
||
},
|
||
//重构整个流程图设计器的宽高
|
||
reinitSize: function (width, height) {
|
||
var w = (width || 800) - 2;
|
||
var h = (height || 500) - 2;
|
||
this.$bgDiv.css({ height: h + "px", width: w + "px" });
|
||
var headHeight = 0, hack = 10;
|
||
if (this.$head != null) {
|
||
headHeight = 24;
|
||
hack = 7;
|
||
}
|
||
if (this.$tool != null) {
|
||
this.$tool.css({ height: h - headHeight - hack + "px" });
|
||
}
|
||
w -= 39;
|
||
h = h - headHeight - (this.$head != null ? 5 : 8);
|
||
this.$workArea.parent().css({ height: h + "px", width: w + "px" });
|
||
this.$workArea.css({ height: h * 3 + "px", width: w * 3 + "px" });
|
||
if (GooFlow.prototype.useSVG == "") {
|
||
this.$draw.coordsize = w * 3 + "," + h * 3;
|
||
}
|
||
this.$draw.style.width = w * 3 + "px";
|
||
this.$draw.style.height = +h * 3 + "px";
|
||
if (this.$group == null) {
|
||
this.$group.css({ height: h * 3 + "px", width: w * 3 + "px" });
|
||
}
|
||
}
|
||
}
|
||
//将此类的构造函数加入至JQUERY对象中
|
||
jQuery.extend({
|
||
createGooFlow: function (bgDiv, property) {
|
||
return new GooFlow(bgDiv, property);
|
||
}
|
||
});
|
||
//获取一个DIV的绝对坐标的功能函数,即使是非绝对定位,一样能获取到
|
||
function getElCoordinate(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
|
||
};
|
||
}
|
||
//兼容各种浏览器的,获取鼠标真实位置
|
||
function mousePosition(ev) {
|
||
if (!ev) ev = window.event;
|
||
if (ev.pageX || ev.pageY) {
|
||
return { x: ev.pageX, y: ev.pageY };
|
||
}
|
||
return {
|
||
x: ev.clientX + document.documentElement.scrollLeft - document.body.clientLeft,
|
||
y: ev.clientY + document.documentElement.scrollTop - document.body.clientTop
|
||
};
|
||
} |