Browse Source

前端流程编排

lee 8 years ago
parent
commit
bdd565884a
40 changed files with 3500 additions and 4527 deletions
  1. 15 5
      src/main/webapp/WEB-INF/ehr/jsp/system/process/process.jsp
  2. 233 44
      src/main/webapp/WEB-INF/ehr/jsp/system/process/processJs.jsp
  3. 0 102
      src/main/webapp/develop/lib/gooflow/GooFunc.js
  4. 712 0
      src/main/webapp/develop/lib/gooflow/css/GooFlow.css
  5. 0 19
      src/main/webapp/develop/lib/gooflow/default.css
  6. BIN
      src/main/webapp/develop/lib/gooflow/goo/GooFlow_line_oper.png
  7. BIN
      src/main/webapp/develop/lib/gooflow/goo/Thumbs.db
  8. BIN
      src/main/webapp/develop/lib/gooflow/goo/bullet_blue.png
  9. 0 1
      src/main/webapp/develop/lib/gooflow/goo/child.js
  10. 0 138
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.css
  11. 0 135
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.css.bak
  12. 0 2000
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.js
  13. 0 1915
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.js.bak
  14. 0 131
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow2.css
  15. 0 16
      src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow_color.js
  16. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/Thumbs.db
  17. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_bg.png
  18. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank.gif
  19. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank2.gif
  20. 0 12
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank2.htm
  21. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_btn_bg.png
  22. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_icon.png
  23. BIN
      src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_icon2.png
  24. 0 1
      src/main/webapp/develop/lib/gooflow/goo/data.js
  25. BIN
      src/main/webapp/develop/lib/gooflow/goo/ui-icons_222222_256x240.png
  26. BIN
      src/main/webapp/develop/lib/gooflow/goo/未命名-3 - 副本.png
  27. BIN
      src/main/webapp/develop/lib/gooflow/goo/未命名-3.png
  28. 0 0
      src/main/webapp/develop/lib/gooflow/img/GooFlow_line_oper.png
  29. BIN
      src/main/webapp/develop/lib/gooflow/img/arrow.png
  30. 0 0
      src/main/webapp/develop/lib/gooflow/img/gooflow_bullet.png
  31. BIN
      src/main/webapp/develop/lib/gooflow/img/gooflow_icon.png
  32. 0 0
      src/main/webapp/develop/lib/gooflow/img/gooflow_tip.png
  33. BIN
      src/main/webapp/develop/lib/gooflow/img/sprite.head-tool.png
  34. BIN
      src/main/webapp/develop/lib/gooflow/img/sprite.tool.png
  35. BIN
      src/main/webapp/develop/lib/gooflow/img/sprite.work-are.png
  36. 0 2
      src/main/webapp/develop/lib/gooflow/jquery.min.js
  37. 2314 0
      src/main/webapp/develop/lib/gooflow/js/GooFlow.js
  38. 4 0
      src/main/webapp/develop/lib/gooflow/js/jquery.min.js
  39. 0 6
      src/main/webapp/develop/lib/gooflow/json2.js
  40. 222 0
      src/main/webapp/develop/lib/gooflow/test.json

+ 15 - 5
src/main/webapp/WEB-INF/ehr/jsp/system/process/process.jsp

@ -2,9 +2,19 @@
<%@include file="/WEB-INF/ehr/commons/jsp/commonInclude.jsp" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!--######用户管理页面Title设置######-->
<div class="container" style="width:1800px;">
    <div id="demo" style="margin:10px"></div>
    <input id="submit" type="button" class="btn" value='导出结果' onclick="Export()"/>
    <textarea id="result" row="6"></textarea>
<style>
	.back-box{
		overflow:hidden;
		padding:10px 0;
		text-align:center;
		border-bottom:1px solid #e1e1e1;
		line-height:30px;
	}
</style>
<div style="position:relative">
	<div class="back-box">
		<div class="back-box-btn l-button">返回</div>
		返回上一级目录
	</div>
	<div id="esb" class="GooFlow"></div>
</div>

+ 233 - 44
src/main/webapp/WEB-INF/ehr/jsp/system/process/processJs.jsp

@ -1,48 +1,237 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %>
<%@include file="/WEB-INF/ehr/commons/jsp/commonInclude.jsp" %>
<link rel="stylesheet" type="text/css" href="${contextRoot}/develop/lib/gooflow/goo/codebase/GooFlow2.css"/>
<link rel="stylesheet" type="text/css" href="${contextRoot}/develop/lib/gooflow/default.css"/>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/goo/data.js"></script>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/GooFunc.js"></script>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/json2.js"></script>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/goo/codebase/GooFlow.js"></script>
<link rel="stylesheet" type="text/css" href="${contextRoot}/develop/lib/gooflow/css/GooFlow.css"/>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/js/jquery.min.js"></script>
<script type="text/javascript" src="${contextRoot}/develop/lib/ligerui/ligerui.min.js"></script>
<script type="text/javascript" src="${contextRoot}/develop/lib/gooflow/js/GooFlow.js"></script>
<script type="text/javascript">
    var property = {
        width: 1600,
        height: 700,
        toolBtns: ["start round", "end round", "task round", "node", "chat", "state", "plug", "join", "fork", "complex mix"],
        haveHead: true,
        headBtns: ["new", "open", "save", "undo", "redo", "reload"], //如果haveHead=true,则定义HEAD区的按钮
        haveTool: true,
        haveGroup: true,
        useOperStack: true
    };
    var remark = {
        cursor: "选择指针",
        direct: "结点连线",
        start: "入口结点",
        "end": "结束结点",
        "task": "任务结点",
        node: "自动结点",
        chat: "决策结点",
        state: "状态结点",
        plug: "附加插件",
        fork: "分支结点",
        "join": "联合结点",
        "complex mix": "复合结点",
        group: "组织划分框编辑开关"
    };
    var demo;
    $(document).ready(function() {
        demo = $.createGooFlow($("#demo"), property);
        demo.setNodeRemarks(remark);
        //demo.onItemDel=function(id,type){
        //	return confirm("确定要删除该单元吗?");
        //}
        //  demo.loadData(jsondata);
    });
    var out;
    function Export() {
        document.getElementById("result").value = JSON.stringify(demo.exportData());
    }
 	$(function () {
		var demo1 = $('#esb').createGooFlow();
		$('#demo1Export').click(function () {
			console.log(demo1.exportData());
		});
        var data = {
        "nodes": {
        "esb_node_0": {
        "name": "SDf",
        "left": 64,
        "top": 71,
        "type": "task",
        "value": "sd",
        "sType": "service",
        "width": 140,
        "height": 50
        },
        "esb_node_1": {
        "name": "crawler转换器",
        "left": 283,
        "top": 71,
        "type": "plug",
        "value": "CrawlerProcessor0",
        "sType": "processor",
        "width": 140,
        "height": 50
        },
        "esb_node_2": {
        "name": "判断",
        "left": 75,
        "top": 213,
        "type": "state",
        "sType": "judgement",
        "width": 120,
        "height": 70
        },
        "esb_node_3": {
        "name": "循环",
        "left": 100,
        "top": 363,
        "type": "complex",
        "sType": "circle",
        "width": 70,
        "height": 70
        },
        "esb_node_4": {
        "name": "全流程-用户信息",
        "left": 65,
        "top": 560,
        "type": "task",
        "value": "全流程-用户信息",
        "sType": "service",
        "width": 140,
        "height": 50
        },
        "esb_node_5": {
        "name": "全流程-就诊信息",
        "left": 319,
        "top": 435,
        "type": "task",
        "value": "jetty:http://localhost:8080/clinicInfo",
        "sType": "service",
        "width": 140,
        "height": 50
        },
        "esb_node_6": {
        "name": "分流",
        "left": 333,
        "top": 223,
        "type": "fork",
        "sType": "multicast",
        "width": 120,
        "height": 50
        },
        "esb_node_7": {
        "name": "crawler转换器",
        "left": 536,
        "top": 132,
        "type": "plug",
        "value": "CrawlerProcessor0",
        "sType": "processor",
        "width": 140,
        "height": 50
        },
        "esb_node_8": {
        "name": "crawler转换器",
        "left": 540,
        "top": 223,
        "type": "plug",
        "value": "CrawlerProcessor0",
        "sType": "processor",
        "width": 140,
        "height": 50
        },
        "esb_node_9": {
        "name": "crawler转换器",
        "left": 537,
        "top": 311,
        "type": "plug",
        "value": "CrawlerProcessor0",
        "sType": "processor",
        "width": 140,
        "height": 50
        },
        "esb_node_10": {
        "name": "聚合",
        "left": 830,
        "top": 305,
        "type": "join",
        "sType": "aggregate",
        "width": 90,
        "height": 60
        },
        "esb_node_11": {
        "name": "全流程-患者信息",
        "left": 687,
        "top": 453,
        "type": "task",
        "value": "全流程-患者信息",
        "sType": "service",
        "width": 140,
        "height": 50
        },
        "esb_node_12": {
        "name": "全流程-就诊信息",
        "left": 928,
        "top": 452,
        "type": "task",
        "value": "jetty:http://localhost:8080/clinicInfo",
        "sType": "service",
        "width": 140,
        "height": 50
        }
        },
        "lines": {
        "esb_line_0": {
        "type": "sl",
        "from": "esb_node_0",
        "to": "esb_node_1",
        "name": "",
        "marked": false
        },
        "esb_line_1": {
        "type": "tb",
        "M": 171.5,
        "from": "esb_node_1",
        "to": "esb_node_2",
        "name": "",
        "marked": false
        },
        "esb_line_2": {
        "type": "sl",
        "from": "esb_node_2",
        "to": "esb_node_3",
        "name": "自定义内容",
        "marked": false
        },
        "esb_line_3": {
        "type": "tb",
        "from": "esb_node_3",
        "to": "esb_node_5",
        "name": "自定义内容",
        "marked": false,
        "M": 390
        },
        "esb_line_4": {
        "type": "sl",
        "from": "esb_node_3",
        "to": "esb_node_4",
        "name": "自定义内容",
        "marked": false
        },
        "esb_line_5": {
        "type": "sl",
        "from": "esb_node_2",
        "to": "esb_node_6",
        "name": "自定义内容",
        "marked": false
        },
        "esb_line_6": {
        "type": "sl",
        "from": "esb_node_6",
        "to": "esb_node_8",
        "name": "",
        "marked": false
        },
        "esb_line_7": {
        "type": "lr",
        "M": 499.5,
        "from": "esb_node_6",
        "to": "esb_node_7",
        "name": "",
        "marked": false
        },
        "esb_line_8": {
        "type": "lr",
        "M": 500,
        "from": "esb_node_6",
        "to": "esb_node_9",
        "name": "",
        "marked": false
        },
        "esb_line_9": {
        "type": "sl",
        "from": "esb_node_9",
        "to": "esb_node_10",
        "name": "",
        "marked": false
        },
        "esb_line_10": {
        "type": "tb",
        "M": 406.5,
        "from": "esb_node_11",
        "to": "esb_node_10",
        "name": "",
        "marked": false
        },
        "esb_line_11": {
        "type": "tb",
        "M": 406,
        "from": "esb_node_12",
        "to": "esb_node_10",
        "name": "",
        "marked": false
        }
        }
        }
		demo1.loadData(data);
	});
