myflow.js

(function(b)
{
    var a = {};
    
    a.arrNode = {};// "zengwenfeng";// 保存界面节点
    a.arrLine = {};// "zwf01"; // 保存界面连线
    a.curNode = {};
    a.curId = "";
    
    a.config = 
    {
        editable:true,
        lineHeight:15,
        basePath:"",
        arr1:[],
        rect:
        {
            attr:
            {
				x:10,
				y:10,
				width:100,
				height:50,
				r:5,
				fill:"90-#fff-#C0C0C0",
				stroke:"#000",
				"stroke-width":1
            },
            
            showType:"image&text",
            type:"state",
            
            name:
            {
                text:"state",
                "font-style":"italic"
            },
            
            text:
            {
                text:"状态",
                "font-size":13
            },
            
            margin:5,
            props:[],
            img:{}
        },
        
        path:
        {
            attr:
            {
                path:
                {
                    path:"M10 10L100 100",
                    stroke:"#808080",
                    fill:"none",
                    "stroke-width":2
                },
                
                arrow:
                {
                    path:"M10 10L10 10",
                    stroke:"#808080",
                    fill:"#808080",
                    "stroke-width":2,
                    radius:4
                },
                
                fromDot:
                {
                    width:5,
                    height:5,
                    stroke:"#fff",
                    fill:"#000",
                    cursor:"move",
                    "stroke-width":2
                },
                
                toDot:
                {
                    width:5,
                    height:5,
                    stroke:"#fff",
                    fill:"#000",
                    cursor:"move",
                    "stroke-width":2
                },
                
                bigDot:
                {
                    width:5,
                    height:5,
                    stroke:"#fff",
                    fill:"#000",
                    cursor:"move",
                    "stroke-width":2
                },
                
                smallDot:
                {
                    width:5,
                    height:5,
                    stroke:"#fff",
                    fill:"#000",
                    cursor:"move",
                    "stroke-width":3
                }
            },
            
            text:
            {
                text:"TO {to}",
                cursor:"move",
                background:"#000"
            },
            
            textPos:
            {
                x:0,
                y:-10
            },
            
            props:
            {
                text:
                {
                    name:"text",
                    label:"显示",
                    value:"",
                    editor:function() 
                    {
                        return new a.editors.textEditor();
                    }
                }
            }
        },
        
        tools:
        {
            attr:
            {
                left:10,
                top:10
            },
            pointer:{},
            path:{},
            states:{},
            save:
            {
                onclick:function(c) 
                {
                    alert(c);
                }
            }
        },
        
        props:
        {
            attr:
            {
                top:10,
                right:30
            },
            
            props:{}
        },
        
        restore:"",
        activeRects:
        {
            rects:[],
            rectAttr:
            {
                stroke:"#ff0000",
                "stroke-width":2
            }
        },
        
        historyRects:
        {
            rects:[],
            pathAttr:
            {
                path:
                {
                    stroke:"#00ff00"
                },
                
                arrow:
                {
                    stroke:"#00ff00",
                    fill:"#00ff00"
                }
            }
        }
    };
    
    a.util =
    {
    	isLine:function(g, f, e) 
        {
            var d, c;
            
            if ((g.x - e.x) == 0) 
            {
                d = 1;
            }
            else 
            {
                d = (g.y - e.y) / (g.x - e.x);
            }
            
            c = (f.x - e.x) * d + e.y;
            
            if ((f.y - c) < 10 && (f.y - c) > -10)
            {
                f.y = c;
                return true;
            }
            
            return false;
        },
        
        center:function(d, c) 
        {
        	var x1 = 0;
        	var y1 = 0;
        	
        	x1 = (d.x - c.x) / 2 + c.x;
        	y1 = (d.y - c.y) / 2 + c.y;
        	
        	var o = new Object();
        	o.x = x1;
        	o.y = y1;
        	
            return o;
        },
        
        nextId:(function() 
        {
            var c = 0;
            return function()
            {
                return ++c;
            };
        })(),
        
        // 点连线方法
        connPoint:function(j, d)
        {
            var c = d,
            e = 
            {
                x:j.x + j.width / 2,
                y:j.y + j.height / 2
            };
            
            var l = (e.y - c.y) / (e.x - c.x);
            l = isNaN(l) ? 0 :l;
            
            var k = j.height / j.width;
            var h = c.y < e.y ? -1 :1,
            f = c.x < e.x ? -1 :1,
            g = 0,
            i = 0;
            
            if (Math.abs(l) > k && h == -1)
            {
                g = e.y - j.height / 2;
                i = e.x + h * j.height / 2 / l;
            }
            else
            {
                if (Math.abs(l) > k && h == 1) 
                {
                    g = e.y + j.height / 2;
                    i = e.x + h * j.height / 2 / l;
                }
                else 
                {
                    if (Math.abs(l) < k && f == -1)
                    {
                        g = e.y + f * j.width / 2 * l;
                        i = e.x - j.width / 2;
                    }
                    else 
                    {
                        if (Math.abs(l) < k && f == 1)
                        {
                            g = e.y + j.width / 2 * l;
                            i = e.x + j.width / 2;
                        }
                    }
                }
            }
            
            return {x:i, y:g};
        },
        
        arrow:function(l, k, d) 
        {
            var g = Math.atan2(l.y - k.y, k.x - l.x) * (180 / Math.PI);
            var h = k.x - d * Math.cos(g * (Math.PI / 180));
            var f = k.y + d * Math.sin(g * (Math.PI / 180));
            var e = h + d * Math.cos((g + 120) * (Math.PI / 180));
            var j = f - d * Math.sin((g + 120) * (Math.PI / 180));
            var c = h + d * Math.cos((g + 240) * (Math.PI / 180));
            var i = f - d * Math.sin((g + 240) * (Math.PI / 180));
            
            return [k, {x:e, y:j}, {x:c, y:i}];
        }
    };
    
    /**
	 * 
	 * @param p myflow.config.tools.states
	 * @param m j{customAttributes:......}
	 */
    a.rect = function(p, m)
    {
        var u = this,
        g = "rect" + a.util.nextId(),
        E = b.extend(true, {}, a.config.rect, p),
        C = m,
        t,
        e,
        n,
        f,
        x = 0,
        v = 0;
        t = C.rect(E.attr.x, E.attr.y, E.attr.width, E.attr.height, E.attr.r).hide().attr(E.attr);
        e = C.image(a.config.basePath + E.img.src, E.attr.x + E.img.width / 2, E.attr.y + (E.attr.height - E.img.height) / 2, E.img.width, E.img.height).hide();
        n = C.text(E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2, E.attr.y + a.config.lineHeight / 2, E.name.text).hide().attr(E.name);
        f = C.text(E.attr.x + E.img.width + (E.attr.width - E.img.width) / 2, E.attr.y + (E.attr.height - a.config.lineHeight) / 2 + a.config.lineHeight, E.text.text).hide().attr(E.text);
        
        //
        t.drag(
        function(r, o)
        {
            A(r, o);
        },
        
        function()
        {
            z();
        },
        
        function()
        {
            l();
        });
        
        //
        e.drag(
        function(r, o) 
        {
            A(r, o);
        },
        
        function() {
            z();
        },
        
        function() {
            l();
        });
        
        //
        n.drag(
        function(r, o)
        {
            A(r, o);
        },
        
        function()
        {
            z();
        },
        
        function()
        {
            l();
        });
        
        //
        f.drag(
        function(r, o) 
        {
            A(r, o);
        },
        
        function() {
            z();
        },
        
        function() {
            l();
        });
        
        //
        var A = function(F, r)
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            var o = (x + F);
            var G = (v + r);
            q.x = o - E.margin;
            q.y = G - E.margin;
            
            B();
        };
        
        //
        var z = function()
        {
            x = t.attr("x");
            v = t.attr("y");

            t.attr({opacity:0.5});// 透明度
            e.attr({opacity:0.5});
            f.attr({opacity:0.5});
        };
        
        //
        var l = function()
        {
            t.attr({opacity:1});// 透明度
            e.attr({opacity:1});
            f.attr({opacity:1});
        };
        
        var s, i = {},
        h = 5,
        q = 
        {
            x:E.attr.x - E.margin,
            y:E.attr.y - E.margin,
            width:E.attr.width + E.margin * 2,
            height:E.attr.height + E.margin * 2
        };
        
        s = C.path("M0 0L1 1").hide();
        
        //
        i.t = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"s-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "t");
        },
        
        function()
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "t");
        },
        
        function() {});
        
        //
        i.lt = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"nw-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "lt");
        },
        
        function()
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lt");
        },
        
        function() {});
        
        //
        i.l = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"w-resize"}).hide().drag(
        function(r, o) 
        {
            D(r, o, "l");
        },
        
        function() 
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "l");
        },
        
        function() {});
        
        //
        i.lb = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"sw-resize" }).hide().drag(
        function(r, o) 
        {
            D(r, o, "lb");
        },
        
        function() 
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "lb");
        },
        
        function() {});
        
        //
        i.b = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"s-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "b");
        },
        
        function()
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "b");
        },
        
        function() {});
        
        //
        i.rb = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"se-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "rb");
        },
        
        function() 
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rb");
        },
        
        function() {});
        
        //
        i.r = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"w-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "r");
        },
        
        function()
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "r");
        },
        
        function() {});
        
        //
        i.rt = C.rect(0, 0, h, h).attr({fill:"#000", stroke:"#fff", cursor:"ne-resize"}).hide().drag(
        function(r, o)
        {
            D(r, o, "rt");
        },
        
        function()
        {
            k(this.attr("x") + h / 2, this.attr("y") + h / 2, "rt");
        },
        
        function() {});
        
        //
        var D = function(F, r, G)
        {
            if (!a.config.editable)
            {
                return;
            }
            
            var o = _bx + F,
            H = _by + r;
            switch (G)
            {
	            case "t":
	                q.height += q.y - H;
	                q.y = H;
	                break;
	                
	            case "lt":
	                q.width += q.x - o;
	                q.height += q.y - H;
	                q.x = o;
	                q.y = H;
	                break;
	                
	            case "l":
	                q.width += q.x - o;
	                q.x = o;
	                break;
	                
	            case "lb":
	                q.height = H - q.y;
	                q.width += q.x - o;
	                q.x = o;
	                break;
	                
	            case "b":
	                q.height = H - q.y;
	                break;
	                
	            case "rb":
	                q.height = H - q.y;
	                q.width = o - q.x;
	                break;
	                
	            case "r":
	                q.width = o - q.x;
	                break;
	                
	            case "rt":
	                q.width = o - q.x;
	                q.height += q.y - H;
	                q.y = H;
	                break;
            }
            
            B();
        };
        
        var k = function(r, o, F)
        {
            _bx = r;
            _by = o;
        };
        
        b([t.node, f.node, n.node, e.node]).bind("click",
        function() 
        {
            if (!a.config.editable) 
            {
                return;
            }
        	
            w();
            
            // 获取模式,是点,还是要做连线
            var o = b(C).data("mod");
            
            switch (o)
            {
	            case "pointer":
	                break;
	            case "path":
	            	// 获取前面保存的节点
	                var nodeFrom = b(C).data("curNode");
	                
	                if (nodeFrom && nodeFrom.getId() != g && nodeFrom.getId().substring(0, 4) == "rect") 
	                {
	                	// 起点
	                	var nodeFromId = nodeFrom.getId();
	                	var nodeFromType = nodeFrom.getType();
	                	
	                	// 终点
	                	var nodeToId = u.getId();
	                	var nodeToType = u.getType();
	                	
	                	// 所有线段
	                	var arrLine = a.arrLine;//zwf
	                	var cnt = 0;
	                	// 开始节点有且只能做一次起点
	                	if (nodeFromType == "start")
	                	{
	                		cnt = getCntInLines(nodeFromId, arrLine, "from");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	// 结束节点不能作为起点
	                	else if (nodeFromType == "end")
	                	{
	                		return;
	                	}
	                	// 分支节点可以做多次的起点,不计算
	                	else if (nodeFromType == "fork")
	                	{
	                		;
	                	}
	                	// 合并节点有且只能做一次起点
	                	else if (nodeFromType == "join")
	                	{
	                		cnt = getCntInLines(nodeFromId, arrLine, "from");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	// 其他节点有且只能做一次起点
	                	else
	                	{
	                		cnt = getCntInLines(nodeFromId, arrLine, "from");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	
	                	//--------------------------------------------------------
	                	// 开始节点不能做终点
	                	if (nodeToType == "start")
	                	{
	                		return;
	                	}
	                	// 结束节点只能做一次终点
	                	else if (nodeToType == "end")
	                	{
	                		cnt = getCntInLines(nodeToId, arrLine, "to");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	// 分支节点可以做多次的起点,不计算
	                	else if (nodeToType == "fork")
	                	{
	                		cnt = getCntInLines(nodeToId, arrLine, "to");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	// 合并节点有且只能做一次起点
	                	else if (nodeToType == "join")
	                	{
	                		;
	                	}
	                	// 其他节点有且只能做一次起点
	                	else
	                	{
	                		cnt = getCntInLines(nodeToId, arrLine, "to");
	                		if (cnt > 0)
	                		{
	                			return;
	                		}
	                	}
	                	
	                	// 触发添加连线事件
	                    b(C).trigger("addpath", [nodeFrom, u]);
	                    
	                    //
		                $("#path").removeClass("selected");
		                $("#pointer").addClass("selected");
		                b(C).data("mod", "pointer");
	                }
	                
	                break;
            }
            
            b(C).trigger("click", u);
            
            b(C).data("curNode", u);
            a.curNode = u; // zengwenfeng,绑定
            a.curId = u.getId();
            
            // 获取当前节点
            var _curNode = b(C).data("curNode");
            if (_curNode)
            {
            	// 当前节点是开始或者结束节点,不显示属性对话框
            	if (_curNode.getId().substring(0, 4) == "rect" && (_curNode.getType() == "start" || _curNode.getType() == "end"))
            	{
            		$("#myflow_props").hide();
            	}
            	// 其他节点显示
            	else
            	{
            		$("#myflow_props").show();
            	}
            }
            
            // 显示 属性对话框
//          $("#myflow_props").show();
            
            // 移除 属性扩展对话框
        	$("#myflow_props_detail").remove();
            
        	//
            return false;
        });
        
        var j = function(o, r) 
        {
            if (!a.config.editable) 
            {
                return;
            }
        
            if (r.getId() == g)
            {
                b(C).trigger("showprops", [E.props, r]);
            }
            else
            {
                d();
            }
        };
        b(C).bind("click", j);
        
        //
        var c = function(o, F, r)
        {
            if (r.getId() == g) 
            {
                f.attr({text:F});
            }
        };
        b(C).bind("textchange", c);
        
        function y() 
        {
            return "M" + q.x + " " + q.y + "L" + q.x + " " + (q.y + q.height) + "L" + (q.x + q.width) + " " + (q.y + q.height) + "L" + (q.x + q.width) + " " + q.y + "L" + q.x + " " + q.y;
        }
        
        function w() 
        {
            s.show();
            
            for (var o in i) 
            {
                i[o].show();
            }
        }
        
        function d() 
        {
        	s.hide();
        	
        	for (var o in i)
        	{
                i[o].hide();
            }
        }
        
        function B()
        {
            var F = q.x + E.margin,
            r = q.y + E.margin,
            G = q.width - E.margin * 2,
            o = q.height - E.margin * 2;
            
            t.attr({x:F, y:r, width:G, height:o});//显示边框
            
            switch (E.showType) 
            {
	            case "image":
	                e.attr({x:F + (G - E.img.width) / 2, y:r + (o - E.img.height) / 2}).show();
	                break;
	                
	            case "text":
	                t.show();
	                f.attr({x:F + G / 2, y:r + o / 2}).show();
	                break;
	                
	            case "image&text":
	                t.show();
	                e.attr({x:F + E.img.width / 2, y:r + (o - E.img.height) / 2}).show();
	                n.attr({x:F + E.img.width + (G - E.img.width) / 2, y:r + a.config.lineHeight / 2}).show();
	                f.attr({x:F + E.img.width + (G - E.img.width) / 2, y:r + (o - a.config.lineHeight) / 2 + a.config.lineHeight}).show();
	                break;
	                
	            case "showType04":
//	            	e.attr({x:F + (G - E.img.width) / 2, y:r + (o - E.img.height) / 2  - a.config.lineHeight}).show();
//	            	f.attr({x:F + G / 2, y:r + o / 2  + a.config.lineHeight}).show();
	            	e.attr({x:F + (G - E.img.width) / 2, y:r + (o - E.img.height) / 2}).show();
	            	f.attr({x:F + G / 2, y:r + o / 2  + a.config.lineHeight * 2}).show();
	            	
	            	break;
            }
            
            i.t.attr({x:q.x + q.width / 2 - h / 2, y:q.y - h / 2});
            
            i.lt.attr({x:q.x - h / 2, y:q.y - h / 2});
            
            i.l.attr({x:q.x - h / 2, y:q.y - h / 2 + q.height / 2});
            
            i.lb.attr({x:q.x - h / 2, y:q.y - h / 2 + q.height});
            
            i.b.attr({x:q.x - h / 2 + q.width / 2, y:q.y - h / 2 + q.height});
            
            i.rb.attr({x:q.x - h / 2 + q.width, y:q.y - h / 2 + q.height});
            
            i.r.attr({x:q.x - h / 2 + q.width, y:q.y - h / 2 + q.height / 2});
            
            i.rt.attr({x:q.x - h / 2 + q.width, y:q.y - h / 2});
            
            s.attr({path:y()});
            
            b(C).trigger("rectresize", u);
        }
        
        this.toJson = function() 
        {
            var r = "{type:'" + E.type + "',text:{text:'" + f.attr("text") + "'}, attr:{ x:" + Math.round(t.attr("x")) + ", y:" + Math.round(t.attr("y")) + ", width:" + Math.round(t.attr("width")) + ", height:" + Math.round(t.attr("height")) + "}, props:{";
            
            for (var o in E.props) 
            {
                r += o + ":{value:'" + E.props[o].value + "'},";
            }
            
            if (r.substring(r.length - 1, r.length) == ",") 
            {
                r = r.substring(0, r.length - 1);
            }
            
            r += "}}";
            
            return r;
        };
        
        this.restore = function(o) 
        {
            var r = o;
            E = b.extend(true, E, o);
            f.attr({text:r.text.text});
            
            B();
        };
        
        // 获取 节点控件 x、y、weight、height
        this.getBBox = function() 
        {
            return q;
        };
        
        // 获取 节点 控件 类型, 例如:myflow.jpdl5.js文件中定义节点的类型 task、fork、start、end
        this.getType = function()
        {
        	return E.type;
        };
        
        // 获取 节点 id
        this.getId = function()
        {
            return g;
        };
        
        this.remove = function() 
        {
            t.remove();
            f.remove();
            n.remove();
            e.remove();
            s.remove();
            
            for (var o in i) 
            {
                i[o].remove();
            }
        };
        
        this.text = function() 
        {
            return f.attr("text");
        };
        
        this.attr = function(o) 
        {
            if (o) 
            {
                t.attr(o);
            }
        };
        
        B();
    };
    
    a.path = function(q, n, u, e)
    {
    	var v = this,
        z = n,
        B = b.extend(true, {}, a.config.path),
        i,
        t,
        f,
        h = B.textPos,
        y=0,
        w=0,
        k = u,
        s = e,
        
        //线段的ID
        g = "path" + a.util.nextId(),
        x;
        
    	function p(G, H, D, L)
        {
            var F = this,
            M = G,
            r=0, o = D,
            O = L,
            K=0, I=0, N = H;
            
            switch (M)
            {
	            case "from":
	                r = z.rect(H.x - B.attr.fromDot.width / 2, H.y - B.attr.fromDot.height / 2, B.attr.fromDot.width, B.attr.fromDot.height).attr(B.attr.fromDot);
	                break;
	                
	            case "big":
	                r = z.rect(H.x - B.attr.bigDot.width / 2, H.y - B.attr.bigDot.height / 2, B.attr.bigDot.width, B.attr.bigDot.height).attr(B.attr.bigDot);
	                break;
	                
	            case "small":
	                r = z.rect(H.x - B.attr.smallDot.width / 2, H.y - B.attr.smallDot.height / 2, B.attr.smallDot.width, B.attr.smallDot.height).attr(B.attr.smallDot);
	                break;
	                
	            case "to":
	                r = z.rect(H.x - B.attr.toDot.width / 2, H.y - B.attr.toDot.height / 2, B.attr.toDot.width, B.attr.toDot.height).attr(B.attr.toDot);
	                break;
            }
            
            if (r && (M == "big" || M == "small"))
            {
                r.drag(
                function(Q, P)
                {
                    C(Q, P);
                },
                
                function()
                {
                    J();
                },
                
                function()
                {
                    E();
                });
                
                var C = function(R, Q)
                {
                    var P = (K + R),
                    S = (I + Q);
                    F.moveTo(P, S);
                };
                
                var J = function()
                {
                    if (M == "big")
                    {
                        K = r.attr("x") + B.attr.bigDot.width / 2;
                        I = r.attr("y") + B.attr.bigDot.height / 2;
                    }
                    
                    if (M == "small")
                    {
                        K = r.attr("x") + B.attr.smallDot.width / 2;
                        I = r.attr("y") + B.attr.smallDot.height / 2;
                    }
                };
                
                var E = function() {};
            }
            
            this.type = function(P)
            {
                if (P) 
                {
                    M = P;
                }
                else
                {
                    return M;
                }
            };
            
            this.node = function(P)
            {
                if (P) 
                {
                	r = P;
                }
                else
                {
                    return r;
                }
            };
            
            this.left = function(P)
            {
                if (P)
                {
                    o = P;
                }
                else
                {
                    return o;
                }
            };
            
            this.right = function(P)
            {
                if (P)
                {
                    O = P;
                }
                else
                {
                    return O;
                }
            };
            
            this.remove = function() 
            {
                o = null;
                O = null;
                r.remove();
            };
            
            this.pos = function(P) 
            {
                if (P)
                {
                    N = P;
                    r.attr({x:N.x - r.attr("width") / 2, y:N.y - r.attr("height") / 2});
                    
                    return this;
                }
                else
                {
                    return N;
                }
            };
            
            this.moveTo = function(Q, T)
            {
                this.pos({x:Q, y:T});
                switch (M) 
                {
	                case "from":
	                    if (O && O.right() && O.right().type() == "to") 
	                    {
	                        O.right().pos(a.util.connPoint(s.getBBox(), N));
	                    }
	                    
	                    if (O && O.right())
	                    {
	                        O.pos(a.util.center(N, O.right().pos()));
	                    }
	                    
	                    break;
	                case "big":
	                    if (O && O.right() && O.right().type() == "to") 
	                    {
	                        O.right().pos(a.util.connPoint(s.getBBox(), N));
	                    }
	                    
	                    if (o && o.left() && o.left().type() == "from") 
	                    {
	                        o.left().pos(a.util.connPoint(k.getBBox(), N));
	                    }
	                    
	                    if (O && O.right()) 
	                    {
	                        O.pos(a.util.center(N, O.right().pos()));
	                    }
	                    
	                    if (o && o.left()) 
	                    {
	                        o.pos(a.util.center(N, o.left().pos()));
	                    }
	                    
	                    var S = {x:N.x, y:N.y};
	                    
	                    if (a.util.isLine(o.left().pos(), S, O.right().pos()))
	                    {
	                        M = "small";
	                        r.attr(B.attr.smallDot);
	                        this.pos(S);
	                        var P = o;
	                        o.left().right(o.right());
	                        o = o.left();
	                        P.remove();
	                        var R = O;
	                        O.right().left(O.left());
	                        O = O.right();
	                        R.remove();
	                    }
	                    
	                    break;
	                    
	                case "small":
	                    if (o && O && !a.util.isLine(o.pos(), {x:N.x, y:N.y}, O.pos())) 
	                    {
	                        M = "big";
	                        r.attr(B.attr.bigDot);
	                        var P = new p("small", a.util.center(o.pos(), N), o, o.right());
	                        o.right(P);
	                        o = P;
	                        var R = new p("small", a.util.center(O.pos(), N), O.left(), O);
	                        O.left(R);
	                        O = R;
	                    }
	                    
	                    break;
	                    
	                case "to":
	                    if (o && o.left() && o.left().type() == "from")
	                    {
	                        o.left().pos(a.util.connPoint(k.getBBox(), N));
	                    }
	                    
	                    if (o && o.left())
	                    {
	                        o.pos(a.util.center(N, o.left().pos()));
	                    }
	                    
	                    break;
                }
                
                m();
            };
        }
    	
        function j()
        {
            var D, C, E = k.getBBox(),
            F = s.getBBox(),
            r,
            o;
            r = a.util.connPoint(E, {x:F.x + F.width / 2, y:F.y + F.height / 2});
            
            o = a.util.connPoint(F, r);
            
            D = new p("from", r, null, new p("small", {x:(r.x + o.x) / 2, y:(r.y + o.y) / 2}));
            
            D.right().left(D);
            C = new p("to", o, D.right(), null);
            D.right().right(C);
            
            this.toPathString = function()
            {
                if (!D) 
                {
                    return "";
                }
                var J = D,
                I = "M" + J.pos().x + " " + J.pos().y,
                H = "";
                
                while (J.right()) 
                {
                    J = J.right();
                    I += "L" + J.pos().x + " " + J.pos().y;
                }
                
                var G = a.util.arrow(J.left().pos(), J.pos(), B.attr.arrow.radius);
                H = "M" + G[0].x + " " + G[0].y + "L" + G[1].x + " " + G[1].y + "L" + G[2].x + " " + G[2].y + "z";
                
                return [I, H];
            };
            
            this.toJson = function()
            {
                var G = "[",
                H = D;
                while (H)
                {
                    if (H.type() == "big")
                    {
                        G += "{x:" + Math.round(H.pos().x) + ",y:" + Math.round(H.pos().y) + "},";
                    }
                    
                    H = H.right();
                }
                
                if (G.substring(G.length - 1, G.length) == ",") 
                {
                    G = G.substring(0, G.length - 1);
                }
                
                G += "]";
                
                return G;
            };
            
            this.restore = function(H)
            {
                var I = H,
                J = D.right();
                
                for (var G = 0; G < I.length; G++) 
                {
                    J.moveTo(I[G].x, I[G].y);
                    J.moveTo(I[G].x, I[G].y);
                    J = J.right();
                }
                
                this.hide();
            };
            
            this.fromDot = function()
            {
                return D;
            };
            
            this.toDot = function()
            {
                return C;
            };
            
            this.midDot = function()
            {
                var H = D.right(),
                G = D.right().right();
                while (G.right() && G.right().right())
                {
                    G = G.right().right();
                    H = H.right();
                }
                return H;
            };
            
            this.show = function()
            {
                var G = D;
                while (G)
                {
                    G.node().show();
                    G = G.right();
                }
            };
            
            this.hide = function()
            {
                var G = D;
                while (G)
                {
                    G.node().hide();
                    G = G.right();
                }
            };
            
            this.remove = function() 
            {
                var G = D;
                while (G)
                {
                    if (G.right())
                    {
                        G = G.right();
                        G.left().remove();
                    }
                    else
                    {
                        G.remove();
                        G = null;
                    }
                }
            };
        }
        B = b.extend(true, B, q);
        i = z.path(B.attr.path.path).attr(B.attr.path);
        t = z.path(B.attr.arrow.path).attr(B.attr.arrow);
        x = new j();
        x.hide();
        
        
        var strToText = "";
        var strFromType = k.getType();
        if (strFromType == "fork")
        {
        	strToText = s.text() + " " + s.getId();
        }
        else
        {
        	strToText = s.text();
        }
        
        // 如果线段上只要显示线段ID,直接上
        strToText = g;
        
        f = z.text(0, 0, B.text.text).attr(B.text).attr({text:B.text.text.replace("{from}", k.text()).replace("{to}", strToText)});
//      f = z.text(0, 0, B.text.text).attr(B.text).attr({text:B.text.text.replace("{from}", k.text()).replace("{to}", s.text())});
        
        f.drag(
		function(r, o) 
		{
			if (!a.config.editable) 
			{
				return;
			}
			
			f.attr({
				x:y + r,
				y:w + o
			});
        },
        
        function() 
        {
            y = f.attr("x");
            w = f.attr("y");
        },
        
        function() 
        {
            var o = x.midDot().pos();
            
            h = {
                x:f.attr("x") - o.x,
                y:f.attr("y") - o.y
            };
        });
        
        m();
        
        b([i.node, t.node]).bind("click", function() 
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            b(z).trigger("click", v);
            
            
            b(z).data("curNode", v);
            a.curNode = v; // zengwenfeng
            a.curId = v.getId();
            
            return false;
        });
        
        var l = function(r, C) 
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            if (C && C.getId() == g) 
            {
                x.show();
                
                b(z).trigger("showprops", [B.props, v]);
            }
            else
            {
                x.hide();
            }
            
            var o = b(z).data("mod");
            switch (o) 
            {
	            case "pointer":
	                break;
	            case "path":
	                break;
            }
        };
        b(z).bind("click", l);
        
        
        var A = function(o, r) 
        {
            if (!a.config.editable)
            {
                return;
            }
            
            if (r && (r.getId() == k.getId() || r.getId() == s.getId()))
            {
                b(z).trigger("removepath", v);
            }
        };
        b(z).bind("removerect", A);
        
        
        var d = function(C, D) 
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            if (k && k.getId() == D.getId()) 
            {
                var o = null;
                
                if (x.fromDot().right().right().type() == "to") 
                {
                    o = 
                    {
                        x:s.getBBox().x + s.getBBox().width / 2,
                        y:s.getBBox().y + s.getBBox().height / 2
                    };
                }
                else 
                {
                    o = x.fromDot().right().right().pos();
                }
                
                var r = a.util.connPoint(k.getBBox(), o);
                
                x.fromDot().moveTo(r.x, r.y);
                
                m();
            }
            
            if (s && s.getId() == D.getId())
            {
                var o = null;
                
                if (x.toDot().left().left().type() == "from")
                {
                    o = 
                    {
                        x:k.getBBox().x + k.getBBox().width / 2,
                        y:k.getBBox().y + k.getBBox().height / 2
                    };
                }
                else
                {
                    o = x.toDot().left().left().pos();
                }
                
                var r = a.util.connPoint(s.getBBox(), o);
                
                x.toDot().moveTo(r.x, r.y);
                
                m();
            }
        };
        b(z).bind("rectresize", d);
        
        var c = function(r, o, C)
        {
            if (C.getId() == g) 
            {
                f.attr({text:o});
            }
        };
        b(z).bind("textchange", c);
        
        this.from = function() 
        {
            return k;
        };
        
        this.to = function() 
        {
            return s;
        };
        
        this.toJson = function() 
        {
            var r = "{from:'" + k.getId() + "',to:'" + s.getId() + "', dots:" + x.toJson() + ",text:{text:'" + f.attr("text") + "'},textPos:{x:" + Math.round(h.x) + ",y:" + Math.round(h.y) + "}, props:{";
            
            for (var o in B.props) 
            {
                r += o + ":{value:'" + B.props[o].value + "'},";
            }
            
            if (r.substring(r.length - 1, r.length) == ",") 
            {
                r = r.substring(0, r.length - 1);
            }
            
            r += "}}";
            
            return r;
        };
        
        this.restore = function(o)
        {
            var r = o;
            B = b.extend(true, B, o);
            x.restore(r.dots);
        };
        
        this.remove = function() 
        {
            x.remove();
            i.remove();
            t.remove();
            f.remove();
            
            try 
            {
                b(z).unbind("click", l);
            }
            catch(o)
            {
            	
            }
            
            try 
            {
                b(z).unbind("removerect", A);
            } 
            catch(o)
            {
            	
            }
            
            try 
            {
                b(z).unbind("rectresize", d);
            }
            catch(o) 
            {
            	
            }
            
            try 
            {
                b(z).unbind("textchange", c);
            }
            catch(o)
            {
            	
            }
        };
        
        function m()
        {
            var r = x.toPathString(),
            
            o = x.midDot().pos();
            
            i.attr({path:r[0]});
            
            t.attr({path:r[1]});
            
            f.attr({x:o.x + h.x, y:o.y + h.y});
        }
        
        // 获取 连线 id
        this.getId = function() 
        {
            return g;
        };
        
        this.text = function()
        {
            return f.attr("text");
        };
        
        this.attr = function(o)
        {
            if (o && o.path) 
            {
                i.attr(o.path);
            }
            
            if (o && o.arrow) 
            {
                t.attr(o.arrow);
            }
        };
    };
    
    a.props = function(h, f) 
    {
// var j = this;
        var c = b("#myflow_props").hide().draggable({handle:"#myflow_props_handle"}).
        		resizable().css(a.config.props.attr).bind("click",function() {return false;});
        
        var e = c.find("table");
        var g = f;
        var i = null;
        var d = function(n, m, o) 
        {
            if (i && i.getId() == o.getId()) 
            {
                return;
            }
            
            i = o;
            
            b(e).find(".editor").each(function() 
            {
                var k = b(this).data("editor");
                
                if (k) 
                {
                    k.destroy();
                }
            });
            
            e.empty();
            c.show();
            
            for (var l in m) 
            {
            	// 属性行 zengwenfeng
                e.append("<tr><th>" + m[l].label + '</th><td><div id="p' + l + '" class="editor"></div></td></tr>');
                
                if (m[l].editor) 
                {
                    m[l].editor().init(m, l, "p" + l, o, g);
                }
            }
        };
        b(g).bind("showprops", d);
    };
    
    a.editors = 
    {
        textEditor:function() 
        {
            var c = null;
            var d = null;
            var e = null;
            var f = null;
            var g = null;
            
            this.init = function(i, h, m, l, j) 
            {
                d = i;
                e = h;
                c = m;
                g = l;
                f = j;
                
                //
                b("<input  style='width:100%;'/>").click(function()
                {
                	// desc:移除属性扩展控件 author:zengwenfeng date:2015.12.01
                	$("#myflow_props_detail").remove();
                	
                }).val(g.text()).change(function()
                {
                    i[e].value = b(this).val();
                    b(f).trigger("textchange", [b(this).val(), g]);
                }).appendTo("#" + c);
                
                //
                b("#" + c).data("editor", this);
            };
            
            this.destroy = function() 
            {
                b("#" + c + " input").each(function()
                {
                    d[e].value = b(this).val();
                    b(f).trigger("textchange", [b(this).val(), g]);
                });
            };
        }
    };
    
    // desc:初始化页面 author:zengwenfeng
    a.init = function(x, r) 
    {
        var v = b(window).width(),
        e = b(window).height(),
        y = Raphael(x, v * 1.5, e * 1.5),
        q = {}, // 节点集合
        g = {}; // 连线集合
        
        b.extend(true, a.config, r);
        
        //
        b(document).keydown(function(i) 
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            // 键盘DEL事件
            if (i.keyCode == 46) 
            {
                var j = b(y).data("curNode");
                
                if (j) 
                {
                	// 如果是节点,节点为开始或者结束,不允许删除
                	if (j.getId().substring(0, 4) == "rect" && (j.getType() == "start" || j.getType() == "end"))
                	{
                		return;
                	}
                	
                	//
                    if (j.getId().substring(0, 4) == "rect")
                    {
                        b(y).trigger("removerect", j);
                    }
                    else
                    {
                        if (j.getId().substring(0, 4) == "path") 
                        {
                            b(y).trigger("removepath", j);
                        }
                    }
                    
                    b(y).removeData("curNode");
                    a.curNode = null;// 移除绑定
                    a.curId = "";
                    
                    // 删除后,隐藏属性对话框
                    $("#myflow_props").hide();
                }
            }
        });
        
        //页面单击事件
        b(document).click(function()
        {
        	// desc:移除属性扩展控件 author:zengwenfeng date:2015.12.01
        	$("#myflow_props").hide();
        	$("#myflow_props_detail").remove();
            
        	//
        	b(y).data("curNode", null);
        	a.curNode = null; // zengwenfeng 移除绑定
        	a.curId = ""; // zengwenfeng 移除绑定
        	
            b(y).trigger("click", {getId:function() { return "00000000";}});
            
//          b(y).trigger("showprops", [a.config.props.props, {getId:function() {return "00000000";}}]);
        });
        
        // 删除节点以及连线
        var w = function(c, i) 
        {
            if (!a.config.editable) 
            {
                return;
            }
            
            if (i.getId().substring(0, 4) == "rect") 
            {
                q[i.getId()] = null;
                
                // 从界面把节点控件移除
                i.remove();
            }
            else if (i.getId().substring(0, 4) == "path")
            {
            	g[i.getId()] = null;
            	
            	// 从界面把连线控件移除
            	i.remove();
            }
        };
        //绑定删除连线事件
        b(y).bind("removepath", w);
        //绑定删除节点事件
        b(y).bind("removerect", w);
        
        // 新增节点
        b(y).bind("addrect", function(j, c, k) 
        {
            var i = new a.rect(b.extend(true, {}, a.config.tools.states[c], k), y);
            
            q[i.getId()] = i;
        });
        
        // 新增连线
        var f = function(i, nodeFrom, nodeTo) 
        {
            var c = new a.path({}, y, nodeFrom, nodeTo);
            
            var kid = nodeFrom.getId();
            var jid = nodeTo.getId();
            var ktype = nodeFrom.getType();
            var jtype = nodeTo.getType();
            
            
            g[c.getId()] = c;
        };
        b(y).bind("addpath", f);
        
        //
        b(y).data("mod", "point");
        
        if (a.config.editable) 
        {
        	//
            b("#myflow_tools").draggable({handle:"#myflow_tools_handle"}).css(a.config.tools.attr);
            
            //
            b("#myflow_tools .node").hover(
	        	function() 
	        	{
	        		b(this).addClass("mover");
	        	},
	        	
	        	function()
	        	{
	        		b(this).removeClass("mover");
	        	}
            );
            
            //
            b("#myflow_tools .selectable").click(function() 
            {
                b(".selected").removeClass("selected");
                b(this).addClass("selected");
                b(y).data("mod", this.id);
            });
            
            //
            b("#myflow_tools .state").each(function() 
            {
                b(this).draggable({helper:"clone"});
            });
            
            b(x).droppable(
            {
                accept:".state",
                drop:function(c, i) 
                {
                    b(y).trigger("addrect", [i.helper.attr("type"), {
                        attr:
                        {
                            x:i.helper.offset().left,
                            y:i.helper.offset().top
                        }
                    }]);
                }
            });
            
            // 保存方法
            b("#myflow_save").click(function()
            {
            	var i = "{states:{";
                
            	for (var c in q)
            	{
            		if (q[c])
            		{
                        i += q[c].getId() + ":" + q[c].toJson() + ",";
                    }
                }
                
                if (i.substring(i.length - 1, i.length) == ",")
                {
                    i = i.substring(0, i.length - 1);
                }
                
                i += "},paths:{";
                
                for (var c in g)
                {
                    if (g[c])
                    {
                        i += g[c].getId() + ":" + g[c].toJson() + ",";
                    }
                }
                
                if (i.substring(i.length - 1, i.length) == ",")
                {
                    i = i.substring(0, i.length - 1);
                }
                
                i += "},props:{props:{";
                
                for (var c in a.config.props.props)
                {
                    i += c + ":{value:'" + a.config.props.props[c].value + "'},";
                }
                
                if (i.substring(i.length - 1, i.length) == ",")
                {
                    i = i.substring(0, i.length - 1);
                }
                
                i += "}}}";
                
                a.config.tools.save.onclick(i);
            });
            
            new a.props({}, y);
        }
        
        if (r.restore)
        {
            var B = r.restore;
            var z = {};
            
            if (B.states)
            {
                for (var s in B.states)
                {
                    var d = new a.rect(b.extend(true, {}, a.config.tools.states[B.states[s].type], B.states[s]), y);
                    d.restore(B.states[s]);
                    
                    z[s] = d;
                    
                    q[d.getId()] = d;
                }
            }
            
            if (B.paths)
            {
                for (var s in B.paths)
                {
                    var n = new a.path(b.extend(true, {}, a.config.tools.path, B.paths[s]), y, z[B.paths[s].from], z[B.paths[s].to]);
                    n.restore(B.paths[s]);
                    
                    g[n.getId()] = n;
                }
            }
        }
        
        var A = a.config.historyRects;
        var l = a.config.activeRects;
        
        if (A.rects.length || l.rects.length)
        {
        	var m = {};
        	var z = {};
            
            for (var h in g)
            {
                if (!z[g[h].from().text()])
                {
                    z[g[h].from().text()] = {rect:g[h].from(), paths:{}};
                }
                
                z[g[h].from().text()].paths[g[h].text()] = g[h];
                
                if (!z[g[h].to().text()])
                {
                    z[g[h].to().text()] = {rect:g[h].to(), paths:{}};
                }
            }
            
            for (var u = 0; u < A.rects.length; u++) 
            {
                if (z[A.rects[u].name])
                {
                    z[A.rects[u].name].rect.attr(A.rectAttr);
                }
                
                for (var t = 0; t < A.rects[u].paths.length; t++)
                {
                    if (z[A.rects[u].name].paths[A.rects[u].paths[t]]) 
                    {
                        z[A.rects[u].name].paths[A.rects[u].paths[t]].attr(A.pathAttr);
                    }
                }
            }
            
            for (var u = 0; u < l.rects.length; u++)
            {
                if (z[l.rects[u].name]) 
                {
                    z[l.rects[u].name].rect.attr(l.rectAttr);
                }
                
                for (var t = 0; t < l.rects[u].paths.length; t++)
                {
                    if (z[l.rects[u].name].paths[l.rects[u].paths[t]])
                    {
                        z[l.rects[u].name].paths[l.rects[u].paths[t]].attr(l.pathAttr);
                    }
                }
            }
        }
        
        a.arrNode = q; // "zengwenfeng";// 保存界面节点
        a.arrLine = g; // "zwf01"; // 保存界面连线
    };
    
    b.fn.myflow = function(c) 
    {
        return this.each(function()
        {
            a.init(this, c);
        });
    };
    
    b.myflow = a;
    
    /**
	 * 计算节点在线集合中作为起点的次数
	 * 
	 * @author zengwenfeng
	 * @date 2015.12.12
	 * @param id     当前选中节点id
	 * @param lines  当前页面所有连线
	 */
	function getCntInLines(id, lines, flag)
	{
		var cnt = 0;
		if (id == null || lines == null)
		{
			return cnt;
		}
		
		// 
		if (typeof (lines) == "object")
		{
			for (var i in lines)
			{
				if (lines[i])
				{
					var nodeId = "";
					if (flag == "from")
					{
						nodeId = lines[i].from().getId();
					}
					else if (flag == "to")
					{
						nodeId = lines[i].to().getId();
					}
					
					if (nodeId == id)
					{
						cnt++;
					}
				}
			}
		}
		
		return cnt;
	}
})(jQuery);


