(function(){function $empty(){}function $extend(original,extended){for(var key in (extended||{})){original[key]=extended[key]}return original}function $lambda(value){return(typeof value=="function")?value:function(){return value}}var $time=Date.now||function(){return +new Date};function $splat(obj){var type=$type(obj);return(type)?((type!="array")?[obj]:obj):[]}var $type=function(elem){return $type.s.call(elem).match(/^\[object\s(.*)\]$/)[1].toLowerCase()};$type.s=Object.prototype.toString;function $each(iterable,fn){var type=$type(iterable);if(type=="object"){for(var key in iterable){fn(iterable[key],key)}}else{for(var i=0;i<iterable.length;i++){fn(iterable[i],i)}}}function $merge(){var mix={};for(var i=0,l=arguments.length;i<l;i++){var object=arguments[i];if($type(object)!="object"){continue}for(var key in object){var op=object[key],mp=mix[key];mix[key]=(mp&&$type(op)=="object"&&$type(mp)=="object")?$merge(mp,op):$unlink(op)}}return mix}function $unlink(object){var unlinked;switch($type(object)){case"object":unlinked={};for(var p in object){unlinked[p]=$unlink(object[p])}break;case"array":unlinked=[];for(var i=0,l=object.length;i<l;i++){unlinked[i]=$unlink(object[i])}break;default:return object}return unlinked}function $rgbToHex(srcArray,array){if(srcArray.length<3){return null}if(srcArray.length==4&&srcArray[3]==0&&!array){return"transparent"}var hex=[];for(var i=0;i<3;i++){var bit=(srcArray[i]-0).toString(16);hex.push((bit.length==1)?"0"+bit:bit)}return(array)?hex:"#"+hex.join("")}function $destroy(elem){$clean(elem);if(elem.parentNode){elem.parentNode.removeChild(elem)}if(elem.clearAttributes){elem.clearAttributes()}}function $clean(elem){for(var ch=elem.childNodes,i=0;i<ch.length;i++){$destroy(ch[i])}}function $addEvent(obj,type,fn){if(obj.addEventListener){obj.addEventListener(type,fn,false)}else{obj.attachEvent("on"+type,fn)}}function $hasClass(obj,klass){return(" "+obj.className+" ").indexOf(" "+klass+" ")>-1}function $addClass(obj,klass){if(!$hasClass(obj,klass)){obj.className=(obj.className+" "+klass)}}function $removeClass(obj,klass){obj.className=obj.className.replace(new RegExp("(^|\\s)"+klass+"(?:\\s|$)"),"$1")}function $get(id){return document.getElementById(id)}var Class=function(properties){properties=properties||{};var klass=function(){this.constructor=klass;if(Class.prototyping){return this}var instance=(this.initialize)?this.initialize.apply(this,arguments):this;return instance};for(var mutator in Class.Mutators){if(!properties[mutator]){continue}properties=Class.Mutators[mutator](properties,properties[mutator]);delete properties[mutator]}$extend(klass,this);klass.constructor=Class;klass.prototype=properties;return klass};Class.Mutators={Extends:function(self,klass){Class.prototyping=klass.prototype;var subclass=new klass;delete subclass.parent;subclass=Class.inherit(subclass,self);delete Class.prototyping;return subclass},Implements:function(self,klasses){$each($splat(klasses),function(klass){Class.prototying=klass;$extend(self,($type(klass)=="function")?new klass:klass);delete Class.prototyping});return self}};$extend(Class,{inherit:function(object,properties){var caller=arguments.callee.caller;for(var key in properties){var override=properties[key];var previous=object[key];var type=$type(override);if(previous&&type=="function"){if(override!=previous){if(caller){override.__parent=previous;object[key]=override}else{Class.override(object,key,override)}}}else{if(type=="object"){object[key]=$merge(previous,override)}else{object[key]=override}}}if(caller){object.parent=function(){return arguments.callee.caller.__parent.apply(this,arguments)}}return object},override:function(object,name,method){var parent=Class.prototyping;if(parent&&object[name]!=parent[name]){parent=null}var override=function(){var previous=this.parent;this.parent=parent?parent[name]:object[name];var value=method.apply(this,arguments);this.parent=previous;return value};object[name]=override}});Class.prototype.implement=function(){var proto=this.prototype;$each(Array.prototype.slice.call(arguments||[]),function(properties){Class.inherit(proto,properties)});return this};this.TreeUtil={prune:function(tree,maxLevel){this.each(tree,function(elem,i){if(i==maxLevel&&elem.children){delete elem.children;elem.children=[]}})},getParent:function(tree,id){if(tree.id==id){return false}var ch=tree.children;if(ch&&ch.length>0){for(var i=0;i<ch.length;i++){if(ch[i].id==id){return tree}else{var ans=this.getParent(ch[i],id);if(ans){return ans}}}}return false},getSubtree:function(tree,id){if(tree.id==id){return tree}for(var i=0,ch=tree.children;i<ch.length;i++){var t=this.getSubtree(ch[i],id);if(t!=null){return t}}return null},getLeaves:function(node,maxLevel){var leaves=[],levelsToShow=maxLevel||Number.MAX_VALUE;this.each(node,function(elem,i){if(i<levelsToShow&&(!elem.children||elem.children.length==0)){leaves.push({node:elem,level:levelsToShow-i})}});return leaves},eachLevel:function(tree,initLevel,toLevel,action){if(initLevel<=toLevel){action(tree,initLevel);for(var i=0,ch=tree.children;i<ch.length;i++){this.eachLevel(ch[i],initLevel+1,toLevel,action)}}},each:function(tree,action){this.eachLevel(tree,0,Number.MAX_VALUE,action)},loadSubtrees:function(tree,controller){var maxLevel=controller.request&&controller.levelsToShow;var leaves=this.getLeaves(tree,maxLevel),len=leaves.length,selectedNode={};if(len==0){controller.onComplete()}for(var i=0,counter=0;i<len;i++){var leaf=leaves[i],id=leaf.node.id;selectedNode[id]=leaf.node;controller.request(id,leaf.level,{onComplete:function(nodeId,tree){var ch=tree.children;selectedNode[nodeId].children=ch;if(++counter==len){controller.onComplete()}}})}}};this.Canvas=(function(){var config={injectInto:"id",width:200,height:200,backgroundColor:"#333333",styles:{fillStyle:"#000000",strokeStyle:"#000000"},backgroundCanvas:false};function hasCanvas(){hasCanvas.t=hasCanvas.t||typeof(HTMLCanvasElement);return"function"==hasCanvas.t||"object"==hasCanvas.t}function create(tag,prop,styles){var elem=document.createElement(tag);(function(obj,prop){if(prop){for(var p in prop){obj[p]=prop[p]}}return arguments.callee})(elem,prop)(elem.style,styles);if(tag=="canvas"&&!hasCanvas()&&G_vmlCanvasManager){elem=G_vmlCanvasManager.initElement(document.body.appendChild(elem))}return elem}function get(id){return document.getElementById(id)}function translateToCenter(canvas,ctx,w,h){var width=w?(canvas.width-w):canvas.width;var height=h?(canvas.height-h):canvas.height;ctx.translate(width/2,height/2)}return function(id,opt){var ctx,bkctx,mainContainer,labelContainer,canvas,bkcanvas;if(arguments.length<1){throw"Arguments missing"}var idLabel=id+"-label",idCanvas=id+"-canvas",idBCanvas=id+"-bkcanvas";opt=$merge(config,opt||{});var dim={width:opt.width,height:opt.height};mainContainer=create("div",{id:id},$merge(dim,{position:"relative"}));labelContainer=create("div",{id:idLabel},{overflow:"visible",position:"absolute",top:0,left:0,width:dim.width+"px",height:0});var dimPos={position:"absolute",top:0,left:0,width:dim.width+"px",height:dim.height+"px"};canvas=create("canvas",$merge({id:idCanvas},dim),dimPos);var bc=opt.backgroundCanvas;if(bc){bkcanvas=create("canvas",$merge({id:idBCanvas},dim),dimPos);mainContainer.appendChild(bkcanvas)}mainContainer.appendChild(canvas);mainContainer.appendChild(labelContainer);get(opt.injectInto).appendChild(mainContainer);ctx=canvas.getContext("2d");translateToCenter(canvas,ctx);var st=opt.styles;var s;for(s in st){ctx[s]=st[s]}if(bc){bkctx=bkcanvas.getContext("2d");st=bc.styles;for(s in st){bkctx[s]=st[s]}translateToCenter(bkcanvas,bkctx);bc.impl.init(bkcanvas,bkctx);bc.impl.plot(bkcanvas,bkctx)}return{id:id,getCtx:function(){return ctx},getElement:function(){return mainContainer},resize:function(width,height){var pwidth=canvas.width,pheight=canvas.height;canvas.width=width;canvas.height=height;canvas.style.width=width+"px";canvas.style.height=height+"px";if(bc){bkcanvas.width=width;bkcanvas.height=height;bkcanvas.style.width=width+"px";bkcanvas.style.height=height+"px"}if(!hasCanvas()){translateToCenter(canvas,ctx,pwidth,pheight)}else{translateToCenter(canvas,ctx)}var st=opt.styles;var s;for(s in st){ctx[s]=st[s]}if(bc){st=bc.styles;for(s in st){bkctx[s]=st[s]}if(!hasCanvas()){translateToCenter(bkcanvas,bkctx,pwidth,pheight)}else{translateToCenter(bkcanvas,bkctx)}bc.impl.init(bkcanvas,bkctx);bc.impl.plot(bkcanvas,bkctx)}},getSize:function(){return{width:canvas.width,height:canvas.height}},path:function(type,action){ctx.beginPath();action(ctx);ctx[type]();ctx.closePath()},clear:function(){var size=this.getSize();ctx.clearRect(-size.width/2,-size.height/2,size.width,size.height)},clearRectangle:function(top,right,bottom,left){if(!hasCanvas()){var f0=ctx.fillStyle;ctx.fillStyle=opt.backgroundColor;ctx.fillRect(left,top,Math.abs(right-left),Math.abs(bottom-top));ctx.fillStyle=f0}else{ctx.clearRect(left,top,Math.abs(right-left),Math.abs(bottom-top))}}}}})();this.Polar=function(theta,rho){this.theta=theta;this.rho=rho};Polar.prototype={getc:function(simple){return this.toComplex(simple)},getp:function(){return this},set:function(v){v=v.getp();this.theta=v.theta;this.rho=v.rho},setc:function(x,y){this.rho=Math.sqrt(x*x+y*y);this.theta=Math.atan2(y,x);if(this.theta<0){this.theta+=Math.PI*2}},setp:function(theta,rho){this.theta=theta;this.rho=rho},clone:function(){return new Polar(this.theta,this.rho)},toComplex:function(simple){var x=Math.cos(this.theta)*this.rho;var y=Math.sin(this.theta)*this.rho;if(simple){return{x:x,y:y}}return new Complex(x,y)},add:function(polar){return new Polar(this.theta+polar.theta,this.rho+polar.rho)},scale:function(number){return new Polar(this.theta,this.rho*number)},equals:function(c){return this.theta==c.theta&&this.rho==c.rho},$add:function(polar){this.theta=this.theta+polar.theta;this.rho+=polar.rho;return this},$madd:function(polar){this.theta=(this.theta+polar.theta)%(Math.PI*2);this.rho+=polar.rho;return this},$scale:function(number){this.rho*=number;return this},interpolate:function(elem,delta){var pi=Math.PI,pi2=pi*2;var ch=function(t){return(t<0)?(t%pi2)+pi2:t%pi2};var tt=this.theta,et=elem.theta;var sum;if(Math.abs(tt-et)>pi){if(tt>et){sum=ch((et+((tt-pi2)-et)*delta))}else{sum=ch((et-pi2+(tt-(et-pi2))*delta))}}else{sum=ch((et+(tt-et)*delta))}var r=(this.rho-elem.rho)*delta+elem.rho;return{theta:sum,rho:r}}};var $P=function(a,b){return new Polar(a,b)};Polar.KER=$P(0,0);this.Complex=function(x,y){this.x=x;this.y=y};Complex.prototype={getc:function(){return this},getp:function(simple){return this.toPolar(simple)},set:function(c){c=c.getc(true);this.x=c.x;this.y=c.y},setc:function(x,y){this.x=x;this.y=y},setp:function(theta,rho){this.x=Math.cos(theta)*rho;this.y=Math.sin(theta)*rho},clone:function(){return new Complex(this.x,this.y)},toPolar:function(simple){var rho=this.norm();var atan=Math.atan2(this.y,this.x);if(atan<0){atan+=Math.PI*2}if(simple){return{theta:atan,rho:rho}}return new Polar(atan,rho)},norm:function(){return Math.sqrt(this.squaredNorm())},squaredNorm:function(){return this.x*this.x+this.y*this.y},add:function(pos){return new Complex(this.x+pos.x,this.y+pos.y)},prod:function(pos){return new Complex(this.x*pos.x-this.y*pos.y,this.y*pos.x+this.x*pos.y)},conjugate:function(){return new Complex(this.x,-this.y)},scale:function(factor){return new Complex(this.x*factor,this.y*factor)},equals:function(c){return this.x==c.x&&this.y==c.y},$add:function(pos){this.x+=pos.x;this.y+=pos.y;return this},$prod:function(pos){var x=this.x,y=this.y;this.x=x*pos.x-y*pos.y;this.y=y*pos.x+x*pos.y;return this},$conjugate:function(){this.y=-this.y;return this},$scale:function(factor){this.x*=factor;this.y*=factor;return this},$div:function(pos){var x=this.x,y=this.y;var sq=pos.squaredNorm();this.x=x*pos.x+y*pos.y;this.y=y*pos.x-x*pos.y;return this.$scale(1/sq)}};var $C=function(a,b){return new Complex(a,b)};Complex.KER=$C(0,0);this.Graph=new Class({initialize:function(opt){var innerOptions={complex:false,Node:{}};this.opt=$merge(innerOptions,opt||{});this.nodes={}},getNode:function(id){if(this.hasNode(id)){return this.nodes[id]}return false},getAdjacence:function(id,id2){var adjs=[];if(this.hasNode(id)&&this.hasNode(id2)&&this.nodes[id].adjacentTo({id:id2})&&this.nodes[id2].adjacentTo({id:id})){adjs.push(this.nodes[id].getAdjacency(id2));adjs.push(this.nodes[id2].getAdjacency(id));return adjs}return false},addNode:function(obj){if(!this.nodes[obj.id]){this.nodes[obj.id]=new Graph.Node($extend({id:obj.id,name:obj.name,data:obj.data},this.opt.Node),this.opt.complex)}return this.nodes[obj.id]},addAdjacence:function(obj,obj2,data){var adjs=[];if(!this.hasNode(obj.id)){this.addNode(obj)}if(!this.hasNode(obj2.id)){this.addNode(obj2)}obj=this.nodes[obj.id];obj2=this.nodes[obj2.id];for(var i in this.nodes){if(this.nodes[i].id==obj.id){if(!this.nodes[i].adjacentTo(obj2)){adjs.push(this.nodes[i].addAdjacency(obj2,data))}}if(this.nodes[i].id==obj2.id){if(!this.nodes[i].adjacentTo(obj)){adjs.push(this.nodes[i].addAdjacency(obj,data))}}}return adjs},removeNode:function(id){if(this.hasNode(id)){var node=this.nodes[id];for(var i=0 in node.adjacencies){var adj=node.adjacencies[i];this.removeAdjacence(id,adj.nodeTo.id)}delete this.nodes[id]}},removeAdjacence:function(id1,id2){if(this.hasNode(id1)){this.nodes[id1].removeAdjacency(id2)}if(this.hasNode(id2)){this.nodes[id2].removeAdjacency(id1)}},hasNode:function(id){return id in this.nodes}});Graph.Node=new Class({initialize:function(opt,complex){var innerOptions={id:"",name:"",data:{},adjacencies:{},selected:false,drawn:false,exist:false,angleSpan:{begin:0,end:0},alpha:1,startAlpha:1,endAlpha:1,pos:(complex&&$C(0,0))||$P(0,0),startPos:(complex&&$C(0,0))||$P(0,0),endPos:(complex&&$C(0,0))||$P(0,0)};$extend(this,$extend(innerOptions,opt))},adjacentTo:function(node){return node.id in this.adjacencies},getAdjacency:function(id){return this.adjacencies[id]},addAdjacency:function(node,data){var adj=new Graph.Adjacence(this,node,data);return this.adjacencies[node.id]=adj},removeAdjacency:function(id){delete this.adjacencies[id]}});Graph.Adjacence=function(nodeFrom,nodeTo,data){this.nodeFrom=nodeFrom;this.nodeTo=nodeTo;this.data=data||{};this.alpha=1;this.startAlpha=1;this.endAlpha=1};Graph.Util={filter:function(param){if(!param||!($type(param)=="string")){return function(){return true}}var props=param.split(" ");return function(elem){for(var i=0;i<props.length;i++){if(elem[props[i]]){return false}}return true}},getNode:function(graph,id){return graph.getNode(id)},eachNode:function(graph,action,flags){var filter=this.filter(flags);for(var i in graph.nodes){if(filter(graph.nodes[i])){action(graph.nodes[i])}}},eachAdjacency:function(node,action,flags){var adj=node.adjacencies,filter=this.filter(flags);for(var id in adj){if(filter(adj[id])){action(adj[id],id)}}},computeLevels:function(graph,id,startDepth,flags){startDepth=startDepth||0;var filter=this.filter(flags);this.eachNode(graph,function(elem){elem._flag=false;elem._depth=-1},flags);var root=graph.getNode(id);root._depth=startDepth;var queue=[root];while(queue.length!=0){var node=queue.pop();node._flag=true;this.eachAdjacency(node,function(adj){var n=adj.nodeTo;if(n._flag==false&&filter(n)){if(n._depth<0){n._depth=node._depth+1+startDepth}queue.unshift(n)}},flags)}},eachBFS:function(graph,id,action,flags){var filter=this.filter(flags);this.clean(graph);var queue=[graph.getNode(id)];while(queue.length!=0){var node=queue.pop();node._flag=true;action(node,node._depth);this.eachAdjacency(node,function(adj){var n=adj.nodeTo;if(n._flag==false&&filter(n)){n._flag=true;queue.unshift(n)}},flags)}},eachLevel:function(node,levelBegin,levelEnd,action,flags){var d=node._depth,filter=this.filter(flags),that=this;levelEnd=levelEnd===false?Number.MAX_VALUE-d:levelEnd;(function loopLevel(node,levelBegin,levelEnd){var d=node._depth;if(d>=levelBegin&&d<=levelEnd&&filter(node)){action(node,d)}if(d<levelEnd){that.eachAdjacency(node,function(adj){var n=adj.nodeTo;if(n._depth>d){loopLevel(n,levelBegin,levelEnd)}})}})(node,levelBegin+d,levelEnd+d)},eachSubgraph:function(node,action,flags){this.eachLevel(node,0,false,action,flags)},eachSubnode:function(node,action,flags){this.eachLevel(node,1,1,action,flags)},anySubnode:function(node,cond,flags){var flag=false;cond=cond||$lambda(true);var c=$type(cond)=="string"?function(n){return n[cond]}:cond;this.eachSubnode(node,function(elem){if(c(elem)){flag=true}},flags);return flag},getSubnodes:function(node,level,flags){var ans=[],that=this;level=level||0;var levelStart,levelEnd;if($type(level)=="array"){levelStart=level[0];levelEnd=level[1]}else{levelStart=level;levelEnd=Number.MAX_VALUE-node._depth}this.eachLevel(node,levelStart,levelEnd,function(n){ans.push(n)},flags);return ans},getParents:function(node){var ans=[];this.eachAdjacency(node,function(adj){var n=adj.nodeTo;if(n._depth<node._depth){ans.push(n)}});return ans},isDescendantOf:function(node,id){if(node.id==id){return true}var pars=this.getParents(node),ans=false;for(var i=0;!ans&&i<pars.length;i++){ans=ans||this.isDescendantOf(pars[i],id)}return ans},clean:function(graph){this.eachNode(graph,function(elem){elem._flag=false})}};Graph.Op={options:{type:"nothing",duration:2000,hideLabels:true,fps:30},removeNode:function(node,opt){var viz=this.viz;var options=$merge(this.options,viz.controller,opt);var n=$splat(node);var i,that,nodeObj;switch(options.type){case"nothing":for(i=0;i<n.length;i++){viz.graph.removeNode(n[i])}break;case"replot":this.removeNode(n,{type:"nothing"});viz.fx.clearLabels();viz.refresh(true);break;case"fade:seq":case"fade":that=this;for(i=0;i<n.length;i++){nodeObj=viz.graph.getNode(n[i]);nodeObj.endAlpha=0}viz.fx.animate($merge(options,{modes:["fade:nodes"],onComplete:function(){that.removeNode(n,{type:"nothing"});viz.fx.clearLabels();viz.reposition();viz.fx.animate($merge(options,{modes:["linear"]}))}}));break;case"fade:con":that=this;for(i=0;i<n.length;i++){nodeObj=viz.graph.getNode(n[i]);nodeObj.endAlpha=0;nodeObj.ignore=true}viz.reposition();viz.fx.animate($merge(options,{modes:["fade:nodes","linear"],onComplete:function(){that.removeNode(n,{type:"nothing"})}}));break;case"iter":that=this;viz.fx.sequence({condition:function(){return n.length!=0},step:function(){that.removeNode(n.shift(),{type:"nothing"});viz.fx.clearLabels()},onComplete:function(){options.onComplete()},duration:Math.ceil(options.duration/n.length)});break;default:this.doError()}},removeEdge:function(vertex,opt){var viz=this.viz;var options=$merge(this.options,viz.controller,opt);var v=($type(vertex[0])=="string")?[vertex]:vertex;var i,that,adjs;switch(options.type){case"nothing":for(i=0;i<v.length;i++){viz.graph.removeAdjacence(v[i][0],v[i][1])}break;case"replot":this.removeEdge(v,{type:"nothing"});viz.refresh(true);break;case"fade:seq":case"fade":that=this;for(i=0;i<v.length;i++){adjs=viz.graph.getAdjacence(v[i][0],v[i][1]);if(adjs){adjs[0].endAlpha=0;adjs[1].endAlpha=0}}viz.fx.animate($merge(options,{modes:["fade:vertex"],onComplete:function(){that.removeEdge(v,{type:"nothing"});viz.reposition();viz.fx.animate($merge(options,{modes:["linear"]}))}}));break;case"fade:con":that=this;for(i=0;i<v.length;i++){adjs=viz.graph.getAdjacence(v[i][0],v[i][1]);if(adjs){adjs[0].endAlpha=0;adjs[0].ignore=true;adjs[1].endAlpha=0;adjs[1].ignore=true}}viz.reposition();viz.fx.animate($merge(options,{modes:["fade:vertex","linear"],onComplete:function(){that.removeEdge(v,{type:"nothing"})}}));break;case"iter":that=this;viz.fx.sequence({condition:function(){return v.length!=0},step:function(){that.removeEdge(v.shift(),{type:"nothing"});viz.fx.clearLabels()},onComplete:function(){options.onComplete()},duration:Math.ceil(options.duration/v.length)});break;default:this.doError()}},sum:function(json,opt){var viz=this.viz;var options=$merge(this.options,viz.controller,opt),root=viz.root;var GUtil,graph;viz.root=opt.id||viz.root;switch(options.type){case"nothing":graph=viz.construct(json);GUtil=Graph.Util;GUtil.eachNode(graph,function(elem){GUtil.eachAdjacency(elem,function(adj){viz.graph.addAdjacence(adj.nodeFrom,adj.nodeTo,adj.data)})});break;case"replot":viz.refresh(true);this.sum(json,{type:"nothing"});viz.refresh(true);break;case"fade:seq":case"fade":case"fade:con":GUtil=Graph.Util;that=this;graph=viz.construct(json);var fadeEdges=this.preprocessSum(graph);var modes=!fadeEdges?["fade:nodes"]:["fade:nodes","fade:vertex"];viz.reposition();if(options.type!="fade:con"){viz.fx.animate($merge(options,{modes:["linear"],onComplete:function(){viz.fx.animate($merge(options,{modes:modes,onComplete:function(){options.onComplete()}}))}}))}else{GUtil.eachNode(viz.graph,function(elem){if(elem.id!=root&&elem.pos.getp().equals(Polar.KER)){elem.pos.set(elem.endPos);elem.startPos.set(elem.endPos)}});viz.fx.animate($merge(options,{modes:["linear"].concat(modes)}))}break;default:this.doError()}},morph:function(json,opt){var viz=this.viz;var options=$merge(this.options,viz.controller,opt),root=viz.root;var GUtil,graph;viz.root=opt.id||viz.root;switch(options.type){case"nothing":graph=viz.construct(json);GUtil=Graph.Util;GUtil.eachNode(graph,function(elem){GUtil.eachAdjacency(elem,function(adj){viz.graph.addAdjacence(adj.nodeFrom,adj.nodeTo,adj.data)})});GUtil.eachNode(viz.graph,function(elem){GUtil.eachAdjacency(elem,function(adj){if(!graph.getAdjacence(adj.nodeFrom.id,adj.nodeTo.id)){viz.graph.removeAdjacence(adj.nodeFrom.id,adj.nodeTo.id)}});if(!graph.hasNode(elem.id)){viz.graph.removeNode(elem.id)}});break;case"replot":viz.fx.clearLabels(true);this.morph(json,{type:"nothing"});viz.refresh(true);viz.refresh(true);break;case"fade:seq":case"fade":case"fade:con":GUtil=Graph.Util;that=this;graph=viz.construct(json);var fadeEdges=this.preprocessSum(graph);GUtil.eachNode(viz.graph,function(elem){if(!graph.hasNode(elem.id)){elem.alpha=1;elem.startAlpha=1;elem.endAlpha=0;elem.ignore=true}});GUtil.eachNode(viz.graph,function(elem){if(elem.ignore){return}GUtil.eachAdjacency(elem,function(adj){if(adj.nodeFrom.ignore||adj.nodeTo.ignore){return}var nodeFrom=graph.getNode(adj.nodeFrom.id);var nodeTo=graph.getNode(adj.nodeTo.id);if(!nodeFrom.adjacentTo(nodeTo)){var adjs=viz.graph.getAdjacence(nodeFrom.id,nodeTo.id);fadeEdges=true;adjs[0].alpha=1;adjs[0].startAlpha=1;adjs[0].endAlpha=0;adjs[0].ignore=true;adjs[1].alpha=1;adjs[1].startAlpha=1;adjs[1].endAlpha=0;adjs[1].ignore=true}})});var modes=!fadeEdges?["fade:nodes"]:["fade:nodes","fade:vertex"];viz.reposition();GUtil.eachNode(viz.graph,function(elem){if(elem.id!=root&&elem.pos.getp().equals(Polar.KER)){elem.pos.set(elem.endPos);elem.startPos.set(elem.endPos)}});viz.fx.animate($merge(options,{modes:["polar"].concat(modes),onComplete:function(){GUtil.eachNode(viz.graph,function(elem){if(elem.ignore){viz.graph.removeNode(elem.id)}});GUtil.eachNode(viz.graph,function(elem){GUtil.eachAdjacency(elem,function(adj){if(adj.ignore){viz.graph.removeAdjacence(adj.nodeFrom.id,adj.nodeTo.id)}})});options.onComplete()}}));break;default:this.doError()}},preprocessSum:function(graph){var viz=this.viz;var GUtil=Graph.Util;GUtil.eachNode(graph,function(elem){if(!viz.graph.hasNode(elem.id)){viz.graph.addNode(elem);var n=viz.graph.getNode(elem.id);n.alpha=0;n.startAlpha=0;n.endAlpha=1}});var fadeEdges=false;GUtil.eachNode(graph,function(elem){GUtil.eachAdjacency(elem,function(adj){var nodeFrom=viz.graph.getNode(adj.nodeFrom.id);var nodeTo=viz.graph.getNode(adj.nodeTo.id);if(!nodeFrom.adjacentTo(nodeTo)){var adjs=viz.graph.addAdjacence(nodeFrom,nodeTo,adj.data);if(nodeFrom.startAlpha==nodeFrom.endAlpha&&nodeTo.startAlpha==nodeTo.endAlpha){fadeEdges=true;adjs[0].alpha=0;adjs[0].startAlpha=0;adjs[0].endAlpha=1;adjs[1].alpha=0;adjs[1].startAlpha=0;adjs[1].endAlpha=1}}})});return fadeEdges}};Graph.Plot={Interpolator:{moebius:function(elem,delta,vector){if(delta<=1||vector.norm()<=1){var x=vector.x,y=vector.y;var ans=elem.startPos.getc().moebiusTransformation(vector);elem.pos.setc(ans.x,ans.y);vector.x=x;vector.y=y}},linear:function(elem,delta){var from=elem.startPos.getc(true);var to=elem.endPos.getc(true);elem.pos.setc((to.x-from.x)*delta+from.x,(to.y-from.y)*delta+from.y)},"fade:nodes":function(elem,delta){if(delta<=1&&(elem.endAlpha!=elem.alpha)){var from=elem.startAlpha;var to=elem.endAlpha;elem.alpha=from+(to-from)*delta}},"fade:vertex":function(elem,delta){var adjs=elem.adjacencies;for(var id in adjs){this["fade:nodes"](adjs[id],delta)}},polar:function(elem,delta){var from=elem.startPos.getp(true);var to=elem.endPos.getp();var ans=to.interpolate(from,delta);elem.pos.setp(ans.theta,ans.rho)}},labelsHidden:false,labelContainer:false,labels:{},getLabelContainer:function(){return this.labelContainer?this.labelContainer:this.labelContainer=document.getElementById(this.viz.config.labelContainer)},getLabel:function(id){return(id in this.labels&&this.labels[id]!=null)?this.labels[id]:this.labels[id]=document.getElementById(id)},hideLabels:function(hide){var container=this.getLabelContainer();if(hide){container.style.display="none"}else{container.style.display=""}this.labelsHidden=hide},clearLabels:function(force){for(var id in this.labels){if(force||!this.viz.graph.hasNode(id)){this.disposeLabel(id);delete this.labels[id]}}},disposeLabel:function(id){var elem=this.getLabel(id);if(elem&&elem.parentNode){elem.parentNode.removeChild(elem)}},hideLabel:function(node,flag){node=$splat(node);var st=flag?"":"none",lab,that=this;$each(node,function(n){var lab=that.getLabel(n.id);if(lab){lab.style.display=st}})},sequence:function(options){var that=this;options=$merge({condition:$lambda(false),step:$empty,onComplete:$empty,duration:200},options||{});var interval=setInterval(function(){if(options.condition()){options.step()}else{clearInterval(interval);options.onComplete()}that.viz.refresh(true)},options.duration)},animate:function(opt,versor){var that=this,viz=this.viz,graph=viz.graph,GUtil=Graph.Util;opt=$merge(viz.controller,opt||{});if(opt.hideLabels){this.hideLabels(true)}this.animation.setOptions($merge(opt,{$animating:false,compute:function(delta){var vector=versor?versor.scale(-delta):null;GUtil.eachNode(graph,function(node){for(var i=0;i<opt.modes.length;i++){that.Interpolator[opt.modes[i]](node,delta,vector)}});that.plot(opt,this.$animating);this.$animating=true},complete:function(){GUtil.eachNode(graph,function(node){node.startPos.set(node.pos);node.startAlpha=node.alpha});if(opt.hideLabels){that.hideLabels(false)}that.plot(opt);opt.onComplete();opt.onAfterCompute()}})).start()},plot:function(opt,animating){var viz=this.viz,aGraph=viz.graph,canvas=viz.canvas,id=viz.root,that=this,ctx=canvas.getCtx(),GUtil=Graph.Util;opt=opt||this.viz.controller;opt.clearCanvas&&canvas.clear();var T=!!aGraph.getNode(id).visited;GUtil.eachNode(aGraph,function(node){GUtil.eachAdjacency(node,function(adj){var nodeTo=adj.nodeTo;if(!!nodeTo.visited===T&&node.drawn&&nodeTo.drawn){!animating&&opt.onBeforePlotLine(adj);ctx.save();ctx.globalAlpha=Math.min(Math.min(node.alpha,nodeTo.alpha),adj.alpha);that.plotLine(adj,canvas,animating);ctx.restore();!animating&&opt.onAfterPlotLine(adj)}});ctx.save();if(node.drawn){ctx.globalAlpha=node.alpha;!animating&&opt.onBeforePlotNode(node);that.plotNode(node,canvas,animating);!animating&&opt.onAfterPlotNode(node)}if(!that.labelsHidden&&opt.withLabels){if(node.drawn&&ctx.globalAlpha>=0.95){that.plotLabel(canvas,node,opt)}else{that.hideLabel(node,false)}}ctx.restore();node.visited=!T})},plotLabel:function(canvas,node,controller){var id=node.id,tag=this.getLabel(id);if(!tag&&!(tag=document.getElementById(id))){tag=document.createElement("div");var container=this.getLabelContainer();container.appendChild(tag);tag.id=id;tag.className="node";tag.style.position="absolute";controller.onCreateLabel(tag,node);this.labels[node.id]=tag}this.placeLabel(tag,node,controller)},plotNode:function(node,canvas,animating){var nconfig=this.node,data=node.data;var cond=nconfig.overridable&&data;var width=cond&&data.$lineWidth||nconfig.lineWidth;var color=cond&&data.$color||nconfig.color;var ctx=canvas.getCtx();ctx.lineWidth=width;ctx.fillStyle=color;ctx.strokeStyle=color;var f=node.data&&node.data.$type||nconfig.type;this.nodeTypes[f].call(this,node,canvas,animating)},plotLine:function(adj,canvas,animating){var econfig=this.edge,data=adj.data;var cond=econfig.overridable&&data;var width=cond&&data.$lineWidth||econfig.lineWidth;var color=cond&&data.$color||econfig.color;var ctx=canvas.getCtx();ctx.lineWidth=width;ctx.fillStyle=color;ctx.strokeStyle=color;var f=adj.data&&adj.data.$type||econfig.type;this.edgeTypes[f].call(this,adj,canvas,animating)},fitsInCanvas:function(pos,canvas){var size=canvas.getSize();if(pos.x>=size.width||pos.x<0||pos.y>=size.height||pos.y<0){return false}return true}};var Loader={construct:function(json){var isGraph=($type(json)=="array");var ans=new Graph(this.graphOptions);if(!isGraph){(function(ans,json){ans.addNode(json);for(var i=0,ch=json.children;i<ch.length;i++){ans.addAdjacence(json,ch[i]);arguments.callee(ans,ch[i])}})(ans,json)}else{(function(ans,json){var getNode=function(id){for(var w=0;w<json.length;w++){if(json[w].id==id){return json[w]}}return undefined};for(var i=0;i<json.length;i++){ans.addNode(json[i]);for(var j=0,adj=json[i].adjacencies;j<adj.length;j++){var node=adj[j],data;if(typeof adj[j]!="string"){data=node.data;node=node.nodeTo}ans.addAdjacence(json[i],getNode(node),data)}}})(ans,json)}return ans},loadJSON:function(json,rootKnoten){this.json=json;this.graph=this.construct(json);if($type(json)!="array"){this.root=json.id}else{this.root=rootKnoten}}};this.Trans={linear:function(p){return p}};(function(){var makeTrans=function(transition,params){params=$splat(params);return $extend(transition,{easeIn:function(pos){return transition(pos,params)},easeOut:function(pos){return 1-transition(1-pos,params)},easeInOut:function(pos){return(pos<=0.5)?transition(2*pos,params)/2:(2-transition(2*(1-pos),params))/2}})};var transitions={Pow:function(p,x){return Math.pow(p,x[0]||6)},Expo:function(p){return Math.pow(2,8*(p-1))},Circ:function(p){return 1-Math.sin(Math.acos(p))},Sine:function(p){return 1-Math.sin((1-p)*Math.PI/2)},Back:function(p,x){x=x[0]||1.618;return Math.pow(p,2)*((x+1)*p-x)},Bounce:function(p){var value;for(var a=0,b=1;1;a+=b,b/=2){if(p>=(7-4*a)/11){value=b*b-Math.pow((11-6*a-11*p)/4,2);break}}return value},Elastic:function(p,x){return Math.pow(2,10*--p)*Math.cos(20*p*Math.PI*(x[0]||1)/3)}};$each(transitions,function(val,key){Trans[key]=makeTrans(val)});$each(["Quad","Cubic","Quart","Quint"],function(elem,i){Trans[elem]=makeTrans(function(p){return Math.pow(p,[i+2])})})})();var Animation=new Class({initalize:function(options){this.setOptions(options)},setOptions:function(options){var opt={duration:2500,fps:40,transition:Trans.Quart.easeInOut,compute:$empty,complete:$empty};this.opt=$merge(opt,options||{});return this},getTime:function(){return $time()},step:function(){var time=this.getTime(),opt=this.opt;if(time<this.time+opt.duration){var delta=opt.transition((time-this.time)/opt.duration);opt.compute(delta)}else{this.timer=clearInterval(this.timer);opt.compute(1);opt.complete()}},start:function(){this.time=0;this.startTimer();return this},startTimer:function(){var that=this,opt=this.opt;if(this.timer){return false}this.time=this.getTime()-this.time;this.timer=setInterval((function(){that.step()}),Math.round(1000/opt.fps));return true}});(function(){var slice=Array.prototype.slice;function getBoundaries(graph,config,level,orn){var dim=config.Node,GUtil=Graph.Util;var multitree=config.multitree;if(dim.overridable){var w=-1,h=-1;GUtil.eachNode(graph,function(n){if(n._depth==level&&(!multitree||("$orn" in n.data)&&n.data.$orn==orn)){var dw=n.data.$width||dim.width;var dh=n.data.$height||dim.height;w=(w<dw)?dw:w;h=(h<dh)?dh:h}});return{width:w<0?dim.width:w,height:h<0?dim.height:h}}else{return dim}}function movetree(node,prop,val,orn){var p=(orn=="left"||orn=="right")?"y":"x";node[prop][p]+=val}function moveextent(extent,val){var ans=[];$each(extent,function(elem){elem=slice.call(elem);elem[0]+=val;elem[1]+=val;ans.push(elem)});return ans}function merge(ps,qs){if(ps.length==0){return qs}if(qs.length==0){return ps}var p=ps.shift(),q=qs.shift();return[[p[0],q[1]]].concat(merge(ps,qs))}function mergelist(ls,def){def=def||[];if(ls.length==0){return def}var ps=ls.pop();return mergelist(ls,merge(ps,def))}function fit(ext1,ext2,subtreeOffset,siblingOffset,i){if(ext1.length<=i||ext2.length<=i){return 0}var p=ext1[i][1],q=ext2[i][0];return Math.max(fit(ext1,ext2,subtreeOffset,siblingOffset,++i)+subtreeOffset,p-q+siblingOffset)}function fitlistl(es,subtreeOffset,siblingOffset){function $fitlistl(acc,es,i){if(es.length<=i){return[]}var e=es[i],ans=fit(acc,e,subtreeOffset,siblingOffset,0);return[ans].concat($fitlistl(merge(acc,moveextent(e,ans)),es,++i))}return $fitlistl([],es,0)}function fitlistr(es,subtreeOffset,siblingOffset){function $fitlistr(acc,es,i){if(es.length<=i){return[]}var e=es[i],ans=-fit(e,acc,subtreeOffset,siblingOffset,0);return[ans].concat($fitlistr(merge(moveextent(e,ans),acc),es,++i))}es=slice.call(es);var ans=$fitlistr([],es.reverse(),0);return ans.reverse()}function fitlist(es,subtreeOffset,siblingOffset,align){var esl=fitlistl(es,subtreeOffset,siblingOffset),esr=fitlistr(es,subtreeOffset,siblingOffset);if(align=="left"){esr=esl}else{if(align=="right"){esl=esr}}for(var i=0,ans=[];i<esl.length;i++){ans[i]=(esl[i]+esr[i])/2}return ans}function design(graph,node,prop,config,orn){var multitree=config.multitree;var auxp=["x","y"],auxs=["width","height"];var ind=+(orn=="left"||orn=="right");var p=auxp[ind],notp=auxp[1-ind];var cnode=config.Node;var s=auxs[ind],nots=auxs[1-ind];var siblingOffset=config.siblingOffset;var subtreeOffset=config.subtreeOffset;var align=config.align;var GUtil=Graph.Util;function $design(node,maxsize,acum){var sval=(cnode.overridable&&node.data["$"+s])||cnode[s];var notsval=maxsize||((cnode.overridable&&node.data["$"+nots])||cnode[nots]);var trees=[],extents=[],chmaxsize=false;var chacum=notsval+config.levelDistance;GUtil.eachSubnode(node,function(n){if(n.exist&&(!multitree||("$orn" in n.data)&&n.data.$orn==orn)){if(!chmaxsize){chmaxsize=getBoundaries(graph,config,n._depth,orn)}var s=$design(n,chmaxsize[nots],acum+chacum);trees.push(s.tree);extents.push(s.extent)}});var positions=fitlist(extents,subtreeOffset,siblingOffset,align);for(var i=0,ptrees=[],pextents=[];i<trees.length;i++){movetree(trees[i],prop,positions[i],orn);pextents.push(moveextent(extents[i],positions[i]))}var resultextent=[[-sval/2,sval/2]].concat(mergelist(pextents));node[prop][p]=0;if(orn=="top"||orn=="left"){node[prop][notp]=acum}else{node[prop][notp]=-acum}return{tree:node,extent:resultextent}}$design(node,false,0)}this.ST=(function(){var nodesInPath=[];function getNodesToHide(node){node=node||this.clickedNode;var Geom=this.geom,GUtil=Graph.Util;var graph=this.graph;var canvas=this.canvas;var level=node._depth,nodeArray=[];GUtil.eachNode(graph,function(n){if(n.exist&&!n.selected){if(GUtil.isDescendantOf(n,node.id)){if(n._depth<=level){nodeArray.push(n)}}else{nodeArray.push(n)}}});var leafLevel=Geom.getRightLevelToShow(node,canvas);GUtil.eachLevel(node,leafLevel,leafLevel,function(n){if(n.exist&&!n.selected){nodeArray.push(n)}});for(var i=0;i<nodesInPath.length;i++){var n=this.graph.getNode(nodesInPath[i]);if(!GUtil.isDescendantOf(n,node.id)){nodeArray.push(n)}}return nodeArray}function getNodesToShow(node){var nodeArray=[],GUtil=Graph.Util,config=this.config;node=node||this.clickedNode;GUtil.eachLevel(this.clickedNode,0,config.levelsToShow,function(n){if(config.multitree&&!("$orn" in n.data)&&GUtil.anySubnode(n,function(ch){return ch.exist&&!ch.drawn})){nodeArray.push(n)}else{if(n.drawn&&!GUtil.anySubnode(n,"drawn")){nodeArray.push(n)}}});return nodeArray}return new Class({Implements:Loader,initialize:function(canvas,controller){var innerController={onBeforeCompute:$empty,onAfterCompute:$empty,onCreateLabel:$empty,onPlaceLabel:$empty,onComplete:$empty,onBeforePlotNode:$empty,onAfterPlotNode:$empty,onBeforePlotLine:$empty,onAfterPlotLine:$empty,request:false};var config={orientation:"left",labelContainer:canvas.id+"-label",levelsToShow:2,subtreeOffset:8,siblingOffset:5,levelDistance:30,withLabels:true,clearCanvas:true,align:"center",indent:10,multitree:false,constrained:true,Node:{overridable:false,type:"rectangle",color:"#ccb",lineWidth:1,height:20,width:90,dim:15,align:"center"},Edge:{overridable:false,type:"line",color:"#ccc",dim:15,lineWidth:1},duration:700,fps:25,transition:Trans.Quart.easeInOut};this.controller=this.config=$merge(config,innerController,controller);this.canvas=canvas;this.graphOptions={complex:true};this.graph=new Graph(this.graphOptions);this.fx=new ST.Plot(this);this.op=new ST.Op(this);this.group=new ST.Group(this);this.geom=new ST.Geom(this);this.clickedNode=null},plot:function(){this.fx.plot(this.controller)},switchPosition:function(pos,method,onComplete){var Geom=this.geom,Plot=this.fx,that=this;if(!Plot.busy){Plot.busy=true;this.contract({onComplete:function(){Geom.switchOrientation(pos);that.compute("endPos",false);Plot.busy=false;if(method=="animate"){that.onClick(that.clickedNode.id,onComplete)}else{if(method=="replot"){that.select(that.clickedNode.id,onComplete)}}}},pos)}},switchAlignment:function(align,method,onComplete){this.config.align=align;if(method=="animate"){this.select(this.clickedNode.id,onComplete)}else{if(method=="replot"){this.onClick(this.clickedNode.id,onComplete)}}},addNodeInPath:function(id){nodesInPath.push(id);this.select((this.clickedNode&&this.clickedNode.id)||this.root)},clearNodesInPath:function(id){nodesInPath.length=0;this.select((this.clickedNode&&this.clickedNode.id)||this.root)},refresh:function(){this.reposition();this.select((this.clickedNode&&this.clickedNode.id)||this.root)},reposition:function(){Graph.Util.computeLevels(this.graph,this.root,0,"ignore");this.geom.setRightLevelToShow(this.clickedNode,this.canvas);Graph.Util.eachNode(this.graph,function(n){if(n.exist){n.drawn=true}});this.compute("endPos")},compute:function(property,computeLevels){var prop=property||"startPos";var node=this.graph.getNode(this.root);$extend(node,{drawn:true,exist:true,selected:true});if(!!computeLevels||!("_depth" in node)){Graph.Util.computeLevels(this.graph,this.root,0,"ignore")}this.computePositions(node,prop)},computePositions:function(node,prop){var config=this.config;var multitree=config.multitree;var align=config.align;var indent=align!=="center"&&config.indent;var orn=config.orientation;var orns=multitree?["top","right","bottom","left"]:[orn];var that=this;$each(orns,function(orn){design(that.graph,node,prop,that.config,orn);var i=["x","y"][+(orn=="left"||orn=="right")];(function red(node){Graph.Util.eachSubnode(node,function(n){if(n.exist&&(!multitree||("$orn" in n.data)&&n.data.$orn==orn)){n[prop][i]+=node[prop][i];if(indent){n[prop][i]+=align=="left"?indent:-indent}red(n)}})})(node)})},requestNodes:function(node,onComplete){var handler=$merge(this.controller,onComplete),lev=this.config.levelsToShow,GUtil=Graph.Util;if(handler.request){var leaves=[],d=node._depth;GUtil.eachLevel(node,0,lev,function(n){if(n.drawn&&!GUtil.anySubnode(n)){leaves.push(n);n._level=lev-(n._depth-d)}});this.group.requestNodes(leaves,handler)}else{handler.onComplete()}},contract:function(onComplete,switched){var orn=this.config.orientation;var Geom=this.geom,Group=this.group;if(switched){Geom.switchOrientation(switched)}var nodes=getNodesToHide.call(this);if(switched){Geom.switchOrientation(orn)}Group.contract(nodes,$merge(this.controller,onComplete))},move:function(node,onComplete){this.compute("endPos",false);var move=onComplete.Move,offset={x:move.offsetX,y:move.offsetY};if(move.enable){this.geom.translate(node.endPos.add(offset).$scale(-1),"endPos")}this.fx.animate($merge(this.controller,{modes:["linear"]},onComplete))},expand:function(node,onComplete){var nodeArray=getNodesToShow.call(this,node);this.group.expand(nodeArray,$merge(this.controller,onComplete))},selectPath:function(node){var GUtil=Graph.Util,that=this;GUtil.eachNode(this.graph,function(n){n.selected=false});function path(node){if(node==null||node.selected){return}node.selected=true;$each(that.group.getSiblings([node])[node.id],function(n){n.exist=true;n.drawn=true});var parents=GUtil.getParents(node);parents=(parents.length>0)?parents[0]:null;path(parents)}for(var i=0,ns=[node.id].concat(nodesInPath);i<ns.length;i++){path(this.graph.getNode(ns[i]))}},setRoot:function(id,method,onComplete){var that=this,canvas=this.canvas;var rootNode=this.graph.getNode(this.root);var clickedNode=this.graph.getNode(id);function $setRoot(){if(this.config.multitree&&clickedNode.data.$orn){var orn=clickedNode.data.$orn;var opp={left:"right",right:"left",top:"bottom",bottom:"top"}[orn];rootNode.data.$orn=opp;(function tag(rootNode){Graph.Util.eachSubnode(rootNode,function(n){if(n.id!=id){n.data.$orn=opp;tag(n)}})})(rootNode);delete clickedNode.data.$orn}this.root=id;this.clickedNode=clickedNode;Graph.Util.computeLevels(this.graph,this.root,0,"ignore")}delete rootNode.data.$orns;if(method=="animate"){this.onClick(id,{onBeforeMove:function(){$setRoot.call(that);that.selectPath(clickedNode)}})}else{if(method=="replot"){$setRoot.call(this);this.select(this.root)}}},addSubtree:function(subtree,method,onComplete){if(method=="replot"){this.op.sum(subtree,$extend({type:"replot"},onComplete||{}))}else{if(method=="animate"){this.op.sum(subtree,$extend({type:"fade:seq"},onComplete||{}))}}},removeSubtree:function(id,removeRoot,method,onComplete){var node=this.graph.getNode(id),subids=[];Graph.Util.eachLevel(node,+!removeRoot,false,function(n){subids.push(n.id)});if(method=="replot"){this.op.removeNode(subids,$extend({type:"replot"},onComplete||{}))}else{if(method=="animate"){this.op.removeNode(subids,$extend({type:"fade:seq"},onComplete||{}))}}},select:function(id,onComplete){var group=this.group,geom=this.geom;var node=this.graph.getNode(id),canvas=this.canvas;var root=this.graph.getNode(this.root);var complete=$merge(this.controller,onComplete);var that=this;complete.onBeforeCompute(node);this.selectPath(node);this.clickedNode=node;this.requestNodes(node,{onComplete:function(){group.hide(group.prepare(getNodesToHide.call(that)),complete);geom.setRightLevelToShow(node,canvas);that.compute("pos");Graph.Util.eachNode(that.graph,function(n){var pos=n.pos.getc(true);n.startPos.setc(pos.x,pos.y);n.endPos.setc(pos.x,pos.y);n.visited=false});that.geom.translate(node.endPos.scale(-1),["pos","startPos","endPos"]);group.show(getNodesToShow.call(that));that.plot();complete.onAfterCompute(that.clickedNode);complete.onComplete()}})},onClick:function(id,options){var canvas=this.canvas,that=this,Fx=this.fx,Util=Graph.Util,Geom=this.geom;var innerController={Move:{enable:true,offsetX:0,offsetY:0},onBeforeRequest:$empty,onBeforeContract:$empty,onBeforeMove:$empty,onBeforeExpand:$empty};var complete=$merge(this.controller,innerController,options);if(!this.busy){this.busy=true;var node=this.graph.getNode(id);this.selectPath(node,this.clickedNode);this.clickedNode=node;complete.onBeforeCompute(node);complete.onBeforeRequest(node);this.requestNodes(node,{onComplete:function(){complete.onBeforeContract(node);that.contract({onComplete:function(){Geom.setRightLevelToShow(node,canvas);complete.onBeforeMove(node);that.move(node,{Move:complete.Move,onComplete:function(){complete.onBeforeExpand(node);that.expand(node,{onComplete:function(){that.busy=false;complete.onAfterCompute(id);complete.onComplete()}})}})}})}})}}})})();ST.Op=new Class({Implements:Graph.Op,initialize:function(viz){this.viz=viz}});ST.Group=new Class({initialize:function(viz){this.viz=viz;this.canvas=viz.canvas;this.config=viz.config;this.animation=new Animation;this.nodes=null},requestNodes:function(nodes,controller){var counter=0,len=nodes.length,nodeSelected={};var complete=function(){controller.onComplete()};var viz=this.viz;if(len==0){complete()}for(var i=0;i<len;i++){nodeSelected[nodes[i].id]=nodes[i];controller.request(nodes[i].id,nodes[i]._level,{onComplete:function(nodeId,data){if(data&&data.children){data.id=nodeId;viz.op.sum(data,{type:"nothing"})}if(++counter==len){Graph.Util.computeLevels(viz.graph,viz.root,0);complete()}}})}},contract:function(nodes,controller){var GUtil=Graph.Util;var viz=this.viz;var that=this;nodes=this.prepare(nodes);this.animation.setOptions($merge(controller,{$animating:false,compute:function(delta){if(delta==1){delta=0.99}that.plotStep(1-delta,controller,this.$animating);this.$animating="contract"},complete:function(){that.hide(nodes,controller)}})).start()},hide:function(nodes,controller){var GUtil=Graph.Util,viz=this.viz;for(var i=0;i<nodes.length;i++){if(true||!controller||!controller.request){GUtil.eachLevel(nodes[i],1,false,function(elem){if(elem.exist){$extend(elem,{drawn:false,exist:false})}})}else{var ids=[];GUtil.eachLevel(nodes[i],1,false,function(n){ids.push(n.id)});viz.op.removeNode(ids,{type:"nothing"});viz.fx.clearLabels()}}controller.onComplete()},expand:function(nodes,controller){var that=this,GUtil=Graph.Util;this.show(nodes);this.animation.setOptions($merge(controller,{$animating:false,compute:function(delta){that.plotStep(delta,controller,this.$animating);this.$animating="expand"},complete:function(){that.plotStep(undefined,controller,false);controller.onComplete()}})).start()},show:function(nodes){var GUtil=Graph.Util,config=this.config;this.prepare(nodes);$each(nodes,function(n){if(config.multitree&&!("$orn" in n.data)){delete n.data.$orns;var orns=" ";GUtil.eachSubnode(n,function(ch){if(("$orn" in ch.data)&&orns.indexOf(ch.data.$orn)<0&&ch.exist&&!ch.drawn){orns+=ch.data.$orn+" "}});n.data.$orns=orns}GUtil.eachLevel(n,0,config.levelsToShow,function(n){if(n.exist){n.drawn=true}})})},prepare:function(nodes){this.nodes=this.getNodesWithChildren(nodes);return this.nodes},getNodesWithChildren:function(nodes){var ans=[],GUtil=Graph.Util,config=this.config,root=this.viz.root;nodes.sort(function(a,b){return(a._depth<=b._depth)-(a._depth>=b._depth)});for(var i=0;i<nodes.length;i++){if(GUtil.anySubnode(nodes[i],"exist")){for(var j=i+1,desc=false;!desc&&j<nodes.length;j++){if(!config.multitree||"$orn" in nodes[j].data){desc=desc||GUtil.isDescendantOf(nodes[i],nodes[j].id)}}if(!desc){ans.push(nodes[i])}}}return ans},plotStep:function(delta,controller,animating){var viz=this.viz,config=this.config,canvas=viz.canvas,ctx=canvas.getCtx(),nodes=this.nodes,GUtil=Graph.Util;var i,node;var nds={};for(i=0;i<nodes.length;i++){node=nodes[i];nds[node.id]=[];var root=config.multitree&&!("$orn" in node.data);var orns=root&&node.data.$orns;GUtil.eachSubgraph(node,function(n){if(root&&orns&&orns.indexOf(n.data.$orn)>0&&n.drawn){n.drawn=false;nds[node.id].push(n)}else{if((!root||!orns)&&n.drawn){n.drawn=false;nds[node.id].push(n)}}});node.drawn=true}if(nodes.length>0){viz.fx.plot()}for(i in nds){$each(nds[i],function(n){n.drawn=true})}for(i=0;i<nodes.length;i++){node=nodes[i];ctx.save();viz.fx.plotSubtree(node,controller,delta,animating);ctx.restore()}},getSiblings:function(nodes){var siblings={},GUtil=Graph.Util;$each(nodes,function(n){var par=GUtil.getParents(n);if(par.length==0){siblings[n.id]=[n]}else{var ans=[];GUtil.eachSubnode(par[0],function(sn){ans.push(sn)});siblings[n.id]=ans}});return siblings}});ST.Geom=new Class({initialize:function(viz){this.viz=viz;this.config=viz.config;this.node=viz.config.Node;this.edge=viz.config.Edge},translate:function(pos,prop){prop=$splat(prop);Graph.Util.eachNode(this.viz.graph,function(elem){$each(prop,function(p){elem[p].$add(pos)})})},switchOrientation:function(orn){this.config.orientation=orn},dispatch:function(){var args=Array.prototype.slice.call(arguments);var s=args.shift(),len=args.length;var val=function(a){return typeof a=="function"?a():a};if(len==2){return(s=="top"||s=="bottom")?val(args[0]):val(args[1])}else{if(len==4){switch(s){case"top":return val(args[0]);case"right":return val(args[1]);case"bottom":return val(args[2]);case"left":return val(args[3])}}}return undefined},getSize:function(n,invert){var node=this.node,data=n.data,config=this.config;var cond=node.overridable,siblingOffset=config.siblingOffset;var s=(this.config.multitree&&("$orn" in n.data)&&n.data.$orn)||this.config.orientation;var w=(cond&&data.$width||node.width)+siblingOffset;var h=(cond&&data.$height||node.height)+siblingOffset;if(!invert){return this.dispatch(s,h,w)}else{return this.dispatch(s,w,h)}},getTreeBaseSize:function(node,level,leaf){var size=this.getSize(node,true),baseHeight=0,that=this;if(leaf(level,node)){return size}if(level===0){return 0}Graph.Util.eachSubnode(node,function(elem){baseHeight+=that.getTreeBaseSize(elem,level-1,leaf)});return(size>baseHeight?size:baseHeight)+this.config.subtreeOffset},getEdge:function(node,type,s){var $C=function(a,b){return function(){return node.pos.add(new Complex(a,b))}};var dim=this.node;var cond=this.node.overridable,data=node.data;var w=cond&&data.$width||dim.width;var h=cond&&data.$height||dim.height;if(type=="begin"){if(dim.align=="center"){return this.dispatch(s,$C(0,h/2),$C(-w/2,0),$C(0,-h/2),$C(w/2,0))}else{if(dim.align=="left"){return this.dispatch(s,$C(0,h),$C(0,0),$C(0,0),$C(w,0))}else{if(dim.align=="right"){return this.dispatch(s,$C(0,0),$C(-w,0),$C(0,-h),$C(0,0))}else{throw"align: not implemented"}}}}else{if(type=="end"){if(dim.align=="center"){return this.dispatch(s,$C(0,-h/2),$C(w/2,0),$C(0,h/2),$C(-w/2,0))}else{if(dim.align=="left"){return this.dispatch(s,$C(0,0),$C(w,0),$C(0,h),$C(0,0))}else{if(dim.align=="right"){return this.dispatch(s,$C(0,-h),$C(0,0),$C(0,0),$C(-w,0))}else{throw"align: not implemented"}}}}}},getScaledTreePosition:function(node,scale){var dim=this.node;var cond=this.node.overridable,data=node.data;var w=(cond&&data.$width||dim.width);var h=(cond&&data.$height||dim.height);var s=(this.config.multitree&&("$orn" in node.data)&&node.data.$orn)||this.config.orientation;var $C=function(a,b){return function(){return node.pos.add(new Complex(a,b)).$scale(1-scale)}};if(dim.align=="left"){return this.dispatch(s,$C(0,h),$C(0,0),$C(0,0),$C(w,0))}else{if(dim.align=="center"){return this.dispatch(s,$C(0,h/2),$C(-w/2,0),$C(0,-h/2),$C(w/2,0))}else{if(dim.align=="right"){return this.dispatch(s,$C(0,0),$C(-w,0),$C(0,-h),$C(0,0))}else{throw"align: not implemented"}}}},treeFitsInCanvas:function(node,canvas,level){var csize=canvas.getSize(node);var s=(this.config.multitree&&("$orn" in node.data)&&node.data.$orn)||this.config.orientation;var size=this.dispatch(s,csize.width,csize.height);var baseSize=this.getTreeBaseSize(node,level,function(level,node){return level===0||!Graph.Util.anySubnode(node)});return(baseSize<size)},setRightLevelToShow:function(node,canvas){var level=this.getRightLevelToShow(node,canvas),fx=this.viz.fx;Graph.Util.eachLevel(node,0,this.config.levelsToShow,function(n){var d=n._depth-node._depth;if(d>level){n.drawn=false;n.exist=false;fx.hideLabel(n,false)}else{n.exist=true}});node.drawn=true},getRightLevelToShow:function(node,canvas){var config=this.config;var level=config.levelsToShow;var constrained=config.constrained;if(!constrained){return level}while(!this.treeFitsInCanvas(node,canvas,level)&&level>1){level--}return level}});ST.Plot=new Class({Implements:Graph.Plot,initialize:function(viz){this.viz=viz;this.config=viz.config;this.node=this.config.Node;this.edge=this.config.Edge;this.animation=new Animation;this.nodeTypes=new ST.Plot.NodeTypes;this.edgeTypes=new ST.Plot.EdgeTypes},plotSubtree:function(node,opt,scale,animating){var viz=this.viz,canvas=viz.canvas;scale=Math.min(Math.max(0.001,scale),1);if(scale>=0){node.drawn=false;var ctx=canvas.getCtx();var diff=viz.geom.getScaledTreePosition(node,scale);ctx.translate(diff.x,diff.y);ctx.scale(scale,scale)}this.plotTree(node,!scale,opt,animating);if(scale>=0){node.drawn=true}},plotTree:function(node,plotLabel,opt,animating){var that=this,viz=this.viz,canvas=viz.canvas,config=this.config,ctx=canvas.getCtx();var root=config.multitree&&!("$orn" in node.data);var orns=root&&node.data.$orns;Graph.Util.eachSubnode(node,function(elem){if((!root||orns.indexOf(elem.data.$orn)>0)&&elem.exist&&elem.drawn){var adj=node.getAdjacency(elem.id);!animating&&opt.onBeforePlotLine(adj);ctx.globalAlpha=Math.min(node.alpha,elem.alpha);that.plotLine(adj,canvas,animating);!animating&&opt.onAfterPlotLine(adj);that.plotTree(elem,plotLabel,opt,animating)}});if(node.drawn){ctx.globalAlpha=node.alpha;!animating&&opt.onBeforePlotNode(node);this.plotNode(node,canvas,animating);!animating&&opt.onAfterPlotNode(node);if(plotLabel&&ctx.globalAlpha>=0.95){this.plotLabel(canvas,node,opt)}else{this.hideLabel(node,false)}}else{this.hideLabel(node,true)}},placeLabel:function(tag,node,controller){var pos=node.pos.getc(true),dim=this.node,canvas=this.viz.canvas;var w=dim.overridable&&node.data.$width||dim.width;var h=dim.overridable&&node.data.$height||dim.height;var radius=canvas.getSize();var labelPos,orn;if(dim.align=="center"){labelPos={x:Math.round(pos.x-w/2+radius.width/2),y:Math.round(pos.y-h/2+radius.height/2)}}else{if(dim.align=="left"){orn=this.config.orientation;if(orn=="bottom"||orn=="top"){labelPos={x:Math.round(pos.x-w/2+radius.width/2),y:Math.round(pos.y+radius.height/2)}}else{labelPos={x:Math.round(pos.x+radius.width/2),y:Math.round(pos.y-h/2+radius.height/2)}}}else{if(dim.align=="right"){orn=this.config.orientation;if(orn=="bottom"||orn=="top"){labelPos={x:Math.round(pos.x-w/2+radius.width/2),y:Math.round(pos.y-h+radius.height/2)}}else{labelPos={x:Math.round(pos.x-w+radius.width/2),y:Math.round(pos.y-h/2+radius.height/2)}}}else{throw"align: not implemented"}}}var style=tag.style;style.left=labelPos.x+"px";style.top=labelPos.y+"px";style.display=this.fitsInCanvas(labelPos,canvas)?"":"none";controller.onPlaceLabel(tag,node)},getAlignedPos:function(pos,width,height){var nconfig=this.node;var square,orn;if(nconfig.align=="center"){square={x:pos.x-width/2,y:pos.y-height/2}}else{if(nconfig.align=="left"){orn=this.config.orientation;if(orn=="bottom"||orn=="top"){square={x:pos.x-width/2,y:pos.y}}else{square={x:pos.x,y:pos.y-height/2}}}else{if(nconfig.align=="right"){orn=this.config.orientation;if(orn=="bottom"||orn=="top"){square={x:pos.x-width/2,y:pos.y-height}}else{square={x:pos.x-width,y:pos.y-height/2}}}else{throw"align: not implemented"}}}return square},getOrientation:function(adj){var config=this.config;var orn=config.orientation;if(config.multitree){var nodeFrom=adj.nodeFrom;var nodeTo=adj.nodeTo;orn=(("$orn" in nodeFrom.data)&&nodeFrom.data.$orn)||(("$orn" in nodeTo.data)&&nodeTo.data.$orn)}return orn}});ST.Plot.NodeTypes=new Class({none:function(){},circle:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var cond=nconfig.overridable&&data;var dim=cond&&data.$dim||nconfig.dim;var algnPos=this.getAlignedPos(pos,dim*2,dim*2);canvas.path("fill",function(context){context.arc(algnPos.x+dim,algnPos.y+dim,dim,0,Math.PI*2,true)})},square:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var cond=nconfig.overridable&&data;var dim=cond&&data.$dim||nconfig.dim;var algnPos=this.getAlignedPos(pos,dim,dim);canvas.getCtx().fillRect(algnPos.x,algnPos.y,dim,dim)},ellipse:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var cond=nconfig.overridable&&data;var width=(cond&&data.$width||nconfig.width)/2;var height=(cond&&data.$height||nconfig.height)/2;var algnPos=this.getAlignedPos(pos,width*2,height*2);var ctx=canvas.getCtx();ctx.save();ctx.scale(width/height,height/width);canvas.path("fill",function(context){context.arc((algnPos.x+width)*(height/width),(algnPos.y+height)*(width/height),height,0,Math.PI*2,true)});ctx.restore()},rectangle:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var cond=nconfig.overridable&&data;var width=cond&&data.$width||nconfig.width;var height=cond&&data.$height||nconfig.height;var algnPos=this.getAlignedPos(pos,width,height);canvas.getCtx().fillRect(algnPos.x,algnPos.y,width,height)}});ST.Plot.EdgeTypes=new Class({none:function(){},line:function(adj,canvas){var orn=this.getOrientation(adj);var nodeFrom=adj.nodeFrom,nodeTo=adj.nodeTo;var begin=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeFrom:nodeTo,"begin",orn);var end=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeTo:nodeFrom,"end",orn);canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.lineTo(end.x,end.y)})},"quadratic:begin":function(adj,canvas){var orn=this.getOrientation(adj);var data=adj.data,econfig=this.edge;var nodeFrom=adj.nodeFrom,nodeTo=adj.nodeTo;var begin=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeFrom:nodeTo,"begin",orn);var end=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeTo:nodeFrom,"end",orn);var cond=econfig.overridable&&data;var dim=cond&&data.$dim||econfig.dim;switch(orn){case"left":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(begin.x+dim,begin.y,end.x,end.y)});break;case"right":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(begin.x-dim,begin.y,end.x,end.y)});break;case"top":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(begin.x,begin.y+dim,end.x,end.y)});break;case"bottom":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(begin.x,begin.y-dim,end.x,end.y)});break}},"quadratic:end":function(adj,canvas){var orn=this.getOrientation(adj);var data=adj.data,econfig=this.edge;var nodeFrom=adj.nodeFrom,nodeTo=adj.nodeTo;var begin=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeFrom:nodeTo,"begin",orn);var end=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeTo:nodeFrom,"end",orn);var cond=econfig.overridable&&data;var dim=cond&&data.$dim||econfig.dim;switch(orn){case"left":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(end.x-dim,end.y,end.x,end.y)});break;case"right":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(end.x+dim,end.y,end.x,end.y)});break;case"top":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(end.x,end.y-dim,end.x,end.y)});break;case"bottom":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.quadraticCurveTo(end.x,end.y+dim,end.x,end.y)});break}},bezier:function(adj,canvas){var data=adj.data,econfig=this.edge;var orn=this.getOrientation(adj);var nodeFrom=adj.nodeFrom,nodeTo=adj.nodeTo;var begin=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeFrom:nodeTo,"begin",orn);var end=this.viz.geom.getEdge(nodeFrom._depth<nodeTo._depth?nodeTo:nodeFrom,"end",orn);var cond=econfig.overridable&&data;var dim=cond&&data.$dim||econfig.dim;switch(orn){case"left":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.bezierCurveTo(begin.x+dim,begin.y,end.x-dim,end.y,end.x,end.y)});break;case"right":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.bezierCurveTo(begin.x-dim,begin.y,end.x+dim,end.y,end.x,end.y)});break;case"top":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.bezierCurveTo(begin.x,begin.y+dim,end.x,end.y-dim,end.x,end.y)});break;case"bottom":canvas.path("stroke",function(ctx){ctx.moveTo(begin.x,begin.y);ctx.bezierCurveTo(begin.x,begin.y-dim,end.x,end.y+dim,end.x,end.y)});break}},arrow:function(adj,canvas){var orn=this.getOrientation(adj);var node=adj.nodeFrom,child=adj.nodeTo;var data=adj.data,econfig=this.edge;var cond=econfig.overridable&&data;var edgeDim=cond&&data.$dim||econfig.dim;if(cond&&data.$direction&&data.$direction.length>1){var nodeHash={};nodeHash[node.id]=node;nodeHash[child.id]=child;var sense=data.$direction;node=nodeHash[sense[0]];child=nodeHash[sense[1]]}var posFrom=this.viz.geom.getEdge(node,"begin",orn);var posTo=this.viz.geom.getEdge(child,"end",orn);var vect=new Complex(posTo.x-posFrom.x,posTo.y-posFrom.y);vect.$scale(edgeDim/vect.norm());var intermediatePoint=new Complex(posTo.x-vect.x,posTo.y-vect.y);var normal=new Complex(-vect.y/2,vect.x/2);var v1=intermediatePoint.add(normal),v2=intermediatePoint.$add(normal.$scale(-1));canvas.path("stroke",function(context){context.moveTo(posFrom.x,posFrom.y);context.lineTo(posTo.x,posTo.y)});canvas.path("fill",function(context){context.moveTo(v1.x,v1.y);context.lineTo(v2.x,v2.y);context.lineTo(posTo.x,posTo.y)})}})})();var AngularWidth={setAngularWidthForNodes:function(){var config=this.config.Node;var overridable=config.overridable;var dim=config.dim;Graph.Util.eachBFS(this.graph,this.root,function(elem,i){var diamValue=(overridable&&elem.data&&elem.data.$aw)||dim;elem._angularWidth=diamValue/i},"ignore")},setSubtreesAngularWidth:function(){var that=this;Graph.Util.eachNode(this.graph,function(elem){that.setSubtreeAngularWidth(elem)},"ignore")},setSubtreeAngularWidth:function(elem){var that=this,nodeAW=elem._angularWidth,sumAW=0;Graph.Util.eachSubnode(elem,function(child){that.setSubtreeAngularWidth(child);sumAW+=child._treeAngularWidth},"ignore");elem._treeAngularWidth=Math.max(nodeAW,sumAW)},computeAngularWidths:function(){this.setAngularWidthForNodes();this.setSubtreesAngularWidth()}};this.RGraph=new Class({Implements:[Loader,AngularWidth],initialize:function(canvas,controller){var config={labelContainer:canvas.id+"-label",interpolation:"linear",levelDistance:100,withLabels:true,Node:{overridable:false,type:"circle",dim:3,color:"#ccb",width:5,height:5,lineWidth:1},Edge:{overridable:false,type:"line",color:"#ccb",lineWidth:1},fps:40,duration:2500,transition:Trans.Quart.easeInOut,clearCanvas:true};var innerController={onBeforeCompute:$empty,onAfterCompute:$empty,onCreateLabel:$empty,onPlaceLabel:$empty,onComplete:$empty,onBeforePlotLine:$empty,onAfterPlotLine:$empty,onBeforePlotNode:$empty,onAfterPlotNode:$empty};this.controller=this.config=$merge(config,innerController,controller);this.graphOptions={complex:false,Node:{selected:false,exist:true,drawn:true}};this.graph=new Graph(this.graphOptions);this.fx=new RGraph.Plot(this);this.op=new RGraph.Op(this);this.json=null;this.canvas=canvas;this.root=null;this.busy=false;this.parent=false},refresh:function(){this.compute();this.plot()},reposition:function(){this.compute("endPos")},plot:function(){this.fx.plot()},compute:function(property){var prop=property||["pos","startPos","endPos"];var node=this.graph.getNode(this.root);node._depth=0;Graph.Util.computeLevels(this.graph,this.root,0,"ignore");this.computeAngularWidths();this.computePositions(prop)},computePositions:function(property){var propArray=$splat(property);var aGraph=this.graph;var GUtil=Graph.Util;var root=this.graph.getNode(this.root);var parent=this.parent;var config=this.config;for(var i=0;i<propArray.length;i++){root[propArray[i]]=$P(0,0)}root.angleSpan={begin:0,end:2*Math.PI};root._rel=1;GUtil.eachBFS(this.graph,this.root,function(elem){if(elem.angleSpan==null){return}var angleSpan=elem.angleSpan.end-elem.angleSpan.begin;var rho=(elem._depth+1)*config.levelDistance;var angleInit=elem.angleSpan.begin;var totalAngularWidths=0,subnodes=[];GUtil.eachSubnode(elem,function(sib){totalAngularWidths+=sib._treeAngularWidth;subnodes.push(sib)},"ignore");if(parent&&parent.id==elem.id&&subnodes.length>0&&subnodes[0].dist){subnodes.sort(function(a,b){return(a.dist>=b.dist)-(a.dist<=b.dist)})}for(var k=0;k<subnodes.length;k++){var child=subnodes[k];if(!child._flag){child._rel=child._treeAngularWidth/totalAngularWidths;var angleProportion=child._rel*angleSpan;var theta=angleInit+angleProportion/2;for(var i=0;i<propArray.length;i++){child[propArray[i]]=$P(theta,rho)}child.angleSpan={begin:angleInit,end:angleInit+angleProportion};angleInit+=angleProportion}}},"ignore")},getNodeAndParentAngle:function(id){var theta=false;var n=this.graph.getNode(id);var ps=Graph.Util.getParents(n);var p=(ps.length>0)?ps[0]:false;if(p){var posParent=p.pos.getc(),posChild=n.pos.getc();var newPos=posParent.add(posChild.scale(-1));theta=Math.atan2(newPos.y,newPos.x);if(theta<0){theta+=2*Math.PI}}return{parent:p,theta:theta}},tagChildren:function(par,id){if(par.angleSpan){var adjs=[];Graph.Util.eachAdjacency(par,function(elem){adjs.push(elem.nodeTo)},"ignore");var len=adjs.length;for(var i=0;i<len&&id!=adjs[i].id;i++){}for(var j=(i+1)%len,k=0;id!=adjs[j].id;j=(j+1)%len){adjs[j].dist=k++}}},onClick:function(id,opt){if(this.root!=id&&!this.busy){this.busy=true;this.root=id;that=this;this.controller.onBeforeCompute(this.graph.getNode(id));var obj=this.getNodeAndParentAngle(id);this.tagChildren(obj.parent,id);this.parent=obj.parent;this.compute("endPos");var thetaDiff=obj.theta-obj.parent.endPos.theta;Graph.Util.eachNode(this.graph,function(elem){elem.endPos.set(elem.endPos.getp().add($P(thetaDiff,0)))});var mode=this.config.interpolation;opt=$merge({onComplete:$empty},opt||{});this.fx.animate($merge({hideLabels:true,modes:[mode]},opt,{onComplete:function(){that.busy=false;opt.onComplete()}}))}}});RGraph.Op=new Class({Implements:Graph.Op,initialize:function(viz){this.viz=viz}});RGraph.Plot=new Class({Implements:Graph.Plot,initialize:function(viz){this.viz=viz;this.config=viz.config;this.node=viz.config.Node;this.edge=viz.config.Edge;this.animation=new Animation;this.nodeTypes=new RGraph.Plot.NodeTypes;this.edgeTypes=new RGraph.Plot.EdgeTypes},placeLabel:function(tag,node,controller){var pos=node.pos.getc(true),canvas=this.viz.canvas;var radius=canvas.getSize();var labelPos={x:Math.round(pos.x+radius.width/2),y:Math.round(pos.y+radius.height/2)};var style=tag.style;style.left=labelPos.x+"px";style.top=labelPos.y+"px";style.display=this.fitsInCanvas(labelPos,canvas)?"":"none";controller.onPlaceLabel(tag,node)}});RGraph.Plot.NodeTypes=new Class({none:function(){},circle:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;canvas.path("fill",function(context){context.arc(pos.x,pos.y,nodeDim,0,Math.PI*2,true)})},square:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var nodeDim2=2*nodeDim;canvas.getCtx().fillRect(pos.x-nodeDim,pos.y-nodeDim,nodeDim2,nodeDim2)},rectangle:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var width=nconfig.overridable&&data&&data.$width||nconfig.width;var height=nconfig.overridable&&data&&data.$height||nconfig.height;canvas.getCtx().fillRect(pos.x-width/2,pos.y-height/2,width,height)},triangle:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var c1x=pos.x,c1y=pos.y-nodeDim,c2x=c1x-nodeDim,c2y=pos.y+nodeDim,c3x=c1x+nodeDim,c3y=c2y;canvas.path("fill",function(ctx){ctx.moveTo(c1x,c1y);ctx.lineTo(c2x,c2y);ctx.lineTo(c3x,c3y)})},star:function(node,canvas){var pos=node.pos.getc(true),nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var ctx=canvas.getCtx(),pi5=Math.PI/5;ctx.save();ctx.translate(pos.x,pos.y);ctx.beginPath();ctx.moveTo(nodeDim,0);for(var i=0;i<9;i++){ctx.rotate(pi5);if(i%2==0){ctx.lineTo((nodeDim/0.525731)*0.200811,0)}else{ctx.lineTo(nodeDim,0)}}ctx.closePath();ctx.fill();ctx.restore()}});RGraph.Plot.EdgeTypes=new Class({none:function(){},line:function(adj,canvas){var pos=adj.nodeFrom.pos.getc(true);var posChild=adj.nodeTo.pos.getc(true);canvas.path("stroke",function(context){context.moveTo(pos.x,pos.y);context.lineTo(posChild.x,posChild.y)})},arrow:function(adj,canvas){var node=adj.nodeFrom,child=adj.nodeTo;var data=adj.data,econfig=this.edge;var cond=econfig.overridable&&data;var edgeDim=cond&&data.$dim||14;if(cond&&data.$direction&&data.$direction.length>1){var nodeHash={};nodeHash[node.id]=node;nodeHash[child.id]=child;var sense=data.$direction;node=nodeHash[sense[0]];child=nodeHash[sense[1]]}var posFrom=node.pos.getc(true),posTo=child.pos.getc(true);var vect=new Complex(posTo.x-posFrom.x,posTo.y-posFrom.y);vect.$scale(edgeDim/vect.norm());var intermediatePoint=new Complex(posTo.x-vect.x,posTo.y-vect.y);var normal=new Complex(-vect.y/2,vect.x/2);var v1=intermediatePoint.add(normal),v2=intermediatePoint.$add(normal.$scale(-1));canvas.path("stroke",function(context){context.moveTo(posFrom.x,posFrom.y);context.lineTo(posTo.x,posTo.y)});canvas.path("fill",function(context){context.moveTo(v1.x,v1.y);context.lineTo(v2.x,v2.y);context.lineTo(posTo.x,posTo.y)})}});Complex.prototype.moebiusTransformation=function(c){var num=this.add(c);var den=c.$conjugate().$prod(this);den.x++;return num.$div(den)};Graph.Util.getClosestNodeToOrigin=function(graph,prop,flags){return this.getClosestNodeToPos(graph,Polar.KER,prop,flags)};Graph.Util.getClosestNodeToPos=function(graph,pos,prop,flags){var node=null;prop=prop||"pos";pos=pos&&pos.getc(true)||Complex.KER;var distance=function(a,b){var d1=a.x-b.x,d2=a.y-b.y;return d1*d1+d2*d2};this.eachNode(graph,function(elem){node=(node==null||distance(elem[prop].getc(true),pos)<distance(node[prop].getc(true),pos))?elem:node},flags);return node};Graph.Util.moebiusTransformation=function(graph,pos,prop,startPos,flags){this.eachNode(graph,function(elem){for(var i=0;i<prop.length;i++){var p=pos[i].scale(-1),property=startPos?startPos:prop[i];elem[prop[i]].set(elem[property].getc().moebiusTransformation(p))}},flags)};this.Hypertree=new Class({Implements:[Loader,AngularWidth],initialize:function(canvas,controller){var config={labelContainer:canvas.id+"-label",withLabels:true,Node:{overridable:false,type:"circle",dim:7,color:"#ccb",width:5,height:5,lineWidth:1,transform:true},Edge:{overridable:false,type:"hyperline",color:"#ccb",lineWidth:1},clearCanvas:true,fps:40,duration:1500,transition:Trans.Quart.easeInOut};var innerController={onBeforeCompute:$empty,onAfterCompute:$empty,onCreateLabel:$empty,onPlaceLabel:$empty,onComplete:$empty,onBeforePlotLine:$empty,onAfterPlotLine:$empty,onBeforePlotNode:$empty,onAfterPlotNode:$empty};this.controller=this.config=$merge(config,innerController,controller);this.graphOptions={complex:false,Node:{selected:false,exist:true,drawn:true}};this.graph=new Graph(this.graphOptions);this.fx=new Hypertree.Plot(this);this.op=new Hypertree.Op(this);this.json=null;this.canvas=canvas;this.root=null;this.busy=false},refresh:function(reposition){if(reposition){this.reposition();Graph.Util.eachNode(this.graph,function(node){node.startPos.rho=node.pos.rho=node.endPos.rho;node.startPos.theta=node.pos.theta=node.endPos.theta})}else{this.compute()}this.plot()},reposition:function(){this.compute("endPos");var vector=this.graph.getNode(this.root).pos.getc().scale(-1);Graph.Util.moebiusTransformation(this.graph,[vector],["endPos"],"endPos","ignore");Graph.Util.eachNode(this.graph,function(node){if(node.ignore){node.endPos.rho=node.pos.rho;node.endPos.theta=node.pos.theta}})},plot:function(){this.fx.plot()},compute:function(property){var prop=property||["pos","startPos"];var node=this.graph.getNode(this.root);node._depth=0;Graph.Util.computeLevels(this.graph,this.root,0,"ignore");this.computeAngularWidths();this.computePositions(prop)},computePositions:function(property){var propArray=$splat(property);var aGraph=this.graph,GUtil=Graph.Util;var root=this.graph.getNode(this.root),that=this,config=this.config;var size=this.canvas.getSize();var scale=Math.min(size.width,size.height)/2;for(var i=0;i<propArray.length;i++){root[propArray[i]]=$P(0,0)}root.angleSpan={begin:0,end:2*Math.PI};root._rel=1;var edgeLength=(function(){var depth=0;GUtil.eachNode(aGraph,function(node){depth=(node._depth>depth)?node._depth:depth;node._scale=scale},"ignore");for(var i=0.51;i<=1;i+=0.01){var valSeries=(function(a,n){return(1-Math.pow(a,n))/(1-a)})(i,depth+1);if(valSeries>=2){return i-0.01}}return 0.5})();GUtil.eachBFS(this.graph,this.root,function(elem){var angleSpan=elem.angleSpan.end-elem.angleSpan.begin;var angleInit=elem.angleSpan.begin;var totalAngularWidths=(function(element){var total=0;GUtil.eachSubnode(element,function(sib){total+=sib._treeAngularWidth},"ignore");return total})(elem);for(var i=1,rho=0,lenAcum=edgeLength,depth=elem._depth;i<=depth+1;i++){rho+=lenAcum;lenAcum*=edgeLength}GUtil.eachSubnode(elem,function(child){if(!child._flag){child._rel=child._treeAngularWidth/totalAngularWidths;var angleProportion=child._rel*angleSpan;var theta=angleInit+angleProportion/2;for(var i=0;i<propArray.length;i++){child[propArray[i]]=$P(theta,rho)}child.angleSpan={begin:angleInit,end:angleInit+angleProportion};angleInit+=angleProportion}},"ignore")},"ignore")},onClick:function(id,opt){var pos=this.graph.getNode(id).pos.getc(true);this.move(pos,opt)},move:function(pos,opt){var versor=$C(pos.x,pos.y);if(this.busy===false&&versor.norm()<1){var GUtil=Graph.Util;this.busy=true;var root=GUtil.getClosestNodeToPos(this.graph,versor),that=this;GUtil.computeLevels(this.graph,root.id,0);this.controller.onBeforeCompute(root);if(versor.norm()<1){opt=$merge({onComplete:$empty},opt||{});this.fx.animate($merge({modes:["moebius"],hideLabels:true},opt,{onComplete:function(){that.busy=false;opt.onComplete()}}),versor)}}}});Hypertree.Op=new Class({Implements:Graph.Op,initialize:function(viz){this.viz=viz}});Hypertree.Plot=new Class({Implements:Graph.Plot,initialize:function(viz){this.viz=viz;this.config=viz.config;this.node=this.config.Node;this.edge=this.config.Edge;this.animation=new Animation;this.nodeTypes=new Hypertree.Plot.NodeTypes;this.edgeTypes=new Hypertree.Plot.EdgeTypes},hyperline:function(adj,canvas){var node=adj.nodeFrom,child=adj.nodeTo,data=adj.data;var pos=node.pos.getc(),posChild=child.pos.getc();var centerOfCircle=this.computeArcThroughTwoPoints(pos,posChild);var size=canvas.getSize();var scale=Math.min(size.width,size.height)/2;if(centerOfCircle.a>1000||centerOfCircle.b>1000||centerOfCircle.ratio>1000){canvas.path("stroke",function(ctx){ctx.moveTo(pos.x*scale,pos.y*scale);ctx.lineTo(posChild.x*scale,posChild.y*scale)})}else{var angleBegin=Math.atan2(posChild.y-centerOfCircle.y,posChild.x-centerOfCircle.x);var angleEnd=Math.atan2(pos.y-centerOfCircle.y,pos.x-centerOfCircle.x);var sense=this.sense(angleBegin,angleEnd);var context=canvas.getCtx();canvas.path("stroke",function(ctx){ctx.arc(centerOfCircle.x*scale,centerOfCircle.y*scale,centerOfCircle.ratio*scale,angleBegin,angleEnd,sense)})}},computeArcThroughTwoPoints:function(p1,p2){var aDen=(p1.x*p2.y-p1.y*p2.x),bDen=aDen;var sq1=p1.squaredNorm(),sq2=p2.squaredNorm();if(aDen==0){return{x:0,y:0,ratio:1001}}var a=(p1.y*sq2-p2.y*sq1+p1.y-p2.y)/aDen;var b=(p2.x*sq1-p1.x*sq2+p2.x-p1.x)/bDen;var x=-a/2;var y=-b/2;var squaredRatio=(a*a+b*b)/4-1;if(squaredRatio<0){return{x:0,y:0,ratio:1001}}var ratio=Math.sqrt(squaredRatio);var out={x:x,y:y,ratio:ratio,a:a,b:b};return out},sense:function(angleBegin,angleEnd){return(angleBegin<angleEnd)?((angleBegin+Math.PI>angleEnd)?false:true):((angleEnd+Math.PI>angleBegin)?true:false)},placeLabel:function(tag,node,controller){var pos=node.pos.getc(true),canvas=this.viz.canvas;var radius=canvas.getSize();var scale=node._scale;var labelPos={x:Math.round(pos.x*scale+radius.width/2),y:Math.round(pos.y*scale+radius.height/2)};var style=tag.style;style.left=labelPos.x+"px";style.top=labelPos.y+"px";style.display="";controller.onPlaceLabel(tag,node)}});Hypertree.Plot.NodeTypes=new Class({none:function(){},circle:function(node,canvas){var nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var p=node.pos.getc(),pos=p.scale(node._scale);var prod=nconfig.transform?nodeDim*(1-p.squaredNorm()):nodeDim;if(prod>=nodeDim/4){canvas.path("fill",function(context){context.arc(pos.x,pos.y,prod,0,Math.PI*2,true)})}},square:function(node,canvas){var nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var p=node.pos.getc(),pos=p.scale(node._scale);var prod=nconfig.transform?nodeDim*(1-p.squaredNorm()):nodeDim;var nodeDim2=2*prod;if(prod>=nodeDim/4){canvas.getCtx().fillRect(pos.x-prod,pos.y-prod,nodeDim2,nodeDim2)}},rectangle:function(node,canvas){var nconfig=this.node,data=node.data;var width=nconfig.overridable&&data&&data.$width||nconfig.width;var height=nconfig.overridable&&data&&data.$height||nconfig.height;var p=node.pos.getc(),pos=p.scale(node._scale);var prod=1-p.squaredNorm();width=nconfig.transform?width*prod:width;height=nconfig.transform?height*prod:height;if(prod>=0.25){canvas.getCtx().fillRect(pos.x-width/2,pos.y-height/2,width,height)}},triangle:function(node,canvas){var nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var p=node.pos.getc(),pos=p.scale(node._scale);var prod=nconfig.transform?nodeDim*(1-p.squaredNorm()):nodeDim;if(prod>=nodeDim/4){var c1x=pos.x,c1y=pos.y-prod,c2x=c1x-prod,c2y=pos.y+prod,c3x=c1x+prod,c3y=c2y;canvas.path("fill",function(ctx){ctx.moveTo(c1x,c1y);ctx.lineTo(c2x,c2y);ctx.lineTo(c3x,c3y)})}},star:function(node,canvas){var nconfig=this.node,data=node.data;var nodeDim=nconfig.overridable&&data&&data.$dim||nconfig.dim;var p=node.pos.getc(),pos=p.scale(node._scale);var prod=nconfig.transform?nodeDim*(1-p.squaredNorm()):nodeDim;if(prod>=nodeDim/4){var ctx=canvas.getCtx(),pi5=Math.PI/5;ctx.save();ctx.translate(pos.x,pos.y);ctx.beginPath();ctx.moveTo(nodeDim,0);for(var i=0;i<9;i++){ctx.rotate(pi5);if(i%2==0){ctx.lineTo((prod/0.525731)*0.200811,0)}else{ctx.lineTo(prod,0)}}ctx.closePath();ctx.fill();ctx.restore()}}});Hypertree.Plot.EdgeTypes=new Class({none:function(){},line:function(adj,canvas){var s=adj.nodeFrom._scale;var pos=adj.nodeFrom.pos.getc(true);var posChild=adj.nodeTo.pos.getc(true);canvas.path("stroke",function(context){context.moveTo(pos.x*s,pos.y*s);context.lineTo(posChild.x*s,posChild.y*s)})},hyperline:function(adj,canvas){this.hyperline(adj,canvas)}});this.TM={layout:{orientation:"h",vertical:function(){return this.orientation=="v"},horizontal:function(){return this.orientation=="h"},change:function(){this.orientation=this.vertical()?"h":"v"}},innerController:{onBeforeCompute:$empty,onAfterCompute:$empty,onComplete:$empty,onCreateElement:$empty,onDestroyElement:$empty,request:false},config:{orientation:"h",titleHeight:13,rootId:"infovis",offset:4,levelsToShow:3,addLeftClickHandler:false,addRightClickHandler:false,selectPathOnHover:false,Color:{allow:false,minValue:-100,maxValue:100,minColorValue:[255,0,50],maxColorValue:[0,255,50]},Tips:{allow:false,offsetX:20,offsetY:20,onShow:$empty}},initialize:function(controller){this.tree=null;this.shownTree=null;this.controller=this.config=$merge(this.config,this.innerController,controller);this.rootId=this.config.rootId;this.layout.orientation=this.config.orientation;if(this.config.Tips.allow&&document.body){var tip=document.getElementById("_tooltip")||document.createElement("div");tip.id="_tooltip";tip.className="tip";var style=tip.style;style.position="absolute";style.display="none";style.zIndex=13000;document.body.appendChild(tip);this.tip=tip}var that=this;var fn=function(){that.empty();if(window.CollectGarbage){window.CollectGarbage()}delete fn};if(window.addEventListener){window.addEventListener("unload",fn,false)}else{window.attachEvent("onunload",fn)}},each:function(f){(function rec(elem){if(!elem){return}var ch=elem.childNodes,len=ch.length;if(len>0){f.apply(this,[elem,len===1,ch[0],ch[1]])}if(len>1){for(var chi=ch[1].childNodes,i=0;i<chi.length;i++){rec(chi[i])}}})($get(this.rootId).firstChild)},toStyle:function(obj){var ans="";for(var s in obj){ans+=s+":"+obj[s]+";"}return ans},leaf:function(tree){return tree.children==0},createBox:function(json,coord,html){var box;if(!this.leaf(json)){box=this.headBox(json,coord)+this.bodyBox(html,coord)}else{box=this.leafBox(json,coord)}return this.contentBox(json,coord,box)},plot:function(json){var coord=json.coord,html="";if(this.leaf(json)){return this.createBox(json,coord,null)}for(var i=0,ch=json.children;i<ch.length;i++){var chi=ch[i],chcoord=chi.coord;if(chcoord.width*chcoord.height>1){html+=this.plot(chi)}}return this.createBox(json,coord,html)},headBox:function(json,coord){var config=this.config,offst=config.offset;var c={height:config.titleHeight+"px",width:(coord.width-offst)+"px",left:offst/2+"px"};return'<div class="head" style="'+this.toStyle(c)+'">'+json.name+"</div>"},bodyBox:function(html,coord){var config=this.config,th=config.titleHeight,offst=config.offset;var c={width:(coord.width-offst)+"px",height:(coord.height-offst-th)+"px",top:(th+offst/2)+"px",left:(offst/2)+"px"};return'<div class="body" style="'+this.toStyle(c)+'">'+html+"</div>"},contentBox:function(json,coord,html){var c={};for(var i in coord){c[i]=coord[i]+"px"}return'<div class="content" style="'+this.toStyle(c)+'" id="'+json.id+'">'+html+"</div>"},leafBox:function(json,coord){var config=this.config;var backgroundColor=config.Color.allow&&this.setColor(json),offst=config.offset,width=coord.width-offst,height=coord.height-offst;var c={top:(offst/2)+"px",height:height+"px",width:width+"px",left:(offst/2)+"px"};if(backgroundColor){c["background-color"]=backgroundColor}return'<div class="leaf" style="'+this.toStyle(c)+'">'+json.name+"</div>"},setColor:function(json){var c=this.config.Color,maxcv=c.maxColorValue,mincv=c.minColorValue,maxv=c.maxValue,minv=c.minValue,diff=maxv-minv,x=(json.data.$color-0);var comp=function(i,x){return Math.round((((maxcv[i]-mincv[i])/diff)*(x-minv)+mincv[i]))};return $rgbToHex([comp(0,x),comp(1,x),comp(2,x)])},enter:function(elem){this.view(elem.parentNode.id)},onLeftClick:function(elem){this.enter(elem)},out:function(){var parent=TreeUtil.getParent(this.tree,this.shownTree.id);if(parent){if(this.controller.request){TreeUtil.prune(parent,this.config.levelsToShow)}this.view(parent.id)}},onRightClick:function(){this.out()},view:function(id){var config=this.config,that=this;var post={onComplete:function(){that.loadTree(id);$get(config.rootId).focus()}};if(this.controller.request){var TUtil=TreeUtil;TUtil.loadSubtrees(TUtil.getSubtree(this.tree,id),$merge(this.controller,post))}else{post.onComplete()}},resetPath:function(tree){var root=this.rootId,previous=this.resetPath.previous;this.resetPath.previous=tree||false;function getParent(c){var p=c.parentNode;return p&&(p.id!=root)&&p}function toggleInPath(elem,remove){if(elem){var container=$get(elem.id);if(container){var parent=getParent(container);while(parent){elem=parent.childNodes[0];if($hasClass(elem,"in-path")){if(remove==undefined||!!remove){$removeClass(elem,"in-path")}}else{if(!remove){$addClass(elem,"in-path")}}parent=getParent(parent)}}}}toggleInPath(previous,true);toggleInPath(tree,false)},initializeElements:function(){var cont=this.controller,that=this;var ff=$lambda(false),tipsAllow=cont.Tips.allow;this.each(function(content,isLeaf,elem1,elem2){var tree=TreeUtil.getSubtree(that.tree,content.id);cont.onCreateElement(content,tree,isLeaf,elem1,elem2);if(cont.addRightClickHandler){elem1.oncontextmenu=ff}if(cont.addLeftClickHandler||cont.addRightClickHandler){$addEvent(elem1,"mouseup",function(e){var rightClick=(e.which==3||e.button==2);if(rightClick){if(cont.addRightClickHandler){that.onRightClick()}}else{if(cont.addLeftClickHandler){that.onLeftClick(elem1)}}if(e.preventDefault){e.preventDefault()}else{e.returnValue=false}})}if(cont.selectPathOnHover||tipsAllow){$addEvent(elem1,"mouseover",function(e){if(cont.selectPathOnHover){if(isLeaf){$addClass(elem1,"over-leaf")}else{$addClass(elem1,"over-head");$addClass(content,"over-content")}if(content.id){that.resetPath(tree)}}if(tipsAllow){cont.Tips.onShow(that.tip,tree,isLeaf,elem1)}});$addEvent(elem1,"mouseout",function(e){if(cont.selectPathOnHover){if(isLeaf){$removeClass(elem1,"over-leaf")}else{$removeClass(elem1,"over-head");$removeClass(content,"over-content")}that.resetPath()}if(tipsAllow){that.tip.style.display="none"}});if(tipsAllow){$addEvent(elem1,"mousemove",function(e,win){var tip=that.tip;win=win||window;e=e||win.event;var doc=win.document;doc=doc.html||doc.body;var page={x:e.pageX||e.clientX+doc.scrollLeft,y:e.pageY||e.clientY+doc.scrollTop};tip.style.display="";win={height:document.body.clientHeight,width:document.body.clientWidth};var obj={width:tip.offsetWidth,height:tip.offsetHeight};var style=tip.style,x=cont.Tips.offsetX,y=cont.Tips.offsetY;style.top=((page.y+y+obj.height>win.height)?(page.y-obj.height-y):page.y+y)+"px";style.left=((page.x+obj.width+x>win.width)?(page.x-obj.width-x):page.x+x)+"px"})}}})},destroyElements:function(){if(this.controller.onDestroyElement!=$empty){var cont=this.controller,that=this;this.each(function(content,isLeaf,elem1,elem2){cont.onDestroyElement(content,TreeUtil.getSubtree(that.tree,content.id),isLeaf,elem1,elem2)})}},empty:function(){this.destroyElements();$clean($get(this.rootId))},loadTree:function(id){this.empty();this.loadJSON(TreeUtil.getSubtree(this.tree,id))}};TM.SliceAndDice=new Class({Implements:TM,loadJSON:function(json){this.controller.onBeforeCompute(json);var container=$get(this.rootId),config=this.config,width=container.offsetWidth,height=container.offsetHeight;var p={coord:{top:0,left:0,width:width,height:height+config.titleHeight+config.offset}};if(this.tree==null){this.tree=json}this.shownTree=json;this.compute(p,json,this.layout.orientation);container.innerHTML=this.plot(json);this.initializeElements();this.controller.onAfterCompute(json)},compute:function(par,json,orientation){var config=this.config,coord=par.coord,offst=config.offset,width=coord.width-offst,height=coord.height-offst-config.titleHeight,pdata=par.data,fact=(pdata&&("$area" in pdata))?json.data.$area/pdata.$area:1;var otherSize,size,dim,pos,pos2;var horizontal=(orientation=="h");if(horizontal){orientation="v";otherSize=height;size=Math.round(width*fact);dim="height";pos="top";pos2="left"}else{orientation="h";otherSize=Math.round(height*fact);size=width;dim="width";pos="left";pos2="top"}json.coord={width:size,height:otherSize,top:0,left:0};var offsetSize=0,tm=this;$each(json.children,function(elem){tm.compute(json,elem,orientation);elem.coord[pos]=offsetSize;elem.coord[pos2]=0;offsetSize+=Math.floor(elem.coord[dim])})}});TM.Area=new Class({loadJSON:function(json){this.controller.onBeforeCompute(json);var container=$get(this.rootId),width=container.offsetWidth,height=container.offsetHeight,offst=this.config.offset,offwdth=width-offst,offhght=height-offst-this.config.titleHeight;json.coord={height:height,width:width,top:0,left:0};var coord=$merge(json.coord,{width:offwdth,height:offhght});this.compute(json,coord);container.innerHTML=this.plot(json);if(this.tree==null){this.tree=json}this.shownTree=json;this.initializeElements();this.controller.onAfterCompute(json)},computeDim:function(tail,initElem,w,coord,comp){if(tail.length+initElem.length==1){var l=(tail.length==1)?tail:initElem;this.layoutLast(l,w,coord);return}if(tail.length>=2&&initElem.length==0){initElem=[tail[0]];tail=tail.slice(1)}if(tail.length==0){if(initElem.length>0){this.layoutRow(initElem,w,coord)}return}var c=tail[0];if(comp(initElem,w)>=comp([c].concat(initElem),w)){this.computeDim(tail.slice(1),initElem.concat([c]),w,coord,comp)}else{var newCoords=this.layoutRow(initElem,w,coord);this.computeDim(tail,[],newCoords.dim,newCoords,comp)}},worstAspectRatio:function(ch,w){if(!ch||ch.length==0){return Number.MAX_VALUE}var areaSum=0,maxArea=0,minArea=Number.MAX_VALUE;for(var i=0;i<ch.length;i++){var area=ch[i]._area;areaSum+=area;minArea=(minArea<area)?minArea:area;maxArea=(maxArea>area)?maxArea:area}var sqw=w*w,sqAreaSum=areaSum*areaSum;return Math.max(sqw*maxArea/sqAreaSum,sqAreaSum/(sqw*minArea))},avgAspectRatio:function(ch,w){if(!ch||ch.length==0){return Number.MAX_VALUE}var arSum=0;for(var i=0;i<ch.length;i++){var area=ch[i]._area;var h=area/w;arSum+=(w>h)?w/h:h/w}return arSum/ch.length},layoutLast:function(ch,w,coord){ch[0].coord=coord}});TM.Squarified=new Class({Implements:[TM,TM.Area],compute:function(json,coord){if(!(coord.width>=coord.height&&this.layout.horizontal())){this.layout.change()}var ch=json.children,config=this.config;if(ch.length>0){this.processChildrenLayout(json,ch,coord);for(var i=0;i<ch.length;i++){var chcoord=ch[i].coord,offst=config.offset,height=chcoord.height-(config.titleHeight+offst),width=chcoord.width-offst;coord={width:width,height:height,top:0,left:0};this.compute(ch[i],coord)}}},processChildrenLayout:function(par,ch,coord){var parentArea=coord.width*coord.height;var i,totalChArea=0,chArea=[];for(i=0;i<ch.length;i++){chArea[i]=parseFloat(ch[i].data.$area);totalChArea+=chArea[i]}for(i=0;i<chArea.length;i++){ch[i]._area=parentArea*chArea[i]/totalChArea}var minimumSideValue=(this.layout.horizontal())?coord.height:coord.width;ch.sort(function(a,b){return(a._area<=b._area)-(a._area>=b._area)});var initElem=[ch[0]];var tail=ch.slice(1);this.squarify(tail,initElem,minimumSideValue,coord)},squarify:function(tail,initElem,w,coord){this.computeDim(tail,initElem,w,coord,this.worstAspectRatio)},layoutRow:function(ch,w,coord){if(this.layout.horizontal()){return this.layoutV(ch,w,coord)}else{return this.layoutH(ch,w,coord)}},layoutV:function(ch,w,coord){var totalArea=0,rnd=Math.round;$each(ch,function(elem){totalArea+=elem._area});var width=rnd(totalArea/w),top=0;for(var i=0;i<ch.length;i++){var h=rnd(ch[i]._area/width);ch[i].coord={height:h,width:width,top:coord.top+top,left:coord.left};top+=h}var ans={height:coord.height,width:coord.width-width,top:coord.top,left:coord.left+width};ans.dim=Math.min(ans.width,ans.height);if(ans.dim!=ans.height){this.layout.change()}return ans},layoutH:function(ch,w,coord){var totalArea=0,rnd=Math.round;$each(ch,function(elem){totalArea+=elem._area});var height=rnd(totalArea/w),top=coord.top,left=0;for(var i=0;i<ch.length;i++){ch[i].coord={height:height,width:rnd(ch[i]._area/height),top:top,left:coord.left+left};left+=ch[i].coord.width}var ans={height:coord.height-height,width:coord.width,top:coord.top+height,left:coord.left};ans.dim=Math.min(ans.width,ans.height);if(ans.dim!=ans.width){this.layout.change()}return ans}});TM.Strip=new Class({Implements:[TM,TM.Area],compute:function(json,coord){var ch=json.children,config=this.config;if(ch.length>0){this.processChildrenLayout(json,ch,coord);for(var i=0;i<ch.length;i++){var chcoord=ch[i].coord,offst=config.offset,height=chcoord.height-(config.titleHeight+offst),width=chcoord.width-offst;coord={width:width,height:height,top:0,left:0};this.compute(ch[i],coord)}}},processChildrenLayout:function(par,ch,coord){var area=coord.width*coord.height;var dataValue=parseFloat(par.data.$area);$each(ch,function(elem){elem._area=area*parseFloat(elem.data.$area)/dataValue});var side=(this.layout.horizontal())?coord.width:coord.height;var initElem=[ch[0]];var tail=ch.slice(1);this.stripify(tail,initElem,side,coord)},stripify:function(tail,initElem,w,coord){this.computeDim(tail,initElem,w,coord,this.avgAspectRatio)},layoutRow:function(ch,w,coord){if(this.layout.horizontal()){return this.layoutH(ch,w,coord)}else{return this.layoutV(ch,w,coord)}},layoutV:function(ch,w,coord){var totalArea=0,rnd=function(x){return x};$each(ch,function(elem){totalArea+=elem._area});var width=rnd(totalArea/w),top=0;for(var i=0;i<ch.length;i++){var h=rnd(ch[i]._area/width);ch[i].coord={height:h,width:width,top:coord.top+(w-h-top),left:coord.left};top+=h}var ans={height:coord.height,width:coord.width-width,top:coord.top,left:coord.left+width,dim:w};return ans},layoutH:function(ch,w,coord){var totalArea=0,rnd=function(x){return x};$each(ch,function(elem){totalArea+=elem._area});var height=rnd(totalArea/w),top=coord.height-height,left=0;for(var i=0;i<ch.length;i++){ch[i].coord={height:height,width:rnd(ch[i]._area/height),top:top,left:coord.left+left};left+=ch[i].coord.width}var ans={height:coord.height-height,width:coord.width,top:coord.top,left:coord.left,dim:w};return ans}})})();
