text: var flowjs=flowjs||{};
  flowjs.DiFlowChart=function(a,b){this.stage=new createjs.Stage(a);this.stage.enableMouseOver(5);this.graph=b;this.flowItems={};this.width=this.stage.canvas.width;this.height=this.stage.canvas.height;this.itemRadius=15;this.yJumpSize=4*this.itemRadius;this.xJumpSize=9*this.itemRadius;this.lineWidth=6;this.color="purple";this.background="white";this.startX=this.width/2-(this.graph.getLongestLength()-1)*this.xJumpSize/2;this.startY=this.height/2;this.stage.canvas.style.background=this.background;createjs.Ticker.setFPS(60);
  createjs.Ticker.addEventListener("tick",this.stage)};flowjs.DiFlowChart.prototype.draw=function(){var a={},b=new flowjs.GraphWalker(this.graph);b.forEach(function(b){a=this._drawNode(b,a)},this);b.forEach(this._fixLongConnections,this);b.forEach(this._balancePoints,this);b.forEach(this._drawNodeConnections,this);this.submitItems()};
  flowjs.DiFlowChart.prototype._drawNode=function(a,b){var c=b[a.rank]||0;b[a.rank]=c+1;c=this._createItem(a,a.rank,this.graph.getRankSize(a.rank),c);this.flowItems[a.id]=c;return b};flowjs.DiFlowChart.prototype._drawNodeConnections=function(a){var b=this.flowItems[a.id];a.next.each(function(a){a=this._createConnector(b.flowItem,this.flowItems[a].flowItem);b.connectors=b.connectors||[];b.connectors.push(a)},this);this.flowItems[a.id]=b};
  flowjs.DiFlowChart.prototype._fixLongConnections=function(a){a.next.each(function(b){b=this.graph.getNode(b);var c=b.rank-a.rank;if(1<c){console.log("long distance reletaionship",a.id,b.id,"how long?",c);var c=this.flowItems[a.id].flowItem,d=this.flowItems[b.id].flowItem,f=Math.max(c.y,d.y),e=Math.min(c.y,d.y),g=f-e;console.log("things",e,f,g,c,d);c=[];for(d=a.rank+1;d<b.rank;d++)c=c.concat(this.graph.getNodesWithRank(d));console.log("affected nodes",c);c.forEach(function(a){a=this.flowItems[a.id].flowItem;
  a.y=a.y<f?a.y-1.25*g:a.y+.75*g},this)}},this)};flowjs.DiFlowChart.prototype._balancePoints=function(a){var b=this;this.graph.getNodesWithRank(a.rank).forEach(function(c){var d;if(a.id===c.id||0===a.getCallCount()||0===c.getCallCount())d=!1;else{d=b._getNodeAvgPrevY(a);var f=b._getNodeAvgPrevY(c),e=b._getFlowItem(a.id).y,g=b._getFlowItem(c.id).y;d=e>g&&f>d||g>e&&d>f?!0:!1}d&&(console.log("swapping",a.id,c.id),d=this._getFlowItem(a.id),c=this._getFlowItem(c.id),f=c.y,c.y=d.y,d.y=f)},this)};
  flowjs.DiFlowChart.prototype._straighten_connections=function(a){var b=[];this.graph.getNodesWithRank(a).forEach(function(a){b.push(this.flowItems[a.id])},this);b.sort(function(a,b){return a.flowItem.y-b.flowItem.y});var c=function(a,b){a.forEach(function(c){console.log("moving",c.node.id,"by",b,"affectedNodes",a);c.flowItem.y+=b;(c.connectors||[]).forEach(function(a){a.ya+=b})},this)};b.forEach(function(a,f){if(0!==a.node.getCallCount()){var e=a.flowItem,g=this._getNodeAvgPrevY(a.node),h=g-e.y;console.log("diff",
  h,g,e.y);Math.abs(h)<=e.radius?(console.log("COOL",a.node.id),e.y=g):(e=[],e=0<h?b.slice(f):b.slice(0,f+1),c(e,-h))}},this)};flowjs.DiFlowChart.prototype._getFlowItem=function(a){return this.flowItems[a].flowItem};flowjs.DiFlowChart.prototype._getNodeAvgPrevY=function(a){if(0===a.getCallCount())throw Error("cant find the avarge previous y of no previous items. node="+a.id);var b=0;a.callers.each(function(a){b+=this._getFlowItem(a).y},this);return b/a.callers.size()};
  flowjs.DiFlowChart.prototype._createItem=function(a,b,c,d){b=new flowjs.flowItem(this.startX+b*this.xJumpSize,this.startY-this.itemRadius-this.yJumpSize/2*(c-1)+d*this.yJumpSize,a.id,this.itemRadius,this.onItemUpdate);b.color=this.color;b.background=this.background;b.refresh();return{node:a,flowItem:b}};
  flowjs.DiFlowChart.prototype._createConnector=function(a,b){var c=a.getLocation(),d=b.getLocation(),c=new flowjs.flowConnector(c.x,c.y,d.x,d.y);c.color=this.color;c.strokeWidth=this.lineWidth;c.refresh();return c};
  flowjs.DiFlowChart.prototype.submitItems=function(){var a=[],b=[],c;for(c in this.flowItems){var d=this.flowItems[c].flowItem;d.getDrawableItems().forEach(function(a){b.push(a)});d.refresh();d=this.flowItems[c].connectors;void 0!==d&&d.forEach(function(b){b.refresh();b.getDrawableItems().forEach(function(b){a.push(b)})})}var f=this.stage;a.forEach(function(a){f.addChild(a)});b.forEach(function(a){f.addChild(a)});this.stage.update()};
  flowjs.DiFlowChart.prototype.updateItem=function(a,b){var c=this.flowItems[a];void 0!==c&&(b(c),c.flowItem.refresh(),void 0!==c.connectors&&c.connectors.forEach(function(a){a.refresh()}),this.stage.update())};flowjs=flowjs||{};
  flowjs.flowItem=function(a,b,c,d,f){this.x=a;this.y=b;this.color="black";this.background="blue";this.alpha=1;this.radius=d||40;this.text=c||"Hello";this.link="#";this.font="Arial";this.fontSize="16px";this.strokeWidth=2;this.circle=new createjs.Shape;this.textShape=new createjs.Text;this.listener=f||function(){};var e=this;a=function(){console.log("click");window.open(e.link)};b=function(){e.originalColor=e.color;e.color="green";e.updateShape()};c=function(){e.color=e.originalColor||"black";e.updateShape()};
  this.circle.addEventListener("click",a);this.textShape.addEventListener("click",a);this.circle.addEventListener("mouseout",c);this.textShape.addEventListener("mouseout",c);this.circle.addEventListener("mouseover",b);this.textShape.addEventListener("mouseover",b)};
  flowjs.flowItem.prototype.refresh=function(){this.circle.graphics.clear();this.circle.graphics.setStrokeStyle(this.strokeWidth).beginStroke(this.color).beginFill(this.background).drawCircle(0,0,this.radius);this.circle.x=this.getLocation().x;this.circle.y=this.getLocation().y;this.circle.alpha=this.alpha;this.textShape.text=this.text;this.textShape.color=this.color;this.textShape.font=this.fontSize+" "+this.font;var a=this.textShape.getBounds().width;this.textShape.x=this.x+this.radius-a/2;this.textShape.y=
  this.y+2.2*this.radius;this.textShape.alpha=this.alpha;this.loadingAnimation=this.loadingAnimation||this._getLoadingAnimation()};flowjs.flowItem.prototype.getLocation=function(){return{x:this.getX(),y:this.getY()}};flowjs.flowItem.prototype.getX=function(){return this.x+this.radius};flowjs.flowItem.prototype.getY=function(){return this.y+this.radius};flowjs.flowItem.prototype.setX=function(a){this.x=a-this.radius};flowjs.flowItem.prototype.setY=function(a){this.y=a-this.radius};
  flowjs.flowItem.prototype.updateShape=function(){this.refresh();this.listener()};flowjs.flowItem.prototype.getDrawableItems=function(){return[this.circle,this.textShape]};flowjs.flowItem.prototype.toggleFlashing=function(){this.loadingAnimation.setPaused(!this.loadingAnimation._paused)};
  flowjs.flowItem.prototype._getLoadingAnimation=function(){var a=this.getLocation().y,b=this.radius/2,a=createjs.Tween.get(this.circle,{loop:!0,paused:!0}).to({y:a-b},300,createjs.Ease.getPowIn(2)).to({y:a+b},300,createjs.Ease.getPowIn(2)).to({y:a},100);a.setPaused(!0);return a};flowjs=flowjs||{};flowjs.flowConnector=function(a,b,c,d){this.color="blue";this.alpha=1;this.strokeWidth=3;this.xa=a;this.ya=b;this.xb=c;this.yb=d};flowjs.flowConnector.prototype.generateLine=function(a,b,c){a.graphics.clear();a.graphics.setStrokeStyle(this.strokeWidth).beginStroke(this.color).moveTo(b.x,b.y).lineTo(c.x,c.y);a.alpha=this.alpha;return a};
  flowjs.flowConnector.prototype.generateDot=function(a,b){a.graphics.clear();a.graphics.beginFill(this.color).drawCircle(b.x,b.y,this.strokeWidth/2);a.alpha=this.alpha;return a};
  flowjs.flowConnector.prototype.refresh=function(){var a=Math.abs(this.yb-this.ya),b=Math.abs(this.xb-this.xa);a>b&&console.log("warning, too steep");var c={x:this.xa,y:this.ya},b={x:this.xa+(b-a)/2,y:this.ya},a={x:b.x+a,y:this.yb},d={x:this.xb,y:this.yb};void 0===this.lines||void 0==this.dots?(this.lines=[this.generateLine(new createjs.Shape,c,b),this.generateLine(new createjs.Shape,b,a),this.generateLine(new createjs.Shape,a,d)],this.dots=[this.generateDot(new createjs.Shape,b),this.generateDot(new createjs.Shape,
  a)]):(this.generateLine(this.lines[0],c,b),this.generateLine(this.lines[1],b,a),this.generateLine(this.lines[2],a,d),this.generateDot(this.dots[0],b),this.generateDot(this.dots[1],a))};flowjs.flowConnector.prototype.getDrawableItems=function(){return this.lines.concat(this.dots)};flowjs=flowjs||{};flowjs.DiGraph=function(){this._nodes={};this._cacheRankCount={};this._longestPathLength=0};flowjs.DiGraph.prototype.addPaths=function(a){a.forEach(function(a){this._addPath(a)},this);this._refreshMeta()};flowjs.DiGraph.prototype.addPath=function(a){this._addPath(a);this._refreshMeta()};flowjs.DiGraph.prototype.getNodes=function(){return this._nodes};flowjs.DiGraph.prototype.getNode=function(a){return this._nodes[a]};
  flowjs.DiGraph.prototype.getNodesWithRank=function(a){var b=[],c=new flowjs.GraphWalker(this);if(0==this.getRankSize(a))return b;c.forEach(function(c){c.rank==a&&b.push(c)},this);return b};flowjs.DiGraph.prototype.getLongestLength=function(){return this._longestPathLength};flowjs.DiGraph.prototype.getRankSize=function(a){return this._cacheRankCount[a]||0};flowjs.DiGraph.prototype._refreshMeta=function(){this._longestPathLength=this._rankNodes();this._organize();this._cacheRankCount=this._getRankCount()};
  flowjs.DiGraph.prototype._addPath=function(a){var b=void 0;a.forEach(function(a){void 0===this._nodes[a]&&(this._nodes[a]=new flowjs.node(a));a=this._nodes[a];void 0!==b&&b.addNext(a);b=a},this)};
  flowjs.DiGraph.prototype._rankNodes=function(){var a=function(){var a=[],c;for(c in b)0===b[c]&&a.push(c);return a},b={},c;for(c in this._nodes)b[c]=this._nodes[c].getCallCount();var d=0;do c=a(),c.forEach(function(a){a=this.getNode(a);a.rank=d;--b[a.id];a.next.each(function(a){0>b[a]?console.log("strange next item, maybe a loop?",a,b[a]):--b[a]},this)},this),d++;while(0<c.length);return d-1};
  flowjs.DiGraph.prototype._getRankCount=function(){var a={},b;for(b in this._nodes){var c=this._nodes[b];a[c.rank]=a[c.rank]||0;a[c.rank]+=1}return a};
  flowjs.DiGraph.prototype._organize=function(){var a=this,b=function(c){var d;c.next.each(function(b){b=a.getNode(b).rank-c.rank;d=void 0===d?b:Math.min(d,b)},a);if(1>=d)return!1;c.rank+=d-1;c.callers.each(function(c){b(a.getNode(c))},a);return!0};(new flowjs.GraphWalker(this)).forEach(function(a){a.next.each(function(d){1<this.getNode(d).rank-a.rank&&b(a)},this)},this)};flowjs.GraphWalker=function(a){this.graph=a};
  flowjs.GraphWalker.prototype.forEach=function(a,b){var c=this.graph.getNodes(),d;for(d in c){var f=c[d];void 0!==f&&a.call(b,f)}};flowjs.GraphWalker.prototype.iterNext=function(a,b,c){return this._iterNodeProperty(a,b,"next",c)};flowjs.GraphWalker.prototype.iterPrev=function(a,b,c){return this._iterNodeProperty(a,b,"callers",c)};
  flowjs.GraphWalker.prototype._iterNodeProperty=function(a,b,c,d){for(b=b[c]||new flowjs.set;0<b.size();)c=new flowjs.set,b.each(function(b){b=this.graph.getNode(b);a.call(d,b)},this),b=c};flowjs.GraphWalker.prototype.getForefathers=function(a){var b=[];this.iterPrev(function(a){console.log("what is hiding here?",a);0===a.getCallCount()&&b.push(a)},a,this);return b};flowjs.node=function(a,b){this.id=a;this.next=new flowjs.set;this.callers=new flowjs.set;this.rank=0};
  flowjs.node.prototype={getCallCount:function(){return this.callers.size()},addNext:function(a){this.next.add(a.id)&&a._addCaller(this)},_addCaller:function(a){this.callers.add(a.id)}};flowjs.set=function(a){this._hashFunction=a||JSON.stringify;this._values={};this._size=0};
  flowjs.set.prototype={add:function(a){return this.contains(a)?!1:(this._values[this._hashFunction(a)]=a,this._size++,!0)},remove:function(a){this.contains(a)&&(delete this._values[this._hashFunction(a)],this._size--)},contains:function(a){return"undefined"!==typeof this._values[this._hashFunction(a)]},size:function(){return this._size},each:function(a,b){for(var c in this._values)void 0!==this._values[c]&&a.call(b,this._values[c])},append:function(a){a.each(function(a){this.add(a)},this)}};