</script>

+ 0 - 102
src/main/webapp/develop/lib/gooflow/GooFunc.js

@ -1,102 +0,0 @@
/*本系列框架中,一些用得上的小功能函数,一些UI必须使用到它们,用户也可以单独拿出来用*/
//获取一个DIV的绝对坐标的功能函数,即使是非绝对定位,一样能获取到
function getElCoordinate(dom) {
  var t = dom.offsetTop;
  var l = dom.offsetLeft;
  dom=dom.offsetParent;
  while (dom) {
    t += dom.offsetTop;
    l += dom.offsetLeft;
	dom=dom.offsetParent;
  }; return {
    top: t,
    left: l
  };
}
//兼容各种浏览器的,获取鼠标真实位置
function mousePosition(ev){
	if(!ev) ev=window.event;
    if(ev.pageX || ev.pageY){
        return {x:ev.pageX, y:ev.pageY};
    }
    return {
        x:ev.clientX + document.documentElement.scrollLeft - document.body.clientLeft,
        y:ev.clientY + document.documentElement.scrollTop  - document.body.clientTop
    };
}
//给DATE类添加一个格式化输出字串的方法
Date.prototype.format = function(format)   
{   
   var o = {   
      "M+" : this.getMonth()+1, //month  
      "d+" : this.getDate(),    //day  
      "h+" : this.getHours(),   //hour  
      "m+" : this.getMinutes(), //minute  
      "s+" : this.getSeconds(), //second  ‘
	  //quarter  
      "q+" : Math.floor((this.getMonth()+3)/3), 
      "S" : this.getMilliseconds() //millisecond  
   }   
   if(/(y+)/.test(format)) format=format.replace(RegExp.$1,(this.getFullYear()+"").substr(4 - RegExp.$1.length));   
    for(var k in o)if(new RegExp("("+ k +")").test(format))   
      format = format.replace(RegExp.$1,   
        RegExp.$1.length==1 ? o[k] :    
          ("00"+ o[k]).substr((""+ o[k]).length));   
    return format;   
}
//JS]根据格式字符串分析日期(MM与自动匹配两位的09和一位的9)
//alert(getDateFromFormat(sDate,sFormat));
function getDateFromFormat(dateString,formatString){
	var regDate = /\d+/g;
	var regFormat = /[YyMmdHhSs]+/g;
	var dateMatches = dateString.match(regDate);
	var formatmatches = formatString.match(regFormat);
	var date = new Date();
	for(var i=0;i<dateMatches.length;i++){
		switch(formatmatches[i].substring(0,1)){
			case 'Y':
			case 'y':
				date.setFullYear(parseInt(dateMatches[i]));break;
			case 'M':
				date.setMonth(parseInt(dateMatches[i])-1);break;
			case 'd':
				date.setDate(parseInt(dateMatches[i]));break;
			case 'H':
			case 'h':
				date.setHours(parseInt(dateMatches[i]));break;
			case 'm':
				date.setMinutes(parseInt(dateMatches[i]));break;
			case 's':
				date.setSeconds(parseInt(dateMatches[i]));break;
		}
	}
	return date;
}
//货币分析成浮点数
//alert(parseCurrency("¥1,900,000.12"));
function parseCurrency(currentString){
	var regParser = /[\d\.]+/g;
	var matches = currentString.match(regParser);
	var result = '';
	var dot = false;
	for(var i=0;i<matches.length;i++){
		var temp = matches[i];
		if(temp =='.'){
			if(dot) continue;
		}
		result += temp;
	}
	return parseFloat(result);
}
//将#XXXXXX颜色格式转换为RGB格式,并附加上透明度
function brgba(hex, opacity) {
    if( ! /#?\d+/g.test(hex) ) return hex; //如果是“red”格式的颜色值,则不转换。//正则错误,参考后面的PS内容
    var h = hex.charAt(0) == "#" ? hex.substring(1) : hex,
        r = parseInt(h.substring(0,2),16),
        g = parseInt(h.substring(2,4),16),
        b = parseInt(h.substring(4,6),16),
        a = opacity;
    return "rgba(" + r + "," + g + "," + b + "," + a + ")";
}

+ 712 - 0
src/main/webapp/develop/lib/gooflow/css/GooFlow.css

@ -0,0 +1,712 @@
/**
* 2015-12-03 下载于 17素材: http://www.17sucai.com/pins/3175.html 的演示代码。
* 
* 更新记录:
* 2016-04-19--sam--1. 重写大部分样式,格式化样式列表,去大部分除针对png图片的依赖。
*/
body{
    color: #333;
}
.GooFlow{
    width: 100%;
    overflow: hidden;
    background:#fff;
    font: 12px Arial, Helvetica, sans-serif;
    -moz-user-select:none;
    -webkit-user-select:none;
    -ms-user-select:none;
    -o-user-select:none;
}
.GooFlow_flowChart,.GooFlow_tool{
    overflow: hidden;
    float: left;
}
.GooFlow_flowChart i,.GooFlow_tool i{
    width: 50px;
    height: 60px;
    display: block;
    margin-left:20px;
    float: left;
    cursor: pointer;
}
/*头部*/
.GooFlow_top_box{
    overflow: hidden;
    padding: 10px 0;
}
.GooFlow_head label{
    font-weight: bold;
    width: 200px;
    text-align: center;
    float: left;
    color: #fff;
    overflow: hidden;
    font-size:18px;
}
.GooFlow_head span {
    float: left;
    height: 22px;
    width: 0px;
    overflow: hidden;
    border-left: #9AC6FF 1px solid;
    border-right: whiteFFF 1px solid;
    margin: 0px 1px;
}
/*工具栏*/
.GooFlow_tool i{
    margin-bottom: 2px;
}
.GooFlow_tool_btndown{
    overflow: hidden;
    background: #49A2DF;
    border-radius: 3px;
}
/*工作区-端点*/
.GooFlow_cont_box{
    border-top: 1px solid #e1e1e1;
    overflow: hidden;
    height: 600px;
}
.GooFlow_left,.GooFlow_right{
    width:202px;
    float:left;
    height:100%;
    overflow:hidden;
}
.GooFlow_right{
    float: right;
}
.GooFlow_app{
    font-size: 14px;
    border-left: 1px solid #e1e1e1;
    border-right: 1px solid #e1e1e1;
}
.GooFlow_app_head{
    overflow: hidden;
    background: #f0f0f0;
    padding: 10px;
}
.GooFlow_app_tit{
    font-size: 18px;
    font-size: 14px;
    height: 40px;
    line-height: 40px;
}
.GooFlow_app_search{
    border: 1px solid #e1e1e1;
    background: #fff;
    height: 30px;
    line-height: 30px;
    position: relative;
}
.GooFlow_app_search_input{
    border: none;
    background: none;
    width: 150px;
    height: 30px;
    line-height: 30px;
    text-indent: 10px;
    outline:none;
}
.GooFlow_search_btn{
    position: absolute;
    background:url(../img/sprite.tool.png);
    background-position: 0px -288px;
    width: 30px;
    height: 30px;
    border: none;
    /*cursor: pointer;*/
    outline:none;
    display: inline-block;
}
.GooFlow_app_cont{
    width: 250px;
    height: 500px;
    overflow: auto;
}
.GooFlow_app_list{
    width: 202px;
    background: #fff;
    list-style: none;
}
.GooFlow_left .GooFlow_app_list_item{
    border-top: 1px solid #e1e1e1;
}
.GooFlow_app_list_item:last-child{
    border-bottom: 1px solid #e1e1e1;
}
.GooFlow_app_list_tit{
    padding: 10px;
    background: #fff;
    position: relative;
    overflow: hidden;
    cursor: pointer;
}
.search_result{
    list-style: none;
    padding: 10px 0 0 5px;
    display: none;
    overflow: hidden;
}
.GooFlow_app_list_tit:after{
    content:'';
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -21px;
    width: 11px;
    height: 11px;
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
}
.GooFlow_app_list_item.selected .GooFlow_app_list_tit{
    background: #F5F8FA;
}
.GooFlow_app_list_item.selected .GooFlow_app_list_box{
    display: block;
}
.GooFlow_app_list_item.selected .GooFlow_app_list_tit:after{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px 0px;
}
.GooFlow_left .GooFlow_app_list_box,.GooFlow_right .GooFlow_app_list_box{
    padding: 10px 0 10px 5px;
    overflow: hidden;
    float: left;
}
.GooFlow_left .GooFlow_app_list_box{
    border-bottom: 1px solid #e1e1e1;
}
.GooFlow_left .GooFlow_app_list_box{
    display: none;
    width: 100%;
}
.GooFlow_app_item{
    width: 60px;
    height: 80px;
    overflow: hidden;
    float: left;
    margin:0 5px 5px 0;
    cursor: move
}
.GooFlow_app_item:hover{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -410px;
}
.GooFlow_app_item.active{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -410px;
}
.GooFlow_left .app_icon,.GooFlow_right .app_icon{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -180px;
    width: 26px;
    height: 26px;
    margin: 8px auto 0;
}
.GooFlow_right .app_icon{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -252px;
}
.app_name{
    padding: 10px 0;
    font-size: 12px;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
    text-align: center;
}
/*工作区-控制器*/
/*工作区-画布*/
.GooFlow_work {
    margin: 0 202px;
    position: relative;
    width: inherit;
    height: inherit;
    overflow: auto;
}
.GooFlow_work .GooFlow_work_inner {
    width: 1920px;
    height: 700px;
    position: relative;
    overflow: hidden;
}
.GooFlow_work .GooFlow_work_group {
    position: absolute;
    overflow: hidden;
    top: 0px;
    left: 0px
}
/*组织划分框*/
.GooFlow_area {
    position: absolute;
    overflow: hidden;
}
.GooFlow_area.lock {
    cursor: default;
}
.GooFlow_area .bg {
    cursor: move;
    filter: Alpha(Opacity=30);
    -moz-opacity: 0.3;
    opacity: 0.3;
}
.GooFlow_area label {
    cursor: text;
    top: 1px;
    left: 1px;
    position: absolute;
    display: block;
    font-size: 12px;
    text-indent: 18px;
    height: 18px;
    line-height: 18px
}
.GooFlow_area i{
    font-size: 1em;
    display: block;
    height: 11px;
    width: 11px;
    top: 1px;
    left: 1px;
    padding: 2px;
    position: absolute;
    cursor: pointer;
    border-top: white 1px solid;
    border-left: white 1px solid;
    border-bottom: gray 1px solid;
    border-right: gray 1px solid;
}
.GooFlow_area i:before{
    content: "\f192";
}
.GooFlow_work .area_red .bg {
    border: 1px solid red;
    background-color: #FF7865
}
.GooFlow_work .area_red{
    color: red;
}
.GooFlow_work .area_yellow .bg {
    border: 1px solid #CD925A;
    background-color: #FFD564
}
.GooFlow_work .area_yellow{
    color: #AA7600;
}
.GooFlow_work .area_blue .bg {
    border: 1px solid #347BB1;
    background-color: #549CDE
}
.GooFlow_work .area_blue{
    color: #347BB1;
}
.GooFlow_work .area_green .bg {
    border: 1px solid green;
    background-color: #84CA04
}
.GooFlow_work .area_green{
    color: green;
}
/*svg、vml样式*/
v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox {
    display:inline-block;
    background:transparent
}
.GooFlow_work svg{display:block;position:absolute}
.GooFlow_work v\:group{position:relative;display:block}
.GooFlow_work v\:group v\:line{overflow:visible}
.GooFlow_work v\:group v\:polyline{overflow:visible}
.GooFlow_work v\:group div {
    cursor: text;
    position: absolute;
    overflow: visible;
    display: inline;
    float: left;
    white-space: nowrap
}
.GooFlow_work .draw {
    color: #ff3300
}
/*方形元素(可拉伸的边缘)*/
.GooFlow div .rs_right {
    overflow: hidden;
    position: absolute;
    right: -1px;
    top: -1px;
    height: 100%;
    width: 6px;
    cursor: w-resize
}
.GooFlow div .rs_bottom {
    overflow: hidden;
    position: absolute;
    left: -1px;
    bottom: -1px;
    width: 100%;
    height: 6px;
    cursor: n-resize
}
#node-ghost{
    position: absolute;
    opacity: 0.5;
}
.GooFlow div .rs_rb {
    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;
}
.GooFlow div .rs_close {
    z-index: 9;
    cursor: pointer;
    position: absolute;
    right: 0px;
    top: 50%;
    transform: translate(50%,-50%);
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -42px;
    width: 20px;
    height: 20px;
}
/*遮罩层*/
.GooFlow .rs_ghost {
    position: absolute;
    display: none;
    filter: Alpha(Opacity=60);
    -moz-opacity: 0.6;
    opacity: 0.6;
    z-index: 10
}
.GooFlow textarea {
    position: absolute;
    border: #5068AE 1px solid;
    display: none;
    font-size: 14px;
    overflow-y: visible;
    width: 200px;
    padding: 10px;
    z-index: 10001;
    /*top: 50%;*/
    /*left: 50%;*/
    /*transform: translate(-50%,-50%);*/
}
/*线条工具栏*/
.GooFlow .GooFlow_line_oper {
    width: 80px;
    height: 15px;
    background-color: #D8E8FC;
    border: #7DA2CE 1px solid;
    position: absolute;
    filter: Alpha(Opacity=50);
    -moz-opacity: 0.5;
    opacity: 0.5;
    z-index: 10000;
}
.GooFlow .GooFlow_line_move {
    filter: Alpha(Opacity=50);
    -moz-opacity: 0.5;
    opacity: 0.5;
    overflow: hidden;
    position: absolute;
    z-index: 9999
}
.GooFlow .GooFlow_line_oper b {
    display: inline-block;
    width: 15px;
    height: 15px;
    margin-left: 2px;
    cursor: pointer
}
.GooFlow .GooFlow_line_oper .b_l1 {
    background: url(../img/GooFlow_line_oper.png) no-repeat 1px 1px
}
.GooFlow .GooFlow_line_oper .b_l2 {
    background: url(../img/GooFlow_line_oper.png) no-repeat 1px -14px
}
.GooFlow .GooFlow_line_oper .b_l3 {
    background: url(../img/GooFlow_line_oper.png) no-repeat 1px -29px
}
.GooFlow .GooFlow_line_oper .b_x {
    background: url(../img/GooFlow_line_oper.png) no-repeat 1px -44px;
    margin-left: 10px
}
.GooFlow .GooFlow_line_oper b[class^="b_"]:hover{
    background-color: #7DA2CE;
}
/**
* 图标头部工具栏
*/
/*保存*/
.GooFlow_top_box .ico_save{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -70px;
}
.GooFlow_top_box .ico_save:hover{
    background-position: 0px -630px;
}
/*撤销*/
.GooFlow_top_box .ico_undo {
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -140px;
}
.GooFlow_top_box .ico_undo:hover{
    background-position: 0px -210px;
}
/*重做*/
.GooFlow_top_box .ico_redo{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -280px;
}
.GooFlow_top_box .ico_redo:hover{
    background-position: 0px -350px;
}
/*指针*/
.GooFlow_top_box .ico_cursor{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -1120px;
}
.GooFlow_top_box .ico_cursor:hover,.GooFlow_top_box .ico_cursor.active{
    background-position: 0px -1190px;
}
/*连线*/
.GooFlow_top_box .ico_direct{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -700px;
}
.GooFlow_top_box .ico_direct:hover,.GooFlow_tool_btndown .ico_direct{
    background-position: 0px -770px;
}
/*判断*/
.GooFlow_top_box .ico_state{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -840px;
}
.GooFlow_top_box .ico_state:hover,.GooFlow_tool_btndown .ico_state{
    background-position: 0px -910px;
}
/*循环*/
.GooFlow_top_box .ico_complex{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -980px;
}
.GooFlow_top_box .ico_complex:hover,.GooFlow_tool_btndown .ico_complex{
    background-position: 0px -1050px;
}
/*聚合*/
.GooFlow_top_box .ico_join{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px 0px;
}
.GooFlow_top_box .ico_join:hover,.GooFlow_tool_btndown .ico_join{
    background-position: 0px -560px;
}
/*分流*/
.GooFlow_top_box .ico_fork{
    background-image: url(../img/sprite.head-tool.png);
    background-position: 0px -420px;
}
.GooFlow_top_box .ico_fork:hover,.GooFlow_tool_btndown .ico_fork{
    background-position: 0px -490px;
}
/**
* 工作区图标
*/
.GooFlow .GooFlow_item{
    position: absolute;
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px 0px;
    width: 140px;
    height: 50px;
    cursor: move;
    
}
.GooFlow .GooFlow_item .line-begin{
    overflow: hidden;
    position: absolute;
    top: -15px;
    left: -30px;
}
.GooFlow .GooFlow_item.item-mark{
    border: 1px dashed #00b7ee;
}
.GooFlow .GooFlow_item .line-begin-icon{
    background: url("../img/arrow.png");
    background-size: 100%;
    width: 21px;
    height: 12px;
    position: absolute;
    opacity: 0.5;
    cursor: crosshair;
}
.GooFlow .GooFlow_item .line-begin-icon:hover{
    opacity: 1;
}
.GooFlow .GooFlow_item .line-begin-icon.top{
    left: 50%;
    transform: translateX(-50%);
    top: 0px;
}
.GooFlow .GooFlow_item .line-begin-icon.bottom{
    left: 50%;
    transform: translateX(-50%) rotate(180deg);
    bottom: 0px;
}
.GooFlow .GooFlow_item .line-begin-icon.left{
    top: 50%;
    transform: translateY(-50%) rotate(-90deg);
    left: 0px;
}
.GooFlow .GooFlow_item .line-begin-icon.right{
    top: 50%;
    transform: translateY(-50%) rotate(90deg);
    right: 0px;
}
.GooFlow .node-task{
    position: absolute;
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px 0px;
    width: 140px;
    height: 50px;
}
.GooFlow .GooFlow_item_cont{
    position: absolute;
    left: 0;
    width: 100%;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: move;
}
.GooFlow .node-task .GooFlow_item_cont,.GooFlow .node-plug .GooFlow_item_cont{
    justify-content:flex-start;
    padding-left:10px;
}
.GooFlow_item .GooFlow_item_cont i{
    width: 26px;
    height: 26px;
    display: inline-block;
}
.GooFlow_item_txt{
    display: inline-block;
    margin-left: 10px;
}
/*端点*/
.GooFlow_item .ico_task{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -180px;
}
/*转换器*/
.GooFlow_item .ico_plug{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -252px;
}
.GooFlow .node-plug{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -120px;
    width: 140px;
    height: 50px;
}
/*判断*/
.GooFlow_item .ico_state{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -72px;
}
.GooFlow .node-state{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -250px;
    width: 120px;
    height: 70px;
}
/*循环*/
.GooFlow_item .ico_complex{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -216px;
}
.GooFlow .node-complex{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -330px;
    width: 70px;
    height: 70px;
}
/*聚合*/
.GooFlow_item .ico_join{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -108px;
}
.GooFlow .node-join{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -180px;
    width: 90px;
    height: 60px;
}
/*分流*/
.GooFlow_item .ico_fork{
    background-image: url(../img/sprite.tool.png);
    background-position: 0px -144px;
}
.GooFlow .node-fork{
    background-image: url(../img/sprite.work-are.png);
    background-position: 0px -60px;
    width: 120px;
    height: 50px;
}
.node-error{
    border:2px dashed #f00;
}
.line-error{
    stroke:#f00
}

