修正版gooflow流程解决方案(源码分享+在线演示+U…
2018-06-22 06:14:52来源:未知 阅读 ()
一、功能简介
gooflow功能清单
1、自定义流程绘制
2、自定义属性添加
3、支持3种步骤类型
普通审批步骤
自动决策步骤
手动决策步骤
4、决策方式(支持js决策,sql语句决策)
5、审批人员参与方式,可以自定配置,系统目前自带(员工,部门,岗位,sql语句4种方式)
6、响应方式(支持多人审批通过,和单人审批通过)
7、事件执行方式(审批通过后可以触发配置事件)
8、消息提醒(支持实时提醒)
9、流程决策条件,自定义配置
10、版本控制
11、后台管理
二、流程审批功能
1、提交
2、退回
3、退回上一步
4、退回到开始节点
5、表单退回
6、审批不通过
7、附件上传
8、传阅、转办、撤回、查看流程图。
9、提供WebAPI接口
10、可配置审批参与者数据源
三、接口说明
作用 |
接口名称 |
参数 |
返回值 |
获取审批列表 |
GetApprovalList |
1.(string)userdata 2.(int)page 3.(int)pagesize 4.(int)isOver 5.(string) flowLevel 6.(string)where |
Dynamic->JsonData
|
获取审批列表汇总信息 |
LoadApprovalListSummary |
1.(string)userData |
Dynamic->JsonData
|
初始化流程状态 |
InitFlowState |
1.string userData 2.string flowNo 3.int appID 4.string formHtml 5.string formData 6.string formUrl |
Dynamic-> { status = ? flowID = ? } |
获取当前步骤信息 |
GetCurrentStepInfo |
1.string userData 2.int approvalID = 0 3.int? flowID = 0 4.int? appID = 0 |
Dynamic -> { status = ? stepData =? isBack = ? isTurnRead =? isTurnRead=? isTurnDo = ? }; |
获取审批参与者 |
FindFlowApprovers |
1.string userData 2.int flowID 3.int approvalID 4. int appID 5. string toNodeID = "" |
Dynamic ->{ status = ? data = ? } |
获取审批意见 |
GetApprovalOpinions |
|
Dynamic -> { data = ? } |
获取下个节点(所有) |
GetNextFlowNodes |
1.int flowID 2.int appID 3.int approvalID |
Dynamic -> { status = ? data = ? } |
获取决策方案 |
GetFlowDecisionModes |
|
Dynamic -> { status = ? data = ? } |
流转主要功能接口 |
FlowAction |
1.string userData 2.string actionType 3.int stateID 4.int approvalID 5.int appID; 6.bool isPass 7.string opinion 8.string formName 9.string participantJson 10.string participantValue 11.int level 12.int turnToDoID = 0 |
Dynamic -> { status = ? data = ? } |
获取待阅 列表数据 |
GetTurnToReadPageList |
1.string userData 2.int page 3.int pagesize 4.int isRead 5.string where |
Dynamic->JsonData |
查找传阅参与者 |
FindFlowTurnToReaders |
1.string userData, 2.int flowID, 3.string nodeID |
Dynamic -> { status = ?, data = ? } |
浏览传阅表单 |
ReadApprovalForm |
1.tring userData 2.int approvalID |
Dynamic -> { status = ? } |
获取传阅数据 |
GetTurnToReadList |
int stateID |
Dynamic->JsonData |
获取代办参与者数据 |
FindFlowTurnToApprovers |
|
Dynamic -> { status = ?, data=? } |
获取代办数据 |
GetTurnToDoPageList |
1.string userData 2.int pag 3.int pagesize 4.int isOver 5.string where |
Dynamic->JsonData |
获取流程图流转标记 |
GetFlowElementMarked |
1.int flowID 2. int appID |
Dynamic -> { status = ?, data=? } |
四、流转界面
1 function currentDate() { 2 //日期 3 var date = new Date(); 4 var y = date.getYear(); 5 var m = date.getMonth() + 1; 6 var d = date.getDate(); 7 var hh = date.getHours(); 8 var mm = date.getMinutes(); 9 var ss = date.getMilliseconds(); 10 return y + (m < 10 ? ('0' + m) : m) + (d < 10 ? ('0' + d) : d) + (hh < 10 ? ('0' + hh) : hh) + (mm < 10 ? ('0' + mm) : mm) + (ss < 100 ? ('00' + ss) : ss) 11 } 12 //定义一个区域图类: 13 function GooFlow(bgDiv, property) { 14 if (navigator.userAgent.indexOf("MSIE 8.0") > 0 || navigator.userAgent.indexOf("MSIE 7.0") > 0 || navigator.userAgent.indexOf("MSIE 6.0") > 0) 15 GooFlow.prototype.useSVG = ""; 16 else GooFlow.prototype.useSVG = "1"; 17 //初始化区域图的对象 18 this.$id = bgDiv.attr("id"); 19 this.$bgDiv = bgDiv;//最父框架的DIV 20 this.$bgDiv.addClass("GooFlow"); 21 if (GooFlow.prototype.color.font) { 22 this.$bgDiv.css("color", GooFlow.prototype.color.font); 23 } 24 var width = (property.width || 800) - 2; 25 var height = (property.height || 500) - 2; 26 this.$bgDiv.css({ width: width + "px", height: height + "px" }); 27 this.$tool = null;//左侧工具栏对象 28 this.$head = null;//顶部标签及工具栏按钮 29 this.$title = "newFlow_1";//流程图的名称 30 this.$nodeRemark = {};//每一种结点或按钮的说明文字,JSON格式,key为类名,value为用户自定义文字说明 31 this.$nowType = "cursor";//当前要绘制的对象类型 32 this.$lineData = {}; 33 this.$lineCount = 0; 34 this.$nodeData = {}; 35 this.$nodeCount = 0; 36 this.$areaData = {}; 37 this.$areaCount = 0; 38 this.$lineDom = {}; 39 this.$nodeDom = {}; 40 this.$areaDom = {}; 41 this.$max = property.initNum || 1;//计算默认ID值的起始SEQUENCE 42 this.$focus = "";//当前被选定的结点/转换线ID,如果没选中或者工作区被清空,则为"" 43 this.$cursor = "default";//鼠标指针在工作区内的样式 44 this.$editable = false;//工作区是否可编辑 45 this.$deletedItem = {};//在流程图的编辑操作中被删除掉的元素ID集合,元素ID为KEY,元素类型(node,line.area)为VALUE 46 var headHeight = 0; 47 var tmp = ""; 48 if (property.haveHead) { 49 tmp = "<div class='GooFlow_head' " + (GooFlow.prototype.color.main ? "style='border-bottom-color:" + GooFlow.prototype.color.main + "'" : "") 50 + ">"; 51 if (property.headLabel) { 52 tmp += "<label title='" + (property.initLabelText || "newFlow_1") + "' " 53 + (GooFlow.prototype.color.main ? "style='background:" + GooFlow.prototype.color.main + "'" : "") + ">" + (property.initLabelText || "newFlow_1") + "</label>"; 54 } 55 for (var x = 0; x < property.headBtns.length; ++x) { 56 tmp += "<a href='javascript:void(0)' class='GooFlow_head_btn'><i class='ico_" + property.headBtns[x] + "'></i></a>" 57 } 58 tmp += "</div>"; 59 this.$head = $(tmp); 60 this.$bgDiv.append(this.$head); 61 headHeight = 24; 62 //以下是当工具栏按钮被点击时触发的事件自定义(虚函数),格式为function(),因为可直接用THIS操作对象本身,不用传参;用户可自行重定义: 63 this.onBtnNewClick = null;//新建流程图按钮被点中 64 this.onBtnOpenClick = null;//打开流程图按钮定义 65 this.onBtnSaveClick = null;//保存流程图按钮定义 66 this.onFreshClick = null;//重载流程图按钮定义 67 this.onCloseClick = null; 68 if (property.headBtns) 69 this.$head.on("click", { inthis: this }, function (e) { 70 if (!e) e = window.event; 71 var tar = e.target; 72 if (tar.tagName == "DIV" || tar.tagName == "SPAN") return; 73 else if (tar.tagName == "a") tar = tar.childNode[0]; 74 var This = e.data.inthis; 75 //定义顶部操作栏按钮的事件 76 switch ($(tar).attr("class")) { 77 case "ico_new": if (This.onBtnNewClick != null) This.onBtnNewClick(); break; 78 case "ico_open": if (This.onBtnOpenClick != null) This.onBtnOpenClick(); break; 79 case "ico_save": if (This.onBtnSaveClick != null) This.onBtnSaveClick(); break; 80 case "ico_undo": This.undo(); break; 81 case "ico_redo": This.redo(); break; 82 case "ico_reload": if (This.onFreshClick != null) This.onFreshClick(); break; 83 case "ico_close": if (This.onCloseClick != null) This.onCloseClick(); break; 84 } 85 }); 86 } 87 var toolWidth = 0; 88 if (property.haveTool) { 89 this.$bgDiv.append("<div class='GooFlow_tool'" + (property.haveHead ? "" : " style='margin-top:3px'") + "><div style='height:" + (height - headHeight - (property.haveHead ? 7 : 10)) + "px' class='GooFlow_tool_div'></div></div>"); 90 this.$tool = this.$bgDiv.find(".GooFlow_tool div"); 91 //未加代码:加入绘图工具按钮 92 this.$tool.append( 93 "<a href='javascript:void(0)' type='cursor' class='GooFlow_tool_btndown' id='" + this.$id + "_btn_cursor'><i class='ico_cursor'/></a>" 94 //+ "<a href='javascript:void(0)' type='mutiselect' class='GooFlow_tool_btn' id='" + this.$id + "_btn_mutiselect'><i class='ico_mutiselect'/></a>" 95 + "<a href='javascript:void(0)' type='direct' class='GooFlow_tool_btn' id='" + this.$id + "_btn_direct'><i class='ico_direct'/></a>" 96 ); 97 if (property.toolBtns && property.toolBtns.length > 0) { 98 tmp = "<span/>"; 99 for (var i = 0; i < property.toolBtns.length; ++i) { 100 tmp += "<a href='javascript:void(0)' type='" + property.toolBtns[i] + "' id='" + this.$id + "_btn_" + property.toolBtns[i].split(" ")[0] + "' class='GooFlow_tool_btn'><i class='ico_" + property.toolBtns[i] + "'/></a>";//加入自定义按钮 101 } 102 this.$tool.append(tmp); 103 } 104 //加入区域划分框工具开关按钮 105 if (property.haveGroup) 106 this.$tool.append("<span/><a href='javascript:void(0)' type='group' class='GooFlow_tool_btn' id='" + this.$id + "_btn_group'><i class='ico_group'/></a>"); 107 toolWidth = 35; 108 this.$nowType = "cursor"; 109 //绑定各个按钮的点击事件 110 this.$tool.on("click", { inthis: this }, function (e) { 111 if (!e) e = window.event; 112 var tar; 113 switch (e.target.tagName) { 114 case "SPAN": return false; 115 case "DIV": return false; 116 case "I": tar = e.target.parentNode; break; 117 case "A": tar = e.target; 118 }; 119 var type = $(tar).attr("type"); 120 e.data.inthis.switchToolBtn(type); 121 return false; 122 }); 123 this.$editable = true;//只有具有工具栏时可编辑 124 } 125 width = width - toolWidth - 9; 126 height = height - headHeight - (property.haveHead ? 5 : 8); 127 this.$bgDiv.append("<div class='GooFlow_work' style='width:" + (width) + "px;height:" + (height) + "px;" + (property.haveHead ? "" : "margin-top:3px") + "'></div>"); 128 this.$workArea = $("<div class='GooFlow_work_inner' style='width:" + width * 3 + "px;height:" + height * 3 + "px'></div>") 129 .attr({ "unselectable": "on", "onselectstart": 'return false', "onselect": 'document.selection.empty()' }); 130 this.$bgDiv.children(".GooFlow_work").append(this.$workArea); 131 this.$draw = null;//画矢量线条的容器 132 this.initDraw("draw_" + this.$id, width, height); 133 this.$group = null; 134 if (property.haveGroup) 135 this.initGroup(width, height); 136 if (this.$editable) { 137 this.$workArea.on("click", { inthis: this }, function (e) { 138 if (!e) e = window.event; 139 var This = e.data.inthis; 140 if (!This.$editable) return; 141 var type = This.$nowType; 142 if (type == "cursor") { 143 var t = $(e.target); 144 var n = t.prop("tagName"); 145 //alert(n); 146 if (n == "svg" || (n == "DIV" && t.prop("class").indexOf("GooFlow_work") > -1) || n == "LABEL") { 147 if (This.$lineOper.data("tid")) { 148 This.focusItem(This.$lineOper.data("tid"), false); 149 //This.$mpFrom.removeData("p"); 150 } 151 else { This.blurItem(); } 152 } 153 return; 154 } 155 else if (type == "direct" || type == "group") return; 156 var X, Y; 157 var ev = mousePosition(e), t = getElCoordinate(this); 158 X = ev.x - t.left + this.parentNode.scrollLeft - 1; 159 Y = ev.y - t.top + this.parentNode.scrollTop - 1; 160 161 //2015-01-13 TXF 162 //This.addNode(This.$id + "_node_" + This.$max, { name: "node_" + This.$max, left: X, top: Y, type: This.$nowType }); 163 //This.$max++; 164 This.addNode(This.$id + "_node_" + currentDate(), { name: "node_" + currentDate(), left: X, top: Y, type: e.data.inthis.$nowType, width: 135, height: 50 }); 165 }); 166 //划线或改线时用的绑定 167 this.$workArea.mousemove({ inthis: this }, function (e) { 168 if (e.data.inthis.$nowType != "direct" && !e.data.inthis.$mpTo.data("p")) return; 169 var lineStart = $(this).data("lineStart"); 170 var lineEnd = $(this).data("lineEnd"); 171 if (!lineStart && !lineEnd) return; 172 173 var ev = mousePosition(e), t = getElCoordinate(this); 174 var X, Y; 175 X = ev.x - t.left + this.parentNode.scrollLeft; 176 Y = ev.y - t.top + this.parentNode.scrollTop; 177 var line = document.getElementById("GooFlow_tmp_line"); 178 if (lineStart) { 179 if (GooFlow.prototype.useSVG != "") { 180 line.childNodes[0].setAttribute("d", "M " + lineStart.x + " " + lineStart.y + " L " + X + " " + Y); 181 line.childNodes[1].setAttribute("d", "M " + lineStart.x + " " + lineStart.y + " L " + X + " " + Y); 182 if (line.childNodes[1].getAttribute("marker-end") == "url(\"#arrow2\")") 183 line.childNodes[1].setAttribute("marker-end", "url(#arrow3)"); 184 else line.childNodes[1].setAttribute("marker-end", "url(#arrow2)"); 185 } 186 else line.points.value = lineStart.x + "," + lineStart.y + " " + X + "," + Y; 187 } else if (lineEnd) { 188 if (GooFlow.prototype.useSVG != "") { 189 line.childNodes[0].setAttribute("d", "M " + X + " " + Y + " L " + lineEnd.x + " " + lineEnd.y); 190 line.childNodes[1].setAttribute("d", "M " + X + " " + Y + " L " + lineEnd.x + " " + lineEnd.y); 191 if (line.childNodes[1].getAttribute("marker-end") == "url(\"#arrow2\")") 192 line.childNodes[1].setAttribute("marker-end", "url(#arrow3)"); 193 else line.childNodes[1].setAttribute("marker-end", "url(#arrow2)"); 194 } 195 else line.points.value = X + "," + Y + " " + lineEnd.x + "," + lineEnd.y; 196 } 197 }); 198 this.$workArea.mouseup({ inthis: this }, function (e) { 199 var This = e.data.inthis; 200 if (This.$nowType != "direct" && !This.$mpTo.data("p")) return; 201 var tmp = document.getElementById("GooFlow_tmp_line"); 202 if (tmp) { 203 $(this).css("cursor", "auto").removeData("lineStart").removeData("lineEnd"); 204 This.$mpTo.hide().removeData("p"); 205 This.$mpFrom.hide().removeData("p"); 206 This.$draw.removeChild(tmp); 207 This.focusItem(This.$focus, false); 208 } else { 209 This.$lineOper.removeData("tid"); 210 } 211 }); 212 //为了结点而增加的一些集体delegate绑定 213 this.initWorkForNode(); 214 //对结点进行移动或者RESIZE时用来显示的遮罩层 215 this.$ghost = $("<div class='rs_ghost'></div>").attr({ "unselectable": "on", "onselectstart": 'return false', "onselect": 'document.selection.empty()' }); 216 this.$bgDiv.append(this.$ghost); 217 this.$textArea = $("<textarea></textarea>"); 218 this.$bgDiv.append(this.$textArea); 219 this.$lineMove = $("<div class='GooFlow_line_move' style='display:none'></div>");//操作折线时的移动框 220 this.$workArea.append(this.$lineMove); 221 this.$lineMove.on("mousedown", { inthis: this }, function (e) { 222 if (e.button == 2) return false; 223 var lm = $(this); 224 lm.css({ "background-color": GooFlow.prototype.color.font || "#333" }); 225 var This = e.data.inthis; 226 var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]); 227 var X, Y; 228 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 229 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 230 var p = This.$lineMove.position(); 231 var vX = X - p.left, vY = Y - p.top; 232 var isMove = false; 233 document.onmousemove = function (e) { 234 if (!e) e = window.event; 235 var ev = mousePosition(e); 236 var ps = This.$lineMove.position(); 237 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 238 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 239 if (This.$lineMove.data("type") == "lr") { 240 X = X - vX; 241 if (X < 0) X = 0; 242 else if (X > This.$workArea.width()) 243 X = This.$workArea.width(); 244 This.$lineMove.css({ left: X + "px" }); 245 } 246 else if (This.$lineMove.data("type") == "tb") { 247 Y = Y - vY; 248 if (Y < 0) Y = 0; 249 else if (Y > This.$workArea.height()) 250 Y = This.$workArea.height(); 251 This.$lineMove.css({ top: Y + "px" }); 252 } 253 isMove = true; 254 } 255 document.onmouseup = function (e) { 256 if (isMove) { 257 var p = This.$lineMove.position(); 258 if (This.$lineMove.data("type") == "lr") 259 This.setLineM(This.$lineMove.data("tid"), p.left + 3); 260 else if (This.$lineMove.data("type") == "tb") 261 This.setLineM(This.$lineMove.data("tid"), p.top + 3); 262 } 263 This.$lineMove.css({ "background-color": "transparent" }); 264 if (This.$focus == This.$lineMove.data("tid")) { 265 This.focusItem(This.$lineMove.data("tid")); 266 } 267 document.onmousemove = null; 268 document.onmouseup = null; 269 } 270 }); 271 //选定一条转换线后出现的浮动操作栏,有改变线的样式和删除线等按钮。 272 this.$lineOper = $("<div class='GooFlow_line_oper' style='display:none'><i class='b_l1'></i><i class='b_l2'></i><i class='b_l3'></i><i class='b_x'></i></div>");//选定线时显示的操作框 273 this.$workArea.parent().append(this.$lineOper); 274 this.$lineOper.on("click", { inthis: this }, function (e) { 275 if (!e) e = window.event; 276 if (e.target.tagName != "I") return; 277 var This = e.data.inthis; 278 var id = $(this).data("tid"); 279 switch ($(e.target).attr("class")) { 280 case "b_x": 281 This.delLine(id); 282 this.style.display = "none"; break; 283 case "b_l1": 284 This.setLineType(id, "lr"); break; 285 case "b_l2": 286 This.setLineType(id, "tb"); break; 287 case "b_l3": 288 This.setLineType(id, "sl"); break; 289 } 290 }); 291 //新增移动线两个端点至新的结点功能移动功能,这里要提供移动用的DOM 292 this.$mpFrom = $("<div class='GooFlow_line_mp' style='display:none'></div>"); 293 this.$mpTo = $("<div class='GooFlow_line_mp' style='display:none'></div>"); 294 this.$workArea.append(this.$mpFrom).append(this.$mpTo); 295 this.initLinePointsChg(); 296 297 //下面绑定当结点/线/分组块的一些操作事件,这些事件可直接通过this访问对象本身 298 //当操作某个单元(结点/线/分组块)被添加时,触发的方法,返回FALSE可阻止添加事件的发生 299 //格式function(id,type,json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json. 300 this.onItemAdd = null; 301 //当操作某个单元(结点/线/分组块)被删除时,触发的方法,返回FALSE可阻止删除事件的发生 302 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值 303 this.onItemDel = null; 304 //当操作某个单元(结点/分组块)被移动时,触发的方法,返回FALSE可阻止移动事件的发生 305 //格式function(id,type,left,top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值,线line不支持移动,left是新的左边距坐标,top是新的顶边距坐标 306 this.onItemMove = null; 307 //当操作某个单元(结点/线/分组块)被重命名时,触发的方法,返回FALSE可阻止重命名事件的发生 308 //格式function(id,name,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称 309 this.onItemRename = null; 310 //当操作某个单元(结点/线)被由不选中变成选中时,触发的方法,返回FALSE可阻止选中事件的发生 311 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中 312 this.onItemFocus = null; 313 //当操作某个单元(结点/线)被由选中变成不选中时,触发的方法,返回FALSE可阻止取消选中事件的发生 314 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中 315 this.onItemBlur = null; 316 //当操作某个单元(结点/分组块)被重定义大小或造型时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 317 //格式function(id,type,width,height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值;width是新的宽度,height是新的高度 318 this.onItemResize = null; 319 //当移动某条折线中段的位置,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 320 //格式function(id,M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标 321 this.onLineMove = null; 322 //当变换某条连接线的类型,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 323 //格式function(id,type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线 324 this.onLineSetType = null; 325 //当变换某条连接线的端点变更连接的结点时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 326 //格式function(id,newStart,newEnd):id是连线单元的唯一标识ID,newStart,newEnd分别是起始结点的ID和到达结点的ID 327 this.onLinePointMove = null; 328 //当用重色标注某个结点/转换线时触发的方法,返回FALSE可阻止重定大小/造型事件的发生 329 //格式function(id,type,mark):id是单元的唯一标识ID,type是单元类型("node"结点,"line"转换线),mark为布尔值,表示是要标注TRUE还是取消标注FALSE 330 this.onItemMark = null; 331 //分组区域颜色改变事件 332 this.onAreaSetColor = null; 333 334 if (property.useOperStack && this.$editable) {//如果要使用堆栈记录操作并提供“撤销/重做”的功能,只在编辑状态下有效 335 this.$undoStack = []; 336 this.$redoStack = []; 337 this.$isUndo = 0; 338 ///////////////以下是构造撤销操作/重做操作的方法 339 //为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放40步操作;超过40步时,将自动删掉最旧的一个缓存 340 this.pushOper = function (funcName, paras) { 341 var len = this.$undoStack.length; 342 if (this.$isUndo == 1) { 343 this.$redoStack.push([funcName, paras]); 344 this.$isUndo = false; 345 if (this.$redoStack.length > 40) this.$redoStack.shift(); 346 } else { 347 this.$undoStack.push([funcName, paras]); 348 if (this.$undoStack.length > 40) this.$undoStack.shift(); 349 if (this.$isUndo == 0) { 350 this.$redoStack.splice(0, this.$redoStack.length); 351 } 352 this.$isUndo = 0; 353 } 354 }; 355 //将外部的方法加入到GooFlow对象的事务操作堆栈中,在过后的undo/redo操作中可以进行控制,一般用于对流程图以外的附加信息进行编辑的事务撤销/重做控制; 356 //传参func为要执行方法对象,jsonPara为外部方法仅有的一个面向字面的JSON传参,由JSON对象带入所有要传的信息; 357 //提示:为了让外部方法能够被UNDO/REDO,需要在编写这些外部方法实现时,加入对该方法执行后效果回退的另一个执行方法的pushExternalOper 358 this.pushExternalOper = function (func, jsonPara) { 359 this.pushOper("externalFunc", [func, jsonPara]); 360 }; 361 //撤销上一步操作 362 this.undo = function () { 363 if (this.$undoStack.length == 0) return; 364 this.blurItem(); 365 var tmp = this.$undoStack.pop(); 366 this.$isUndo = 1; 367 if (tmp[0] == "externalFunc") { 368 tmp[1][0](tmp[1][1]); 369 } 370 else { 371 //传参的数量,最多支持6个. 372 switch (tmp[1].length) { 373 case 0: this[tmp[0]](); break; 374 case 1: this[tmp[0]](tmp[1][0]); break; 375 case 2: this[tmp[0]](tmp[1][0], tmp[1][1]); break; 376 case 3: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]); break; 377 case 4: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]); break; 378 case 5: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]); break; 379 case 6: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4], tmp[1][5]); break; 380 } 381 } 382 }; 383 //重做最近一次被撤销的操作 384 this.redo = function () { 385 if (this.$redoStack.length == 0) return; 386 this.blurItem(); 387 var tmp = this.$redoStack.pop(); 388 this.$isUndo = 2; 389 if (tmp[0] == "externalFunc") { 390 tmp[1][0](tmp[1][1]); 391 } 392 else { 393 //传参的数量,最多支持6个. 394 switch (tmp[1].length) { 395 case 0: this[tmp[0]](); break; 396 case 1: this[tmp[0]](tmp[1][0]); break; 397 case 2: this[tmp[0]](tmp[1][0], tmp[1][1]); break; 398 case 3: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2]); break; 399 case 4: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3]); break; 400 case 5: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4]); break; 401 case 6: this[tmp[0]](tmp[1][0], tmp[1][1], tmp[1][2], tmp[1][3], tmp[1][4], tmp[1][5]); break; 402 } 403 } 404 }; 405 } 406 $(document).keydown({ inthis: this }, function (e) { 407 //绑定键盘操作 408 var This = e.data.inthis; 409 if (This.$focus == "") return; 410 switch (e.keyCode) { 411 case 46://删除 412 This.delNode(This.$focus, true); 413 This.delLine(This.$focus); 414 break; 415 } 416 }); 417 } 418 } 419 GooFlow.prototype = { 420 useSVG: "", 421 getSvgMarker: function (id, color) { 422 var m = document.createElementNS("http://www.w3.org/2000/svg", "marker"); 423 m.setAttribute("id", id); 424 m.setAttribute("viewBox", "0 0 6 6"); 425 m.setAttribute("refX", 5); 426 m.setAttribute("refY", 3); 427 m.setAttribute("markerUnits", "strokeWidth"); 428 m.setAttribute("markerWidth", 6); 429 m.setAttribute("markerHeight", 6); 430 m.setAttribute("orient", "auto"); 431 var path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 432 path.setAttribute("d", "M 0 0 L 6 3 L 0 6 z"); 433 path.setAttribute("fill", color); 434 path.setAttribute("stroke-width", 0); 435 m.appendChild(path); 436 return m; 437 }, 438 initDraw: function (id, width, height) { 439 var elem; 440 if (GooFlow.prototype.useSVG != "") { 441 this.$draw = document.createElementNS("http://www.w3.org/2000/svg", "svg");//可创建带有指定命名空间的元素节点 442 this.$workArea.prepend(this.$draw); 443 var defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); 444 this.$draw.appendChild(defs); 445 defs.appendChild(GooFlow.prototype.getSvgMarker("arrow1", GooFlow.prototype.color.line || "#3892D3")); 446 defs.appendChild(GooFlow.prototype.getSvgMarker("arrow2", GooFlow.prototype.color.mark || "#ff3300")); 447 defs.appendChild(GooFlow.prototype.getSvgMarker("arrow3", GooFlow.prototype.color.mark || "#ff3300")); 448 } 449 else { 450 this.$draw = document.createElement("v:group"); 451 this.$draw.coordsize = width * 3 + "," + height * 3; 452 this.$workArea.prepend("<div class='GooFlow_work_vml' style='position:relative;width:" + width * 3 + "px;height:" + height * 3 + "px'></div>"); 453 this.$workArea.children("div")[0].insertBefore(this.$draw, null); 454 } 455 this.$draw.id = id; 456 this.$draw.style.width = width * 3 + "px"; 457 this.$draw.style.height = +height * 3 + "px"; 458 //绑定连线的点击选中以及双击编辑事件 459 var tmpClk = null; 460 if (GooFlow.prototype.useSVG != "") tmpClk = "g"; 461 else tmpClk = "PolyLine"; 462 if (!this.$editable) return; 463 464 $(this.$draw).delegate(tmpClk, "click", { inthis: this }, function (e) { 465 e.data.inthis.focusItem(this.id, true); 466 }); 467 $(this.$draw).delegate(tmpClk, "dblclick", { inthis: this }, function (e) { 468 var oldTxt, x, y, from, to; 469 var This = e.data.inthis; 470 if (GooFlow.prototype.useSVG != "") { 471 oldTxt = this.childNodes[2].textContent; 472 from = this.getAttribute("from").split(","); 473 to = this.getAttribute("to").split(","); 474 } else { 475 oldTxt = this.childNodes[1].innerHTML; 476 var n = this.getAttribute("fromTo").split(","); 477 from = [n[0], n[1]]; 478 to = [n[2], n[3]]; 479 } 480 if (This.$lineData[this.id].type == "lr") { 481 from[0] = This.$lineData[this.id].M; 482 to[0] = from[0]; 483 } 484 else if (This.$lineData[this.id].type == "tb") { 485 from[1] = This.$lineData[this.id].M; 486 to[1] = from[1]; 487 } 488 x = (parseInt(from[0], 10) + parseInt(to[0], 10)) / 2 - 60; 489 y = (parseInt(from[1], 10) + parseInt(to[1], 10)) / 2 - 12; 490 var t = getElCoordinate(This.$workArea[0]); 491 This.$textArea.val(oldTxt).css({ 492 display: "block", width: 120, height: 14, 493 left: t.left + x - This.$workArea[0].parentNode.scrollLeft, 494 top: t.top + y - This.$workArea[0].parentNode.scrollTop 495 }).data("id", This.$focus).focus(); 496 This.$workArea.parent().one("mousedown", function (e) { 497 if (e.button == 2) return false; 498 This.setName(This.$textArea.data("id"), This.$textArea.val(), "line"); 499 This.$textArea.val("").removeData("id").hide(); 500 }); 501 }); 502 }, 503 initGroup: function (width, height) { 504 this.$group = $("<div class='GooFlow_work_group' style='width:" + width * 3 + "px;height:" + height * 3 + "px'></div>");//存放背景区域的容器 505 this.$workArea.prepend(this.$group); 506 if (!this.$editable) return; 507 //区域划分框操作区的事件绑定 508 this.$group.on("mousedown", { inthis: this }, function (e) {//绑定RESIZE功能以及移动功能 509 if (e.button == 2) return false; 510 var This = e.data.inthis; 511 if (This.$nowType != "group") return; 512 if (This.$textArea.css("display") == "block") { 513 This.setName(This.$textArea.data("id"), This.$textArea.val(), "area"); 514 This.$textArea.val("").removeData("id").hide(); 515 return false; 516 }; 517 if (!e) e = window.event; 518 var cursor = $(e.target).css("cursor"); 519 var id = e.target.parentNode; 520 switch (cursor) { 521 case "nw-resize": id = id.parentNode; break; 522 case "w-resize": id = id.parentNode; break; 523 case "n-resize": id = id.parentNode; break; 524 case "move": break; 525 default: return; 526 } 527 id = id.id; 528 var hack = 1; 529 if (navigator.userAgent.indexOf("8.0") != -1) hack = 0; 530 var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]); 531 532 var X, Y; 533 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 534 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 535 if (cursor != "move") { 536 This.$ghost.css({ 537 display: "block", 538 width: This.$areaData[id].width - 2 + "px", height: This.$areaData[id].height - 2 + "px", 539 top: This.$areaData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px", 540 left: This.$areaData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor 541 }); 542 var vX = (This.$areaData[id].left + This.$areaData[id].width) - X; 543 var vY = (This.$areaData[id].top + This.$areaData[id].height) - Y; 544 } 545 else { 546 var vX = X - This.$areaData[id].left; 547 var vY = Y - This.$areaData[id].top; 548 } 549 var isMove = false; 550 This.$ghost.css("cursor", cursor); 551 document.onmousemove = function (e) { 552 if (!e) e = window.event; 553 var ev = mousePosition(e); 554 if (cursor != "move") { 555 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft - This.$areaData[id].left + vX; 556 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop - This.$areaData[id].top + vY; 557 if (X < 200) X = 200; 558 if (Y < 100) Y = 100; 559 switch (cursor) { 560 case "nw-resize": This.$ghost.css({ width: X - 2 + "px", height: Y - 2 + "px" }); break; 561 case "w-resize": This.$ghost.css({ width: X - 2 + "px" }); break; 562 case "n-resize": This.$ghost.css({ height: Y - 2 + "px" }); break; 563 } 564 } 565 else { 566 if (This.$ghost.css("display") == "none") { 567 This.$ghost.css({ 568 display: "block", 569 width: This.$areaData[id].width - 2 + "px", height: This.$areaData[id].height - 2 + "px", 570 top: This.$areaData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px", 571 left: This.$areaData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor 572 }); 573 } 574 X = ev.x - vX; Y = ev.y - vY; 575 if (X < t.left - This.$workArea[0].parentNode.scrollLeft) 576 X = t.left - This.$workArea[0].parentNode.scrollLeft; 577 else if (X + This.$workArea[0].parentNode.scrollLeft + This.$areaData[id].width > t.left + This.$workArea.width()) 578 X = t.left + This.$workArea.width() - This.$workArea[0].parentNode.scrollLeft - This.$areaData[id].width; 579 if (Y < t.top - This.$workArea[0].parentNode.scrollTop) 580 Y = t.top - This.$workArea[0].parentNode.scrollTop; 581 else if (Y + This.$workArea[0].parentNode.scrollTop + This.$areaData[id].height > t.top + This.$workArea.height()) 582 Y = t.top + This.$workArea.height() - This.$workArea[0].parentNode.scrollTop - This.$areaData[id].height; 583 This.$ghost.css({ left: X + hack + "px", top: Y + hack + "px" }); 584 } 585 isMove = true; 586 } 587 document.onmouseup = function (e) { 588 This.$ghost.empty().hide(); 589 document.onmousemove = null; 590 document.onmouseup = null; 591 if (!isMove) return; 592 if (cursor != "move") 593 This.resizeArea(id, This.$ghost.outerWidth(), This.$ghost.outerHeight()); 594 else 595 This.moveArea(id, X + This.$workArea[0].parentNode.scrollLeft - t.left, Y + This.$workArea[0].parentNode.scrollTop - t.top); 596 return false; 597 } 598 }); 599 //绑定修改文字说明功能 600 this.$group.on("dblclick", { inthis: this }, function (e) { 601 var This = e.data.inthis; 602 if (This.$nowType != "group") return; 603 if (!e) e = window.event; 604 if (e.target.tagName != "LABEL") return false; 605 var oldTxt = e.target.innerHTML; 606 var p = e.target.parentNode; 607 var x = parseInt(p.style.left, 10) + 18, y = parseInt(p.style.top, 10) + 1; 608 var t = getElCoordinate(This.$workArea[0]); 609 This.$textArea.val(oldTxt).css({ 610 display: "block", width: 100, height: 14, 611 left: t.left + x - This.$workArea[0].parentNode.scrollLeft, 612 top: t.top + y - This.$workArea[0].parentNode.scrollTop 613 }).data("id", p.id).focus(); 614 This.$workArea.parent().one("mousedown", function (e) { 615 if (e.button == 2) return false; 616 if (This.$textArea.css("display") == "block") { 617 This.setName(This.$textArea.data("id"), This.$textArea.val(), "area"); 618 This.$textArea.val("").removeData("id").hide(); 619 } 620 }); 621 return false; 622 }); 623 //绑定点击事件 624 this.$group.mouseup({ inthis: this }, function (e) { 625 626 var This = e.data.inthis; 627 if (This.$nowType != "group") return; 628 if (!e) e = window.event; 629 switch ($(e.target).attr("class")) { 630 case "rs_close": This.delArea(e.target.parentNode.parentNode.id); return false;//删除该分组区域 631 case "bg": return; 632 } 633 switch (e.target.tagName) { 634 case "LABEL": return false; 635 case "I"://绑定变色功能 636 var id = e.target.parentNode.id; 637 switch (This.$areaData[id].color) { 638 case "red": This.setAreaColor(id, "yellow"); break; 639 case "yellow": This.setAreaColor(id, "blue"); break; 640 case "blue": This.setAreaColor(id, "green"); break; 641 case "green": This.setAreaColor(id, "red"); break; 642 } 643 return false; 644 } 645 if (e.data.inthis.$ghost.css("display") == "none") { 646 var X, Y; 647 var ev = mousePosition(e), t = getElCoordinate(this); 648 X = ev.x - t.left + this.parentNode.parentNode.scrollLeft - 1; 649 Y = ev.y - t.top + this.parentNode.parentNode.scrollTop - 1; 650 var color = ["red", "yellow", "blue", "green"]; 651 //TXF 2015-01-13 652 //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 }); 653 //e.data.inthis.$max++; 654 e.data.inthis.addArea(e.data.inthis.$id + "_area_" + currentDate(), { name: "area_" + currentDate(), left: X, top: Y, color: color[e.data.inthis.$max % 4], width: 200, height: 100 }); 655 return false; 656 } 657 }); 658 }, 659 //初始化用来改变连线的连接端点的两个小方块的操作事件 660 initLinePointsChg: function () { 661 this.$mpFrom.on("mousedown", { inthis: this }, function (e) { 662 var This = e.data.inthis; 663 This.switchToolBtn("cursor"); 664 var ps = This.$mpFrom.data("p").split(","); 665 var pe = This.$mpTo.data("p").split(","); 666 $(this).hide(); 667 This.$workArea.data("lineEnd", { "x": pe[0], "y": pe[1], "id": This.$lineData[This.$lineOper.data("tid")].to }).css("cursor", "crosshair"); 668 var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [ps[0], ps[1]], [pe[0], pe[1]], true, true); 669 This.$draw.appendChild(line); 670 return false; 671 }); 672 this.$mpTo.on("mousedown", { inthis: this }, function (e) { 673 var This = e.data.inthis; 674 This.switchToolBtn("cursor"); 675 var ps = This.$mpFrom.data("p").split(","); 676 var pe = This.$mpTo.data("p").split(","); 677 $(this).hide(); 678 This.$workArea.data("lineStart", { "x": ps[0], "y": ps[1], "id": This.$lineData[This.$lineOper.data("tid")].from }).css("cursor", "crosshair"); 679 var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [ps[0], ps[1]], [pe[0], pe[1]], true, true); 680 This.$draw.appendChild(line); 681 return false; 682 }); 683 }, 684 //每一种类型结点及其按钮的说明文字 685 setNodeRemarks: function (remark) { 686 if (this.$tool == null) return; 687 this.$tool.children("a").each(function () { 688 this.title = remark[$(this).attr("id").split("btn_")[1]]; 689 }); 690 this.$nodeRemark = remark; 691 }, 692 693 //切换左边工具栏按钮,传参TYPE表示切换成哪种类型的按钮 694 switchToolBtn: function (type) { 695 if (!this.$tool) return; 696 this.$tool.children("#" + this.$id + "_btn_" + this.$nowType.split(" ")[0]).attr("class", "GooFlow_tool_btn"); 697 if (this.$nowType == "group") { 698 this.$workArea.prepend(this.$group); 699 for (var key in this.$areaDom) this.$areaDom[key].addClass("lock").children("div:eq(1)").css("display", "none"); 700 } 701 this.$nowType = type; 702 this.$tool.children("#" + this.$id + "_btn_" + type.split(" ")[0]).attr("class", "GooFlow_tool_btndown"); 703 if (this.$nowType == "group") { 704 this.blurItem(); 705 this.$workArea.append(this.$group); 706 for (var key in this.$areaDom) this.$areaDom[key].removeClass("lock").children("div:eq(1)").css("display", ""); 707 } else if (this.$nowType == "direct") { 708 this.blurItem(); 709 } 710 if (this.$textArea.css("display") == "none") this.$textArea.removeData("id").val("").hide(); 711 }, 712 //增加一个流程结点,传参为一个JSON,有id,name,top,left,width,height,type(结点类型)等属性 713 //2015-07-28 TXF 714 addNode: function (id, json, disabled) { 715 if (!disabled) 716 if (this.onItemAdd != null && !this.onItemAdd(id, "node", json)) return; 717 if (this.$undoStack && this.$editable) { 718 this.pushOper("delNode", [id]); 719 } 720 var mark = json.marked ? " item_mark" : ""; 721 if (json.type != "start" && json.type != "end") { 722 if (!json.width || json.width < 135) json.width = 135; 723 if (!json.height || json.height < 50) json.height = 50; 724 if (!json.top || json.top < 0) json.top = 0; 725 if (!json.left || json.left < 0) json.left = 0; 726 var hack = 0; 727 if (navigator.userAgent.indexOf("8.0") != -1) hack = 2; 728 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 - 2) + "px;height:" + (json.height - 2) + "px;'><tr><td class='ico'><i class='ico_" + json.type + "'></i></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>"); 729 } 730 else { 731 json.width = 24; json.height = 24; 732 //2015-07-27 TXF 733 if (json.type == "start") 734 json.name = "开始"; 735 else if (json.type == "end") 736 json.name = "结束"; 737 this.$nodeDom[id] = $("<div class='GooFlow_item item_round" + mark + "' id='" + id + "' style='top:" + json.top + "px;left:" + json.left + "px'><table cellspacing='0'><tr><td class='ico'><i class='ico_" + json.type + "'></i></td></tr></table><div style='display:none'><div class='rs_close'></div></div><div class='span'>" + json.name + "</div></div>"); 738 } 739 if (GooFlow.prototype.color.node) { 740 if (json.type.indexOf(" mix") > -1) { 741 this.$nodeDom[id].css({ "background-color": GooFlow.prototype.color.mix, "border-color": GooFlow.prototype.color.mix }); 742 } else { 743 this.$nodeDom[id].css({ "background-color": GooFlow.prototype.color.node, "border-color": GooFlow.prototype.color.node }); 744 } 745 if (mark && GooFlow.prototype.color.mark) { 746 this.$nodeDom[id].css({ "border-color": GooFlow.prototype.color.mark }); 747 } 748 } 749 if (json.type.indexOf(" mix") > -1) { 750 this.$nodeDom[id].addClass("item_mix"); 751 } 752 753 var ua = navigator.userAgent.toLowerCase(); 754 if (ua.indexOf('msie') != -1 && ua.indexOf('8.0') != -1) 755 this.$nodeDom[id].css("filter", "progid:DXImageTransform.Microsoft.Shadow(color=#94AAC2,direction=135,strength=2)"); 756 this.$workArea.append(this.$nodeDom[id]); 757 this.$nodeData[id] = json; 758 ++this.$nodeCount; 759 if (this.$editable) { 760 this.$nodeData[id].alt = true; 761 if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 762 } 763 //2017-07-15 Taffy添加 764 this.focusItem(id, true); 765 }, 766 initWorkForNode: function () { 767 //绑定点击事件 768 this.$workArea.delegate(".GooFlow_item", "click", { inthis: this }, function (e) { 769 e.data.inthis.focusItem(this.id, true); 770 $(this).removeClass("item_mark"); 771 }); 772 //绑定用鼠标移动事件 773 this.$workArea.delegate(".ico", "mousedown", { inthis: this }, function (e) { 774 if (!e) e = window.event; 775 if (e.button == 2) return false; 776 var This = e.data.inthis; 777 if (This.$nowType == "direct") return; 778 var Dom = $(this).parents(".GooFlow_item"); 779 var id = Dom.attr("id"); 780 This.focusItem(id, true); 781 var hack = 1; 782 if (navigator.userAgent.indexOf("8.0") != -1) hack = 0; 783 var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]); 784 785 Dom.children("table").clone().prependTo(This.$ghost); 786 var X, Y; 787 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 788 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 789 var vX = X - This.$nodeData[id].left, vY = Y - This.$nodeData[id].top; 790 var isMove = false; 791 document.onmousemove = function (e) { 792 if (!e) e = window.event; 793 var ev = mousePosition(e); 794 if (X == ev.x - vX && Y == ev.y - vY) return false; 795 X = ev.x - vX; Y = ev.y - vY; 796 797 if (isMove && This.$ghost.css("display") == "none") { 798 This.$ghost.css({ 799 display: "block", 800 width: This.$nodeData[id].width - 2 + "px", height: This.$nodeData[id].height - 2 + "px", 801 top: This.$nodeData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px", 802 left: This.$nodeData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: "move" 803 }); 804 } 805 806 if (X < t.left - This.$workArea[0].parentNode.scrollLeft) 807 X = t.left - This.$workArea[0].parentNode.scrollLeft; 808 else if (X + This.$workArea[0].parentNode.scrollLeft + This.$nodeData[id].width > t.left + This.$workArea.width()) 809 X = t.left + This.$workArea.width() - This.$workArea[0].parentNode.scrollLeft - This.$nodeData[id].width; 810 if (Y < t.top - This.$workArea[0].parentNode.scrollTop) 811 Y = t.top - This.$workArea[0].parentNode.scrollTop; 812 else if (Y + This.$workArea[0].parentNode.scrollTop + This.$nodeData[id].height > t.top + This.$workArea.height()) 813 Y = t.top + This.$workArea.height() - This.$workArea[0].parentNode.scrollTop - This.$nodeData[id].height; 814 This.$ghost.css({ left: X + hack + "px", top: Y + hack + "px" }); 815 isMove = true; 816 } 817 document.onmouseup = function (e) { 818 if (isMove) This.moveNode(id, X + This.$workArea[0].parentNode.scrollLeft - t.left, Y + This.$workArea[0].parentNode.scrollTop - t.top); 819 This.$ghost.empty().hide(); 820 document.onmousemove = null; 821 document.onmouseup = null; 822 } 823 }); 824 if (!this.$editable) return; 825 //绑定鼠标覆盖/移出事件 826 this.$workArea.delegate(".GooFlow_item", "mouseenter", { inthis: this }, function (e) { 827 if (e.data.inthis.$nowType != "direct" && !document.getElementById("GooFlow_tmp_line")) return; 828 $(this).addClass("item_mark").addClass("crosshair").css("border-color", GooFlow.prototype.color.mark || "#ff3300"); 829 }); 830 this.$workArea.delegate(".GooFlow_item", "mouseleave", { inthis: this }, function (e) { 831 if (e.data.inthis.$nowType != "direct" && !document.getElementById("GooFlow_tmp_line")) return; 832 $(this).removeClass("item_mark").removeClass("crosshair"); 833 if (this.id == e.data.inthis.$focus) { 834 $(this).css("border-color", GooFlow.prototype.color.line || "#3892D3"); 835 } else { 836 $(this).css("border-color", GooFlow.prototype.color.node || "#A1DCEB"); 837 } 838 }); 839 //绑定连线时确定初始点 840 this.$workArea.delegate(".GooFlow_item", "mousedown", { inthis: this }, function (e) { 841 if (e.button == 2) return false; 842 var This = e.data.inthis; 843 if (This.$nowType != "direct") return; 844 var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]); 845 var X, Y; 846 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 847 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 848 This.$workArea.data("lineStart", { "x": X, "y": Y, "id": this.id }).css("cursor", "crosshair"); 849 var line = GooFlow.prototype.drawLine("GooFlow_tmp_line", [X, Y], [X, Y], true, true); 850 This.$draw.appendChild(line); 851 }); 852 //绑定连线时确定结束点 853 this.$workArea.delegate(".GooFlow_item", "mouseup", { inthis: this }, function (e) { 854 var This = e.data.inthis; 855 if (This.$nowType != "direct" && !This.$mpTo.data("p")) return; 856 var lineStart = This.$workArea.data("lineStart"); 857 var lineEnd = This.$workArea.data("lineEnd"); 858 if (lineStart && !This.$mpTo.data("p")) { 859 //2015-01-13 TXF 860 //This.addLine(This.$id + "_line_" + This.$max, { from: lineStart.id, to: this.id, name: "" }); 861 //This.$max++; 862 if (lineStart) This.addLine(This.$id + "_line_" + currentDate(), { from: lineStart.id, to: this.id, name: "", type: "sl" }); 863 } 864 else { 865 if (lineStart) { 866 This.moveLinePoints(This.$focus, lineStart.id, this.id); 867 } else if (lineEnd) { 868 This.moveLinePoints(This.$focus, this.id, lineEnd.id); 869 } 870 if (!This.$nodeData[this.id].marked) { 871 $(this).removeClass("item_mark"); 872 if (this.id != This.$focus) { 873 $(this).css("border-color", GooFlow.prototype.color.node); 874 } 875 else { 876 $(this).css("border-color", GooFlow.prototype.color.line); 877 } 878 } 879 } 880 }); 881 //绑定双击编辑事件 882 this.$workArea.delegate(".GooFlow_item > .span", "dblclick", { inthis: this }, function (e) { 883 var oldTxt = this.innerHTML; 884 var This = e.data.inthis; 885 var id = this.parentNode.id; 886 var t = getElCoordinate(This.$workArea[0]); 887 This.$textArea.val(oldTxt).css({ 888 display: "block", height: $(this).height(), width: 100, 889 left: t.left + This.$nodeData[id].left - This.$workArea[0].parentNode.scrollLeft - 24, 890 top: t.top + This.$nodeData[id].top - This.$workArea[0].parentNode.scrollTop + 26 891 }) 892 .data("id", This.$focus).focus(); 893 This.$workArea.parent().one("mousedown", function (e) { 894 if (e.button == 2) return false; 895 This.setName(This.$textArea.data("id"), This.$textArea.val(), "node"); 896 This.$textArea.val("").removeData("id").hide(); 897 }); 898 }); 899 this.$workArea.delegate(".ico + td", "dblclick", { inthis: this }, function (e) { 900 var oldTxt = this.innerHTML; 901 var This = e.data.inthis; 902 var id = $(this).parents(".GooFlow_item").attr("id"); 903 var t = getElCoordinate(This.$workArea[0]); 904 This.$textArea.val(oldTxt).css({ 905 display: "block", width: $(this).width() + 24, height: $(this).height(), 906 left: t.left + 24 + This.$nodeData[id].left - This.$workArea[0].parentNode.scrollLeft, 907 top: t.top + 2 + This.$nodeData[id].top - This.$workArea[0].parentNode.scrollTop 908 }) 909 .data("id", This.$focus).focus(); 910 This.$workArea.parent().one("mousedown", function (e) { 911 if (e.button == 2) return false; 912 This.setName(This.$textArea.data("id"), This.$textArea.val(), "node"); 913 This.$textArea.val("").removeData("id").hide(); 914 }); 915 }); 916 //绑定结点的删除功能 917 this.$workArea.delegate(".rs_close", "click", { inthis: this }, function (e) { 918 if (!e) e = window.event; 919 e.data.inthis.delNode(e.data.inthis.$focus); 920 return false; 921 }); 922 //绑定结点的RESIZE功能 923 this.$workArea.delegate(".GooFlow_item > div > div[class!=rs_close]", "mousedown", { inthis: this }, function (e) { 924 if (!e) e = window.event; 925 if (e.button == 2) return false; 926 var cursor = $(this).css("cursor"); 927 if (cursor == "pointer") { return; } 928 var This = e.data.inthis; 929 var id = This.$focus; 930 This.switchToolBtn("cursor"); 931 e.cancelBubble = true; 932 e.stopPropagation(); 933 var hack = 1; 934 if (navigator.userAgent.indexOf("8.0") != -1) hack = 0; 935 var ev = mousePosition(e), t = getElCoordinate(This.$workArea[0]); 936 This.$ghost.css({ 937 display: "block", 938 width: This.$nodeData[id].width - 2 + "px", height: This.$nodeData[id].height - 2 + "px", 939 top: This.$nodeData[id].top + t.top - This.$workArea[0].parentNode.scrollTop + hack + "px", 940 left: This.$nodeData[id].left + t.left - This.$workArea[0].parentNode.scrollLeft + hack + "px", cursor: cursor 941 }); 942 var X, Y; 943 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft; 944 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop; 945 var vX = (This.$nodeData[id].left + This.$nodeData[id].width) - X; 946 var vY = (This.$nodeData[id].top + This.$nodeData[id].height) - Y; 947 var isMove = false; 948 This.$ghost.css("cursor", cursor); 949 document.onmousemove = function (e) { 950 if (!e) e = window.event; 951 var ev = mousePosition(e); 952 X = ev.x - t.left + This.$workArea[0].parentNode.scrollLeft - This.$nodeData[id].left + vX; 953 Y = ev.y - t.top + This.$workArea[0].parentNode.scrollTop - This.$nodeData[id].top + vY; 954 if (X < 100) X = 100; 955 if (Y < 24) Y = 24; 956 isMove = true; 957 switch (cursor) { 958 case "nw-resize": This.$ghost.css({ width: X - 2 + "px", height: Y - 2 + "px" }); break; 959 case "w-resize": This.$ghost.css({ width: X - 2 + "px" }); break; 960 case "n-resize": This.$ghost.css({ height: Y - 2 + "px" }); break; 961 } 962 } 963 document.onmouseup = function (e) { 964 This.$ghost.hide(); 965 if (!isMove) return; 966 if (!e) e = window.event; 967 This.resizeNode(id, This.$ghost.outerWidth(), This.$ghost.outerHeight()); 968 document.onmousemove = null; 969 document.onmouseup = null; 970 } 971 }); 972 }, 973 //获取结点/连线/分组区域的详细信息 974 getItemInfo: function (id, type) { 975 switch (type) { 976 case "node": return this.$nodeData[id] || null; 977 case "line": return this.$lineData[id] || null; 978 case "area": return this.$areaData[id] || null; 979 } 980 }, 981 //取消所有结点/连线被选定的状态 982 blurItem: function () { 983 if (this.$focus != "") { 984 var jq = $("#" + this.$focus); 985 if (jq.prop("tagName") == "DIV") { 986 if (this.onItemBlur != null && !this.onItemBlur(this.$focus, "node")) return false; 987 jq.removeClass("item_focus").children("div:eq(0)").css("display", "none"); 988 if (GooFlow.prototype.color.line) { 989 if (this.$nodeData[this.$focus].marked) { 990 jq.css("border-color", GooFlow.prototype.color.mark || "#ff3300"); 991 } 992 else { 993 jq.css("border-color", GooFlow.prototype.color.node || "#A1DCEB"); 994 } 995 } 996 } 997 else { 998 if (this.onItemBlur != null && !this.onItemBlur(this.$focus, "line")) return false; 999 if (GooFlow.prototype.useSVG != "") { 1000 if (!this.$lineData[this.$focus].marked) { 1001 jq[0].childNodes[1].setAttribute("stroke", GooFlow.prototype.color.line || "#3892D3"); 1002 jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow1)"); 1003 } 1004 } 1005 else { 1006 if (!this.$lineData[this.$focus].marked) jq[0].strokeColor = GooFlow.prototype.color.line || "#3892D3"; 1007 } 1008 this.$lineMove.hide().removeData("type").removeData("tid"); 1009 if (this.$editable) { 1010 this.$lineOper.hide().removeData("tid"); 1011 this.$mpFrom.hide().removeData("p"); 1012 this.$mpTo.hide().removeData("p"); 1013 } 1014 } 1015 } 1016 this.$focus = ""; 1017 return true; 1018 }, 1019 //选定某个结点/转换线 bool:TRUE决定了要触发选中事件,FALSE则不触发选中事件,多用在程序内部调用。 1020 focusItem: function (id, bool) { 1021 var jq = $("#" + id); 1022 if (jq.length == 0) return; 1023 if (!this.blurItem()) return;//先执行"取消选中",如果返回FLASE,则也会阻止选定事件继续进行. 1024 if (jq.prop("tagName") == "DIV") { 1025 if (bool && this.onItemFocus != null && !this.onItemFocus(id, "node")) return; 1026 jq.addClass("item_focus"); 1027 if (GooFlow.prototype.color.line) { 1028 jq.css("border-color", GooFlow.prototype.color.line); 1029 } 1030 if (this.$editable) jq.children("div:eq(0)").css("display", "block"); 1031 this.$workArea.append(jq); 1032 } 1033 else {//如果是连接线 1034 if (this.onItemFocus != null && !this.onItemFocus(id, "line")) return; 1035 if (GooFlow.prototype.useSVG != "") { 1036 jq[0].childNodes[1].setAttribute("stroke", GooFlow.prototype.color.mark || "#ff3300"); 1037 jq[0].childNodes[1].setAttribute("marker-end", "url(#arrow2)"); 1038 } 1039 else jq[0].strokeColor = GooFlow.prototype.color.mark || "#ff3300"; 1040 if (!this.$editable) return; 1041 var x, y, from, to, n; 1042 if (GooFlow.prototype.useSVG != "") { 1043 from = jq.attr("from").split(","); 1044 to = jq.attr("to").split(","); 1045 n = [from[0], from[1], to[0], to[1]]; 1046 } else { 1047 n = jq[0].getAttribute("fromTo").split(","); 1048 from = [n[0], n[1]]; 1049 to = [n[2], n[3]]; 1050 } 1051 from[0] = parseInt(from[0], 10); 1052 from[1] = parseInt(from[1], 10); 1053 to[0] = parseInt(to[0], 10); 1054 to[1] = parseInt(to[1], 10); 1055 //var t=getElCoordinate(this.$workArea[0]); 1056 if (this.$lineData[id].type == "lr") { 1057 from[0] = this.$lineData[id].M; 1058 to[0] = from[0]; 1059 1060 this.$lineMove.css({ 1061 width: "5px", height: (to[1] - from[1]) * (to[1] > from[1] ? 1 : -1) + "px", 1062 left: from[0] - 3 + "px", 1063 top: (to[1] > from[1] ? from[1] : to[1]) + 1 + "px", 1064 cursor: "e-resize", display: "block" 1065 }).data({ "type": "lr", "tid": id }); 1066 } 1067 else if (this.$lineData[id].type == "tb") { 1068 from[1] = this.$lineData[id].M; 1069 to[1] = from[1]; 1070 this.$lineMove.css({ 1071 width: (to[0] - from[0]) * (to[0] > from[0] ? 1 : -1) + "px", height: "5px", 1072 left: (to[0] > from[0] ? from[0] : to[0]) + 1 + "px", 1073 top: from[1] - 3 + "px", 1074 cursor: "s-resize", display: "block" 1075 }).data({ "type": "tb", "tid": id }); 1076 } 1077 x = (from[0] + to[0]) / 2 - 35; 1078 y = (from[1] + to[1]) / 2 + 6; 1079 this.$lineOper.css({ display: "block", left: x + "px", top: y + "px" }).data("tid", id); 1080 if (this.$editable) { 1081 this.$mpFrom.css({ display: "block", left: n[0] - 4 + "px", top: n[1] - 4 + "px" }).data("p", n[0] + "," + n[1]); 1082 this.$mpTo.css({ display: "block", left: n[2] - 4 + "px", top: n[3] - 4 + "px" }).data("p", n[2] + "," + n[3]); 1083 } 1084 this.$draw.appendChild(jq[0]); 1085 } 1086 this.$focus = id; 1087 this.switchToolBtn("cursor"); 1088 }, 1089 //移动结点到一个新的位置 1090 moveNode: function (id, left, top) { 1091 if (!this.$nodeData[id]) return; 1092 if (this.onItemMove != null && !this.onItemMove(id, "node", left, top)) return; 1093 if (this.$undoStack) { 1094 var paras = [id, this.$nodeData[id].left, this.$nodeData[id].top]; 1095 this.pushOper("moveNode", paras); 1096 } 1097 if (left < 0) left = 0; 1098 if (top < 0) top = 0; 1099 $("#" + id).css({ left: left + "px", top: top + "px" }); 1100 this.$nodeData[id].left = left; 1101 this.$nodeData[id].top = top; 1102 //重画转换线 1103 this.resetLines(id, this.$nodeData[id]); 1104 if (this.$editable) { 1105 this.$nodeData[id].alt = true; 1106 } 1107 }, 1108 //设置结点/连线/分组区域的文字信息 1109 setName: function (id, name, type) { 1110 var oldName; 1111 if (type == "node") {//如果是结点 1112 if (!this.$nodeData[id]) return; 1113 if (this.$nodeData[id].name == name) return; 1114 if (this.onItemRename != null && !this.onItemRename(id, name, "node")) return; 1115 oldName = this.$nodeData[id].name; 1116 this.$nodeData[id].name = name; 1117 if (this.$nodeData[id].type.indexOf("round") > 1) { 1118 this.$nodeDom[id].children(".span").text(name); 1119 } 1120 else { 1121 this.$nodeDom[id].find("td:eq(1)").text(name); 1122 var hack = 0; 1123 if (navigator.userAgent.indexOf("8.0") != -1) hack = 2; 1124 var width = this.$nodeDom[id].outerWidth(); 1125 var height = this.$nodeDom[id].outerHeight(); 1126 this.$nodeDom[id].children("table").css({ width: width - 2 + "px", height: height - 2 + "px" }); 1127 this.$nodeData[id].width = width; 1128 this.$nodeData[id].height = height; 1129 } 1130 if (this.$editable) { 1131 this.$nodeData[id].alt = true; 1132 } 1133 //重画转换线 1134 this.resetLines(id, this.$nodeData[id]); 1135 } 1136 else if (type == "line") {//如果是线 1137 if (!this.$lineData[id]) return; 1138 if (this.$lineData[id].name == name) return; 1139 if (this.onItemRename != null && !this.onItemRename(id, name, "line")) return; 1140 oldName = this.$lineData[id].name; 1141 this.$lineData[id].name = name; 1142 if (GooFlow.prototype.useSVG != "") { 1143 this.$lineDom[id].childNodes[2].textContent = name; 1144 } 1145 else { 1146 this.$lineDom[id].childNodes[1].innerHTML = name; 1147 var n = this.$lineDom[id].getAttribute("fromTo").split(","); 1148 var x; 1149 if (this.$lineData[id].type != "lr") { 1150 x = (n[2] - n[0]) / 2; 1151 } 1152 else { 1153 var Min = n[2] > n[0] ? n[0] : n[2]; 1154 if (Min > this.$lineData[id].M) Min = this.$lineData[id].M; 1155 x = this.$lineData[id].M - Min; 1156 } 1157 if (x < 0) x = x * -1; 1158 this.$lineDom[id].childNodes[1].style.left = x - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4 + "px"; 1159 } 1160 if (this.$editable) { 1161 this.$lineData[id].alt = true; 1162 } 1163 } 1164 else if (type == "area") {//如果是分组区域 1165 if (!this.$areaData[id]) return; 1166 if (this.$areaData[id].name == name) return; 1167 if (this.onItemRename != null && !this.onItemRename(id, name, "area")) return; 1168 oldName = this.$areaData[id].name; 1169 this.$areaData[id].name = name; 1170 this.$areaDom[id].children("label").text(name); 1171 if (this.$editable) { 1172 this.$areaData[id].alt = true; 1173 } 1174 } 1175 if (this.$undoStack) { 1176 var paras = [id, oldName, type]; 1177 this.pushOper("setName", paras); 1178 } 1179 }, 1180 //设置结点的尺寸,仅支持非开始/结束结点 1181 resizeNode: function (id, width, height) { 1182 if (!this.$nodeData[id]) return; 1183 if (this.onItemResize != null && !this.onItemResize(id, "node", width, height)) return; 1184 if (this.$nodeData[id].type == "start" || this.$nodeData[id].type == "end") return; 1185 if (this.$undoStack) { 1186 var paras = [id, this.$nodeData[id].width, this.$nodeData[id].height]; 1187 this.pushOper("resizeNode", paras); 1188 } 1189 var hack = 0; 1190 if (navigator.userAgent.indexOf("8.0") != -1) hack = 2; 1191 this.$nodeDom[id].children("table").css({ width: width - 2 + "px", height: height - 2 + "px" }); 1192 width = this.$nodeDom[id].outerWidth() - hack; 1193 height = this.$nodeDom[id].outerHeight() - hack; 1194 this.$nodeDom[id].children("table").css({ width: width - 2 + "px", height: height - 2 + "px" }); 1195 this.$nodeData[id].width = width; 1196 this.$nodeData[id].height = height; 1197 if (this.$editable) { 1198 this.$nodeData[id].alt = true; 1199 } 1200 //重画转换线 1201 this.resetLines(id, this.$nodeData[id]); 1202 }, 1203 //删除结点 1204 delNode: function (id) { 1205 if (!this.$nodeData[id]) return; 1206 if (this.onItemDel != null && !this.onItemDel(id, "node")) return; 1207 //先删除可能的连线 1208 for (var k in this.$lineData) { 1209 if (this.$lineData[k].from == id || this.$lineData[k].to == id) { 1210 //this.$draw.removeChild(this.$lineDom[k]); 1211 //delete this.$lineData[k]; 1212 //delete this.$lineDom[k]; 1213 this.delLine(k); 1214 } 1215 } 1216 //再删除结点本身 1217 if (this.$undoStack) { 1218 var paras = [id, this.$nodeData[id]]; 1219 this.pushOper("addNode", paras); 1220 } 1221 delete this.$nodeData[id]; 1222 this.$nodeDom[id].remove(); 1223 delete this.$nodeDom[id]; 1224 --this.$nodeCount; 1225 if (this.$focus == id) this.$focus = ""; 1226 1227 if (this.$editable) { 1228 //在回退新增操作时,如果节点ID以this.$id+"_node_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 1229 if (id.indexOf(this.$id + "_node_") < 0) 1230 this.$deletedItem[id] = "node"; 1231 } 1232 }, 1233 //设置流程图的名称 1234 setTitle: function (text) { 1235 this.$title = text; 1236 if (this.$head) this.$head.children("label").attr("title", text).text(text); 1237 }, 1238 //载入一组数据 1239 loadData: function (data) { 1240 var t = this.$editable; 1241 this.$editable = false; 1242 if (data.title) this.setTitle(data.title); 1243 if (data.initNum) this.$max = data.initNum; 1244 for (var i in data.nodes) 1245 this.addNode(i, data.nodes[i], true);//2015-07-28 加载不要触发onItemAdd事件 1246 for (var j in data.lines) 1247 this.addLine(j, data.lines[j], true); 1248 for (var k in data.areas) 1249 this.addArea(k, data.areas[k], true); 1250 this.$editable = t; 1251 this.$deletedItem = {}; 1252 }, 1253 //用AJAX方式,远程读取一组数据 1254 //参数para为JSON结构,与JQUERY中$.ajax()方法的传参一样 1255 //TXF 2015-07-29 1256 loadDataAjax: function (param) { 1257 var This = this; 1258 $.ajax({ 1259 type: param.type, 1260 url: param.url, 1261 dataType: "json", 1262 data: param.data, 1263 cache: false, 1264 success: function (obj) { 1265 if (param.dataFilter) param.dataFilter(obj.flow_elements, "json"); 1266 This.loadData($.parseJSON(obj.flow_elements)); 1267 if (param.success) param.success(obj); 1268 }, 1269 error: function (XMLHttpRequest, textStatus, errorThrown) { 1270 if (param.error) param.error(textStatus, errorThrown); 1271 } 1272 }) 1273 }, 1274 //把画好的整个流程图导出到一个变量中(其实也可以直接访问GooFlow对象的$nodeData,$lineData,$areaData这三个JSON属性) 1275 exportData: function () { 1276 var ret = { title: this.$title, nodes: this.$nodeData, lines: this.$lineData, areas: this.$areaData, initNum: this.$max }; 1277 for (var k1 in ret.nodes) { 1278 if (!ret.nodes[k1].marked) { 1279 delete ret.nodes[k1]["marked"]; 1280 } 1281 } 1282 for (var k2 in ret.lines) { 1283 if (!ret.lines[k2].marked) { 1284 delete ret.lines[k2]["marked"]; 1285 } 1286 } 1287 return ret; 1288 }, 1289 //只把本次编辑流程图中作了变更(包括增删改)的元素导出到一个变量中,以方便用户每次编辑载入的流程图后只获取变更过的数据 1290 exportAlter: function () { 1291 var ret = { nodes: {}, lines: {}, areas: {} }; 1292 for (var k1 in this.$nodeData) { 1293 if (this.$nodeData[k1].alt) { 1294 ret.nodes[k1] = this.$nodeData[k1]; 1295 } 1296 } 1297 for (var k2 in this.$lineData) { 1298 if (this.$lineData[k2].alt) { 1299 ret.lines[k2] = this.$lineData[k2]; 1300 } 1301 } 1302 for (var k3 in this.$areaData) { 1303 if (this.$areaData[k3].alt) { 1304 ret.areas[k3] = this.$areaData[k3]; 1305 } 1306 } 1307 ret.deletedItem = this.$deletedItem; 1308 return ret; 1309 }, 1310 //变更元素的ID,一般用于快速保存后,将后台返回新元素的ID更新到页面中;type为元素类型(节点,连线,区块) 1311 transNewId: function (oldId, newId, type) { 1312 var tmp; 1313 switch (type) { 1314 case "node": 1315 if (this.$nodeData[oldId]) { 1316 tmp = this.$nodeData[oldId]; 1317 delete this.$nodeData[oldId]; 1318 this.$nodeData[newId] = tmp; 1319 tmp = this.$nodeDom[oldId].attr("id", newId); 1320 delete this.$nodeDom[oldId]; 1321 this.$nodeDom[newId] = tmp; 1322 } 1323 break; 1324 case "line": 1325 if (this.$lineData[oldId]) { 1326 tmp = this.$lineData[oldId]; 1327 delete this.$lineData[oldId]; 1328 this.$lineData[newId] = tmp; 1329 tmp = this.$lineDom[oldId].attr("id", newId); 1330 delete this.$lineDom[oldId]; 1331 this.$lineDom[newId] = tmp; 1332 } 1333 break; 1334 case "area": 1335 if (this.$areaData[oldId]) { 1336 tmp = this.$areaData[oldId]; 1337 delete this.$areaData[oldId]; 1338 this.$areaData[newId] = tmp; 1339 tmp = this.$areaDom[oldId].attr("id", newId); 1340 delete this.$areaDom[oldId]; 1341 this.$areaDom[newId] = tmp; 1342 } 1343 break; 1344 } 1345 }, 1346 //清空工作区及已载入的数据 1347 clearData: function () { 1348 for (var key in this.$nodeData) { 1349 this.delNode(key); 1350 } 1351 for (var key in this.$lineData) { 1352 this.delLine(key); 1353 } 1354 for (var key in this.$areaData) { 1355 this.delArea(key); 1356 } 1357 this.$deletedItem = {}; 1358 }, 1359 //销毁自己 1360 destrory: function () { 1361 this.$bgDiv.empty(); 1362 this.$lineData = null; 1363 this.$nodeData = null; 1364 this.$lineDom = null; 1365 this.$nodeDom = null; 1366 this.$areaDom = null; 1367 this.$areaData = null; 1368 this.$nodeCount = 0; 1369 this.$areaCount = 0; 1370 this.$areaCount = 0; 1371 this.$deletedItem = {}; 1372 }, 1373 ///////////以下为有关画线的方法 1374 //绘制一条箭头线,并返回线的DOM 1375 drawLine: function (id, sp, ep, mark, dash) { 1376 var line; 1377 if (GooFlow.prototype.useSVG != "") { 1378 line = document.createElementNS("http://www.w3.org/2000/svg", "g"); 1379 var hi = document.createElementNS("http://www.w3.org/2000/svg", "path"); 1380 var path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 1381 1382 if (id != "") line.setAttribute("id", id); 1383 line.setAttribute("from", sp[0] + "," + sp[1]); 1384 line.setAttribute("to", ep[0] + "," + ep[1]); 1385 hi.setAttribute("visibility", "hidden"); 1386 hi.setAttribute("stroke-width", 9); 1387 hi.setAttribute("fill", "none"); 1388 hi.setAttribute("stroke", "white"); 1389 hi.setAttribute("d", "M " + sp[0] + " " + sp[1] + " L " + ep[0] + " " + ep[1]); 1390 hi.setAttribute("pointer-events", "stroke"); 1391 path.setAttribute("d", "M " + sp[0] + " " + sp[1] + " L " + ep[0] + " " + ep[1]); 1392 path.setAttribute("stroke-width", 1.4); 1393 path.setAttribute("stroke-linecap", "round"); 1394 path.setAttribute("fill", "none"); 1395 if (dash) path.setAttribute("style", "stroke-dasharray:6,5"); 1396 if (mark) { 1397 path.setAttribute("stroke", GooFlow.prototype.color.mark || "#ff3300"); 1398 path.setAttribute("marker-end", "url(#arrow2)"); 1399 } 1400 else { 1401 path.setAttribute("stroke", GooFlow.prototype.color.line || "#3892D3"); 1402 path.setAttribute("marker-end", "url(#arrow1)"); 1403 } 1404 line.appendChild(hi); 1405 line.appendChild(path); 1406 line.style.cursor = "crosshair"; 1407 if (id != "" && id != "GooFlow_tmp_line") { 1408 var text = document.createElementNS("http://www.w3.org/2000/svg", "text"); 1409 text.setAttribute("fill", GooFlow.prototype.color.font || "#333"); 1410 line.appendChild(text); 1411 var x = (ep[0] + sp[0]) / 2; 1412 var y = (ep[1] + sp[1]) / 2; 1413 text.setAttribute("text-anchor", "middle"); 1414 text.setAttribute("x", x); 1415 text.setAttribute("y", y); 1416 line.style.cursor = "pointer"; 1417 text.style.cursor = "text"; 1418 } 1419 } else { 1420 line = document.createElement("v:polyline"); 1421 if (id != "") line.id = id; 1422 //line.style.position="absolute"; 1423 line.points.value = sp[0] + "," + sp[1] + " " + ep[0] + "," + ep[1]; 1424 line.setAttribute("fromTo", sp[0] + "," + sp[1] + "," + ep[0] + "," + ep[1]); 1425 line.strokeWeight = "1.2"; 1426 line.stroke.EndArrow = "Block"; 1427 line.style.cursor = "crosshair"; 1428 if (id != "" && id != "GooFlow_tmp_line") { 1429 var text = document.createElement("div"); 1430 //text.innerHTML=id; 1431 line.appendChild(text); 1432 var x = (ep[0] - sp[0]) / 2; 1433 var y = (ep[1] - sp[1]) / 2; 1434 if (x < 0) x = x * -1; 1435 if (y < 0) y = y * -1; 1436 text.style.left = x + "px"; 1437 text.style.top = y - 6 + "px"; 1438 line.style.cursor = "pointer"; 1439 } 1440 if (dash) line.stroke.dashstyle = "Dash"; 1441 if (mark) line.strokeColor = GooFlow.prototype.color.mark || "#ff3300"; 1442 else line.strokeColor = GooFlow.prototype.color.line || "#3892D3"; 1443 line.fillColor = GooFlow.prototype.color.line || "#3892D3"; 1444 } 1445 return line; 1446 }, 1447 //画一条只有两个中点的折线 1448 drawPoly: function (id, sp, m1, m2, ep, mark) { 1449 var poly, strPath; 1450 if (GooFlow.prototype.useSVG != "") { 1451 poly = document.createElementNS("http://www.w3.org/2000/svg", "g"); 1452 var hi = document.createElementNS("http://www.w3.org/2000/svg", "path"); 1453 var path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 1454 if (id != "") poly.setAttribute("id", id); 1455 poly.setAttribute("from", sp[0] + "," + sp[1]); 1456 poly.setAttribute("to", ep[0] + "," + ep[1]); 1457 hi.setAttribute("visibility", "hidden"); 1458 hi.setAttribute("stroke-width", 9); 1459 hi.setAttribute("fill", "none"); 1460 hi.setAttribute("stroke", "white"); 1461 strPath = "M " + sp[0] + " " + sp[1]; 1462 if (m1[0] != sp[0] || m1[1] != sp[1]) 1463 strPath += " L " + m1[0] + " " + m1[1]; 1464 if (m2[0] != ep[0] || m2[1] != ep[1]) 1465 strPath += " L " + m2[0] + " " + m2[1]; 1466 strPath += " L " + ep[0] + " " + ep[1]; 1467 hi.setAttribute("d", strPath); 1468 hi.setAttribute("pointer-events", "stroke"); 1469 path.setAttribute("d", strPath); 1470 path.setAttribute("stroke-width", 1.4); 1471 path.setAttribute("stroke-linecap", "round"); 1472 path.setAttribute("fill", "none"); 1473 if (mark) { 1474 path.setAttribute("stroke", GooFlow.prototype.color.mark || "#ff3300"); 1475 path.setAttribute("marker-end", "url(#arrow2)"); 1476 } 1477 else { 1478 path.setAttribute("stroke", GooFlow.prototype.color.line || "#3892D3"); 1479 path.setAttribute("marker-end", "url(#arrow1)"); 1480 } 1481 poly.appendChild(hi); 1482 poly.appendChild(path); 1483 var text = document.createElementNS("http://www.w3.org/2000/svg", "text"); 1484 text.setAttribute("fill", GooFlow.prototype.color.font || "#333"); 1485 poly.appendChild(text); 1486 var x = (m2[0] + m1[0]) / 2; 1487 var y = (m2[1] + m1[1]) / 2; 1488 text.setAttribute("text-anchor", "middle"); 1489 text.setAttribute("x", x); 1490 text.setAttribute("y", y); 1491 text.style.cursor = "text"; 1492 poly.style.cursor = "pointer"; 1493 } 1494 else { 1495 poly = document.createElement("v:Polyline"); 1496 if (id != "") poly.id = id; 1497 poly.filled = "false"; 1498 strPath = sp[0] + "," + sp[1]; 1499 if (m1[0] != sp[0] || m1[1] != sp[1]) 1500 strPath += " " + m1[0] + "," + m1[1]; 1501 if (m2[0] != ep[0] || m2[1] != ep[1]) 1502 strPath += " " + m2[0] + "," + m2[1]; 1503 strPath += " " + ep[0] + "," + ep[1]; 1504 poly.points.value = strPath; 1505 poly.setAttribute("fromTo", sp[0] + "," + sp[1] + "," + ep[0] + "," + ep[1]); 1506 poly.strokeWeight = "1.2"; 1507 poly.stroke.EndArrow = "Block"; 1508 var text = document.createElement("div"); 1509 //text.innerHTML=id; 1510 poly.appendChild(text); 1511 var x = (m2[0] - m1[0]) / 2; 1512 var y = (m2[1] - m1[1]) / 2; 1513 if (x < 0) x = x * -1; 1514 if (y < 0) y = y * -1; 1515 text.style.left = x + "px"; 1516 text.style.top = y - 4 + "px"; 1517 poly.style.cursor = "pointer"; 1518 if (mark) poly.strokeColor = GooFlow.prototype.color.mark || "#ff3300"; 1519 else poly.strokeColor = GooFlow.prototype.color.line || "#3892D3"; 1520 } 1521 return poly; 1522 }, 1523 //计算两个结点间要连直线的话,连线的开始坐标和结束坐标 1524 calcStartEnd: function (n1, n2) { 1525 var X_1, Y_1, X_2, Y_2; 1526 //X判断: 1527 var x11 = n1.left, x12 = n1.left + n1.width, x21 = n2.left, x22 = n2.left + n2.width; 1528 //结点2在结点1左边 1529 if (x11 >= x22) { 1530 X_1 = x11; X_2 = x22; 1531 } 1532 //结点2在结点1右边 1533 else if (x12 <= x21) { 1534 X_1 = x12; X_2 = x21; 1535 } 1536 //结点2在结点1水平部分重合 1537 else if (x11 <= x21 && x12 >= x21 && x12 <= x22) { 1538 X_1 = (x12 + x21) / 2; X_2 = X_1; 1539 } 1540 else if (x11 >= x21 && x12 <= x22) { 1541 X_1 = (x11 + x12) / 2; X_2 = X_1; 1542 } 1543 else if (x21 >= x11 && x22 <= x12) { 1544 X_1 = (x21 + x22) / 2; X_2 = X_1; 1545 } 1546 else if (x11 <= x22 && x12 >= x22) { 1547 X_1 = (x11 + x22) / 2; X_2 = X_1; 1548 } 1549 1550 //Y判断: 1551 var y11 = n1.top, y12 = n1.top + n1.height, y21 = n2.top, y22 = n2.top + n2.height; 1552 //结点2在结点1上边 1553 if (y11 >= y22) { 1554 Y_1 = y11; Y_2 = y22; 1555 } 1556 //结点2在结点1下边 1557 else if (y12 <= y21) { 1558 Y_1 = y12; Y_2 = y21; 1559 } 1560 //结点2在结点1垂直部分重合 1561 else if (y11 <= y21 && y12 >= y21 && y12 <= y22) { 1562 Y_1 = (y12 + y21) / 2; Y_2 = Y_1; 1563 } 1564 else if (y11 >= y21 && y12 <= y22) { 1565 Y_1 = (y11 + y12) / 2; Y_2 = Y_1; 1566 } 1567 else if (y21 >= y11 && y22 <= y12) { 1568 Y_1 = (y21 + y22) / 2; Y_2 = Y_1; 1569 } 1570 else if (y11 <= y22 && y12 >= y22) { 1571 Y_1 = (y11 + y22) / 2; Y_2 = Y_1; 1572 } 1573 return { "start": [X_1, Y_1], "end": [X_2, Y_2] }; 1574 }, 1575 //计算两个结点间要连折线的话,连线的所有坐标 1576 calcPolyPoints: function (n1, n2, type, M) { 1577 //开始/结束两个结点的中心 1578 var SP = { x: n1.left + n1.width / 2, y: n1.top + n1.height / 2 }; 1579 var EP = { x: n2.left + n2.width / 2, y: n2.top + n2.height / 2 }; 1580 var sp = [], m1 = [], m2 = [], ep = []; 1581 //如果是允许中段可左右移动的折线,则参数M为可移动中段线的X坐标 1582 //粗略计算起始点 1583 sp = [SP.x, SP.y]; 1584 ep = [EP.x, EP.y]; 1585 if (type == "lr") { 1586 //粗略计算2个中点 1587 m1 = [M, SP.y]; 1588 m2 = [M, EP.y]; 1589 //再具体分析修改开始点和中点1 1590 if (m1[0] > n1.left && m1[0] < n1.left + n1.width) { 1591 m1[1] = (SP.y > EP.y ? n1.top : n1.top + n1.height); 1592 sp[0] = m1[0]; sp[1] = m1[1]; 1593 } 1594 else { 1595 sp[0] = (m1[0] < n1.left ? n1.left : n1.left + n1.width) 1596 } 1597 //再具体分析中点2和结束点 1598 if (m2[0] > n2.left && m2[0] < n2.left + n2.width) { 1599 m2[1] = (SP.y > EP.y ? n2.top + n2.height : n2.top); 1600 ep[0] = m2[0]; ep[1] = m2[1]; 1601 } 1602 else { 1603 ep[0] = (m2[0] < n2.left ? n2.left : n2.left + n2.width) 1604 } 1605 } 1606 //如果是允许中段可上下移动的折线,则参数M为可移动中段线的Y坐标 1607 else if (type == "tb") { 1608 //粗略计算2个中点 1609 m1 = [SP.x, M]; 1610 m2 = [EP.x, M]; 1611 //再具体分析修改开始点和中点1 1612 if (m1[1] > n1.top && m1[1] < n1.top + n1.height) { 1613 m1[0] = (SP.x > EP.x ? n1.left : n1.left + n1.width); 1614 sp[0] = m1[0]; sp[1] = m1[1]; 1615 } 1616 else { 1617 sp[1] = (m1[1] < n1.top ? n1.top : n1.top + n1.height) 1618 } 1619 //再具体分析中点2和结束点 1620 if (m2[1] > n2.top && m2[1] < n2.top + n2.height) { 1621 m2[0] = (SP.x > EP.x ? n2.left + n2.width : n2.left); 1622 ep[0] = m2[0]; ep[1] = m2[1]; 1623 } 1624 else { 1625 ep[1] = (m2[1] < n2.top ? n2.top : n2.top + n2.height); 1626 } 1627 } 1628 return { start: sp, m1: m1, m2: m2, end: ep }; 1629 }, 1630 //初始化折线中段的X/Y坐标,mType='rb'时为X坐标,mType='tb'时为Y坐标 1631 getMValue: function (n1, n2, mType) { 1632 if (mType == "lr") { 1633 return (n1.left + n1.width / 2 + n2.left + n2.width / 2) / 2; 1634 } 1635 else if (mType == "tb") { 1636 return (n1.top + n1.height / 2 + n2.top + n2.height / 2) / 2; 1637 } 1638 }, 1639 //原lineData已经设定好的情况下,只在绘图工作区画一条线的页面元素 1640 addLineDom: function (id, lineData) { 1641 var n1 = this.$nodeData[lineData.from], n2 = this.$nodeData[lineData.to];//获取开始/结束结点的数据 1642 if (!n1 || !n2) return; 1643 //开始计算线端点坐标 1644 var res; 1645 if (lineData.type && lineData.type != "sl") 1646 res = GooFlow.prototype.calcPolyPoints(n1, n2, lineData.type, lineData.M); 1647 else 1648 res = GooFlow.prototype.calcStartEnd(n1, n2); 1649 if (!res) return; 1650 1651 if (lineData.type == "sl") 1652 this.$lineDom[id] = GooFlow.prototype.drawLine(id, res.start, res.end, lineData.marked); 1653 else 1654 this.$lineDom[id] = GooFlow.prototype.drawPoly(id, res.start, res.m1, res.m2, res.end, lineData.marked); 1655 this.$draw.appendChild(this.$lineDom[id]); 1656 if (GooFlow.prototype.useSVG == "") { 1657 this.$lineDom[id].childNodes[1].innerHTML = lineData.name; 1658 if (lineData.type != "sl") { 1659 var Min = (res.start[0] > res.end[0] ? res.end[0] : res.start[0]); 1660 if (Min > res.m2[0]) Min = res.m2[0]; 1661 if (Min > res.m1[0]) Min = res.m1[0]; 1662 this.$lineDom[id].childNodes[1].style.left = (res.m2[0] + res.m1[0]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4; 1663 Min = (res.start[1] > res.end[1] ? res.end[1] : res.start[1]); 1664 if (Min > res.m2[1]) Min = res.m2[1]; 1665 if (Min > res.m1[1]) Min = res.m1[1]; 1666 this.$lineDom[id].childNodes[1].style.top = (res.m2[1] + res.m1[1]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetHeight / 2; 1667 } else 1668 this.$lineDom[id].childNodes[1].style.left = 1669 ((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[id].childNodes[1].offsetWidth) / 2 + 4; 1670 } 1671 else this.$lineDom[id].childNodes[2].textContent = lineData.name; 1672 }, 1673 //增加一条线 1674 addLine: function (id, json, disabled) { 1675 if (!disabled) 1676 if (this.onItemAdd != null && !this.onItemAdd(id, "line", json)) return; 1677 if (this.$undoStack && this.$editable) { 1678 this.pushOper("delLine", [id]); 1679 } 1680 if (json.from == json.to) return; 1681 var n1 = this.$nodeData[json.from], n2 = this.$nodeData[json.to];//获取开始/结束结点的数据 1682 if (!n1 || !n2) return; 1683 //避免两个节点间不能有一条以上同向接连线 1684 for (var k in this.$lineData) { 1685 if ((json.from == this.$lineData[k].from && json.to == this.$lineData[k].to)) 1686 return; 1687 } 1688 //设置$lineData[id] 1689 this.$lineData[id] = {}; 1690 if (json.type) { 1691 this.$lineData[id].type = json.type; 1692 this.$lineData[id].M = json.M; 1693 } 1694 else this.$lineData[id].type = "sl";//默认为直线 1695 this.$lineData[id].from = json.from; 1696 this.$lineData[id].to = json.to; 1697 this.$lineData[id].name = json.name; 1698 if (json.marked) this.$lineData[id].marked = json.marked; 1699 else this.$lineData[id].marked = false; 1700 //设置$lineData[id]完毕 1701 1702 this.addLineDom(id, this.$lineData[id]); 1703 1704 ++this.$lineCount; 1705 if (this.$editable) { 1706 this.$lineData[id].alt = true; 1707 if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 1708 } 1709 }, 1710 //重构所有连向某个结点的线的显示,传参结构为$nodeData数组的一个单元结构 1711 resetLines: function (id, node) { 1712 for (var i in this.$lineData) { 1713 var other = null;//获取结束/开始结点的数据 1714 var res; 1715 if (this.$lineData[i].from == id) {//找结束点 1716 other = this.$nodeData[this.$lineData[i].to] || null; 1717 if (other == null) continue; 1718 if (this.$lineData[i].type == "sl") 1719 res = GooFlow.prototype.calcStartEnd(node, other); 1720 else 1721 res = GooFlow.prototype.calcPolyPoints(node, other, this.$lineData[i].type, this.$lineData[i].M) 1722 if (!res) break; 1723 } 1724 else if (this.$lineData[i].to == id) {//找开始点 1725 other = this.$nodeData[this.$lineData[i].from] || null; 1726 if (other == null) continue; 1727 if (this.$lineData[i].type == "sl") 1728 res = GooFlow.prototype.calcStartEnd(other, node); 1729 else 1730 res = GooFlow.prototype.calcPolyPoints(other, node, this.$lineData[i].type, this.$lineData[i].M); 1731 if (!res) break; 1732 } 1733 if (other == null) continue; 1734 this.$draw.removeChild(this.$lineDom[i]); 1735 if (this.$lineData[i].type == "sl") { 1736 this.$lineDom[i] = GooFlow.prototype.drawLine(i, res.start, res.end, this.$lineData[i].marked); 1737 } 1738 else { 1739 this.$lineDom[i] = GooFlow.prototype.drawPoly(i, res.start, res.m1, res.m2, res.end, this.$lineData[i].marked); 1740 } 1741 this.$draw.appendChild(this.$lineDom[i]); 1742 if (GooFlow.prototype.useSVG == "") { 1743 this.$lineDom[i].childNodes[1].innerHTML = this.$lineData[i].name; 1744 if (this.$lineData[i].type != "sl") { 1745 var Min = (res.start[0] > res.end[0] ? res.end[0] : res.start[0]); 1746 if (Min > res.m2[0]) Min = res.m2[0]; 1747 if (Min > res.m1[0]) Min = res.m1[0]; 1748 this.$lineDom[i].childNodes[1].style.left = (res.m2[0] + res.m1[0]) / 2 - Min - this.$lineDom[i].childNodes[1].offsetWidth / 2 + 4; 1749 Min = (res.start[1] > res.end[1] ? res.end[1] : res.start[1]); 1750 if (Min > res.m2[1]) Min = res.m2[1]; 1751 if (Min > res.m1[1]) Min = res.m1[1]; 1752 this.$lineDom[i].childNodes[1].style.top = (res.m2[1] + res.m1[1]) / 2 - Min - this.$lineDom[i].childNodes[1].offsetHeight / 2 - 4; 1753 } else 1754 this.$lineDom[i].childNodes[1].style.left = 1755 ((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[i].childNodes[1].offsetWidth) / 2 + 4; 1756 } 1757 else this.$lineDom[i].childNodes[2].textContent = this.$lineData[i].name; 1758 } 1759 }, 1760 //重新设置连线的样式 newType= "sl":直线, "lr":中段可左右移动型折线, "tb":中段可上下移动型折线 1761 setLineType: function (id, newType, M) { 1762 if (!newType || newType == null || newType == "" || newType == this.$lineData[id].type) return false; 1763 if (this.onLineSetType != null && !this.onLineSetType(id, newType)) return; 1764 if (this.$undoStack) { 1765 var paras = [id, this.$lineData[id].type, this.$lineData[id].M]; 1766 this.pushOper("setLineType", paras); 1767 } 1768 var from = this.$lineData[id].from; 1769 var to = this.$lineData[id].to; 1770 this.$lineData[id].type = newType; 1771 var res; 1772 //如果是变成折线 1773 if (newType != "sl") { 1774 var res = GooFlow.prototype.calcPolyPoints(this.$nodeData[from], this.$nodeData[to], this.$lineData[id].type, this.$lineData[id].M); 1775 if (M) { 1776 this.setLineM(id, M, true); 1777 } else { 1778 this.setLineM(id, this.getMValue(this.$nodeData[from], this.$nodeData[to], newType), true); 1779 } 1780 } 1781 //如果是变回直线 1782 else { 1783 delete this.$lineData[id].M; 1784 this.$lineMove.hide().removeData("type").removeData("tid"); 1785 res = GooFlow.prototype.calcStartEnd(this.$nodeData[from], this.$nodeData[to]); 1786 if (!res) return; 1787 this.$draw.removeChild(this.$lineDom[id]); 1788 this.$lineDom[id] = GooFlow.prototype.drawLine(id, res.start, res.end, this.$lineData[id].marked || this.$focus == id); 1789 this.$draw.appendChild(this.$lineDom[id]); 1790 if (GooFlow.prototype.useSVG == "") { 1791 this.$lineDom[id].childNodes[1].innerHTML = this.$lineData[id].name; 1792 this.$lineDom[id].childNodes[1].style.left = 1793 ((res.end[0] - res.start[0]) * (res.end[0] > res.start[0] ? 1 : -1) - this.$lineDom[id].childNodes[1].offsetWidth) / 2 + 4; 1794 } 1795 else 1796 this.$lineDom[id].childNodes[2].textContent = this.$lineData[id].name; 1797 } 1798 if (this.$focus == id) { 1799 this.focusItem(id); 1800 } 1801 if (this.$editable) { 1802 this.$lineData[id].alt = true; 1803 } 1804 }, 1805 //设置折线中段的X坐标值(可左右移动时)或Y坐标值(可上下移动时) 1806 setLineM: function (id, M, noStack) { 1807 if (!this.$lineData[id] || M < 0 || !this.$lineData[id].type || this.$lineData[id].type == "sl") return false; 1808 if (this.onLineMove != null && !this.onLineMove(id, M)) return false; 1809 if (this.$undoStack && !noStack) { 1810 var paras = [id, this.$lineData[id].M]; 1811 this.pushOper("setLineM", paras); 1812 } 1813 var from = this.$lineData[id].from; 1814 var to = this.$lineData[id].to; 1815 this.$lineData[id].M = M; 1816 var ps = GooFlow.prototype.calcPolyPoints(this.$nodeData[from], this.$nodeData[to], this.$lineData[id].type, this.$lineData[id].M); 1817 this.$draw.removeChild(this.$lineDom[id]); 1818 this.$lineDom[id] = GooFlow.prototype.drawPoly(id, ps.start, ps.m1, ps.m2, ps.end, this.$lineData[id].marked || this.$focus == id); 1819 this.$draw.appendChild(this.$lineDom[id]); 1820 if (GooFlow.prototype.useSVG == "") { 1821 this.$lineDom[id].childNodes[1].innerHTML = this.$lineData[id].name; 1822 var Min = (ps.start[0] > ps.end[0] ? ps.end[0] : ps.start[0]); 1823 if (Min > ps.m2[0]) Min = ps.m2[0]; 1824 if (Min > ps.m1[0]) Min = ps.m1[0]; 1825 this.$lineDom[id].childNodes[1].style.left = (ps.m2[0] + ps.m1[0]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetWidth / 2 + 4; 1826 Min = (ps.start[1] > ps.end[1] ? ps.end[1] : ps.start[1]); 1827 if (Min > ps.m2[1]) Min = ps.m2[1]; 1828 if (Min > ps.m1[1]) Min = ps.m1[1]; 1829 this.$lineDom[id].childNodes[1].style.top = (ps.m2[1] + ps.m1[1]) / 2 - Min - this.$lineDom[id].childNodes[1].offsetHeight / 2 - 4; 1830 } 1831 else this.$lineDom[id].childNodes[2].textContent = this.$lineData[id].name; 1832 if (this.$editable) { 1833 this.$lineData[id].alt = true; 1834 } 1835 }, 1836 //删除转换线 1837 delLine: function (id) { 1838 if (!this.$lineData[id]) return; 1839 if (this.onItemDel != null && !this.onItemDel(id, "line")) return; 1840 if (this.$undoStack) { 1841 var paras = [id, this.$lineData[id]]; 1842 this.pushOper("addLine", paras); 1843 } 1844 this.$draw.removeChild(this.$lineDom[id]); 1845 delete this.$lineData[id]; 1846 delete this.$lineDom[id]; 1847 if (this.$focus == id) this.$focus = ""; 1848 --this.$lineCount; 1849 if (this.$editable) { 1850 //在回退新增操作时,如果节点ID以this.$id+"_line_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 1851 if (id.indexOf(this.$id + "_line_") < 0) 1852 this.$deletedItem[id] = "line"; 1853 this.$mpFrom.hide().removeData("p"); 1854 this.$mpTo.hide().removeData("p"); 1855 } 1856 this.$lineOper.hide().removeData("tid"); 1857 }, 1858 //变更连线两个端点所连的结点 1859 //参数:要变更端点的连线ID,新的开始结点ID、新的结束结点ID;如果开始/结束结点ID是传入null或者"",则表示原端点不变 1860 moveLinePoints: function (lineId, newStart, newEnd, noStack) { 1861 if (newStart == newEnd) return; 1862 if (!lineId || !this.$lineData[lineId]) return; 1863 if (newStart == null || newStart == "") 1864 newStart = this.$lineData[lineId].from; 1865 if (newEnd == null || newEnd == "") 1866 newEnd = this.$lineData[lineId].to; 1867 1868 //避免两个节点间不能有一条以上同向接连线 1869 for (var k in this.$lineData) { 1870 if ((newStart == this.$lineData[k].from && newEnd == this.$lineData[k].to)) 1871 return; 1872 } 1873 if (this.onLinePointMove != null && !this.onLinePointMove(lineId, newStart, newEnd)) return; 1874 if (this.$undoStack && !noStack) { 1875 var paras = [lineId, this.$lineData[lineId].from, this.$lineData[lineId].to]; 1876 this.pushOper("moveLinePoints", paras); 1877 } 1878 if (newStart != null && newStart != "") { 1879 this.$lineData[lineId].from = newStart; 1880 } 1881 if (newEnd != null && newEnd != "") { 1882 this.$lineData[lineId].to = newEnd; 1883 } 1884 //重建转换线 1885 this.$draw.removeChild(this.$lineDom[lineId]); 1886 this.addLineDom(lineId, this.$lineData[lineId]); 1887 if (this.$editable) { 1888 this.$lineData[lineId].alt = true; 1889 } 1890 }, 1891 1892 //用颜色标注/取消标注一个结点或转换线,常用于显示重点或流程的进度。 1893 //这是一个在编辑模式中无用,但是在纯浏览模式中非常有用的方法,实际运用中可用于跟踪流程的进度。 1894 markItem: function (id, type, mark) { 1895 if (type == "node") { 1896 if (!this.$nodeData[id]) return; 1897 if (this.onItemMark != null && !this.onItemMark(id, "node", mark)) return; 1898 this.$nodeData[id].marked = mark || false; 1899 if (mark) { 1900 this.$nodeDom[id].addClass("item_mark"); 1901 this.$nodeDom[id].css("border-color", GooFlow.prototype.color.mark); 1902 } 1903 else { 1904 this.$nodeDom[id].removeClass("item_mark"); 1905 if (id != this.$focus) jq.css("border-color", "transparent"); 1906 } 1907 1908 } else if (type == "line") { 1909 if (!this.$lineData[id]) return; 1910 if (this.onItemMark != null && !this.onItemMark(id, "line", mark)) return; 1911 this.$lineData[id].marked = mark || false; 1912 if (GooFlow.prototype.useSVG != "") { 1913 if (mark) { 1914 this.$lineDom[id].childNodes[1].setAttribute("stroke", GooFlow.prototype.color.mark || "#ff3300"); 1915 this.$lineDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow2)"); 1916 } else { 1917 this.$lineDom[id].childNodes[1].setAttribute("stroke", GooFlow.prototype.color.line || "#3892D3"); 1918 this.$lineDom[id].childNodes[1].setAttribute("marker-end", "url(#arrow1)"); 1919 } 1920 } else { 1921 if (mark) this.$lineDom[id].strokeColor = GooFlow.prototype.color.mark || "#ff3300"; 1922 else this.$lineDom[id].strokeColor = GooFlow.prototype.color.line || "#3892D3" 1923 } 1924 } 1925 if (this.$undoStatck) { 1926 var paras = [id, type, !mark]; 1927 this.pushOper("markItem", paras); 1928 } 1929 }, 1930 ////////////////////////以下为区域分组块操作 1931 moveArea: function (id, left, top) { 1932 if (!this.$areaData[id]) return; 1933 if (this.onItemMove != null && !this.onItemMove(id, "area", left, top)) return; 1934 if (this.$undoStack) { 1935 var paras = [id, this.$areaData[id].left, this.$areaData[id].top]; 1936 this.pushOper("moveNode", paras); 1937 } 1938 if (left < 0) left = 0; 1939 if (top < 0) top = 0; 1940 $("#" + id).css({ left: left + "px", top: top + "px" }); 1941 this.$areaData[id].left = left; 1942 this.$areaData[id].top = top; 1943 if (this.$editable) { 1944 this.$areaData[id].alt = true; 1945 } 1946 }, 1947 //删除区域分组 1948 delArea: function (id) { 1949 if (!this.$areaData[id]) return; 1950 if (this.$undoStack) { 1951 var paras = [id, this.$areaData[id]]; 1952 this.pushOper("addArea", paras); 1953 } 1954 if (this.onItemDel != null && !this.onItemDel(id, "area")) return; 1955 delete this.$areaData[id]; 1956 this.$areaDom[id].remove(); 1957 delete this.$areaDom[id]; 1958 --this.$areaCount; 1959 if (this.$editable) { 1960 //在回退新增操作时,如果节点ID以this.$id+"_area_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 1961 if (id.indexOf(this.$id + "_area_") < 0) 1962 this.$deletedItem[id] = "area"; 1963 } 1964 }, 1965 //设置区域分组的颜色 1966 setAreaColor: function (id, color) { 1967 if (!this.$areaData[id]) return; 1968 if (this.onAreaSetColor != null && !this.onAreaSetColor(id, color)) return; 1969 if (this.$undoStack) { 1970 var paras = [id, this.$areaData[id].color]; 1971 this.pushOper("setAreaColor", paras); 1972 } 1973 if (color == "red" || color == "yellow" || color == "blue" || color == "green") { 1974 this.$areaDom[id].removeClass("area_" + this.$areaData[id].color).addClass("area_" + color); 1975 this.$areaData[id].color = color; 1976 } 1977 if (this.$editable) { 1978 this.$areaData[id].alt = true; 1979 } 1980 }, 1981 //设置区域分块的尺寸 1982 resizeArea: function (id, width, height) { 1983 if (!this.$areaData[id]) return; 1984 if (this.onItemResize != null && !this.onItemResize(id, "area", width, height)) return; 1985 if (this.$undoStack) { 1986 var paras = [id, this.$areaData[id].width, this.$areaData[id].height]; 1987 this.pushOper("resizeArea", paras); 1988 } 1989 var hack = 0; 1990 if (navigator.userAgent.indexOf("8.0") != -1) hack = 2; 1991 this.$areaDom[id].children(".bg").css({ width: width - 2 + "px", height: height - 2 + "px" }); 1992 width = this.$areaDom[id].outerWidth(); 1993 height = this.$areaDom[id].outerHeight(); 1994 this.$areaDom[id].children("bg").css({ width: width - 2 + "px", height: height - 2 + "px" }); 1995 this.$areaData[id].width = width; 1996 this.$areaData[id].height = height; 1997 if (this.$editable) { 1998 this.$areaData[id].alt = true; 1999 } 2000 }, 2001 addArea: function (id, json, disabled) { 2002 if (!disabled) 2003 if (this.onItemAdd != null && !this.onItemAdd(id, "area", json)) return; 2004 if (this.$undoStack && this.$editable) { 2005 this.pushOper("delArea", [id]); 2006 } 2007 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>" 2008 + "<label>" + json.name + "</label><i></i><div><div class='rs_bottom'></div><div class='rs_right'></div><div class='rs_rb'></div><div class='rs_close'></div></div></div>"); 2009 this.$areaData[id] = json; 2010 this.$group.append(this.$areaDom[id]); 2011 if (this.$nowType != "group") this.$areaDom[id].children("div:eq(1)").css("display", "none"); 2012 ++this.$areaCount; 2013 if (this.$editable) { 2014 this.$areaData[id].alt = true; 2015 if (this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 2016 } 2017 }, 2018 //重构整个流程图设计器的宽高 2019 reinitSize: function (width, height) { 2020 var w = (width || 800) - 2; 2021 var h = (height || 500) - 2; 2022 this.$bgDiv.css({ height: h + "px", width: w + "px" }); 2023 var headHeight = 0, hack = 10; 2024 if (this.$head != null) { 2025 headHeight = 24; 2026 hack = 7; 2027 } 2028 if (this.$tool != null) { 2029 this.$tool.css({ height: h - headHeight - hack + "px" }); 2030 } 2031 w -= 51; 2032 h = h - headHeight - (this.$head != null ? 5 : 8); 2033 this.$workArea.parent().css({ height: h + "px", width: w + "px" }); 2034 this.$workArea.css({ height: h * 3 + "px", width: w * 3 + "px" }); 2035 if (GooFlow.prototype.useSVG == "") { 2036 this.$draw.coordsize = w * 3 + "," + h * 3; 2037 } 2038 this.$draw.style.width = w * 3 + "px"; 2039 this.$draw.style.height = +h * 3 + "px"; 2040 if (this.$group) { 2041 this.$group.css({ height: h * 3 + "px", width: w * 3 + "px" }); 2042 } 2043 } 2044 } 2045 GooFlow.prototype.color = {}; 2046 //将此类的构造函数加入至JQUERY对象中 2047 jQuery.extend({ 2048 createGooFlow: function (bgDiv, property) { 2049 return new GooFlow(bgDiv, property); 2050 } 2051 });
1 v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent } 2 .GooFlow{ 3 background:#F5F5F5;border:1px solid #ccc;font: 0.8em Microsoft Yahei; 4 -moz-user-select:none;-webkit-user-select:none;border-radius:4px;color:#333 5 } 6 .GooFlow i{font: 1em} 7 .GooFlow_head{clear:both;height:28px;border-bottom: 2px solid #00B4E1;} 8 .GooFlow_head label{ 9 font-weight:bold;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:26px;line-height:26px;padding:2px;width:170px;text-align:center; 10 background:#00B4E1;float:left;color:#fff;border-radius:3px 0px 0px 0px;overflow:hidden;margin:-1px 4px 0px -1px; 11 } 12 .GooFlow_head span{float:left;height:22px;width:0px;overflow:hidden;border-left:1px solid #3892D3;margin:0px 3px;} 13 .GooFlow_head_btn{display:block;border:0px;height:28px;width:28px;cursor:default;margin:0px 3px;float:left;outline:none;blr:expression(this.onFocus=this.blur());} 14 .GooFlow_head_btn i{display:inline-block;overflow:hidden;width:28px;height:28px;border:0px;} 15 .GooFlow_head_btn:hover{border-radius:2px;background:#fff} 16 .GooFlow_head_btn:hover i{} 17 18 .GooFlow_tool{float:left;padding:0px 3px;overflow:hidden;clear:left;border-right:1px solid #ccc} 19 .GooFlow_tool_div{overflow:hidden;border-radius:3px;width:35px;padding:2px} 20 21 .GooFlow_tool span{height:0px;overflow:hidden;border-top:#ccc 1px solid;margin:5px 0;clear:both;display:block;} 22 .GooFlow_tool_btn{display:block;border:0px;cursor:default;margin:5px 0;outline:none;blr:expression(this.onFocus=this.blur()); background:#00B4E1; border:3px solid #00B4E1;} 23 .GooFlow_tool_btn i{display:block;overflow:hidden;width:28px;height:28px;border:0px} 24 .GooFlow_tool_btn:hover{padding:0px;background:#438eb9} 25 26 .GooFlow_tool_btndown{cursor:default;margin:5px 0;outline:none;blr:expression(this.onFocus=this.blur()); 27 display:block; border:3px solid #00B4E1; background:#438eb9;} 28 .GooFlow_tool_btndown i{display:block; width:28px; height:28px;} 29 30 .GooFlow_work{float:left;margin:0px 3px 3px 0px;border:#F5F5F5 1px solid;position:relative;overflow:scroll;} 31 .GooFlow_work .GooFlow_work_inner{background-image:url(img/gooflow_blank2.gif);position:relative;overflow:hidden;} 32 .GooFlow_work .GooFlow_work_group{cursor:default;position:absolute;overflow:hidden;top:0px;left:0px} 33 .GooFlow_work text{color:#fff} 34 .GooFlow_area {cursor: default;position: absolute;overflow: hidden;} 35 .GooFlow_area .lock{cursor:default;} 36 .GooFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;} 37 .GooFlow_work .lock .bg{cursor:default;} 38 .GooFlow_area label{cursor:text;top:1px;left:1px;position:absolute;display:block;font-size:12px;text-indent:18px;height:18px;line-height:18px} 39 .GooFlow_work .lock label{cursor:default;} 40 .GooFlow_area i{display:block;height:18px;width:18px;top:0px;left:0px;position:absolute;cursor:pointer} 41 .GooFlow_work .area_red .bg{border:1px solid red;background-color:#FF7865} 42 .GooFlow_work .area_red label{color:red;background:url(img/gooflow_bullet.png) no-repeat 1px 1px} 43 .GooFlow_work .area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564} 44 .GooFlow_work .area_yellow label{color:#FFBA1D;background:url(img/gooflow_bullet.png) no-repeat 1px -16px} 45 .GooFlow_work .area_blue .bg{border:1px solid #347BB1;background-color:#549CDE} 46 .GooFlow_work .area_blue label{color:#347BB1;background:url(img/gooflow_bullet.png) no-repeat 1px -33px} 47 .GooFlow_work .area_green .bg{border:1px solid green;background-color:#84CA04} 48 .GooFlow_work .area_green label{color:green;background:url(img/gooflow_bullet.png) no-repeat 1px -50px} 49 50 .GooFlow_work svg{display:block;position:absolute} 51 .GooFlow_work v\:group{position:relative;display:block} 52 .GooFlow_work v\:group v\:line{overflow:visible} 53 .GooFlow_work v\:group v\:polyline{overflow:visible} 54 .GooFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap} 55 .GooFlow_work .draw{color:#ff3300} 56 57 .GooFlow_item{ 58 position:absolute;background:#A1DCEB;border:#A1DCEB solid 1px; 59 border-radius:3px;background-color:#C1DCFC;box-shadow:1px 1px 2px rgba(99,99,99,2); 60 } 61 .GooFlow table{padding:1px;border-radius:2px} 62 .GooFlow td{ vertical-align:middle;text-align:center;padding:0px;cursor:default;word-wrap:break-word;word-break:break-all} 63 .GooFlow .ico{width:28px;cursor:move} 64 .GooFlow i{display:block;width:28px;height:28px;overflow:hidden} 65 66 .GooFlow .item_round{border-radius:11px;border:#C1DCFC solid 1px;width:35px;height:35px; overflow:visible} 67 .GooFlow .item_round table{border:0px;padding:2px;width:35px;height:35px} 68 .GooFlow .item_round .span{ 69 display:block;text-align:center; position:absolute;top:35px;left:-20px;width:80px;overflow:visible;text-align:center; 70 padding:0px;cursor:default;word-wrap: break-word;word-break:break-all 71 } 72 .GooFlow .item_mix{background:#B6F700;border-color:#C2DB4E;color:#fff} 73 .GooFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize} 74 .GooFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize} 75 .GooFlow div .rs_rb{ 76 position:absolute;right:-1px;bottom:-1px;width:9px;height:9px;overflow:hidden;cursor:nw-resize;background:url(img/gooflow_tip.png) no-repeat 0px -8px; 77 } 78 .GooFlow div .rs_close{ 79 position:absolute;right:1px;top:1px;width:7px;height:7px;overflow:hidden;cursor:pointer;background:url(img/gooflow_tip.png) no-repeat 0px 0px 80 } 81 .GooFlow .rs_ghost{ 82 position:absolute;display:none;overflow:hidden;border:#8EA4C1 1px dashed; background:#D9E8FB; 83 filter:Alpha(Opacity=60);-moz-opacity:0.6;opacity: 0.6;z-index:10 84 } 85 .GooFlow .item_focus{border:#3892D3 1px solid} 86 .GooFlow .item_mark{border:#ff3300 1px solid} 87 .GooFlow .item_mark td{cursor:crosshair} 88 .GooFlow textarea{position:absolute;border:#3892D3 1px solid;display:none;font: 1em Microsoft Yahei;overflow-y:visible;width:100px;z-index:1000} 89 90 .GooFlow .GooFlow_line_oper{ 91 width:70px;height:15px;background-color:#D8E8FC;border:#7DA2CE 1px solid;position:absolute; 92 filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:1000; 93 } 94 95 .GooFlow .GooFlow_line_mp{ 96 width:9px;height:9px;filter:Alpha(Opacity=40);-moz-opacity:0.4;opacity:0.4;overflow:hidden; 97 position:absolute;z-index:1000;background:#333;cursor:crosshair 98 } 99 100 .GooFlow .GooFlow_line_move{filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:1000;} 101 .GooFlow .GooFlow_line_oper i{display:inline-block;width:15px;height:15px;margin-left:2px;cursor:pointer} 102 .GooFlow .b_l1{background:url(img/GooFlow_line_oper.png) no-repeat 1px 1px} 103 .GooFlow .b_l2{background:url(img/GooFlow_line_oper.png) no-repeat 1px -14px} 104 .GooFlow .b_l3{background:url(img/GooFlow_line_oper.png) no-repeat 1px -29px} 105 .GooFlow .b_x{background:url(img/GooFlow_line_oper.png) no-repeat 1px -44px;margin-left:10px} 106 107 .GooFlow .ico_cursor{background:url(img/gooflow_icon.png) no-repeat -1px -41px} 108 .GooFlow .ico_start{background:url(img/gooflow_icon.png) no-repeat -121px -41px} 109 .GooFlow .ico_end{background:url(img/gooflow_icon.png) no-repeat -161px -41px} 110 .GooFlow .ico_fork{background:url(img/gooflow_icon.png) no-repeat -401px -41px} 111 .GooFlow .ico_join{background:url(img/gooflow_icon.png) no-repeat -441px -41px} 112 .GooFlow .ico_direct{background:url(img/gooflow_icon.png) no-repeat -81px -41px} 113 .GooFlow .ico_group{background:url(img/gooflow_icon.png) no-repeat -41px -81px} 114 .GooFlow .ico_complex{background:url(img/gooflow_icon.png) no-repeat -1px -81px} 115 .GooFlow .ico_node{background:url(img/gooflow_icon.png) no-repeat -241px -41px} 116 .GooFlow .ico_task{background:url(img/gooflow_icon.png) no-repeat -201px -41px} 117 .GooFlow .ico_chat{background:url(img/gooflow_icon.png) no-repeat -281px -41px} 118 .GooFlow .ico_state{background:url(img/gooflow_icon.png) no-repeat -321px -41px} 119 .GooFlow .ico_plug{background:url(img/gooflow_icon.png) no-repeat -361px -41px} 120 .GooFlow .ico_menu{background:url(img/gooflow_icon.png) no-repeat 0px -66px} 121 .GooFlow .ico_sound{background:url(img/gooflow_icon.png) no-repeat -19px -66px} 122 .GooFlow .ico_topo{background:url(img/gooflow_icon.png) no-repeat -118px -46px} 123 124 .GooFlow .ico_open{background:url(img/gooflow_icon.png) no-repeat -40px 0} 125 .GooFlow .ico_new{background:url(img/gooflow_icon.png) no-repeat 0 0} 126 .GooFlow .ico_reload{background:url(img/gooflow_icon.png) no-repeat -200px 0} 127 .GooFlow .ico_save{background:url(img/gooflow_icon.png) no-repeat -80px 0} 128 .GooFlow .ico_undo{background:url(img/gooflow_icon.png) no-repeat -120px 0} 129 .GooFlow .ico_redo{background:url(img/gooflow_icon.png) no-repeat -160px 0} 130 .GooFlow .ico_close{background:url(img/gooflow_icon.png) no-repeat -320px 0} 131 132 .GooFlow .ico_mutiselect{background:url(img/gooflow_icon.png) no-repeat -40px -40px}
1 @{ 2 ViewBag.Title = "流程图"; 3 } 4 @section HeadCss{ 5 <style type="text/css"> 6 #id-div-east tr td div{ 7 line-height: 25px; 8 } 9 </style> 10 } 11 <div class="easyui-layout" id="id-div-layout" style="width:100%;height:100%"> 12 <div data-options="region:'center'" style="overflow: hidden; border-width: 0px;"> 13 <div id="flow"></div> 14 <div id="div-dialog-choose-condition" style="padding: 2px; overflow: hidden;"></div> 15 <div id="div-dialog-edit" style="padding:2px;"></div> 16 </div> 17 <div data-options="region:'east',split:true,title:'属性'" id="id-div-east" style="width: 350px; border-width: 0px 0px 0px 1px; overflow-x:hidden"> 18 <table id="tt-grid" border="0"></table> 19 </div> 20 </div> 21 22 <script type="text/html" id="participant-template"> 23 @Html.Partial("FlowParticipantSetting") 24 </script> 25 <script type="text/html" id="scheme-template"> 26 @Html.Partial("FlowSchemeSetting") 27 </script> 28 29 30 @section scripts{ 31 <script type="text/javascript"> 32 var picPage, myLayer; 33 seajs.use("flow/flow.picture", function (page) { 34 this.picPage = Class.create(page.PageClass); 35 this.myLayer = page.myLayer; 36 }); 37 </script> 38 }
1 define(function (require, exports, module) { 2 require("utils"); 3 exports.myLayer = require("layer.extend"); 4 exports.PageClass = { 5 initialize: function () { 6 this.myGooFlow = require("flow/flow.core"); 7 this.flowID = utils.getUrlParam("flowID") || 0; 8 this.focusElement = {}; 9 }, 10 initializeDOM: function () { 11 this.$grid = $("#tt-grid"); 12 }, 13 initializeControl: function () { 14 var that = this; 15 var title = utils.getUrlParam1("title"); 16 var center = $('#id-div-layout').layout('panel', 'center'); 17 that.myGooFlow.initFlowPic($("#flow"), { 18 "title": title, 19 "flowID": that.flowID, 20 "container": center, 21 "grid": that.$grid, 22 "onClose": function () { 23 parent.myLayer.extend.closeAll(); 24 } 25 }); 26 center.panel({ 27 onResize: function (w, h) { 28 gooFlow.reinitSize(w, h); 29 } 30 }); 31 32 //#region 初始化属性菜单 33 that.propertygrid = that.$grid.propertygrid({ 34 showGroup: true, 35 scrollbarSize: 0, 36 //fit:true, 37 columns: [[ 38 { field: 'name', title: '名称' }, 39 { 40 field: 'value', title: '值', resizable: false, width: 150, formatter: function (value, row, index) { 41 return "<span title=" + value + ">" + value + "</span>" 42 } 43 } 44 ]], 45 onBeginEdit: function (rowIndex, rowData) { 46 var ed = that.$grid.datagrid('getEditor', { index: rowIndex, field: 'value' }); 47 var options = $(ed.target).textbox("options"); 48 if (ed.type == "combobox") { 49 $(ed.target).combobox("setValue", rowData.value); 50 } 51 else if (ed.type == "textbox") { 52 var txt = $(ed.target).textbox("textbox"); 53 $(txt).keydown(function () { return false }); 54 $(txt).click(function () { 55 if (options.title == "设置参与者") { 56 var layerIndex = myLayer.extend.open({ 57 title: options.title, 58 maxmin: false, 59 area: ["700px","320px"], 60 content: $("#participant-template").html() + "</" + "script>", 61 success: function (layero, index) { 62 picPage.participantLayer = layero; 63 $("#id-hd-ParticipantType").attr("name", options.typeField); 64 $("#id-hd-ParticipantText").attr("name", options.textField); 65 $("#id-hd-ParticipantValue").attr("name", options.valueField); 66 }, 67 yes: function (index) { 68 saveForm(function () { 69 var params = participantPage.$form.serializeArray(); 70 $(params).each(function (i, obj) { 71 var row = picPage.focusElement.rowData.where("o.field=='" + obj.name + "'")[0]; 72 if (row) { 73 row.value = obj.value; 74 } 75 }); 76 77 myLayer.extend.close(layerIndex); 78 picPage.$grid.datagrid("refreshRow", rowIndex - 1); 79 picPage.$grid.datagrid("refreshRow", rowIndex); 80 }); 81 } 82 }); 83 } 84 else if (options.title == "设置方案") { 85 var layerIndex = myLayer.extend.open({ 86 title: options.title, 87 maxmin: false, 88 area: ["700px", "320px"], 89 content: $("#scheme-template").html() + "</" + "script>", 90 success: function (layero, index) { 91 var row = picPage.focusElement.rowData.where("o.field=='" + options.valueField + "'")[0]; 92 if (row && row.value) { 93 var schemeValue = eval("(" + row.value + ")"); 94 $("#id-hd-schemeType").val(schemeValue.id); 95 } 96 }, 97 yes: function (index) { 98 saveForm(options, function () { 99 myLayer.extend.close(layerIndex); 100 picPage.$grid.datagrid("refreshRow", rowIndex); 101 }); 102 } 103 }); 104 } 105 }); 106 } 107 else if (ed.type == "checkbox") { 108 $(ed.target).attr("checked", rowData.value == "是"); 109 } 110 }, 111 onEndEdit: function (rowIndex, rowData, changes) { 112 113 }, 114 onLoadSuccess: function () { 115 $("#id-div-east").animate({ scrollTop: 0 }, 100); 116 } 117 }); 118 119 that.propertygrid.loadData = function (rows) { 120 var rowData = rows.where("!o.hidden"); 121 that.$grid.propertygrid("loadData", rowData); 122 } 123 //#endregion 124 }, 125 initializeEvent: function () { 126 }, 127 pageLoad: function () { 128 $("#id-div-layout").layout('panel', 'east').panel({ 129 onResize: function (w, h) { 130 PropertygridFit($("#id-div-east .datagrid-view").height()); 131 } 132 }); 133 var originalHeight; 134 setInterval(function () { 135 var gridHeight = $("#id-div-east .datagrid-view").height(); 136 if (originalHeight != gridHeight) { 137 PropertygridFit(gridHeight); 138 originalHeight = gridHeight; 139 } 140 }, 1000); 141 } 142 } 143 144 function PropertygridFit(gridHeight) { 145 var east = $('#id-div-layout').layout('panel', 'east'); 146 var h = east.height(), w = east.width(); 147 if (gridHeight > h) 148 picPage.$grid.propertygrid("resize", { width: w - 18 }); 149 else 150 picPage.$grid.propertygrid("resize", { width: w }); 151 } 152 });
1 define(function (require, exports, module) { 2 require("../../plugins/GooFlow/Gooflow.css"); 3 //require("../../plugins/GooFlow/default.css"); 4 require("../../plugins/GooFlow/GooFunc.js"); 5 require("../../plugins/GooFlow/GooFlow.js"); 6 7 var nodeRows = [], lineRows = [], areaRows = [], 8 node_extra_attributes = [], 9 line_extra_attributes = [], 10 area_extra_attributes=[], 11 gooflow; 12 GooFlow.prototype.color = { 13 main: "#00B4E1", 14 node: "#A1DCEB", 15 line: "#3892D3", 16 mark: "#ff3300", 17 mix: "#B6F700", 18 font: "#15428B" 19 }; 20 module.exports = { 21 initFlowMap: function (jq, params) { 22 var property = { 23 haveHead: true, 24 headLabel: true, 25 headBtns: [], //如果haveHead=true,则定义HEAD区的按钮 26 haveTool: false, 27 haveGroup: true, 28 useOperStack: false 29 }; 30 gooFlow = $.createGooFlow(jq, property); 31 gooFlow.setTitle(params.title + "·流程绘制"); 32 gooFlow.$editable = false; 33 $(window).on("resize", function () { 34 gooFlow.reinitSize(params.container.width() - 5, params.container.height()); 35 }); 36 $(window).trigger('resize'); 37 //加载数据 38 utils.showLoading(gooFlow.$bgDiv, "图形正在加载中,请稍候……"); 39 var queryParam = { 40 "type": "get", 41 "url": "/Flow/LoadWorkSpace?flowID=" + flowID, 42 "success": function (result) { 43 utils.hideLoading(gooFlow.$bgDiv); 44 params.callBack(); 45 }, 46 "error": function () { 47 myLayer.extend.alert('图形加载失败:' + result, 8, function () { utils.hideLoading(gooFlow.$bgDiv); }); 48 } 49 } 50 gooFlow.loadDataAjax(queryParam); 51 }, 52 initFlowPic: function (jq, params) { 53 var remark = { 54 "cursor": "选择指针", 55 "direct": "节点连线", 56 "start": "开始节点", 57 "end": "结束节点", 58 "task": "普通节点", 59 "chat": "决策结点", 60 "group": "区域" 61 } 62 var property = { 63 toolBtns: ["start", "end", "task", "chat"], 64 headLabel: true, 65 haveHead: true, 66 headBtns: ["new", "save", "undo", "redo", "reload", "close"], //如果haveHead=true,则定义HEAD区的按钮 67 headBtnTitles: ["新增", "保存", "撤销", "撤回", "刷新", "退出"], //如果haveHead=true,则定义HEAD区的按钮 68 haveTool: true, 69 haveGroup: true, 70 useOperStack: true 71 }; 72 gooFlow = $.createGooFlow(jq, property); 73 gooFlow.setTitle(params.title + "·流程绘制"); 74 gooFlow.reinitSize(params.container.width(), params.container.height()); 75 //设定左侧工具栏中每一种节点或按钮的说明文字 76 gooFlow.setNodeRemarks(remark); 77 //加载gooflow数据 78 utils.showLoading(gooFlow.$bgDiv, "图形正在加载中,请稍候……"); 79 gooFlow.loadDataAjax({ 80 "type": "get", 81 "url": "/Flow/LoadWorkSpace?flowID=" + params.flowID, 82 "success": function (result) { 83 node_extra_attributes = result.node_extra_attributes; 84 line_extra_attributes = result.line_extra_attributes; 85 area_extra_attributes = result.area_extra_attributes; 86 var flowElement = $.parseJSON(result.flow_elements); 87 var rows = []; 88 //节点属性 89 for (var nodeID in flowElement.nodes) { 90 var node_extra_attrValues = result.extra_attribute_values.where("o.ElementID=='" + nodeID + "'"); 91 rows = createAttributeData("node", nodeID, flowElement.nodes[nodeID], node_extra_attrValues); 92 nodeRows.push({ "elementID": nodeID, "rowData": rows, "ID": flowElement.nodes[nodeID].ID }); 93 } 94 //连接线属性 95 for (var lineID in flowElement.lines) { 96 var line_extra_attrValues = result.extra_attribute_values.where("o.ElementID=='" + lineID + "'"); 97 rows = createAttributeData("line", lineID, flowElement.lines[lineID], line_extra_attrValues); 98 lineRows.push({ "elementID": lineID, "rowData": rows, "ID": flowElement.lines[lineID].ID }); 99 } 100 //块属性 101 for (var areaID in flowElement.areas) { 102 var area_extra_attrValues = result.extra_attribute_values.where("o.ElementID=='" + areaID + "'"); 103 rows = createAttributeData("area", areaID, flowElement.areas[areaID], area_extra_attrValues); 104 areaRows.push({ "elementID": areaID, "rowData": rows, "ID": flowElement.areas[areaID].ID }); 105 } 106 107 //加载流程属性 108 var form_attributes = [ 109 { "name": "流程名称", "value": "" + result.flowData.FlowName + "", "group": "流程属性" }, 110 { "name": "表单地址", "value": "" + (result.flowData.FormUrl || "") + "", "group": "流程属性" }, 111 { "name": "是否禁用", "value": result.flowData.IsDisabled, "group": "流程属性" }, 112 { "name": "创建时间", "value": utils.dateFormatter(result.flowData.CreateOn, "yyyy-MM-dd hh:mm:ss"), "group": "流程属性" }, 113 { "name": "创建人", "value": result.flowData.CreateBy, "group": "流程属性" }, 114 { "name": "修改时间", "value": utils.dateFormatter(result.flowData.ModifiedOn, "yyyy-MM-dd hh:mm:ss"), "group": "流程属性" }, 115 { "name": "修改人", "value": result.flowData.ModifiedBy, "group": "流程属性" } 116 ]; 117 params.grid.propertygrid("loadData", { 'total': form_attributes.length, "rows": form_attributes }); 118 utils.hideLoading(gooFlow.$bgDiv); 119 }, 120 "error": function () { 121 myLayer.extend.alert('图形加载失败:' + status, 8, function () { utils.hideLoading(gooFlow.$bgDiv); }); 122 } 123 }); 124 125 //#region 头部工具条事件 126 //新建流程 127 gooFlow.onBtnNewClick = function () { 128 gooFlow.clearData(); 129 } 130 //保存流程 131 gooFlow.onBtnSaveClick = function () { 132 var flowData = [], n = 0; 133 $(nodeRows).each(function (i, item) { 134 flowData.push({ "name": "nodes[" + i + "].ID", "value": item.ID }); 135 $(item.rowData).each(function (j, row) { 136 if (!row.attrID) 137 flowData.push({ "name": "nodes[" + i + "]." + row.field, "value": row.value }); 138 else { 139 flowData.push({ "name": "attrValues[" + n + "].ID", "value": row.attrValueID }); 140 flowData.push({ "name": "attrValues[" + n + "].ElementID", "value": item.elementID }); 141 flowData.push({ "name": "attrValues[" + n + "].AttrID", "value": row.attrID }); 142 flowData.push({ "name": "attrValues[" + n + "].AttrName", "value": row.field }); 143 flowData.push({ "name": "attrValues[" + n + "].AttrValue", "value": row.value }); 144 n++; 145 } 146 }); 147 }); 148 //连接线 149 $(lineRows).each(function (i, item) { 150 flowData.push({ "name": "lines[" + i + "].ID", "value": item.ID }); 151 $(item.rowData).each(function (j, row) { 152 if (!row.attrID) 153 flowData.push({ "name": "lines[" + i + "]." + row.field, "value": row.value }); 154 else { 155 flowData.push({ "name": "attrValues[" + n + "].ID", "value": row.attrValueID }); 156 flowData.push({ "name": "attrValues[" + n + "].ElementID", "value": item.elementID }); 157 flowData.push({ "name": "attrValues[" + n + "].AttrID", "value": row.attrID }); 158 flowData.push({ "name": "attrValues[" + n + "].AttrName", "value": row.field }); 159 flowData.push({ "name": "attrValues[" + n + "].AttrValue", "value": row.value }); 160 n++; 161 } 162 }); 163 }); 164 //区域 165 $(areaRows).each(function (i, item) { 166 flowData.push({ "name": "areas[" + i + "].ID", "value": item.ID }); 167 $(item.rowData).each(function (j, row) { 168 flowData.push({ "name": "areas[" + i + "]." + row.field, "value": row.value }); 169 }); 170 }); 171 utils.showLoading(gooFlow.$bgDiv, "数据正在保存中,请稍候……"); 172 flowData.push({ "name": "flowID", "value": params.flowID }); 173 $.ajaxPost({ 174 url: "/Flow/SaveFlowPicture", 175 data: flowData, 176 success: function (msg) { 177 if (msg == "success") { 178 myLayer.extend.alert('保存成功.', 9, function () { location.reload() }); 179 } 180 else 181 myLayer.extend.alert('保存失败:' + msg, 8); 182 utils.hideLoading(gooFlow.$bgDiv); 183 } 184 }); 185 } 186 //刷新 187 gooFlow.onFreshClick = function () { 188 location.reload(); 189 } 190 //关闭 191 gooFlow.onCloseClick = function () { 192 params.onClose(); 193 } 194 //#endregion 195 196 //#region 流程元素事件 197 gooFlow.onItemAdd = function (id, type, element) { 198 if (type == "line") { 199 if (element.from == element.to) return; 200 //防止添加重复的连接线 201 var flag = true; 202 $(lineRows).each(function (i, item) { 203 var n = 0; 204 $(item.rows).each(function (j, row) { 205 if (row.field == "LineFrom" && row.value == element.from) 206 n += 1; 207 if (row.field == "LineTo" && row.value == element.to) 208 n += 1; 209 }); 210 if (n == 2) { 211 flag = false; 212 return false; 213 } 214 }); 215 if (!flag) return; 216 } 217 //获取并创建流程元素属性 218 var rows = []; 219 if (type == "node") { 220 rows = createAttributeData(type, id, element); 221 picPage.focusElement = { "type": "node", "elementID": id, "rowData": rows, "ID": "0" }; 222 nodeRows.push(picPage.focusElement); 223 } 224 else if (type == "line") { 225 rows = createAttributeData(type, id, element); 226 picPage.focusElement = { "type": "line", "elementID": id, "rowData": rows, "ID": "0" }; 227 lineRows.push(picPage.focusElement); 228 } 229 else if (type == "area") { 230 rows = createAttributeData(type, id, element); 231 picPage.focusElement = { "type": "area", "elementID": id, "rowData": rows, "ID": "0" }; 232 areaRows.push(picPage.focusElement); 233 } 234 //picPage.propertygrid.loadData(rows); 235 return true; 236 } 237 gooFlow.onItemFocus = function (id, type) { 238 FlowElementAction(id, type, "focus"); 239 return true; 240 } 241 //流程元素移动事件 242 gooFlow.onItemMove = function (id, type, left, top) { 243 if (type == "node") 244 FlowElementAction(id, type, "modify", { "NodeLeft": left, "NodeTop": top }); 245 else if (type == "area") 246 FlowElementAction(id, type, "modify", { "AreaLeft": left, "AreaTop": top }); 247 return true; 248 } 249 //修改元素大小 250 gooFlow.onItemResize = function (id, type, width, height) { 251 if (type == "node") 252 FlowElementAction(id, type, "modify", { "NodeWidth": width, "NodeHeight": height }); 253 else if (type == "area") 254 FlowElementAction(id, type, "modify", { "AreaWidth": width, "AreaHeight": height }); 255 return true; 256 } 257 gooFlow.onItemRename = function (id, name, type) { 258 if (type == "node") 259 FlowElementAction(id, type, "modify", { "NodeName": name }); 260 else if (type == "line") 261 FlowElementAction(id, type, "modify", { "LineName": name }); 262 else if (type == "area") 263 FlowElementAction(id, type, "modify", { "AreaName": name }); 264 return true; 265 } 266 //操作单元删除事件 267 gooFlow.onItemDel = function (id, type) { 268 FlowElementAction(id, type, "delete"); 269 return true; 270 } 271 //连接线跟换类型事件 272 gooFlow.onLineSetType = function (id, type) { 273 FlowElementAction(id, "line", "modify", { "LineType": type, "LineM": 0 }); 274 return true; 275 } 276 //移动某条折线中段 277 gooFlow.onLineMove = function (id, M) { 278 FlowElementAction(id, "line", "modify", { "LineM": M }); 279 return true; 280 } 281 //更换线条节点事件 282 gooFlow.onLinePointMove = function (id, newStart, newEnd) { 283 FlowElementAction(id, "line", "modify", { "LineFrom": newStart, "LineTo": newEnd }); 284 return true; 285 } 286 //区域修改颜色 287 gooFlow.onAreaSetColor = function (id, color) { 288 FlowElementAction(id, "area", "modify", { "AreaColor": color }); 289 return true; 290 } 291 //#endregion 292 } 293 } 294 295 //#region 创建gooflow元素的属性 296 function createAttributeData(type, id, element,attrValues) { 297 var rows = []; 298 if (type == "node") { 299 rows = [{ "field": "NodeID", "name": "节点ID", "value": "" + id + "", "group": "节点属性" }, 300 { "field": "NodeName", "name": "节点名称", "value": "" + element.name + "", "group": "节点属性" }, 301 { "field": "NodeType", "name": "节点类型", "value": "" + element.type + "", "group": "节点属性" }, 302 { "field": "NodeLeft", "name": "X坐标", "value": element.left, "group": "节点属性" }, 303 { "field": "NodeTop", "name": "Y坐标", "value": element.top, "group": "节点属性" }, 304 { "field": "NodeWidth", "name": "宽度", "value": element.width, "group": "节点属性" }, 305 { "field": "NodeHeight", "name": "高度", "value": element.height, "group": "节点属性" }]; 306 $(node_extra_attributes).each(function (index, obj) { 307 var editor = null; 308 if (obj.Editor) { 309 editor = eval('(' + obj.Editor + ')'); 310 if (editor.type == "combobox") { 311 $.extend(editor.options, { 312 valueField: 'text', 313 textField: 'text', 314 editable: false, 315 panelHeight: 'auto' 316 }); 317 obj.AttrValue = editor.options.defaultValue; 318 } 319 else if (editor.type == "textbox") { 320 $.extend(editor.options, { 321 buttonIcon: 'icon-clear', 322 onClickButton: function () { 323 $(this).textbox('clear'); 324 } 325 }); 326 } 327 } 328 var attrValue = obj.AttrValue || ""; 329 var attrValueID = obj.AttrValueID || 0; 330 if (attrValues) { 331 var attr = attrValues.where("o.ElementID=='"+id+"' && o.AttrID==" + obj.ID)[0]; 332 if (attr) { 333 attrValue = attr.AttrValue; 334 attrValueID = attr.ID; 335 } 336 } 337 rows.push({ 338 "field": "" + obj.AttrName + "", 339 "name": "" + obj.AttrTitle + "", 340 "value": attrValue, 341 "group": "" + obj.GroupName + "", 342 "editor": editor, 343 "hidden": !obj.ShowInList, 344 "attrID": obj.ID, 345 "attrValueID": attrValueID 346 }); 347 }) 348 } 349 else if (type == "line") { 350 rows = [{ "field": "LineID", "name": "连接线ID", "value": "" + id + "", "group": "线条属性" }, 351 { "field": "LineName", "name": "连接线名称", "value": "" + element.name + "", "group": "线条属性" }, 352 { "field": "LineType", "name": "连接线类型", "value": "" + element.type + "", "group": "线条属性" }, 353 { "field": "LineFrom", "name": "开始节点ID", "value": element.from, "group": "线条属性" }, 354 { "field": "LineTo", "name": "结束节点ID", "value": element.to, "group": "线条属性" }, 355 { "field": "LineM", "name": "M值", "value": element.M || 0, "group": "线条属性" }]; 356 $(line_extra_attributes).each(function (index, obj) { 357 var editor = null; 358 if (obj.Editor) { 359 editor = eval('(' + obj.Editor + ')'); 360 if (editor.type == "textbox") { 361 $.extend(editor.options, { 362 buttonIcon: 'icon-clear', 363 onClickButton: function () { 364 $(this).textbox('clear'); 365 var row = picPage.focusElement.rowData.where("o.field=='" + editor.options.valueField + "'")[0]; 366 if (row) row.value = ""; 367 } 368 }); 369 } 370 } 371 var attrValue = obj.AttrValue || ""; 372 var attrValueID = obj.AttrValueID || 0; 373 if (attrValues) { 374 var attr = attrValues.where("o.ElementID=='" + id + "' && o.AttrID==" + obj.ID)[0]; 375 if (attr) { 376 attrValue = attr.AttrValue; 377 attrValueID = attr.ID; 378 } 379 } 380 rows.push({ 381 "field": "" + obj.AttrName + "", 382 "name": "" + obj.AttrTitle + "", 383 "value": attrValue || "", 384 "group": "" + obj.GroupName + "", 385 "editor": editor, 386 "hidden": !obj.ShowInList, 387 "attrID": obj.ID, 388 "attrValueID": attrValueID 389 }); 390 }) 391 } 392 else if (type == "area") { 393 rows = [{ "field": "AreaID", "name": "分组区ID", "value": "" + id + "", "group": "分组区域属性" }, 394 { "field": "AreaName", "name": "分组区名称", "value": "" + element.name + "", "group": "分组区域属性" }, 395 { "field": "AreaLeft", "name": "X坐标", "value": element.left, "group": "分组区域属性" }, 396 { "field": "AreaTop", "name": "Y坐标", "value": element.top, "group": "分组区域属性" }, 397 { "field": "AreaWidth", "name": "宽度", "value": element.width, "group": "分组区域属性" }, 398 { "field": "AreaHeight", "name": "高度", "value": element.height, "group": "分组区域属性" }, 399 { "field": "AreaColor", "name": "颜色", "value": element.color, "group": "分组区域属性" }]; 400 } 401 return rows; 402 } 403 //#endregion 404 405 //#region 流程元素的操作公共方法 406 function FlowElementAction(id, type, action, changes) { 407 if (action == "focus") { 408 if (type == "node") 409 picPage.focusElement = nodeRows.where("o.elementID=='" + id + "'")[0]; 410 else if (type == "line") 411 picPage.focusElement = lineRows.where("o.elementID=='" + id + "'")[0]; 412 if (picPage.focusElement) 413 picPage.propertygrid.loadData(picPage.focusElement.rowData); 414 } 415 else if (action == "modify") { 416 if (type == "area") { 417 picPage.focusElement = areaRows.where("o.elementID=='" + id + "'")[0]; 418 picPage.propertygrid.loadData(picPage.focusElement.rowData); 419 } 420 for (var prop in changes) { 421 var row = picPage.focusElement.rowData.where("o.field=='" + prop + "'")[0] 422 row.value = changes[prop]; 423 var rowIndex = picPage.$grid.datagrid("getRowIndex", row); 424 picPage.$grid.datagrid("refreshRow", rowIndex); 425 } 426 } 427 else if (action == "delete") { 428 if (type == "node") 429 nodeRows.splice($.inArray(picPage.focusElement, nodeRows), 1); 430 else if (type == "line") 431 lineRows.splice($.inArray(picPage.focusElement, lineRows), 1); 432 else if (type == "area") 433 areaRows.splice($.inArray(picPage.focusElement, areaRows), 1); 434 picPage.propertygrid.loadData([]); 435 436 } 437 } 438 //#endregion 439 440 441 442 //propertygrid【checkbox】扩展方法 443 444 $.extend($.fn.datagrid.defaults.editors, { 445 checkbox: { 446 init: function (container, options) { 447 var input = $('<input type="checkbox">').appendTo(container); 448 input.val(options.on); 449 input.attr("offval", options.off); 450 return input; 451 }, 452 destroy: function (target) { 453 $(target).remove(); 454 }, 455 getValue: function (target) { 456 if ($(target).is(":checked")) { 457 return $(target).val(); 458 } else { 459 return $(target).attr("offval"); 460 } 461 }, 462 setValue: function (target, value) { 463 return $(target).val() == value ? true : false; 464 }, 465 resize: function (target, width) { 466 $(target)._outerWidth(width); 467 } 468 } 469 }); 470 });
暂时分享这么多把。
点击右下角【推荐】=================》为您提供演示地址。
联系方式:(QQ:512948935)
Gooflow0.6 UI界面下载
GooFlow0.8 ui界面下载
GooFlow1.1 ui界面下载
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- asp.net mvc中Forms身份验证身份验证流程 2020-02-06
- 【转载】申请软件著作权需要哪些材料以及相应流程(注:此文 2019-05-22
- 【转载】网站域名备案相关流程介绍 2019-02-28
- K2制作流程 2019-02-21
- ASP.NET Web API2返回值处理流程 2018-11-20
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash