1. 程式人生 > >myflow.js 工作流類擴充套件

myflow.js 工作流類擴充套件

 主要修改一下功能:

         1.將線型別精簡成一個path.

         2.增加駁回線路 rejectpath。

         3.增加path_p ,path_arr屬性,記錄線軌跡。

          4.去除自定義屬性顯示。

          5.增加右鍵選單支援。

         6.支援bootstrap .

(function ($) {
    var myflow = {};
    myflow.config = {
        editable: true,
        allowStateMutiLine:true,
        moving:{
            flag:false,
            prepdot:{x:0,y:0},
            dots:[],
            isNewDot:false,
            temp:[],
            preRect:null
        },
        historys:[],
        lineHeight: 15,
        basePath: '',
        rect: {// 狀態
            attr: {
                x: 10,
                y: 10,
                width: 100,
                height: 50,
                r: 5,
                fill: '90-#fff-#C0C0C0',
                stroke: '#000',
                "stroke-width": 1
            },
            showType: 'image&text', // image,text,image&text
            type: 'normal',
            name: {
                text: 'normal',
                'font-style': 'italic'
            },
            text: {
                text: '普通',
                'font-size': 13
            },
            margin: 5,
            props: [],
            img: {}
        },
        path: {// 路徑轉換
            attr: {
                path: {
                    path: 'M10 10L100 100',
                    stroke: '#1296DB',
                    fill: "none",
                    "stroke-width": 2,
                    cursor: "pointer"
                },
                arrow: {
                    path: 'M10 10L10 10',
                    stroke: '#1296DB',
                    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: {
                    cursor: "move",
                    'background': '#000'
                }
            },
            text: {
                patten: '',
                textPos: {
                    x: 0,
                    y: -10
                }
            },
           
            props: {
                text: {
                    name: "text",
                    label: "顯示",
                    value: "",
                    editor: function() {
                        return new myflow.editors.textEditor()
                    }
                }
            }
        },
        lpath: {// 流路徑
            attr: {
                path: {
                    path: 'M10 10L100 100',
                    stroke: '#1E90FF',
                    fill: "none",
                    "stroke-width": 2,
                    cursor: "pointer"
                },
                arrow: {
                    path: 'M10 10L10 10',
                    stroke: '#1E90FF',
                    fill: "#1E90FF",
                    "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: {
                    cursor: "move",
                    'background': '#000'
                }
            },
            text: {
                patten: '',
                textPos: {
                    x: 0,
                    y: -10
                }
            },
            props: {
                text: {
                    name: "text",
                    label: "顯示",
                    value: "",
                    editor: function() {
                        return new myflow.editors.textEditor()
                    }
                },
                tmp0: {
                    name: "tmp0",
                    label: "關聯流1",
                    value: "",
                    editor: function() {
                        return new myflow.editors.inputEditor()
                    }
                },
                tmp1: {
                    name: "tmp1",
                    label: "關聯流2",
                    value: "",
                    editor: function() {
                        return new myflow.editors.inputEditor()
                    }
                } 
            }
        },
        jpath: {// 路徑轉換
            attr: {
                path: {
                    path: 'M10 10L100 100',
                    stroke: '#FFC125',
                    fill: "none",
                    "stroke-width": 2,
                    cursor: "pointer"
                },
                arrow: {
                    path: 'M10 10L10 10',
                    stroke: '#FFC125',
                    fill: "#FFC125",
                    "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: {
                    cursor: "move",
                    'background': '#000'
                }
            },
            text: {
                patten: '',
                textPos: {
                    x: 0,
                    y: -10
                }
            },
            props: {
                text: {
                    name: "text",
                    label: "顯示",
                    value: "",
                    editor: function() {
                        return new myflow.editors.textEditor()
                    }
                },
                tmp0: {
                    name: "tmp0",
                    label: "關聯積1",
                    value: "",
                    editor: function() {
                        return new myflow.editors.inputEditor()
                    }
                },
                tmp1: {
                    name: "tmp1",
                    label: "關聯積2",
                    value: "",
                    editor: function() {
                        return new myflow.editors.inputEditor()
                    }
                } 
            }
        },
        cpath: {// 引數
            attr: {
                path: {
                    path: 'M10 10L100 100',
                    stroke: '#8B3626',
                    fill: "none",

                    "stroke-width": 2,
                    cursor: "pointer"
                },
                arrow: {
                    path: 'M10 10L10 10',
                    stroke: '#8B3626',
                    fill: "#8B3626",
                    "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: {
                    cursor: "move",
                    'background': '#000'
                }
            },
            text: {
                patten: '',
                textPos: {
                    x: 0,
                    y: -10
                }
            },
            props: {
                text: {
                    name: "text",
                    label: "顯示",
                    value: "",
                    editor: function() {

                        return new myflow.editors.textEditor()
                    }
                },
                tmp0: {
                    name: "tmp0",
                    label: "關聯引數1",
                    value: "",
                    editor: function() {
                        //我要取到path的from,再根據from的值取到裝置型別type,再根據type生成{name,value}
                        //console.log(from.getEquipmentType());
                        return new myflow.editors.selectEditor([{name:'',value:0},{name:'溫度',value:1},{name:'bbb',value:2}])
                    }
                },
                tmp1: {
                    name: "tmp1",
                    label: "關聯引數2",
                    value: "",
                    editor: function() {
                        return new myflow.editors.selectEditor([{name:'aaa',value:1},{name:'bbb',value:2}])
                    }
                } 
            }
        },
        tools: {// 工具欄
            attr: {
                left: 10,
                top: 50
            },
            pointer: {},
            path: {},
            states: {
                "normal": { type: "normal" },
                "circulation": { type: "circulation" },
                "meet": { type: "meet" }
            },
            save: {
                onclick: function (data) {
                    alert(data);
                }
            }
        },
        props: {// 屬性編輯器
            attr: {
                top: 30,
                right: 30
            },
            props: {}
        },
        restore: '',
        activeRects: {// 當前啟用狀態
            rects: [],
            rectAttr: {
                stroke: '#ff0000',
                "stroke-width": 2
            }
        },
        historyRects: {// 歷史啟用狀態
            rects: [],
            pathAttr: {
                path: {
                    stroke: '#00ff00'
                },
                arrow: {
                    stroke: '#00ff00',
                    fill: "#00ff00"
                }
            }
        }
    };

    myflow.util = {
        isLine: function (p1, p2, p3) {// 三個點是否在一條直線上
            var s, p2y;
            if ((p1.x - p3.x) == 0)
                s = 1;
            else
                s = (p1.y - p3.y) / (p1.x - p3.x);
            p2y = (p2.x - p3.x) * s + p3.y;
            // $('body').append(p2.y+'-'+p2y+'='+(p2.y-p2y)+', ');
            if ((p2.y - p2y) < 10 && (p2.y - p2y) > -10) {
                p2.y = p2y;
                return true;
            }
            return false;
        },
        center: function (p1, p2) {// 兩個點的中間點
            return {
                x: (p1.x - p2.x) / 2 + p2.x,
                y: (p1.y - p2.y) / 2 + p2.y
            };
        },
        // nextId: (function () {
        //     var uid = 0;
        //     return function () {
        //         return ++uid;
        //     };
        // })(),
        nextId:function(){
            return new Date().getTime();
        },
        connPoint: function (rect, p) {// 計算矩形中心到p的連線與矩形的交叉點
            var start = p, end = {
                x: rect.x + rect.width / 2,
                y: rect.y + rect.height / 2
            };
            // 計算正切角度
            var tag = (end.y - start.y) / (end.x - start.x);
            tag = isNaN(tag) ? 0 : tag;

            var rectTag = rect.height / rect.width;
            // 計算箭頭位置
            var xFlag = start.y < end.y ? -1 : 1, yFlag = start.x < end.x
                    ? -1
                    : 1, arrowTop, arrowLeft;
            // 按角度判斷箭頭位置
            if (Math.abs(tag) > rectTag && xFlag == -1) {// top邊
                arrowTop = end.y - rect.height / 2;
                arrowLeft = end.x + xFlag * rect.height / 2 / tag;
            } else if (Math.abs(tag) > rectTag && xFlag == 1) {// bottom邊
                arrowTop = end.y + rect.height / 2;
                arrowLeft = end.x + xFlag * rect.height / 2 / tag;
            } else if (Math.abs(tag) < rectTag && yFlag == -1) {// left邊
                arrowTop = end.y + yFlag * rect.width / 2 * tag;
                arrowLeft = end.x - rect.width / 2;
            } else if (Math.abs(tag) < rectTag && yFlag == 1) {// right邊
                arrowTop = end.y + rect.width / 2 * tag;
                arrowLeft = end.x + rect.width / 2;
            }
            return {
                x: arrowLeft,
                y: arrowTop
            };
        },

        arrow: function (p1, p2, r) {// 畫箭頭,p1 開始位置,p2 結束位置, r前頭的邊長
            var atan = Math.atan2(p1.y - p2.y, p2.x - p1.x) * (180 / Math.PI);

            var centerX = p2.x - r * Math.cos(atan * (Math.PI / 180));
            var centerY = p2.y + r * Math.sin(atan * (Math.PI / 180));

            var x2 = centerX + r * Math.cos((atan + 120) * (Math.PI / 180));
            var y2 = centerY - r * Math.sin((atan + 120) * (Math.PI / 180));

            var x3 = centerX + r * Math.cos((atan + 240) * (Math.PI / 180));
            var y3 = centerY - r * Math.sin((atan + 240) * (Math.PI / 180));
            return [p2, {
                x: x2,
                y: y2
            }, {
                x: x3,
                y: y3
            }];
        }
    }

    myflow.rect = function (o, r,id) {
        var _this = this, _uid = myflow.util.nextId(), _o = $.extend(true, {},
            myflow.config.rect, o), _id =id || 'rect' + _uid, _r = r, // Raphael畫筆
    _rect, _img, // 圖示
    _name, // 狀態名稱
    _text, // 顯示文字
    _ox, _oy; // 拖動時,儲存起點位置;
    //console.log(_o);

        _rect = _r.rect(_o.attr.x, _o.attr.y, _o.attr.width, _o.attr.height,
            _o.attr.r).hide().attr(_o.attr);
        _img = _r.image(myflow.config.basePath + _o.img.src,
            _o.attr.x + _o.img.width / 2,
            _o.attr.y + (_o.attr.height - _o.img.height) / 2, _o.img.width,
            _o.img.height).hide();
        _name = _r.text(
            _o.attr.x + _o.img.width + (_o.attr.width - _o.img.width) / 2,
            _o.attr.y + myflow.config.lineHeight / 2, _o.name.text).hide()
            .attr(_o.name);
        _text = _r.text(
            _o.attr.x + _o.img.width + (_o.attr.width - _o.img.width) / 2,
            _o.attr.y + (_o.attr.height - myflow.config.lineHeight) / 2
                    + myflow.config.lineHeight, _o.text.text).hide()
            .attr(_o.text); // 文字

        // 拖動處理----------------------------------------
        _rect.drag(function (dx, dy) {
            dragMove(dx, dy);
        }, function () {
            dragStart()
        }, function () {
            dragUp();
        });
        _img.drag(function (dx, dy) {
            dragMove(dx, dy);
        }, function () {
            dragStart()
        }, function () {
            dragUp();
        });
        _name.drag(function (dx, dy) {
            dragMove(dx, dy);
        }, function () {
            dragStart()
        }, function () {
            dragUp();
        });
        _text.drag(function (dx, dy) {
            dragMove(dx, dy);
        }, function () {
            dragStart()
        }, function () {
            dragUp();
        });

        var dragMove = function (dx, dy) {// 拖動中
            if (!myflow.config.editable)
                return;

            var x = (_ox + dx); // -((_ox+dx)%10);
            var y = (_oy + dy); // -((_oy+dy)%10);

            _bbox.x = x - _o.margin;
            _bbox.y = y - _o.margin;
            resize();
        };

        var dragStart = function () {// 開始拖動
            _ox = _rect.attr("x");
            _oy = _rect.attr("y");
            _rect.attr({
                opacity: 0.5
            });
            _img.attr({
                opacity: 0.5
            });
            _text.attr({
                opacity: 0.5
            });
        };

        var dragUp = function () {// 拖動結束
            _rect.attr({
                opacity: 1
            });
            _img.attr({
                opacity: 1
            });
            _text.attr({
                opacity: 1
            });
        };

        // 改變大小的邊框
        var _bpath, _bdots = {}, _bw = 5, _bbox = {
            x: _o.attr.x - _o.margin,
            y: _o.attr.y - _o.margin,
            width: _o.attr.width + _o.margin * 2,
            height: _o.attr.height + _o.margin * 2
        };

        _bpath = _r.path('M0 0L1 1').hide();
        _bdots['t'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 's-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 't');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 't');
        }, function () {
        }); // 上
        _bdots['lt'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'nw-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'lt');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'lt');
        }, function () {
        }); // 左上
        _bdots['l'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'w-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'l');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'l');
        }, function () {
        }); // 左
        _bdots['lb'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'sw-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'lb');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'lb');
        }, function () {
        }); // 左下
        _bdots['b'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 's-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'b');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'b');
        }, function () {
        }); // 下
        _bdots['rb'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'se-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'rb');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'rb');
        }, function () {
        }); // 右下
        _bdots['r'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'w-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'r');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'r')
        }, function () {
        }); // 右
        _bdots['rt'] = _r.rect(0, 0, _bw, _bw).attr({
            fill: '#000',
            stroke: '#fff',
            cursor: 'ne-resize'
        }).hide().drag(function (dx, dy) {
            bdragMove(dx, dy, 'rt');
        }, function () {
            bdragStart(this.attr('x') + _bw / 2, this.attr('y') + _bw
                                / 2, 'rt')
        }, function () {
        }); // 右上
        $([_bdots['t'].node, _bdots['lt'].node, _bdots['l'].node, _bdots['lb'].node, _bdots['b'].node, _bdots['rb'].node, _bdots['r'].node, _bdots['rt'].node]).click(function () { return false; });

        var bdragMove = function (dx, dy, t) {
            if (!myflow.config.editable)
                return;
            var x = _bx + dx, y = _by + dy;
            switch (t) {
                case 't':
                    _bbox.height += _bbox.y - y;
                    _bbox.y = y;
                    break;
                case 'lt':
                    _bbox.width += _bbox.x - x;
                    _bbox.height += _bbox.y - y;
                    _bbox.x = x;
                    _bbox.y = y;
                    break;
                case 'l':
                    _bbox.width += _bbox.x - x;
                    _bbox.x = x;
                    break;
                case 'lb':
                    _bbox.height = y - _bbox.y;
                    _bbox.width += _bbox.x - x;
                    _bbox.x = x;
                    break;
                case 'b':
                    _bbox.height = y - _bbox.y;
                    break;
                case 'rb':
                    _bbox.height = y - _bbox.y;
                    _bbox.width = x - _bbox.x;
                    break;
                case 'r':
                    _bbox.width = x - _bbox.x;
                    break;
                case 'rt':
                    _bbox.width = x - _bbox.x;
                    _bbox.height += _bbox.y - y;
                    _bbox.y = y;
                    break;
            }
            resize();
            // $('body').append(t);
        };
        var bdragStart = function (ox, oy, t) {
            _bx = ox;
            _by = oy;
        };
        // 初始化操作

        _o = $.extend(true, _o, o);
        
        // 事件處理- _text.node, _name.node, _img.node-------------------------------
        $([_rect.node, _text.node, _name.node, _img.node]).bind("contextmenu", function (e) {
            if (_this.getId() == _id) {
                _textself = _text;
                myflow.config.tools.contextmenu(e, _this, _textself,"rect", function (txt) {
                    if (_this.getId() == _id) {
                        _textself.attr({
                            text: txt
                        });
                    }
                });
            }
            return false;
        });
     
       
        $([_rect.node, _text.node, _name.node, _img.node]).bind("dblclick", function (e, src) { myflow.config.tools.dblclickRect(_this.getId(), _this.toJson()); });
        $([_rect.node, _text.node, _name.node, _img.node]).bind('click',
            function () {
                if (!myflow.config.editable)
                    return;

                showBox();
                if (_this.getId() == _id) {
                    _textself = _text;
                    myflow.config.tools.clickRect(_this, _textself, function (txt) {
                        if (_this.getId() == _id) {
                            _textself.attr({
                                text: txt
                            });
                        }
                    });
                }
              
                var mod = $(_r).data('mod');
                switch (mod) {
                    case 'pointer':
                        $(_r).data('currNode', _this);
                        break;
                    
                    case 'jpath':
                        var pre= $(_r).data('currNode');
                        if (pre && pre.getId().substring(0, 4) == 'rect') {
                            if(pre.getId() != _id){
                                $(_r).trigger('addjpath', [pre, _this]);
                            }
                        }
                        $(_r).data('currNode', _this);
                        break;
                    case 'rejectpath'://駁回連線
                        var pre = $(_r).data('currNode');
                        if (pre && pre.getId() != _id
                            && pre.getId().substring(0, 4) == 'rect') {
                            $(_r).trigger('addpathfallback', [pre, _this]);
                        }
                        $(_r).data('currNode', _this);
                        break;
                    case 'lpath':
                        var pre= $(_r).data('currNode');
                        if (pre && pre.getId().substring(0, 4) == 'rect') {
                            if(pre.getId() != _id){
                                $(_r).trigger('addlpath', [pre, _this]);
                            }
                        }
                        $(_r).data('currNode', _this);
                        break;
                    case 'cpath':
                        var pre= $(_r).data('currNode');
                        if (pre && pre.getId().substring(0, 4) == 'rect') {
                            if(pre.getId() != _id){
                                $(_r).trigger('addcpath', [pre, _this]);
                            }
                        }
                        $(_r).data('currNode', _this);
                        break;
                    case 'path':
                        var pre = $(_r).data('currNode');
                        if (pre && pre.getId().substring(0, 4) == 'rect') {
                            if(pre.getId() != _id){
                                $(_r).trigger('addpath', [pre, _this]);
                            }
                        }
                        $(_r).data('currNode', _this);
                        break;
                }

                $(_r).trigger('click', _this);
                return false;
            });

        var clickHandler = function (e, src) {
            if (!myflow.config.editable)
                return;
          
            if (myflow.config.moving.flag) {
               
                if(src.getId().substring(0, 4) == '0000'){
                    myflow.config.moving.isNewDot=true;
                }

                if(myflow.config.moving.preRect == src&&myflow.config.moving.temp.length>2){
                    myflow.config.moving.temp.pop().remove();
                    myflow.config.moving.temp.pop().remove();
                    myflow.config.moving.isNewDot=true;
                }
            }

            if (src.getId() == _id) {
              //  $(_r).trigger('showprops', [_o.props, src]);
            } else {
                hideBox();
            }
        };
       
        $(_r).bind('click', clickHandler);
        //this.setText = function (src,text) {
        //    if (src.getId() == _id) {
        //        _text.attr({
        //            text: text
        //        });
        //    }
        //}
        //var textchangeHandler = function (e, text, src) {
            
        //    if (src.getId() == _id) {
        //        _text.attr({
        //            text: text
        //        });
        //    }
        //};
        //$(_r).bind('textchange', textchangeHandler);
        
        //裝置型別改變函式
        // var equipmentTypeChangeHandler=function(e,v,src){
        //         debugger;
        //         if(src.getType()=="task"){
        //             //console.log(_o);
        //             console.log(src);
        //             //_o.props.assignee["label"]="改!";
        //             //src.extend(true,);
        //         }
                
            
        // }
        // $(_r).bind('equipmentTypeChange',equipmentTypeChangeHandler);
        // 私有函式-----------------------
        // 邊框路徑
        function getBoxPathString() {
            return 'M' + _bbox.x + ' ' + _bbox.y + 'L' + _bbox.x + ' '
                + (_bbox.y + _bbox.height) + 'L' + (_bbox.x + _bbox.width)
                + ' ' + (_bbox.y + _bbox.height) + 'L'
                + (_bbox.x + _bbox.width) + ' ' + _bbox.y + 'L' + _bbox.x
                + ' ' + _bbox.y;
        }
        // 顯示邊框
        function showBox() {
            _bpath.show();
            for (var k in _bdots) {
                _bdots[k].show();
            }
        }
        // 隱藏
        function hideBox() {
            _bpath.hide();
            for (var k in _bdots) {
                _bdots[k].hide();
            }
        }

        // 根據_bbox,更新位置資訊
        function resize() {
            var rx = _bbox.x + _o.margin, ry = _bbox.y + _o.margin, rw = _bbox.width
                - _o.margin * 2, rh = _bbox.height - _o.margin * 2;
            var rxattr = {
                x: rx,
                y: ry,
                width: rw,
                height: rh,
            };
            if (_o.showType == "textcirculation") {
                //傳閱節點   
                rxattr.stroke='#0cba52';
                
            }
            _rect.attr(rxattr);
            switch (_o.showType) {
                case 'image':
                    _img.attr({
                        x: rx + (rw - _o.img.width) / 2,
                        y: ry + (rh - _o.img.height) / 2
                    }).show();
                    break;
                case 'text':
                    _rect.show();
                    _text.attr({
                        x: rx + rw / 2,
                        y: ry + rh / 2
                    }).show(); // 文字
                    break;
                case 'textcirculation':
                    _rect.show();
                    if (_o.IsCurActive) {
                        //流程例項當前節點
                        _text.attr({
                            x: rx + rw / 2,
                            y: ry + rh / 2,
                            fill: "red"
                        }).show();// 文字
                    }
                    else {
                        _text.attr({
                            x: rx + rw / 2,
                            y: ry + rh / 2
                        }).show();// 文字
                    }
                    break;
                case 'image&text':
                    _rect.show();
                    _name.attr({
                        x: rx + _o.img.width + (rw - _o.img.width) / 2,
                        y: ry + myflow.config.lineHeight / 2
                    }).show();
                    _text.attr({
                        x: rx + _o.img.width + (rw - _o.img.width) / 2,
                        y: ry + (rh - myflow.config.lineHeight) / 2
                            + myflow.config.lineHeight
                    }).show(); // 文字
                    _img.attr({
                        x: rx + _o.img.width / 2,
                        y: ry + (rh - _o.img.height) / 2
                    }).show();
                    break;
            }

            _bdots['t'].attr({
                x: _bbox.x + _bbox.width / 2 - _bw / 2,
                y: _bbox.y - _bw / 2
            }); // 上
            _bdots['lt'].attr({
                x: _bbox.x - _bw / 2,
                y: _bbox.y - _bw / 2
            }); // 左上
            _bdots['l'].attr({
                x: _bbox.x - _bw / 2,
                y: _bbox.y - _bw / 2 + _bbox.height / 2
            }); // 左
            _bdots['lb'].attr({
                x: _bbox.x - _bw / 2,
                y: _bbox.y - _bw / 2 + _bbox.height
            }); // 左下
            _bdots['b'].attr({
                x: _bbox.x - _bw / 2 + _bbox.width / 2,
                y: _bbox.y - _bw / 2 + _bbox.height
            }); // 下
            _bdots['rb'].attr({
                x: _bbox.x - _bw / 2 + _bbox.width,
                y: _bbox.y - _bw / 2 + _bbox.height
            }); // 右下
            _bdots['r'].attr({
                x: _bbox.x - _bw / 2 + _bbox.width,
                y: _bbox.y - _bw / 2 + _bbox.height / 2
            }); // 右
            _bdots['rt'].attr({
                x: _bbox.x - _bw / 2 + _bbox.width,
                y: _bbox.y - _bw / 2
            }); // 右上
            _bpath.attr({
                path: getBoxPathString()
            });

            $(_r).trigger('rectresize', _this);
        };
        this.GetConfig = function () { return _config; }
        this.ChangePhaseType = function (showTypeTmp, typeTmp) {
            _o.showType = showTypeTmp;// "textcirculation";
            _o.type = typeTmp;// "state"; 

        }
        // 函式----------------
        //取裝置型別函式
        
        //this.getEquipmentType = function () {
        //    var equipmentType=null;
        //    for(var k in _o.props){
        //        if(k=="equipmentType")
        //           equipmentType = _o.props[k].value;
        //    }
        //    if(equipmentType!=null)
        //        return equipmentType;
        //};

        //取節點型別
        this.getType=function(){
            var type=null;
            type=_o.type;
            return type;
        }
        // 轉化json字串
        this.toJson = function () {
           
            var data = "{type:'" + _o.type + "',ID:'" + (!_o.ID ? "" : _o.ID) + "',text:{text:'"
                + (!_text.node.textContent ? "" : _text.node.textContent) + "'}, attr:{ x:"
                + Math.round(_rect.attr('x')) + ", y:"
                + Math.round(_rect.attr('y')) + ", width:"
                + Math.round(_rect.attr('width')) + ", height:"
                + Math.round(_rect.attr('height')) + "}}";
            //", props:{"
            //for (var k in _o.props) {
            //   data += k + ":{value:'"
            //       + _o.props[k].value + "'},";
            //}

            //if (data.substring(data.length - 1, data.length) == ',')
            //    data = data.substring(0, data.length - 1);
            //data += "}}";
            return data;
        };
        // 從資料中恢復圖
        this.restore = function (data) {
            var obj = data;
            // if (typeof data === 'string')
            // obj = eval(data);
            //console.log(obj);
            _o = $.extend(true, _o, data);

            _text.attr({
                text: obj.text.text
            });
            resize();
        };

        this.getBBox = function () {
            return _bbox;
        };
        this.getId = function () {
            return _id;
        };
        this.remove = function () {
            _rect.remove();
            _text.remove();
            _name.remove();
            _img.remove();
            _bpath.remove();
            for (var k in _bdots) {
                _bdots[k].remove();
            }
        };
        this.text = function () {
            return _text.attr('text');
        };
        this.attr = function (attr) {
            if (attr)
                _rect.attr(attr);
        };

        resize(); // 初始化位置
    };

    myflow.path = function (o, r, from, to, guid, ec, dots, id) {
        
        var _this = this, _r = r, _o = $.extend(true, o, myflow.config.path), _path, _markpath, _arrow, _text,_textPos, _ox, _oy, _from = from, _to = to, _id = id || 'path'
            + myflow.util.nextId(), _dotList, _autoText = true; _o.lineID = guid; oec = (ec > 0 ? (parseInt(ec) == 1 ? 25 : parseInt(ec) * 9 + 22) : 0);
            if (o.text != null) {
                _textPos = o.text.textPos;
            }
            if (o.lineType != "path")
            {
                _o.attr.path.stroke = "#ff0000";
                _o.attr.path.fill = "none";
                _o.attr.arrow.stroke = "#ff0000";
                _o.attr.arrow.fill = "#808080";
               // _o = $.extend(_o, { attr: { path: { storke: "#ff0000", fill: "#808080" }, arrow: { storke: "#ff0000", fill: "#808080" } } });
            }
           // _o.props.PathType = { value: "1" };
          
        // 點
        function dot(type, pos, left, right) {
            var _this = this, _t = type, _n, _lt = left, _rt = right, _ox, _oy, // 快取移動前時位置
            _pos = pos; // 快取位置資訊{x,y}, 注意:這是計算出中心點

            switch (_t) {
                case 'from':
                    _n = _r.rect(pos.x - _o.attr.fromDot.width / 2,
                        pos.y - _o.attr.fromDot.height / 2,
                        _o.attr.fromDot.width, _o.attr.fromDot.height)
                        .attr(_o.attr.fromDot);
                    break;
                case 'big':
                    _n = _r.rect(pos.x - _o.attr.bigDot.width / 2,
                        pos.y - _o.attr.bigDot.height / 2,
                        _o.attr.bigDot.width, _o.attr.bigDot.height)
                        .attr(_o.attr.bigDot);
                    break;
                case 'small':
                    _n = _r.rect(pos.x - _o.attr.smallDot.width / 2,
                        pos.y - _o.attr.smallDot.height / 2,
                        _o.attr.smallDot.width, _o.attr.smallDot.height)
                        .attr(_o.attr.smallDot);
                    break;
                case 'to':
                    _n = _r.rect(pos.x - _o.attr.toDot.width / 2,
                        pos.y - _o.attr.toDot.height / 2,
                        _o.attr.toDot.width, _o.attr.toDot.height)
                        .attr(_o.attr.toDot);

                    break;
            }
            if (_n && (_t == 'big' || _t == 'small')) {
                _n.drag(function (dx, dy) {
                    dragMove(dx, dy);
                }, function () {
                    dragStart()
                }, function () {
                    dragUp();
                }); // 初始化拖動
                var dragMove = function (dx, dy) {// 拖動中
                    var x = (_ox + dx), y = (_oy + dy);
                    _this.moveTo(x, y);
                };

                var dragStart = function () {// 開始拖動
                    if (_t == 'big') {
                        _ox = _n.attr("x") + _o.attr.bigDot.width / 2;
                        _oy = _n.attr("y") + _o.attr.bigDot.height / 2;
                    }
                    if (_t == 'small') {
                        _ox = _n.attr("x") + _o.attr.smallDot.width / 2;
                        _oy = _n.attr("y") + _o.attr.smallDot.height / 2;
                    }
                    console.log(_t);
                };

                var dragUp = function () {// 拖動結束

                };
            }
            $(_n.node).click(function () { return false; });

            this.type = function (t) {
                if (t)
                    _t = t;
                else
                    return _t;
            };
            this.node = function (n) {
                if (n)
                    _n = n;
                else
                    return _n;
            };
            this.left = function (l) {
                if (l)
                    _lt = l;
                else
                    return _lt;
            };
            this.right = function (r) {
                if (r)
                    _rt = r;
                else
                    return _rt;
            };
            this.remove = function () {
                _lt = null;
                _rt = null;
                _n.remove();
            };
            this.pos = function (pos) {
                if (pos) {
                    _pos = pos;
                    _n.attr({
                        x: _pos.x - _n.attr('width') / 2,
                        y: _pos.y - _n.attr('height') / 2
                    });
                    return this;
                } else {
                    return _pos
                }
            };

            this.moveTo = function (x, y) {
                this.pos({
                    x: x,
                    y: y
                });

                switch (_t) {
                    case 'from':
                        if (_rt && _rt.right() && _rt.right().type() == 'to') {
                            _rt.right().pos(myflow.util.connPoint(
                                _to.getBBox(), _pos));
                        }
                        if (_rt && _rt.right()) {
                            _rt
                                .pos(myflow.util.center(_pos, _rt.right()
                                                .pos()));
                        }
                        break;
                    case 'big':

                        if (_rt && _rt.right() && _rt.right().type() == 'to') {
                            _rt.right().pos(myflow.util.connPoint(
                                _to.getBBox(), _pos));
                        }
                        if (_lt && _lt.left() && _lt.left().type() == 'from') {
                            _lt.left().pos(myflow.util.connPoint(_from
                                        .getBBox(), _pos));
                        }
                        if (_rt && _rt.right()) {
                            _rt
                                .pos(myflow.util.center(_pos, _rt.right()
                                                .pos()));
                        }
                        if (_lt && _lt.left()) {
                            _lt.pos(myflow.util.center(_pos, _lt.left().pos()));
                        }
                        // 三個大點在一條線上,移除中間的小點
                        var pos = {
                            x: _pos.x,
                            y: _pos.y
                        };
                        if (myflow.util.isLine(_lt.left().pos(), pos, _rt
                                    .right().pos())) {
                            _t = 'small';
                            _n.attr(_o.attr.smallDot);
                            this.pos(pos);
                            var lt = _lt;
                            _lt.left().right(_lt.right());
                            _lt = _lt.left();
                            lt.remove();
                            var rt = _rt;
                            _rt.right().left(_rt.left());
                            _rt = _rt.right();
                            rt.remove();
                            // $('body').append('ok.');
                        }
                        break;
                    case 'small': // 移動小點時,轉變為大點,增加倆個小點
                        if (_lt && _rt && !myflow.util.isLine(_lt.pos(), {
                            x: _pos.x,
                            y: _pos.y
                        }, _rt.pos())) {

                            _t = 'big';

                            _n.attr(_o.attr.bigDot);
                            var lt = new dot('small', myflow.util.center(_lt
                                                .pos(), _pos), _lt, _lt
                                        .right());
                            _lt.right(lt);
                            _lt = lt;

                            var rt = new dot('small', myflow.util.center(_rt
                                                .pos(), _pos), _rt.left(),
                                _rt);
                            _rt.left(rt);
                            _rt = rt;

                        }
                        break;
                    case 'to':
                        if (_lt && _lt.left() && _lt.left().type() == 'from') {
                            _lt.left().pos(myflow.util.connPoint(_from
                                        .getBBox(), _pos));
                        }
                        if (_lt && _lt.left()) {
                            _lt.pos(myflow.util.center(_pos, _lt.left().pos()));
                        }
                        break;
                }
                if (!_o.path_p || _o.path_p == "")
                {
                    refreshpath();
                }
              
            };
        }

        function dotList() {
            // if(!_from) throw '沒有from節點!';
            var _fromDot, _toDot, _fromBB = _from.getBBox(), _toBB = _to
                .getBBox(), _fromPos, _toPos;

            _fromPos = myflow.util.connPoint(_fromBB, {
                x: _toBB.x + _toBB.width / 2,
                y: _toBB.y + _toBB.height / 2
            });
            _toPos = myflow.util.connPoint(_toBB, _fromPos);

            _fromDot = new dot('from', _fromPos, null, new dot('small', {
                x: (_fromPos.x + _toPos.x) / 2 + oec,
                y: (_fromPos.y + _toPos.y) / 2
            }));
            _fromDot.right().left(_fromDot);
            _toDot = new dot('to', _toPos, _fromDot.right(),null);
            _fromDot.right().right(_toDot);
            
            // 轉換為path格式的字串
            this.toPathString = function () {
                if (!_fromDot)
                    return '';
                //alert(_o.path_p);
                if (o.path_p&&o.path_p != "")
                {
                    var arrrrr = [o.path_p, o.path_arr];
                    o.path_p = "";
                    o.path_arr = "";
                   
                    return arrrrr;
                }
                var d = _fromDot, p = 'M' + d.pos().x + ' ' + d.pos().y, arr = '';
                // 線的路徑
                while (d.right()) {
                    d = d.right();
                    p += 'L' + d.pos().x + ' ' + d.pos().y;
                }
                // 箭頭路徑
                var arrPos = myflow.util.arrow(d.left().pos(), d.pos(),
                    _o.attr.arrow.radius);
                arr = 'M' + arrPos[0].x + ' ' + arrPos[0].y + 'L' + arrPos[1].x
                    + ' ' + arrPos[1].y + 'L' + arrPos[2].x + ' '
                    + arrPos[2].y + 'z';
               
                return [p, arr];
            };
            this.toJson = function () {
                var bigdot = "[", d = _fromDot;
                var fromdot = "[", smalldot = "[", todot = "[";

                while (d) {

                    if (d.type() == 'from') {
                        fromdot += "{x:" + Math.round(d.pos().x) + ",y:"
                            + Math.round(d.pos().y) + "},";
                    }
                    if (d.type() == 'small') {
                        smalldot += "{x:" + Math.round(d.pos().x) + ",y:"
                            + Math.round(d.pos().y) + "},";
                    }
                    if (d.type() == 'to') {
                        todot += "{x:" + Math.round(d.pos().x) + ",y:"
                            + Math.round(d.pos().y) + "},";
                    }
                    if (d.type() == 'big')
                        bigdot += "{x:" + Math.round(d.pos().x) + ",y:"
                            + Math.round(d.pos().y) + "},";

                    d = d.right();
                }
                if (fromdot.substring(fromdot.length - 1, fromdot.length) == ',')
                    fromdot = fromdot.substring(0, fromdot.length - 1);
                fromdot += "]";
                if (smalldot.substring(smalldot.length - 1, smalldot.length) == ',')
                    smalldot = smalldot.substring(0, smalldot.length - 1);
                smalldot += "]";
                if (todot.substring(todot.length - 1, todot.length) == ',')
                    todot = todot.substring(0, todot.length - 1);
                todot += "]";
                if (bigdot.substring(bigdot.length - 1, bigdot.length) == ',')
                    bigdot = bigdot.substring(0, bigdot.length - 1);
                bigdot += "]";
          
                return bigdot;
            };
            this.restore = function (data) {
                var obj = data, d = _fromDot.right();
                if (obj.length) {
                    for (var i = 0; i < obj.length; i++) {
                        if (!d) {
                            break;
                        }
                        d.moveTo(obj[i].x, obj[i].y);
                        d.moveTo(obj[i].x, obj[i].y);
                        d = d.right();
                    }
                }
                this.hide();
            };

            this.fromDot = function () {
                return _fromDot;
            };
            this.toDot = function () {
                return _toDot;
            };
            this.midDot = function () {// 返回中間點
                var mid = _fromDot.right(), end = _fromDot.right().right();
                while (end.right() && end.right().right()) {
                    end = end.right().right();
                    mid = mid.right();
                }
                return mid;
            };
            this.show = function () {
                var d = _fromDot;
                while (d) {
                    d.node().show();
                    d = d.right();
                }
            };
            this.hide = function () {
                var d = _fromDot;
                while (d) {
                    d.node().hide();
                    d = d.right();
                }
            };
            this.remove = function () {
                var d = _fromDot;
                while (d) {
                    if (d.right()) {
                        d = d.right();
                        d.left().remove();
                    } else {
                        d.remove();
                        d = null;
                    }
                }
            };
        }

        // 初始化操作
        _o = $.extend(true, _o, o);
        _path = _r.path(_o.attr.path.path).attr(_o.attr.path);
        _markpath=_r.path(_o.attr.path.path)
            .attr({fill: "none",stroke: "white","stroke-miterlimit": 10,"stroke-width": 14,"-webkit-tap-highlight-color": "rgba(0, 0, 0, 0)","visibility":"hidden","pointer-events": "stroke","cursor": "crosshair"});
        _arrow = _r.path(_o.attr.arrow.path).attr(_o.attr.arrow);

        _dotList = new dotList();
     
        _dotList.hide();

        _text = _r.text(0, 0, _o.text.text || _o.text.patten.replace('{from}', _from.text()).replace('{to}',
                _to.text())).attr(_o.attr.text);
        _text.drag(function (dx, dy) {
            if (!myflow.config.editable)
                return;
            _text.attr({
                x: _ox + dx,
                y: _oy + dy
            });
        }, function () {
            _ox = _text.attr('x');
            _oy = _text.attr('y');
        }, function () {
            var mid = _dotList.midDot().pos();
          
            _textPos = {
                x: _text.attr('x') - mid.x,
                y: _text.attr('y') - mid.y
            };
           
        });

        refreshpath(); // 初始化路徑

        // 事件處理--------------------這裡看不懂
        $([_path.node, _text.node, _arrow.node, _markpath.node]).bind("contextmenu", function (e) {
            if (_this.getId() == _id) {
                _textself = _text;
                myflow.config.tools.contextmenu(e, _this, _textself,"path", function (txt) {
                    if (_this.getId() == _id) {
                        _textself.attr({
                            text: txt
                        });
                    }
                });
            }
            return false;
        });
        $([_path.node, _markpath.node, _arrow.node, _text.node]).bind("dblclick", function () { myflow.config.tools.dblclickPath(_from, _to, _path); });//雙擊線事件
        $([_path.node,_markpath.node, _arrow.node, _text.node]).bind('click', function () {
            if (!myflow.config.editable)
                return;
            $(_r).trigger('click', _this);
            $(_r).data('currNode', _this);
            myflow.config.tools.clickPath(_id);
            return false;
        });

        // 處理點選事件,線或矩形
        var clickHandler = function (e, src) {
            if (!myflow.config.editable)
                return;

            if (src && src.getId() == _id) {
                _dotList.show();
               // $(_r).trigger('showprops', [_o.props, _this]);
            } else {
                _dotList.hide();
            }

            var mod = $(_r).data('mod');
            switch (mod) {
                // case 'pointer':
                //         console.log("點選的是點")  
                //     break;
                // case 'path':
                //         console.log("點選的是線")
                //     break;
            }

        };
        $(_r).bind('click', clickHandler);

        // 刪除事件處理
        var removerectHandler = function (e, src) {
            if (!myflow.config.editable)
                return;
            if (src
                && (src.getId() == _from.getId() || src.getId() == _to.getId())) {
                $(_r).trigger('removepath', _this);
            }
        };
        $(_r).bind('removerect', removerectHandler);
        
        // 矩形移動時間處理
        var rectresizeHandler = function (e, src) {
            if (!myflow.config.editable)
                return;
            if (_from && _from.getId() == src.getId()) {
                var rp;
                if (_dotList.fromDot().right().right().type() == 'to') {
                    rp = {
                        x: _to.getBBox().x + _to.getBBox().width / 2,
                        y: _to.getBBox().y + _to.getBBox().height / 2
                    };
                } else {
                    rp = _dotList.fromDot().right().right().pos();
                }
                var p = myflow.util.connPoint(_from.getBBox(), rp);
                _dotList.fromDot().moveTo(p.x, p.y);
                refreshpath();
            }
            if (_to && _to.getId() == src.getId()) {
                var rp;
                if (_dotList.toDot().left().left().type() == 'from') {
                    rp = {
                        x: _from.getBBox().x + _from.getBBox().width / 2,
                        y: _from.getBBox().y + _from.getBBox().height / 2
                    };
                } else {
                    rp = _dotList.toDot().left().left().pos();
                }
                var p = myflow.util.connPoint(_to.getBBox(), rp);
                _dotList.toDot().moveTo(p.x, p.y);
                refreshpath();
            }
        };
        $(_r).bind('rectresize', rectresizeHandler);

        var textchangeHandler = function (e, v, src) {
            if (src.getId() == _id) {// 改變自身文字
                _text.attr({
                    text: v
                });
                _autoText = false;
            }
            //$('body').append('['+_autoText+','+_text.attr('text')+','+src.getId()+','+_to.getId()+']');
            if (_autoText) {
                if (_to.getId() == src.getId()) {
                    //$('body').append('change!!!');
                    _text.attr({
                        text: _o.text.patten.replace('{from}',
                                    _from.text()).replace('{to}', v)
                    });
                }
                else if (_from.getId() == src.getId()) {
                    //$('body').append('change!!!');
                    _text.attr({
                        text: _o.text.patten.replace('{from}', v)
                                    .replace('{to}', _to.text())
                    });
                }
            }
        };
        $(_r).bind('textchange', textchangeHandler);

        // 函式-------------------------------------------------
        this.from = function () {
            return _from;
        };
        this.getFrom=function(){
            var from=null;
            from=_from;
            return from;
        }
        this.getTo=function(){
            var to=null;
            to=_to;
            return to;
        }
        this.to = function () {
            return _to;
        };
        this.getprops = function () {
            return _o.props;
        };
        this.getlineType = function () {
           
            return _o.lineType;
        };
        // 轉化json資料
        this.toJson = function () {
          
            var _tPos = _dotList.toPathString();
            var data = "{lineID:'" + (!_o.lineID ? "" : _o.lineID) + "',lineType:'" + _o.lineType + "',from:'" + _from.getId() + "',to:'" + _to.getId()
                + "', dots:" + _dotList.toJson() + ",path_p:'" + _tPos[0] + "',path_arr:'" + _tPos[1] + "',text:{text:'"
                + _text.attr('text') + "',textPos:{x:"
                + Math.round(_textPos.x) + ",y:" + Math.round(_textPos.y)
                + "}}}";
         
            //, props:{";
            //for (var k in _o.props) {
            //    data += k + ":{value:'"
            //        + _o.props[k].value + "'},";
            //}
            //if (data.substring(data.length - 1, data.length) == ',')
            //    data = data.substring(0, data.length - 1);
            //data += '}}';
            return data;
        };
       
     
        // 恢復
        this.restore = function (data) {
            var obj = data;

            _o = $.extend(true, _o, data);
            if (_o.text.text != null) {
                //$('body').append('['+_text.attr('text')+','+_o.text.text+']');
                if (_text.attr('text') != _o.text.text) {
                    //$('body').append('['+_text.attr('text')+','+_o.text.text+']');
                    _text.attr({ text: _o.text.text });
                    _autoText = false;
                }
            }
            if (obj.dots != null) {
                _dotList.restore(obj.dots);
            }
        };
        // 刪除
        this.remove = function () {
            _dotList.remove();
            _path.remove();
            _markpath.remove();
            _arrow.remove();
            _text.remove();
            try {
                $(_r).unbind('click', clickHandler);
            } catch (e) {
            }
            try {
                $(_r).unbind('removerect', removerectHandler);
            } catch (e) {
            }
            try {
                $(_r).unbind('rectresize', rectresizeHandler);;
            } catch (e) {
            }
            try {
                $(_r).unbind('textchange', textchangeHandler);
            } catch (e) {
            }
        };
        // 重新整理路徑
        function refreshpath() {
            var p = _dotList.toPathString(), mid = _dotList.midDot().pos();
           
            _path.attr({
                path: p[0]
            });
            _markpath.attr({
                path:p[0]
            });
            _arrow.attr({
                path: p[1]
            });
            _text.attr({
                x: mid.x + _textPos.x,
                y: mid.y + _textPos.y
            });
            // $('body').append('refresh.');
        }

        this.getId = function () {
            return _id;
        };
        this.text = function () {
            return _text.attr('text');
        };
        this.attr = function (attr) {
            if (attr && attr.path)
                _path.attr(attr.path);
            if (attr && attr.arrow)
                _arrow.attr(attr.arrow);
            // $('body').append('aaaaaa');
        };

        if(dots){
            //_dotList.restore(dots);
           // rectresizeHandler(null,_to);
           // $("#path").click();
           // $(_r).data('currNode', null);
        }
        return _this;
    };


    //myflow.props = function (o, r) {
    
    //    var _this = this, _pdiv = $('#myflow_props').hide().draggable({
    //        handle: '#myflow_props_handle'
    //    }).resizable().css(myflow.config.props.attr).bind('click',
    //        function () {
    //            return false;
    //        }), _tb = _pdiv.find('table'), _r = r, _src;

    //    var showpropsHandler = function (e, props, src) {
    //        if (_src && _src.getId() == src.getId()) {// 連續點選不重新整理
    //            return;
    //        }
    //        _src = src;
    //        $(_tb).find('.editor').each(function () {
    //            var e = $(this).data('editor');
    //            if (e)
    //                e.destroy();
    //        });

    //        _tb.empty();
    //       // _pdiv.show();
    //        //for (var k in props) {
    //        //    _tb.append('<tr><th>' + props[k].label + '</th><td><div id="p'
    //        //        + k + '" class="editor"></div></td></tr>');
    //        //    if (props[k].editor)
    /