package com.tansun.rule.ruleFlow.model;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlCDATA;

/**
 * 规则流 实体类
 * 
 * @author ZengWenfeng
 */
@XmlRootElement(name = "RuleFlowModel")
public class RuleFlowModel implements Serializable
{
	private static final long serialVersionUID = 8993578477614234706L;
	
	public final static String TYPE = "ruleFlow";
	public final static String XML_RULEFLOW = "ruleFlow.xml";//XML_RULEFLOW
	public final static String XML_MODEL = "model.xml";//XML_RULEFLOW
	public final static String BPMN_DATA = "data.bpmn";
	
//	public static String xml_file = RuleProject.HOMEPATH + File.separator + RuleProject.CURRPROJECTCODE + File.separator + "ruleFlow" + File.separator + "ruleFlow.xml";
//	public static String xml_path = RuleProject.HOMEPATH + File.separator + RuleProject.CURRPROJECTCODE + File.separator + "ruleFlow" + File.separator;
	
	public final static String STATE_NEW = "1";
	public final static String STATE_PUBLISH = "2";
	public final static String VERSION_INIT_VALUE = "0.01";
	
	public final static String UNDERLINE = "_";
	
	private String project;
	private String type;
	private String code;
	private String name;
	@XmlCDATA
	private String data;
	private String state;
	private String version;
	private String createDate;
	private String creatorId;
	private String updateDate;
	private String updatorId;

	public RuleFlowModel()
	{

	}

	public String getProject()
	{
		return project;
	}

	public void setProject(String project)
	{
		this.project = project;
	}

	public String getType()
	{
		return type;
	}

	public void setType(String type)
	{
		this.type = type;
	}

	public String getCode()
	{
		return code;
	}

	public void setCode(String code)
	{
		this.code = code;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getData()
	{
		return data;
	}

	public void setData(String data)
	{
		this.data = data;
	}

	public String getState()
	{
		return state;
	}

	public void setState(String state)
	{
		this.state = state;
	}

	public String getVersion()
	{
		return version;
	}

	public void setVersion(String version)
	{
		this.version = version;
	}

	public String getCreateDate()
	{
		return createDate;
	}

	public void setCreateDate(String createDate)
	{
		this.createDate = createDate;
	}

	public String getCreatorId()
	{
		return creatorId;
	}

	public void setCreatorId(String creatorId)
	{
		this.creatorId = creatorId;
	}

	public String getUpdateDate()
	{
		return updateDate;
	}

	public void setUpdateDate(String updateDate)
	{
		this.updateDate = updateDate;
	}

	public String getUpdatorId()
	{
		return updatorId;
	}

	public void setUpdatorId(String updatorId)
	{
		this.updatorId = updatorId;
	}
}
data.bpmn

规则引擎定义文件,就是为了用设计器生成这个文件。

myflow.js 百度有,但是混淆和压缩的。

今天面试官问了很多事,我都记不起来了。这几年确实做了很多事。

不是不想记得,而是根本没法子记得了。
针对最近的问题,我要好好复习一下。
脑袋的内存很宝贵,记住最美好的事。




针对这些问题,我觉得本身我自己的工作也有关系。
另外就是企业本身嘛,多数岗位的内容有点交错。


只为成功寻找方向。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值