+ 0 - 19
src/main/webapp/develop/lib/gooflow/default.css

@ -1,19 +0,0 @@
/***** CSS Reset *****/
/**解决所有浏览器兼容性的重置样式代码**/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	vertical-align: baseline;
	background: transparent;
}

BIN
src/main/webapp/develop/lib/gooflow/goo/GooFlow_line_oper.png


BIN
src/main/webapp/develop/lib/gooflow/goo/Thumbs.db


BIN
src/main/webapp/develop/lib/gooflow/goo/bullet_blue.png


File diff suppressed because it is too large
+ 0 - 1
src/main/webapp/develop/lib/gooflow/goo/child.js


+ 0 - 138
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.css

@ -1,138 +0,0 @@
v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent }
.GooFlow{
	background:#D2E1F0 url(img/gooflow_bg.png) repeat-x;border:#99BBE8 1px solid;font: 12px Arial, Helvetica, sans-serif;
	-moz-user-select:none;-webkit-user-select:none;
}
.GooFlow_head{clear:both;height:22px;padding:1px}
.GooFlow_head label{
	font-weight:bold;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;height:15px;margin:2px;border:#B7C8D7 1px solid;border-right:#E9F4FA 1px solid;border-bottom:#E9F4FA 1px solid;padding:1px 1px 1px 12px;width:160px;text-align:center;
	background: url(img/gooflow_icon.png) no-repeat -137px 1px;float:left;color:#15428B;border-radius:3px;overflow:hidden;
}
.GooFlow_head span{float:left;height:22px;width:0px;overflow:hidden;border-left:#9AC6FF 1px solid;border-right:#FFFFFF 1px solid;margin:0px 3px;}
.GooFlow_head_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:0px 3px;float:left;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_head_btn i{display:inline-block;overflow:hidden;width:18px;height:18px;border:0px;}
.GooFlow_head_btn:hover{
	border-radius:2px;width:20px;height:20px;
	padding:0px;border:#8B7654 1px solid; background:url(img/gooflow_btn_bg.png) repeat-x;
}
.GooFlow_head_btn:hover i{border:#F6A32D 1px solid;border-top-color:#B1905D;margin:0px;border-radius:1px}
.GooFlow_tool{
	border:#B7C8D7 1px solid;float:left;margin:0px 3px;overflow:hidden;clear:left;border-radius:3px
}
.GooFlow_tool_div{border:#E9F4FA 1px solid;overflow:hidden;border-radius:2px;width:24px;}
.GooFlow_tool span{height:0px;overflow:hidden;border-bottom:#9AC6FF 1px solid;border-top:#FFFFFF 1px solid;margin:3px 1px;clear:both;display:block;}
.GooFlow_tool_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:3px 0px;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_tool_btn i{display:block;overflow:hidden;width:18px;height:18px;border:0px}
.GooFlow_tool_btn:hover{border-radius:3px;padding:0px;border:#8E9DA6 1px solid;width:20px;height:20px;}
.GooFlow_tool_btn:hover i{border:#F5FAFC 1px solid;border-radius:2px}
.GooFlow_tool_btndown{
	width:20px;height:20px;cursor:default;margin:3px 1px;outline:none;blr:expression(this.onFocus=this.blur());
	border-radius:3px;padding:0px;border:#8B7654 1px solid; background:url(img/gooflow_btn_bg.png) repeat-x;display:block;
}
.GooFlow_tool_btndown i{
	display:block;overflow:hidden;width:14px;height:14px;border:#F6A32D 1px solid;
	border-top-color:#B1905D;margin:0px;border-radius:2px;
}
.GooFlow_work{float:right;margin:0px 3px 3px 0px;border:#99B1CE 1px solid;position:relative;overflow:scroll}
.GooFlow_work .GooFlow_work_inner{background-image:url(img/gooflow_blank.gif);position:relative;overflow:hidden}
.GooFlow_work .GooFlow_work_group{cursor:default;position:absolute;overflow:hidden;top:0px;left:0px}
.GooFlow_area{position:absolute;overflow:hidden;}
.GooFlow_area .lock{cursor:default;}
.GooFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;}
.GooFlow_work .lock .bg{cursor:default;}
.GooFlow_area label{cursor:text;top:1px;left:1px;position:absolute;display:block;font-size:12px;text-indent:18px;height:18px;line-height:18px}
.GooFlow_work .lock label{cursor:default;}
.GooFlow_area i{display:block;height:18px;widht:18px;top:0px;left:0px;position:absolute;cursor:pointer}
.GooFlow_work .area_red .bg{border:1px solid red;background-color:#FF7865}
.GooFlow_work .area_red label{color:red;background:url(img/gooflow_bullet.png) no-repeat 1px 1px}
.GooFlow_work .area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564}
.GooFlow_work .area_yellow label{color:#FFBA1D;background:url(img/gooflow_bullet.png) no-repeat 1px -16px}
.GooFlow_work .area_blue .bg{border:1px solid #347BB1;background-color:#549CDE}
.GooFlow_work .area_blue label{color:#347BB1;background:url(img/gooflow_bullet.png) no-repeat 1px -33px}
.GooFlow_work .area_green .bg{border:1px solid green;background-color:#84CA04}
.GooFlow_work .area_green label{color:green;background:url(img/gooflow_bullet.png) no-repeat 1px -50px}
.GooFlow_work svg{display:block;position:absolute}
.GooFlow_work v\:group{position:relative;display:block}
.GooFlow_work v\:group v\:line{overflow:visible}
.GooFlow_work v\:group v\:polyline{overflow:visible}
.GooFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap}
.GooFlow_work .draw{color:#ff3300}
.GooFlow_item{
	position:absolute;background:#DDE7F4 url(img/gooflow_btn_bg.png) repeat-x 0px -72px;border:#7DA2CE solid 1px;
	border-radius:3px;color:#15428B;background-color:#C1DCFC;
	box-shadow:1px 1px 2px rgba(148,170,194,2);-webkit-box-shadow:1px 1px 2px rgba(148,170,194,2);-moz-box-shadow:1px 1px 2px rgba(148,170,194,2);
}
.GooFlow table{border:1px #EBF4FD solid;padding:0px;border-radius:2px}
.GooFlow td{ vertical-align:middle;text-align:center;padding:0px;cursor:default;word-wrap: break-word;word-break:break-all}
.GooFlow .ico{width:18px;cursor:move}
.GooFlow i{display:block;width:18px;height:18px;overflow:hidden;}
.GooFlow .item_round{background:url(img/gooflow_bg.png) repeat-x;border-radius:11px;border:#7DA2CE solid 1px;width:22px;height:22px; overflow:visible}
.GooFlow .item_round table{border:0px;padding:2px;width:22px;height:22px}
.GooFlow .item_round .span{
	display:block;text-align:center; position:absolute;top:24px;left:-28px;width:80px;overflow:visible;text-align:center;
	padding:0px;cursor:default;word-wrap: break-word;word-break:break-all
}
.GooFlow .item_mix{background:#C2DB4E;}
.GooFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize}
.GooFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize}
.GooFlow div .rs_rb{
	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;
}
.GooFlow div .rs_close{
	position:absolute;right:1px;top:1px;width:7px;height:7px;overflow:hidden;cursor:pointer;background:url(img/gooflow_tip.png) no-repeat 0px 0px
}
.GooFlow .rs_ghost{
	position:absolute;display:none;overflow:hidden;border:#8EA4C1 1px dashed; background:#D9E8FB;
	filter:Alpha(Opacity=60);-moz-opacity:0.6;opacity: 0.6;z-index:10
}
.GooFlow .item_focus{border:#5068AE 1px solid}
.GooFlow .item_mark{border:#ff3300 1px solid}
.GooFlow .item_mark td{cursor:crosshair}
.GooFlow textarea{position:absolute;border:#5068AE 1px solid;display:none;font-size:12px;overflow-y:visible;width:100px;z-index:10001}
.GooFlow .GooFlow_line_oper{
	width:70px;height:15px;background-color:#D8E8FC;border:#7DA2CE 1px solid;position:absolute;
	filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10000;
}
.GooFlow .GooFlow_line_mp{
	width:9px;height:9px;filter:Alpha(Opacity=40);-moz-opacity:0.4;opacity:0.4;overflow:hidden;
	position:absolute;z-index:9999;background:#333;cursor:crosshair
}
.GooFlow .GooFlow_line_move{filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:9999;background:url(0) no-repeat}
.GooFlow .GooFlow_line_oper i{display:inline-block;width:15px;height:15px;margin-left:2px;cursor:pointer}
.GooFlow .b_l1{background:url(img/GooFlow_line_oper.png) no-repeat 1px 1px}
.GooFlow .b_l2{background:url(img/GooFlow_line_oper.png) no-repeat 1px -14px}
.GooFlow .b_l3{background:url(img/GooFlow_line_oper.png) no-repeat 1px -29px}
.GooFlow .b_x{background:url(img/GooFlow_line_oper.png) no-repeat 1px -44px;margin-left:10px}
.GooFlow .ico_cursor{background:url(img/gooflow_icon.png) no-repeat 2px -20px}
.GooFlow .ico_start{background:url(img/gooflow_icon.png) no-repeat -19px -20px}
.GooFlow .ico_end{background:url(img/gooflow_icon.png) no-repeat -39px -20px}
.GooFlow .ico_fork{background:url(img/gooflow_icon.png) no-repeat -59px -20px}
.GooFlow .ico_join{background:url(img/gooflow_icon.png) no-repeat -78px -20px}
.GooFlow .ico_direct{background:url(img/gooflow_icon.png) no-repeat -137px -20px}
.GooFlow .ico_group{background:url(img/gooflow_icon.png) no-repeat -96px -20px}
.GooFlow .ico_complex{background:url(img/gooflow_icon.png) no-repeat -116px -20px}
.GooFlow .ico_node{background:url(img/gooflow_icon.png) no-repeat -19px -45px}
.GooFlow .ico_task{background:url(img/gooflow_icon.png) no-repeat 2px -45px}
.GooFlow .ico_chat{background:url(img/gooflow_icon.png) no-repeat -38px -45px}
.GooFlow .ico_state{background:url(img/gooflow_icon.png) no-repeat -59px -45px}
.GooFlow .ico_plug{background:url(img/gooflow_icon.png) no-repeat -135px -45px}
.GooFlow .ico_menu{background:url(img/gooflow_icon.png) no-repeat 1px -65px}
.GooFlow .ico_sound{background:url(img/gooflow_icon.png) no-repeat -18px -65px}
.GooFlow .ico_topo{background:url(img/gooflow_icon.png) no-repeat -117px -45px}
.GooFlow .ico_open{background:url(img/gooflow_icon.png) no-repeat -19px 1px}
.GooFlow .ico_new{background:url(img/gooflow_icon.png) no-repeat 2px 1px}
.GooFlow .ico_reload{background:url(img/gooflow_icon.png) no-repeat -97px 1px}
.GooFlow .ico_save{background:url(img/gooflow_icon.png) no-repeat -39px 1px}
.GooFlow .ico_undo{background:url(img/gooflow_icon.png) no-repeat -58px 1px}
.GooFlow .ico_redo{background:url(img/gooflow_icon.png) no-repeat -78px 1px}

+ 0 - 135
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.css.bak

@ -1,135 +0,0 @@
v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent }
.GooFlow{
	background:#D2E1F0 url(img/gooflow_bg.png) repeat-x;border:#99BBE8 1px solid;font: 12px Arial, Helvetica, sans-serif;
	-moz-user-select:none;-webkit-user-select:none;
}
.GooFlow_head{clear:both;height:22px;padding:1px}
.GooFlow_head label{
	font-weight:bold;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;height:15px;margin:2px;border:#B7C8D7 1px solid;border-right:#E9F4FA 1px solid;border-bottom:#E9F4FA 1px solid;padding:1px 1px 1px 12px;width:160px;text-align:center;
	background: url(img/gooflow_icon.png) no-repeat -137px 1px;float:left;color:#15428B;border-radius:3px;overflow:hidden;
}
.GooFlow_head span{float:left;height:22px;width:0px;overflow:hidden;border-left:#9AC6FF 1px solid;border-right:#FFFFFF 1px solid;margin:0px 3px;}
.GooFlow_head_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:0px 3px;float:left;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_head_btn i{display:inline-block;overflow:hidden;width:18px;height:18px;border:0px;}
.GooFlow_head_btn:hover{
	border-radius:2px;width:20px;height:20px;
	padding:0px;border:#8B7654 1px solid; background:url(img/gooflow_btn_bg.png) repeat-x;
}
.GooFlow_head_btn:hover i{border:#F6A32D 1px solid;border-top-color:#B1905D;margin:0px;border-radius:1px}
.GooFlow_tool{
	border:#B7C8D7 1px solid;float:left;margin:0px 3px;overflow:hidden;clear:left;border-radius:3px
}
.GooFlow_tool_div{border:#E9F4FA 1px solid;overflow:hidden;border-radius:2px;width:24px;}
.GooFlow_tool span{height:0px;overflow:hidden;border-bottom:#9AC6FF 1px solid;border-top:#FFFFFF 1px solid;margin:3px 1px;clear:both;display:block;}
.GooFlow_tool_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:3px 0px;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_tool_btn i{display:block;overflow:hidden;width:18px;height:18px;border:0px}
.GooFlow_tool_btn:hover{border-radius:3px;padding:0px;border:#8E9DA6 1px solid;width:20px;height:20px;}
.GooFlow_tool_btn:hover i{border:#F5FAFC 1px solid;border-radius:2px}
.GooFlow_tool_btndown{
	width:20px;height:20px;cursor:default;margin:3px 1px;outline:none;blr:expression(this.onFocus=this.blur());
	border-radius:3px;padding:0px;border:#8B7654 1px solid; background:url(img/gooflow_btn_bg.png) repeat-x;display:block;
}
.GooFlow_tool_btndown i{
	display:block;overflow:hidden;width:14px;height:14px;border:#F6A32D 1px solid;
	border-top-color:#B1905D;margin:0px;border-radius:2px;
}
.GooFlow_work{float:right;margin:0px 3px 3px 0px;border:#99B1CE 1px solid;position:relative;overflow:scroll}
.GooFlow_work .GooFlow_work_inner{background-image:url(img/gooflow_blank.gif);position:relative;overflow:hidden}
.GooFlow_work .GooFlow_work_group{cursor:default;position:absolute;overflow:hidden;top:0px;left:0px}
.GooFlow_area{position:absolute;overflow:hidden;}
.GooFlow_area .lock{cursor:default;}
.GooFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;}
.GooFlow_work .lock .bg{cursor:default;}
.GooFlow_area label{cursor:text;top:1px;left:1px;position:absolute;display:block;font-size:12px;text-indent:18px;height:18px;line-height:18px}
.GooFlow_work .lock label{cursor:default;}
.GooFlow_area i{display:block;height:18px;widht:18px;top:0px;left:0px;position:absolute;cursor:pointer}
.GooFlow_work .area_red .bg{border:1px solid red;background-color:#FF7865}
.GooFlow_work .area_red label{color:red;background:url(img/gooflow_bullet.png) no-repeat 1px 1px}
.GooFlow_work .area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564}
.GooFlow_work .area_yellow label{color:#FFBA1D;background:url(img/gooflow_bullet.png) no-repeat 1px -16px}
.GooFlow_work .area_blue .bg{border:1px solid #347BB1;background-color:#549CDE}
.GooFlow_work .area_blue label{color:#347BB1;background:url(img/gooflow_bullet.png) no-repeat 1px -33px}
.GooFlow_work .area_green .bg{border:1px solid green;background-color:#84CA04}
.GooFlow_work .area_green label{color:green;background:url(img/gooflow_bullet.png) no-repeat 1px -50px}
.GooFlow_work svg{display:block;position:absolute}
.GooFlow_work v\:group{position:relative;display:block}
.GooFlow_work v\:group v\:line{overflow:visible}
.GooFlow_work v\:group v\:polyline{overflow:visible}
.GooFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap}
.GooFlow_work .draw{color:#ff3300}
.GooFlow_item{
	position:absolute;background:#DDE7F4 url(img/gooflow_btn_bg.png) repeat-x 0px -72px;border:#7DA2CE solid 1px;
	border-radius:3px;color:#15428B;background-color:#C1DCFC;
	box-shadow:1px 1px 2px rgba(148,170,194,2);-webkit-box-shadow:1px 1px 2px rgba(148,170,194,2);-moz-box-shadow:1px 1px 2px rgba(148,170,194,2);
}
.GooFlow table{border:1px #EBF4FD solid;padding:0px;border-radius:2px}
.GooFlow td{ vertical-align:middle;text-align:center;padding:0px;cursor:default;word-wrap: break-word;word-break:break-all}
.GooFlow .ico{width:18px;cursor:move}
.GooFlow i{display:block;width:18px;height:18px;overflow:hidden;}
.GooFlow .item_round{background:url(img/gooflow_bg.png) repeat-x;border-radius:11px;border:#7DA2CE solid 1px;width:22px;height:22px; overflow:visible}
.GooFlow .item_round table{border:0px;padding:2px;width:22px;height:22px}
.GooFlow .item_round .span{
	display:block;text-align:center; position:absolute;top:24px;left:-28px;width:80px;overflow:visible;text-align:center;
	padding:0px;cursor:default;word-wrap: break-word;word-break:break-all
}
.GooFlow .item_mix{background:#C2DB4E;}
.GooFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize}
.GooFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize}
.GooFlow div .rs_rb{
	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;
}
.GooFlow div .rs_close{
	position:absolute;right:1px;top:1px;width:7px;height:7px;overflow:hidden;cursor:pointer;background:url(img/gooflow_tip.png) no-repeat 0px 0px
}
.GooFlow .rs_ghost{
	position:absolute;display:none;overflow:hidden;border:#8EA4C1 1px dashed; background:#D9E8FB;
	filter:Alpha(Opacity=60);-moz-opacity:0.6;opacity: 0.6;z-index:10
}
.GooFlow .item_focus{border:#5068AE 1px solid}
.GooFlow .item_mark{border:#ff3300 1px solid}
.GooFlow .item_mark td{cursor:crosshair}
.GooFlow textarea{position:absolute;border:#5068AE 1px solid;display:none;font-size:12px;overflow-y:visible;width:100px;z-index:10001}
.GooFlow .GooFlow_line_oper{
	width:70px;height:15px;background-color:#D8E8FC;border:#7DA2CE 1px solid;position:absolute;
	filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10000;
}
.GooFlow .GooFlow_line_mp{
	width:9px;height:9px;filter:Alpha(Opacity=40);-moz-opacity:0.4;opacity:0.4;overflow:hidden;
	position:absolute;z-index:9999;background:#333;cursor:crosshair
}
.GooFlow .GooFlow_line_move{filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:9999;background:url(0) no-repeat}
.GooFlow .GooFlow_line_oper i{display:inline-block;width:15px;height:15px;margin-left:2px;cursor:pointer}
.GooFlow .b_l1{background:url(img/GooFlow_line_oper.png) no-repeat 1px 1px}
.GooFlow .b_l2{background:url(img/GooFlow_line_oper.png) no-repeat 1px -14px}
.GooFlow .b_l3{background:url(img/GooFlow_line_oper.png) no-repeat 1px -29px}
.GooFlow .b_x{background:url(img/GooFlow_line_oper.png) no-repeat 1px -44px;margin-left:10px}
.GooFlow .ico_cursor{background:url(img/gooflow_icon.png) no-repeat 2px -20px}
.GooFlow .ico_start{background:url(img/gooflow_icon.png) no-repeat -19px -20px}
.GooFlow .ico_end{background:url(img/gooflow_icon.png) no-repeat -39px -20px}
.GooFlow .ico_fork{background:url(img/gooflow_icon.png) no-repeat -59px -20px}
.GooFlow .ico_join{background:url(img/gooflow_icon.png) no-repeat -78px -20px}
.GooFlow .ico_direct{background:url(img/gooflow_icon.png) no-repeat -137px -20px}
.GooFlow .ico_group{background:url(img/gooflow_icon.png) no-repeat -96px -20px}
.GooFlow .ico_complex{background:url(img/gooflow_icon.png) no-repeat -116px -20px}
.GooFlow .ico_node{background:url(img/gooflow_icon.png) no-repeat -19px -45px}
.GooFlow .ico_task{background:url(img/gooflow_icon.png) no-repeat 2px -45px}
.GooFlow .ico_chat{background:url(img/gooflow_icon.png) no-repeat -38px -45px}
.GooFlow .ico_state{background:url(img/gooflow_icon.png) no-repeat -59px -45px}
.GooFlow .ico_plug{background:url(img/gooflow_icon.png) no-repeat -135px -45px}
.GooFlow .ico_open{background:url(img/gooflow_icon.png) no-repeat -19px 1px}
.GooFlow .ico_new{background:url(img/gooflow_icon.png) no-repeat 2px 1px}
.GooFlow .ico_reload{background:url(img/gooflow_icon.png) no-repeat -97px 1px}
.GooFlow .ico_save{background:url(img/gooflow_icon.png) no-repeat -39px 1px}
.GooFlow .ico_undo{background:url(img/gooflow_icon.png) no-repeat -58px 1px}
.GooFlow .ico_redo{background:url(img/gooflow_icon.png) no-repeat -78px 1px}

+ 0 - 2000
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.js

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

+ 0 - 1915
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow.js.bak

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

+ 0 - 131
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow2.css

@ -1,131 +0,0 @@
v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent }
.GooFlow{
	background:#F5F5F5;border:#ccc 1px solid;font: 0.8em Microsoft Yahei;
	-moz-user-select:none;-webkit-user-select:none;border-radius:4px;color:#333
}
.GooFlow i{font: 1em}
.GooFlow_head{clear:both;height:20px;padding:1px;border-bottom:#00B4E1 2px solid;}
.GooFlow_head label{
	font-weight:bold;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:18px;padding:2px;width:170px;text-align:center;
	background:#00B4E1;float:left;color:#fff;border-radius:3px 0px 0px 0px;overflow:hidden;margin:-1px 4px 0px -1px;
}
.GooFlow_head span{float:left;height:22px;width:0px;overflow:hidden;border-left:#3892D3 1px solid;margin:0px 3px;}
.GooFlow_head_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:1px;margin:0px 3px;float:left;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_head_btn i{display:inline-block;overflow:hidden;width:18px;height:18px;border:0px;}
.GooFlow_head_btn:hover{border-radius:2px;background:#FFBF00}
.GooFlow_head_btn:hover i{}
.GooFlow_tool{float:left;padding:0px 3px;overflow:hidden;clear:left;border-right:#ccc 1px solid}
.GooFlow_tool_div{overflow:hidden;border-radius:2px;width:24px;padding:2px}
.GooFlow_tool span{height:0px;overflow:hidden;border-top:#ccc 1px solid;margin:3px 1px;clear:both;display:block;}
.GooFlow_tool_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:3px 1px;outline:none;blr:expression(this.onFocus=this.blur());}
.GooFlow_tool_btn i{display:block;overflow:hidden;width:18px;height:18px;border:0px}
.GooFlow_tool_btn:hover{border-radius:3px;padding:0px;border:#99B1CE 1px solid;width:20px;height:20px;background:#fff}
.GooFlow_tool_btn:hover i{margin:1px;border-radius:2px}
.GooFlow_tool_btndown{
	cursor:default;margin:3px 1px;outline:none;blr:expression(this.onFocus=this.blur());
	border-radius:3px;padding:2px;background:#FFBF00;display:block;
}
.GooFlow_tool_btndown i{display:block;overflow:hidden;width:18px;height:18px;border-radius:2px}
.GooFlow_work{float:right;margin:0px 3px 3px 0px;border:#F5F5F5 1px solid;position:relative;overflow:scroll;}
.GooFlow_work .GooFlow_work_inner{background-image:url(img/gooflow_blank2.gif);position:relative;overflow:hidden;}
.GooFlow_work .GooFlow_work_group{cursor:default;position:absolute;overflow:hidden;top:0px;left:0px}
.GooFlow_work text{color:#fff}
.GooFlow_area{cursor:default;position:absolute;overflow:hidden;}
.GooFlow_area .lock{cursor:default;}
.GooFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;}
.GooFlow_work .lock .bg{cursor:default;}
.GooFlow_area label{cursor:text;top:1px;left:1px;position:absolute;display:block;font-size:12px;text-indent:18px;height:18px;line-height:18px}
.GooFlow_work .lock label{cursor:default;}
.GooFlow_area i{display:block;height:18px;widht:18px;top:0px;left:0px;position:absolute;cursor:pointer}
.GooFlow_work .area_red .bg{border:1px solid red;background-color:#FF7865}
.GooFlow_work .area_red label{color:red;background:url(img/gooflow_bullet.png) no-repeat 1px 1px}
.GooFlow_work .area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564}
.GooFlow_work .area_yellow label{color:#FFBA1D;background:url(img/gooflow_bullet.png) no-repeat 1px -16px}
.GooFlow_work .area_blue .bg{border:1px solid #347BB1;background-color:#549CDE}
.GooFlow_work .area_blue label{color:#347BB1;background:url(img/gooflow_bullet.png) no-repeat 1px -33px}
.GooFlow_work .area_green .bg{border:1px solid green;background-color:#84CA04}
.GooFlow_work .area_green label{color:green;background:url(img/gooflow_bullet.png) no-repeat 1px -50px}
.GooFlow_work svg{display:block;position:absolute}
.GooFlow_work v\:group{position:relative;display:block}
.GooFlow_work v\:group v\:line{overflow:visible}
.GooFlow_work v\:group v\:polyline{overflow:visible}
.GooFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap}
.GooFlow_work .draw{color:#ff3300}
.GooFlow_item{
	position:absolute;background:#A1DCEB;border:#A1DCEB solid 1px;
	border-radius:3px;background-color:#C1DCFC;box-shadow:1px 1px 2px rgba(99,99,99,2);
}
.GooFlow table{padding:1px;border-radius:2px}
.GooFlow td{ vertical-align:middle;text-align:center;padding:0px;cursor:default;word-wrap:break-word;word-break:break-all}
.GooFlow .ico{width:18px;cursor:move}
.GooFlow i{display:block;width:18px;height:18px;overflow:hidden}
.GooFlow .item_round{border-radius:11px;border:#C1DCFC solid 1px;width:22px;height:22px; overflow:visible}
.GooFlow .item_round table{border:0px;padding:2px;width:22px;height:22px}
.GooFlow .item_round .span{
	display:block;text-align:center; position:absolute;top:24px;left:-28px;width:80px;overflow:visible;text-align:center;
	padding:0px;cursor:default;word-wrap: break-word;word-break:break-all
}
.GooFlow .item_mix{background:#B6F700;border-color:#C2DB4E;color:#fff}
.GooFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize}
.GooFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize}
.GooFlow div .rs_rb{
	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;
}
.GooFlow div .rs_close{
	position:absolute;right:1px;top:1px;width:7px;height:7px;overflow:hidden;cursor:pointer;background:url(img/gooflow_tip.png) no-repeat 0px 0px
}
.GooFlow .rs_ghost{
	position:absolute;display:none;overflow:hidden;border:#8EA4C1 1px dashed; background:#D9E8FB;
	filter:Alpha(Opacity=60);-moz-opacity:0.6;opacity: 0.6;z-index:10
}
.GooFlow .item_focus{border:#3892D3 1px solid}
.GooFlow .item_mark{border:#ff3300 1px solid}
.GooFlow .item_mark td{cursor:crosshair}
.GooFlow textarea{position:absolute;border:#3892D3 1px solid;display:none;font: 1em Microsoft Yahei;overflow-y:visible;width:100px;z-index:10001}
.GooFlow .GooFlow_line_oper{
	width:70px;height:15px;background-color:#D8E8FC;border:#7DA2CE 1px solid;position:absolute;
	filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10000;
}
.GooFlow .GooFlow_line_mp{
	width:9px;height:9px;filter:Alpha(Opacity=40);-moz-opacity:0.4;opacity:0.4;overflow:hidden;
	position:absolute;z-index:9999;background:#333;cursor:crosshair
}
.GooFlow .GooFlow_line_move{filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:9999;background:url(0) no-repeat}
.GooFlow .GooFlow_line_oper i{display:inline-block;width:15px;height:15px;margin-left:2px;cursor:pointer}
.GooFlow .b_l1{background:url(img/GooFlow_line_oper.png) no-repeat 1px 1px}
.GooFlow .b_l2{background:url(img/GooFlow_line_oper.png) no-repeat 1px -14px}
.GooFlow .b_l3{background:url(img/GooFlow_line_oper.png) no-repeat 1px -29px}
.GooFlow .b_x{background:url(img/GooFlow_line_oper.png) no-repeat 1px -44px;margin-left:10px}
.GooFlow .ico_cursor{background:url(img/gooflow_icon.png) no-repeat 2px -20px}
.GooFlow .ico_start{background:url(img/gooflow_icon.png) no-repeat -19px -20px}
.GooFlow .ico_end{background:url(img/gooflow_icon.png) no-repeat -39px -20px}
.GooFlow .ico_fork{background:url(img/gooflow_icon.png) no-repeat -59px -20px}
.GooFlow .ico_join{background:url(img/gooflow_icon.png) no-repeat -78px -20px}
.GooFlow .ico_direct{background:url(img/gooflow_icon.png) no-repeat -137px -20px}
.GooFlow .ico_group{background:url(img/gooflow_icon.png) no-repeat -96px -20px}
.GooFlow .ico_complex{background:url(img/gooflow_icon.png) no-repeat -116px -20px}
.GooFlow .ico_node{background:url(img/gooflow_icon.png) no-repeat -19px -45px}
.GooFlow .ico_task{background:url(img/gooflow_icon.png) no-repeat 2px -45px}
.GooFlow .ico_chat{background:url(img/gooflow_icon.png) no-repeat -38px -45px}
.GooFlow .ico_state{background:url(img/gooflow_icon.png) no-repeat -59px -45px}
.GooFlow .ico_plug{background:url(img/gooflow_icon.png) no-repeat -135px -45px}
.GooFlow .ico_menu{background:url(img/gooflow_icon.png) no-repeat 1px -65px}
.GooFlow .ico_sound{background:url(img/gooflow_icon.png) no-repeat -18px -65px}
.GooFlow .ico_topo{background:url(img/gooflow_icon.png) no-repeat -117px -45px}
.GooFlow .ico_open{background:url(img/gooflow_icon.png) no-repeat -19px 1px}
.GooFlow .ico_new{background:url(img/gooflow_icon.png) no-repeat 2px 1px}
.GooFlow .ico_reload{background:url(img/gooflow_icon.png) no-repeat -97px 1px}
.GooFlow .ico_save{background:url(img/gooflow_icon.png) no-repeat -39px 1px}
.GooFlow .ico_undo{background:url(img/gooflow_icon.png) no-repeat -58px 1px}
.GooFlow .ico_redo{background:url(img/gooflow_icon.png) no-repeat -78px 1px}
.GooFlow .ico_mutiselect{background:url(img/gooflow_icon.png) no-repeat -156px 1px}

+ 0 - 16
src/main/webapp/develop/lib/gooflow/goo/codebase/GooFlow_color.js

@ -1,16 +0,0 @@
GooFlow.prototype.color={
  main:"#00B4E1",
  node:"#A1DCEB",
  line:"#3892D3",
  mark:"#ff3300",
  mix:"#B6F700",
  font:"#15428B"
};/*
GooFlow.prototype.color={
  main:"#A8C508",
  node:"#DFE9B4",
  line:"#A8C508",
  mark:"#E98200",
  mix:"#B6F700",
  font:"#357425"
};*/

BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/Thumbs.db


BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_bg.png


BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank.gif


BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank2.gif


+ 0 - 12
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_blank2.htm

@ -1,12 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>gooflow_blank2</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--Fireworks CS6 Dreamweaver CS6 target.  Created Sun Oct 20 14:50:21 GMT+0800 2013-->
</head>
<body bgcolor="#ffffff">
<img name="gooflow_blank2" src="gooflow_blank2.gif" width="10" height="10" id="gooflow_blank2" alt="" /></body>
</html>

BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_btn_bg.png


BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_icon.png


BIN
src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_icon2.png


File diff suppressed because it is too large
+ 0 - 1
src/main/webapp/develop/lib/gooflow/goo/data.js


BIN
src/main/webapp/develop/lib/gooflow/goo/ui-icons_222222_256x240.png


BIN
src/main/webapp/develop/lib/gooflow/goo/未命名-3 - 副本.png


BIN
src/main/webapp/develop/lib/gooflow/goo/未命名-3.png


src/main/webapp/develop/lib/gooflow/goo/codebase/img/GooFlow_line_oper.png → src/main/webapp/develop/lib/gooflow/img/GooFlow_line_oper.png


BIN
src/main/webapp/develop/lib/gooflow/img/arrow.png


src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_bullet.png → src/main/webapp/develop/lib/gooflow/img/gooflow_bullet.png


BIN
src/main/webapp/develop/lib/gooflow/img/gooflow_icon.png


src/main/webapp/develop/lib/gooflow/goo/codebase/img/gooflow_tip.png → src/main/webapp/develop/lib/gooflow/img/gooflow_tip.png


BIN
src/main/webapp/develop/lib/gooflow/img/sprite.head-tool.png


BIN
src/main/webapp/develop/lib/gooflow/img/sprite.tool.png


BIN
src/main/webapp/develop/lib/gooflow/img/sprite.work-are.png


File diff suppressed because it is too large
+ 0 - 2
src/main/webapp/develop/lib/gooflow/jquery.min.js


+ 2314 - 0
src/main/webapp/develop/lib/gooflow/js/GooFlow.js

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

File diff suppressed because it is too large
+ 4 - 0
src/main/webapp/develop/lib/gooflow/js/jquery.min.js


File diff suppressed because it is too large
+ 0 - 6
src/main/webapp/develop/lib/gooflow/json2.js


+ 222 - 0
src/main/webapp/develop/lib/gooflow/test.json

@ -0,0 +1,222 @@
    var data = {
      "nodes": {
        "esb_node_0": {
          "name": "SDf",
          "left": 64,
          "top": 71,
          "type": "task",
          "value": "sd",
          "sType": "service",
          "width": 140,
          "height": 50
        },
        "esb_node_1": {
          "name": "crawler转换器",
          "left": 283,
          "top": 71,
          "type": "plug",
          "value": "CrawlerProcessor0",
          "sType": "processor",
          "width": 140,
          "height": 50
        },
        "esb_node_2": {
          "name": "判断",
          "left": 75,
          "top": 213,
          "type": "state",
          "sType": "judgement",
          "width": 120,
          "height": 70
        },
        "esb_node_3": {
          "name": "循环",
          "left": 100,
          "top": 363,
          "type": "complex",
          "sType": "circle",
          "width": 70,
          "height": 70
        },
        "esb_node_4": {
          "name": "全流程-用户信息",
          "left": 65,
          "top": 560,
          "type": "task",
          "value": "全流程-用户信息",
          "sType": "service",
          "width": 140,
          "height": 50
        },
        "esb_node_5": {
          "name": "全流程-就诊信息",
          "left": 319,
          "top": 435,
          "type": "task",
          "value": "jetty:http://localhost:8080/clinicInfo",
          "sType": "service",
          "width": 140,
          "height": 50
        },
        "esb_node_6": {
          "name": "分流",
          "left": 333,
          "top": 223,
          "type": "fork",
          "sType": "multicast",
          "width": 120,
          "height": 50
        },
        "esb_node_7": {
          "name": "crawler转换器",
          "left": 536,
          "top": 132,
          "type": "plug",
          "value": "CrawlerProcessor0",
          "sType": "processor",
          "width": 140,
          "height": 50
        },
        "esb_node_8": {
          "name": "crawler转换器",
          "left": 540,
          "top": 223,
          "type": "plug",
          "value": "CrawlerProcessor0",
          "sType": "processor",
          "width": 140,
          "height": 50
        },
        "esb_node_9": {
          "name": "crawler转换器",
          "left": 537,
          "top": 311,
          "type": "plug",
          "value": "CrawlerProcessor0",
          "sType": "processor",
          "width": 140,
          "height": 50
        },
        "esb_node_10": {
          "name": "聚合",
          "left": 830,
          "top": 305,
          "type": "join",
          "sType": "aggregate",
          "width": 90,
          "height": 60
        },
        "esb_node_11": {
          "name": "全流程-患者信息",
          "left": 687,
          "top": 453,
          "type": "task",
          "value": "全流程-患者信息",
          "sType": "service",
          "width": 140,
          "height": 50
        },
        "esb_node_12": {
          "name": "全流程-就诊信息",
          "left": 928,
          "top": 452,
          "type": "task",
          "value": "jetty:http://localhost:8080/clinicInfo",
          "sType": "service",
          "width": 140,
          "height": 50
        }
      },
      "lines": {
        "esb_line_0": {
          "type": "sl",
          "from": "esb_node_0",
          "to": "esb_node_1",
          "name": "",
          "marked": false
        },
        "esb_line_1": {
          "type": "tb",
          "M": 171.5,
          "from": "esb_node_1",
          "to": "esb_node_2",
          "name": "",
          "marked": false
        },
        "esb_line_2": {
          "type": "sl",
          "from": "esb_node_2",
          "to": "esb_node_3",
          "name": "自定义内容",
          "marked": false
        },
        "esb_line_3": {
          "type": "tb",
          "from": "esb_node_3",
          "to": "esb_node_5",
          "name": "自定义内容",
          "marked": false,
          "M": 390
        },
        "esb_line_4": {
          "type": "sl",
          "from": "esb_node_3",
          "to": "esb_node_4",
          "name": "自定义内容",
          "marked": false
        },
        "esb_line_5": {
          "type": "sl",
          "from": "esb_node_2",
          "to": "esb_node_6",
          "name": "自定义内容",
          "marked": false
        },
        "esb_line_6": {
          "type": "sl",
          "from": "esb_node_6",
          "to": "esb_node_8",
          "name": "",
          "marked": false
        },
        "esb_line_7": {
          "type": "lr",
          "M": 499.5,
          "from": "esb_node_6",
          "to": "esb_node_7",
          "name": "",
          "marked": false
        },
        "esb_line_8": {
          "type": "lr",
          "M": 500,
          "from": "esb_node_6",
          "to": "esb_node_9",
          "name": "",
          "marked": false
        },
        "esb_line_9": {
          "type": "sl",
          "from": "esb_node_9",
          "to": "esb_node_10",
          "name": "",
          "marked": false
        },
        "esb_line_10": {
          "type": "tb",
          "M": 406.5,
          "from": "esb_node_11",
          "to": "esb_node_10",
          "name": "",
          "marked": false
        },
        "esb_line_11": {
          "type": "tb",
          "M": 406,
          "from": "esb_node_12",
          "to": "esb_node_10",
          "name": "",
          "marked": false
        }
      }
    }