/*-----------------Graph---------------------*/
function SVG_Graph(id){
    this.activeNode=null;
    this.activeNodeColor="#0CADD3";
    this.nodeShape="Oval"
    this.selectedNodeColor="Yellow";
    this.selectedNode=null;
    this.textColor="White";
    this.scale=1;
    this.nodes={};
    this.lines={};
    this.lineDashStyle="Solid";
    this.lineArrowStyle="Classic";
    this.id=id;
    this.groupid="group"+id;
    this.coordSizeX=6000;
    this.coordSizeY=4000;
    this.Rules={};
    this.x=0;
    this.y=0;
    this.rulelistMove=false;
    this.rulelistX=10;
    this.rulelistY=600;
    this.minVal=0;
    this.rootNode=null;
    this.RulesLength=0;
    this.fontSize=0;
    this.gSize=1;
    this.ExpandType="Both";    
    this.lineType = "co-occurrence";
}

SVG_GP=SVG_Graph.prototype;

SVG_GP.AddRules=function(activeNode,rules)
{
    this.Rules[activeNode.id]=rules;
}

SVG_GP.SetGraphPos=function()
{
    var svgDoc = document.getElementById('svgGraph');   
    
    var doc = svgDoc.getSVGDocument();
    //    alert(doc);
    //    doc.oncontextmenu=MouseRightClick;
    if (this.layoutMinY)
    {
        var height = this.layoutMaxY - this.layoutMinY;
        svgDoc.style.height = height * 85;
        var width = this.layoutMaxX - this.layoutMinX;
        if (1000 <  width * 85)
        {
            svgDoc.style.width = width * 85;
        }
    }
    var graph=doc.getElementById(this.groupid); 
    
    var trans = "translate(600," + doc.defaultView.innerHeight / 2 +")"
    graph.setAttribute('transform',trans);
    
    
   //set foot style.top value
    Resize_local( svgDoc.style.height );
}

SVG_GP.InsertRules=function(activeNode,rules)
{
    var eRules = this.Rules[activeNode.id];
    var exitRules={};
    if(eRules)
    {
        for(var i in eRules)
        {
            var id = eRules[i].FromText+":"+eRules[i].ToText+":"+eRules[i].Database;
            exitRules[id] = eRules[i];
        }
        if(isNaN(i))
        {
            var t=0;
        }
        else
        {
            var t = Number(i)+1;
        }
        for(var k in rules)
        {
            var id2 = rules[k].FromText+":"+rules[k].ToText+":"+rules[k].Database;
            if(!exitRules[id2])
            {
                exitRules[id2]=rules[k];
                eRules[t]=rules[k];
                t++;
            }
        }
    }
    else
    {
        this.AddRules(activeNode,rules);
    }   
}

SVG_GP.AddNode=function(nodeID,nodeText,count,ruleCount,db)
{
    var node=this.nodes[nodeID];
    if (!node)
    {
        node=new SVG_Node(nodeID,nodeText,count,ruleCount);
        this.nodes[nodeID]=node;
    }
    if(db=="FunnelData")
    {
        if(node.flag==1)
        {
            node.flag=2;
        }
        else if(node.flag==-1)
        {
            node.flag=0;
        }
    }
    else if(db=="FunnelData2")
    {
        if(node.flag==-1)
        {
            node.flag=1;
        }
        else if(node.flag==0)
        {
            node.flag=2;
        }
    }
    return node;
}

SVG_GP.AddLine=function(node1ID,node2ID,flag,edge)
{
    var arr=[node1ID,node2ID];
    var lineID=arr.sort().join("");
    var line=this.lines[lineID];    
    if (!line)
    {   
        var node1=this.nodes[node1ID];
        var node2=this.nodes[node2ID];
        if (!node1||!node2)
        {
            alert("Error: Out range of nodes.");
            return;
        }
        line=new SVG_Line(lineID,node1,node2,flag,edge);
        this.lines[lineID]=line;
    }
    else if(line.arrowFlag==1 && line.fromNode.id != node1ID)
    {
        line.arrowFlag=2;
    }
    else
    {
        return null;
    }
    return line;
}

SVG_GP.ProbabilityFilte=function(count)
{
    var eRules={};
    var skipRules={};
    for(var key in this.Rules)
    {
        var rules = this.Rules[key];
        for(var t in rules)
        {
            var rule = rules[t];
            var ruleId = rule.FromText +":"+ rule.ToText +":"+ rule.Database;
            if(!eRules[ruleId])
            {
                eRules[ruleId] = rule;
                var array = [rule.ToId,rule.FromId];
                var lineId = array.sort().join("");
                var line = this.lines[lineId];
                if(line)
                {
                    if(line.arrowFlag == 0)
                    {
                        if(line.fromNode.id==rule.ToId)
                        {
                            var tempNode=line.toNode;
                            line.toNode=line.fromNode;
                            line.fromNode=tempNode;   
                        }
                        line.arrowFlag=1;
                        
                        var svgDoc = document.getElementById('svgGraph');
                        var doc = svgDoc.getSVGDocument();
                        var domline=doc.getElementById(lineId);                        
                        domline.style.display="block";
                        domline=doc.getElementById(lineId+"lineText");                        
                        domline.style.display="block";
                                                
                    }
                    else if(line.arrowFlag==1 )
                    {
                        if(line.fromNode.id==rule.ToId )
                        {
                            line.arrowFlag=2;
                        }
                        line.ChangeArrow();
                    }
                }
            }
        }
    }
   
    var tR;
   
    for(var l=0;l<count;l++)
    {
        for(var id in eRules)
        {  
            if(!skipRules[id])
            {
                tR=eRules[id];
            }
            for(var id in eRules)
            {
                if(tR.ProbabilityVal>eRules[id].ProbabilityVal && !skipRules[id] )
                {
                    tR=eRules[id];
                }
            }           
        }
        //add by luyinghuai
        //if( tR != null  )
            skipRules[tR.FromText +":"+ tR.ToText +":"+ tR.Database]=tR;
    }
    
    for(var i in skipRules)
    {
        var probability = Number(skipRules[i].ProbabilityVal);
        var node1ID=skipRules[i].ToId;
        var node2ID=skipRules[i].FromId;
        var arr=[node1ID,node2ID];
        var lineID=arr.sort().join("");
        var line=this.lines[lineID];
        if(line)
        {
            if(line.arrowFlag==2)
            {
                if(line.fromNode.id==node2ID)
                {
                    var tempNode=line.toNode;
                    line.toNode=line.fromNode;
                    line.fromNode=tempNode; 
                }
                line.arrowFlag=1;
            }
            else
            {
                if(line.toNode.id==node1ID)
                {
                    line.arrowFlag=0;
                    
                    var svgDoc = document.getElementById('svgGraph');
                    var doc = svgDoc.getSVGDocument();
                    var domline=doc.getElementById(lineID);
                    var domline1=doc.getElementById(lineID+"lineText");
                    domline.style.display="none";
                    domline1.style.display="none";
                }
            }   
            this.lines[lineID]=line;
            line.ChangeArrow();
        }
    }
    for(key in this.nodes)
    {
        if(this.nodes[key].isSelected)
        {
            var activeNode=this.nodes[key];
            break;
        }
    }
    this.SetActiveNode(activeNode);
}
SVG_GP.SetLineType = function(type)
{
    this.lineType = type;
}
SVG_GP.Draw=function()
{
    //creat graph:
    xmlns="http://www.w3.org/2000/svg";

    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var svgRoot=doc.getElementById("SvgRoot");    

    //creat graph:
    var graph = doc.createElementNS(xmlns, "g");
    graph.setAttribute('id', this.groupid);
    svgRoot.appendChild(graph);
    

    
    var nodeInfo = doc.createElementNS(xmlns, "text");
    nodeInfo.setAttribute('id', "nodeinfo");
    nodeInfo.setAttribute('display', "none");
    svgRoot.appendChild(nodeInfo);
       
    nodeInfo.setAttribute('font-size', "12");
    nodeInfo.setAttribute('fill', "black");
    
    
    var newSpan = doc.createElementNS(xmlns, "tspan");
    newSpan.setAttribute('id', "nodeinfotspan1");
    newSpan.setAttribute("space", "preserve");
    newSpan.appendChild(doc.createTextNode("temp"));
    nodeInfo.appendChild(newSpan);
    
    var newSpan = doc.createElementNS(xmlns, "tspan");
    newSpan.setAttribute('id', "nodeinfotspan2");
    newSpan.setAttribute('x', nodeInfo.getAttribute('x'));
    newSpan.setAttribute("dy", "18");
    newSpan.setAttribute("space", "preserve");
    newSpan.appendChild(doc.createTextNode("temp2"));
    nodeInfo.appendChild(newSpan);
    
    
    this.Layout();
    
    //render lines:
    for(var key in this.lines)
    {
        var line = this.lines[key];
        line.Render(graph);
        // line.SetStartEnd("false");
        this.AttachLineEvents(line);        
    }
    //render nodes:
    for(var key in this.nodes)
    {
        var node=this.nodes[key];
        node.Render(graph);
        this.AttachNodeEvents(node);
    }
    this.SetGraphPos();
}


SVG_GP.ExportChart=function()
{
}

SVG_GP.Expand=function(rules,keyword,db)
{
    var node=null;
    for(var key in this.nodes)
    {
        if(this.nodes[key].text==keyword) 
        {
            var activeNode=this.nodes[key];
            break;
        }
    }    
    this.InsertRules(activeNode,rules);
    
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var graph = doc.getElementById(this.groupid);
    for(var i in rules)
    {
        var rule=rules[i];
        
        //add new nodes
        this.AddNode(rule.FromId,rule.FromText,rule.FromCount,rule.FromRuleCount,rule.Database);
        this.AddNode(rule.ToId,rule.ToText,rule.ToCount,rule.ToRuleCount,rule.Database);
        
        //add new lines
        var line=this.AddLine(rule.FromId,rule.ToId,'',rule.Probability);
        if(line && !line.rendered) 
        {
            line.Render(graph);
            this.AttachLineEvents(line);
        }
        else if(line && line.toNode.id != rule.ToId)
        {
            line.arrowFlag=2;
            line.ChangeArrow();
        }
        var node=this.nodes[rule.FromId]; 
        if(!node.rendered )
        {
            node.Render(graph);
            this.AttachNodeEvents(node);
            if(this.fontSize!=0)
            {
                node.ChangeFontSize(this.fontSize);
            }
        }
        var node=this.nodes[rule.ToId]; 
        if(!node.rendered )
        {
            node.Render(graph);
            this.AttachNodeEvents(node);
            if(this.fontSize!=0)
            {
                node.ChangeFontSize(this.fontSize);
            }
        }
    }
    this.ImproveLayout();
    this.SetGraphPos();
    this.RuleListShow();
}

SVG_GP.Layout=function()
{
    var layout=new SVG_Layout(this);
    layout.Layout();
}

SVG_GP.ImproveLayout=function()
{
    var layout=new SVG_Layout(this);
    layout.Layout();
    for(var key in this.nodes)
    {
        var node=this.nodes[key];
        node.SetPosition();
    }
    for(var key in this.lines)
    {
        var line=this.lines[key];
        line.SetStartEnd();
    }
    this.SetGraphPos();
    
    

    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    for(var key in this.nodes)
    {
        var node = doc.getElementById(key);
        node.parentNode.appendChild( node );
        
        var text = doc.getElementById(key + "text");
        text.parentNode.appendChild( text );

        var span = doc.getElementById(key + "tspan");
        span.parentNode.appendChild( span );
    }
    
    
    var spaceLabel = document.getElementById("spaceLabel");
    var graph=doc.getElementById("groupgraph");
    spaceLabel.style.height = doc.defaultView.innerHeight + "px";
}

SVG_GP.RemoveNode=function(discardNode)
{
    if(this.rootNode==discardNode)
    {
        alert("It's Root!! You can not remove it.");
        return;
    }
    var id=discardNode.id;
    
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var graph=doc.getElementById(this.groupid);
    var node=doc.getElementById(id);
    var nodeId = node.id;
    if(node)
    {
        graph.removeChild(node);
        delete this.nodes[id];
        for( var key in this.lines)
        {
            if(this.lines[key].fromNode == discardNode || this.lines[key].toNode == discardNode)
            {
                var lineid = this.lines[key].id;
                var line = doc.getElementById(lineid);
                var line1 = doc.getElementById(lineid+"lineText");
                var discardLineText=doc.getElementById(lineid+"lineNewText");  
                if(this.lines[key].fromNode == discardNode )
                {
                    var keepNodes={};
                    var tnode=this.lines[key].toNode;
                    for(var id in this.Rules)
                    {
                        if(id != discardNode.id)
                        {
                            var rules=this.Rules[id];
                            for(var i in rules)
                            {
                                if(rules[i].FromId==tnode.id || rules[i].ToId==tnode.id)
                                {
                                    keepNodes[tnode.id]=tnode;
                                }
                                if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
                                {
                                    delete rules[i];
                                }
                            }
                        }
                    }                    
                }
                else
                {
                        var keepNodes={};
                        var tnode=this.lines[key].fromNode;
                        for(var id in this.Rules)
                        {
                            if(id != discardNode.id)
                            {
                                var rules=this.Rules[id];
                                for(i in rules)
                                {
                                    if(rules[i].FromId==tnode.id || rules[i].ToId==tnode.id)
                                    {
                                        keepNodes[tnode.id]=tnode;
                                    }
                                    if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
                                    {
                                        delete rules[i];
                                    }
                                }
                            }
                        }                        
                }
                
                var text = doc.getElementById(nodeId+"text");
        
        
                graph.removeChild(text); 
        
                graph.removeChild(line); 
                graph.removeChild(line1);
                graph.removeChild(discardLineText);
                delete this.lines[key];
            }
        }
    }
    if(this.Rules[discardNode.id])
    {
        var rules = this.Rules[discardNode.id];
        for(i in rules)
        {
            if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
            {
                delete rules[i];
            }
        }
    }
    this.SetActiveNode(this.rootNode);
    this.RuleListShow();
}

SVG_GP.RuleListShow=function()
{
    var rulelist = document.getElementById("RuleList");
    for(key in this.nodes)
    {
        if(this.nodes[key].isSelected)
        {
            var node=this.nodes[key];
            break;
        }
    }
    rulelist.innerHTML=this.GetRuleList(node);
}

var SVG_allRulesWindow = null;

SVG_GP.AllRulesShow=function()
{
    if (allRulesWindow == null || allRulesWindow.closed)
        allRulesWindow = window.open("RuleList.htm",null,"height=600,width=400,status=no,menubar=no,location=no,scrollbars=yes");
    var sTable;
    if(this.lineType=="co-occurrence")
    {
        sTable =" <table style='width:400px;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>co-occurrence</center></td> </tr></tHead><tbody>\n";
    }
    else
    {
        sTable =" <table style='width:400px;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>Mutual Info</center></td></tr></tHead><tbody>\n";
    }
    var existRules={};
    for(var key in this.Rules)
    {
        var rules = this.Rules[key];
        for(var i in rules)
        {
            var ruleId = rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            var ruleId2 = rules[i].ToText+":"+rules[i].FromText+":"+rules[i].Database;
            if(!existRules[ruleId] && !existRules[ruleId2])
            {
                existRules[ruleId]=rules[i];
                sTable += "<tr><td align='right' style='width:100px;'>"+rules[i].FromText+"</td> <td style='width:50px;'><center>----></center></td> <td align='left' style='width:100px;'>"+rules[i].ToText+"</td> <td style='width:150px;'><center>"+rules[i].Database+"</center></td> </tr>\n";                   
            }
        }
    }
     sTable += "</tbody></table>\n";
     for(;;)
     {
        if(allRulesWindow.document.body) 
        {
            allRulesWindow.document.body.innerHTML=sTable;
            allRulesWindow.focus();
            break;
        }
     }
}

SVG_GP.GetRuleList=function(node)
{
    var sTable;
    if(this.lineType == "co-occurrence")
    {
        sTable = " <table style='width:90%;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>co-occurrence</center></td> </tr></tHead><tbody>\n";
    }
    else
    {
        sTable = " <table style='width:90%;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>Mutual Info</center></td> </tr></tHead><tbody>\n";
    }    
   
    var text=this.nodes[node.id].text;
    this.RulesLength=this.RuleLength(this.nodes[node.id]);
    var existRules={};
    for(var id in this.Rules)
    {
        var rules=this.Rules[id];
            for (var i in rules)
            {
                    var ruleId = rules[i].FromText +":"+ rules[i].ToText +":"+ rules[i].Database;
                    var ruleId1 = rules[i].ToText +":"+ rules[i].FromText +":"+ rules[i].Database;
                    if((rules[i].FromText==text || rules[i].ToText==text) && !existRules[ruleId])
                    {
                        existRules[ruleId]=rules[i];
                        existRules[ruleId1]=rules[i];
                        sTable += "<tr> <td align='right'>"+rules[i].FromText+"</td> <td><center>---></center></td> <td align='left'>"+rules[i].ToText+"</td> <td><center>"+rules[i].Database+"</center></td> </tr>\n";                        
                    }
            }
     }
     sTable += "</tbody></table>\n";
     return sTable;
}

SVG_GP.SetActiveNode2=function(activeNode)
{
    //fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    //active node
    this.nodes[activeNode.id].Active();
    this.nodes[activeNode.id].isSelected=true;
    //set other nodes in graph
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var fromNode=line.fromNode;
        var toNode=line.toNode;
        if(fromNode==activeNode)
        {
            if(toNode.flag==0)
            {
                toNode.FillColor("#0CADD3");
                toNode.SetTextColor("#0088E4");
            }
            else if(toNode.flag==1)
            {
                toNode.FillColor("#FFF974");
                toNode.SetTextColor("#828282");
            }
            else if(toNode.flag==2)
            {
                toNode.FillColor("#84C225");
                toNode.SetTextColor("#0BBA23");
            }
        }
        else if(toNode==activeNode)
        {
            if(fromNode.flag==0)
            {
                fromNode.FillColor("#0CADD3");
                fromNode.SetTextColor("#0088E4");
            }
            else if(fromNode.flag==1)
            {
                fromNode.FillColor("#FFF974");
                fromNode.SetTextColor("#828282");
            }
            else if(fromNode.flag==2)
            {
                fromNode.FillColor("#84C225");
                fromNode.SetTextColor("#0BBA23");
            }
        }
    } 
    this.RuleListShow();
}

SVG_GP.SetActiveNode=function(activeNode)
{
    //fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    //active node
    this.nodes[activeNode.id].Active();
    this.nodes[activeNode.id].isSelected=true;
    //set other nodes in graph
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var fromNode=line.fromNode;
        var toNode=line.toNode;
        var flag=line.arrowFlag;
        if(flag==2)
        {
            if(fromNode==activeNode)
            {
                    toNode.FillColor("#84C225");
                    toNode.SetTextColor("#0BBA23");
            }
            else if(toNode==activeNode)
            {
                fromNode.FillColor("#84C225");
                fromNode.SetTextColor("#0BBA23");
            } 
        }
        else if(flag==1)
        {
            if(fromNode==activeNode)
            {
                toNode.FillColor("#FFF974");
                toNode.SetTextColor("#828282");
            }
            else if(toNode==activeNode)
            {
                fromNode.FillColor("#0CADD3");
                fromNode.SetTextColor("#0088E4");
            }
        }
    }
    this.RuleListShow();
}

SVG_GP.ActiveNodeNew=function(activeNode)
{ 
//fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    
    var activeNode=this.nodes[activeNode.id];
    activeNode.Active();
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var toNode=line.toNode;
        var fromNode=line.fromNode;
        if(toNode.id==activeNode.id)
        {
            var fromRC=this.MoreRules(fromNode);
            if(fromRC>0)
            {
                this.nodes[fromNode.id].FillColor("#0CADD3");//blue
                this.nodes[fromNode.id].SetTextColor("#0088E4");
            }
            else
            this.nodes[fromNode.id].FillColor("#FFF974");//yellow
        }
        else if(fromNode.id==activeNode.id)
        {
            var toRC=this.MoreRules(toNode);
            if(toRC>0)
            {    
                this.nodes[toNode.id].FillColor("#0CADD3");
                this.nodes[toNode.id].SetTextColor("#0088E4");
            }
            else
            this.nodes[toNode.id].FillColor("#FFF974");
        }
    }
}

SVG_GP.MoreRules=function(node)
{
    var length=0;
    var id=node.id;
    var exsit={};
    for(var key in this.Rules)
    {
        var rules=this.Rules[key];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText +":"+ rule.ToText+":"+rule.Database;
            if(!exsit[ruleId])
            {
                exsit[ruleId]=ruleId;
                if(rule.FromId==id || rule.ToId==id)
                {
                    length++;
                }
            }
        }
    }
    return node.ruleCount-length;
}

SVG_GP.GraphMoveL=function(val)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var graph=doc.getElementById(this.groupid);
    graph.style.left = parseInt(graph.style.left)+val;
}

SVG_GP.GraphMoveUp=function(val)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var graph=doc.getElementById(this.groupid);
    graph.style.top = parseInt(graph.style.top)+val;
}

SVG_GP.SetSelectedNode=function(node)
{
    for(var key in this.nodes)
    {
        this.nodes[key].Fade();
        this.nodes[key].SetBorderWeight(0);
        this.nodes[key].isSelected=false;
    }
    this.nodes[node.id].SetBorderWeight(3);
    this.nodes[node.id].isSelected=true;
    this.SetActiveNode(this.nodes[node.id]);
    this.RuleListShow();
}

SVG_GP.CancelSelected=function()
{
    for(var key in this.nodes)
    {
        this.nodes[key].SetBorderColor("#A36566");
        this.nodes[key].SetBorderWeight(0);
    }
}
SVG_GP.LineTooltipShow=function(line)
{
    var lineinf=this.lines[line.id];
    lineinf.Show(this.lineType);
}
SVG_GP.TooltipShow=function(node)
{
    var nodeinf=this.nodes[node.id];
    nodeinf.Show();
}

SVG_GP.Zoom=function(h)
{
    this.gSize=h;
    var coordSizeX=this.coordSizeX/h;
    var coordSizeY=this.coordSizeY/h;
    
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var group=doc.getElementById(this.groupid);
    group.coordSize=coordSizeX+","+coordSizeY;
    for(var key in this.nodes)
    {   //change font-size
        var node=this.nodes[key];
        var fontsize=node.textFontSize * h ;
        var temp = doc.getElementById(node.id);
        var text = doc.getElementById(node.id+"text");
        this.fontSize=fontsize;
        text.setAttribute('font-size', fontsize);
        //change text position
//        
//        var x=temp.getAttribute('cx')*h;
//        var y=temp.getAttribute('cy')*h;
//    text.setAttribute('x', x);
//    text.setAttribute('y', y);
//    var span = doc.getElementById(node.id + "tspan");
//    span.setAttribute('x', x);
    }
    for(var key in this.lines)
    {
        //change line weight
        var line=this.lines[key];
        var lineweight=line.lineWeight*h;
        var linestroke=doc.getElementById(line.id);
        // linestroke.stroke.weight=lineweight+"pt";
    }
}

SVG_GP.RuleListAdd=function(node)
{
    node=this.nodes[node.id];
    var l=this.RuleLength(node);
    this.RulesLength=l;
    var str=node.text+";"+l;
    ExpandNode("Add:"+str);
}
    
    
SVG_GP.RuleLength=function(node)
{
    var l=0;
    var eR={};
    for(var key in this.Rules)
    {
        var rules=this.Rules[key];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.FromId==node.id || rule.ToId==node.id  )
            {
                if( !eR[ruleId])
                {
                    eR[ruleId]=rule;
                    l++;
                }
            }
        }
    }
    return l;
}

SVG_GP.OutRuleLength=function(node)
{
    var l=0;
    var eR={};
        var rules=this.Rules[node.id];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.FromId==node.id && !eR[ruleId] )
            {
                eR[ruleId]=rule;
                    l++;
            }
        }
    return l;
}

SVG_GP.OutRuleAdd=function(node)
{
    node=this.nodes[node.id];
    var outL = this.OutRuleLength(node);
    if(outL>=5)
    {
        outL++;
    }
    var str = node.text+";"+outL;
    ExpandNode("AddOut:"+str);
}

SVG_GP.InRuleLength=function(node)
{
    var l=0;
    var eR={};
        var rules=this.Rules[node.id];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.ToId==node.id && !eR[ruleId] )
            {
                eR[ruleId]=rule;
                    l++;
            }
        }
    return l;
}

SVG_GP.InRuleAdd=function(node)
{
    node=this.nodes[node.id];
    var inL = this.InRuleLength(node);
    if(inL>=5)
    {
        inL++;
    }
    var str = node.text+";"+inL;
    ExpandNode("AddIn:"+str);
}

SVG_GP.CheckLength=function(length,db)
{
    length=parseInt(length);
    for(var key in this.nodes)
    {
        if (this.nodes[key].isSelected)
        {
            var id=this.nodes[key].id;
            break;
        }
    }
    var rules={};
    var tRs={};
    var outL=0;
    for(var k in this.Rules)
    {
        if(k==id)
        {
            rules=this.Rules[k];
        }
        else
        {
            var nRules=this.Rules[k];
            for(var t in nRules)
            {
                var rule = nRules[t];
                var RId = rule.FromText+":"+rule.ToText+":"+rule.Database ;
                if((rule.FromId==id || rule.ToId==id) && !tRs[RId])
                {
                    tRs[RId]=rule;
                    outL++;
                }
            }
        }
    }
    var length = length-outL;
    var loop=0;
    var fRules={};
    for(var i in rules)
    {
        if(loop>=length)
        {
            var tId=rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            if(!tRs[tId])
            {
                delete rules[i];
                loop++;
            }
            else
            {
            }
        }
        else
        {
            var tId=rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            if(!tRs[tId])
            {
                loop++;
            }
        }
    }
    return rules;
}

SVG_GP.AttachNodeEvents=function(node)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    for(var e in this.NodeEvents)
    {
        var dom=doc.getElementById(node.id);
        dom[e]=this.NodeEvents[e];
    }
}
SVG_GP.AttachLineEvents=function(line)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    for(var e in this.LineEvents)
    {
        var dom=doc.getElementById(line.id);
        dom[e]=this.LineEvents[e];
    }
}
SVG_GP.DragStart=function(e, node)
{
    this.x=e.clientX;
    this.y=e.clientY;
    this.nodes[node.id].canMove=true;;
    node.style.cursor="move";
}

SVG_GP.Draging=function(e, node)
{
    try
    {
        if(document.selection)
            document.selection.empty();
    }
    catch(e)
    {
        // alert(e.message);
    }
}

SVG_GP.DragStop=function(e, node)
{
    var nodeid=node.id;
    this.nodes[nodeid].canMove=false;
    node.style.cursor="default";
}

SVG_GP.DragDone=function()
{
}

SVG_GP.LineEvents={
    onmouseover:function(e){
                    var line=e.target;
                    if(line.tagName=='DIV')line=line.parentNode;
                    g.LineTooltipShow(line);
                },
    onmouseout: function(e){
                    var line=e.target;
                    if(line.tagName=='DIV')line=line.parentNode;
                    g.lines[line.id].Hide();                    
    }
}
SVG_GP.NodeEvents={
    onmouseover:function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.TooltipShow(node);
                },
    onmouseout: function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.nodes[node.id].Hide();
                    g.Draging(e, node);
                },
    onclick:    function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.SetSelectedNode(node);
                },
    ondblclick: function(e){                   
                    if(document.selection)
                        document.selection.empty();
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    var val=g.nodes[node.id].text;
                    val = "E:"+val+";"+"5";                    
                    ExpandNode(val);
                },
     onmousedown:function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.DragStart(e, node);
                },
     onmousemove:function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.Draging(e, node);
                },
     onmouseup:function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.DragStop(e, node);
                },
     oncontextmenu:function(e){
                    var node = e.target;
                    while(node.nodeType != node.ELEMENT_NODE)
	                    node = node.parentNode;
                    g.SetSelectedNode(node);
                }
}


/*-------------------Node--------------------------*/

function SVG_Node(id,text,count,ruleCount)
{
    this.borderColor="#999900";
    this.borderWidth=2;
    this.color="White";
    this.left=2;
    this.top=1;
    this.text=text;
    this.textColor="#549FE3";
    this.width=54;
    this.height=33;
    this.shape="oval";
    this.coordinate="0,0";
    this.id=id;
    this.fillColor="Green";
    this.textFontSize=14;
    this.textPosX=1;
    this.textPosY=13;
    this.isSelected=false;
    this.count=count;
    this.rendered=false;
    this.canMove=false;
    this.ruleCount=ruleCount;
    this.flag=-1;
}

SVG_NP=SVG_Node.prototype;

SVG_NP.Draging=function()
{
    
}

SVG_NP.Render=function(graph)
{
    if(!this.rendered)
    {
        this.rendered=true;
        this.left *= 60;
        this.top *= 60;
        var x = this.left;
        var y = this.top;
        
        xmlns="http://www.w3.org/2000/svg";
        
        var svgDoc = document.getElementById('svgGraph');
        var doc = svgDoc.getSVGDocument();
        var newNode = doc.createElementNS(xmlns, "ellipse");
        newNode.setAttribute('id', this.id);
        newNode.setAttribute('cx', x);
        newNode.setAttribute('cy', y);
        newNode.setAttribute('rx', this.width);
        newNode.setAttribute('ry', this.height);
        newNode.setAttribute('stroke-width', this.borderWidth);
        newNode.setAttribute('stroke', this.borderColor);
        newNode.setAttribute('style', "fill:url(#yellow_blank)");
        graph.appendChild(newNode);
        
        var newText = doc.createElementNS(xmlns, "text");
        newText.setAttribute('id', this.id + "text");
        newText.setAttribute('x', x);
        newText.setAttribute('y', y);
        newText.setAttribute('font-size', this.textFontSize);
        newText.setAttribute('font-family', "Arial");
        newText.setAttribute('fill', "black");
        newText.setAttribute('text-align', "center");
        newText.setAttribute('font-weight', "bolder");
        newText.setAttribute('text-anchor', "middle");
        newText.setAttribute("space", "preserve");
        
        
        var content;
        if(this.text.length>10)
        {
            content= this.text.substring(0,9)+"...";
        }
        else
        {
            content= this.text.replace("<","<<");
        }
        
        var newSpan = doc.createElementNS(xmlns, "tspan");
        newSpan.setAttribute("space", "preserve");
        newSpan.appendChild(doc.createTextNode(content));
        newText.appendChild(newSpan);
        
        var newSpan = doc.createElementNS(xmlns, "tspan");
        newSpan.setAttribute('id', this.id + "tspan");
        newSpan.setAttribute('x', x);
        newSpan.setAttribute("dy", "18");
        newSpan.setAttribute("space", "preserve");
        newSpan.appendChild(doc.createTextNode(this.count));
        newText.appendChild(newSpan);
        
        graph.appendChild(newText);
    } 
}

SVG_NP.Remove=function(graph)
{
    var discardNode=graph.children(this.id);
    graph.removeChild(discardNode);
}

SVG_NP.Active=function()
{
    this.FillColor("#0CADD3");//blue
    this.FillColor("#DB214C");//red
    this.SetTextColor("black");
    this.isSelected=true;
}

SVG_NP.Fade=function()
{
    this.FillColor("#C7C7C7");
    this.SetTextColor("#AAAAAA")
    this.SetBorderColor("#888888");
    this.isSelected=false;
}

SVG_NP.Hide=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var info=doc.getElementById("nodeinfo");
    info.setAttribute('display', "none");
}

SVG_NP.FillColor=function(color)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    this.fillColor=color;
    var node = doc.getElementById(this.id);
    node.setAttribute('style', "fill:" + this.fillColor);
}

SVG_NP.ChangeFontSize=function(size)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var text=doc.getElementById(this.id+"text");
    text.setAttribute('font-size', size);
}

SVG_NP.setTextFont=function(size)
{
    this.textFontSize=size;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var text=doc.getElementById(this.id+"text");
    text.setAttribute('font-size', this.textFontSize);
}

SVG_NP.SetArea=function()
{
}

SVG_NP.SetBorderColor=function(color)
{
    this.borderColor=color;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var node=doc.getElementById(this.id);
    node.setAttribute('stroke', this.borderColor);
}

SVG_NP.SetBorderWeight=function(h)
{
    this.borderWidth=h;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var node=doc.getElementById(this.id);
    node.setAttribute('stroke-width', this.borderWidth);
}

SVG_NP.SetCoordinate=function()
{
}

SVG_NP.SetPosition=function()
{
    this.left*=60;
    this.top*=60;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var node = doc.getElementById(this.id);
    var x = this.left;
    var y = this.top;
        
    node.setAttribute('cx', x);
    node.setAttribute('cy', y);
    
    
    var text = doc.getElementById(this.id + "text");
    text.setAttribute('x', x);
    text.setAttribute('y', y);
    
    var span = doc.getElementById(this.id + "tspan");
    span.setAttribute('x', x);
}

SVG_NP.SetShape=function()
{    
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var node = doc.getElementById(this.id);
    node.setAttribute('rx', this.width);
    node.setAttribute('ry', this.height);
}

SVG_NP.SetText=function(text)
{
    this.text=text;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    doc.getElementById(this.id+"text").innerText=this.text;
}

SVG_NP.SetTextPos=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var nodeText=doc.getElementById(this.id+"text");
}

SVG_NP.SetTextColor=function(color)
{
    this.textColor=color;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    doc.getElementById(this.id+"text").setAttribute('color', this.textColor);
}

SVG_NP.Show=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var info=doc.getElementById("nodeinfo");
    var node=doc.getElementById(this.id);
    var graph=doc.getElementById("groupgraph");
    info.setAttribute('display', 'block');
    var x = node.getAttribute('cx')/1 + doc.defaultView.innerWidth/2+this.width/2;
    var y = node.getAttribute('cy')/1 + doc.defaultView.innerHeight/2+this.height/2;
    info.setAttribute('x', x);
    info.setAttribute('y', y);
    
    var nodeinfotspan1 = doc.getElementById("nodeinfotspan1");
    nodeinfotspan1.firstChild.nodeValue = this.text;
    
    var nodeinfotspan2 = doc.getElementById("nodeinfotspan2");
    nodeinfotspan2.setAttribute('x', x);
    nodeinfotspan2.firstChild.nodeValue = this.count + " users searched this entity in a month";
    
    
//    if( (info.style.posLeft+121) > doc.offsetWidth)
//    {
//        info.style.posLeft -= 210;
//    }
//    if(info.style.posTop+58 > doc.offsetHeight)
//    {
//        info.style.posTop -= info.offsetHeight;
//    }
    
}

SVG_NP.AttachEvent=function(eventName,func)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    doc.getElementById(this.id).attachEvent(eventName,func);
}

/*------------------Line-------------------*/

function SVG_Line(id,from,to,flag,text)
{
    this.color="#5586A3";
    this.fromNode=from;
    this.toNode=to;
    this.dashType="Solid";
    this.arrowFlag=1;
    this.arrowType="classic";
    this.width=10;
    this.id=id;
    this.lineWeight=(parseInt(text)/100000)+1;
    this.rendered=false; 
    this.text = text;
}

SVG_LP=SVG_Line.prototype;

SVG_LP.Hide=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var info=doc.getElementById("nodeinfo");
    info.setAttribute('display', "none");
}
SVG_LP.Show=function(lineType)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var info=doc.getElementById("nodeinfo");    
    var graph=doc.getElementById("groupgraph");
    info.setAttribute('display', "block");
    var startpointX=(this.fromNode.left+this.toNode.left+this.fromNode.width+this.toNode.width)/4;
    var startpointY=(this.fromNode.top+this.toNode.top+this.fromNode.height+this.toNode.height)/4;
    info.setAttribute('x', startpointX + doc.defaultView.innerWidth/2);
    info.setAttribute('y', startpointY + doc.defaultView.innerHeight/2 -10);
    
    var nodeinfotspan1 = doc.getElementById("nodeinfotspan1");
    if(lineType == "co-occurrence")
    { 
        nodeinfotspan1.firstChild.nodeValue = "The two entities were search together "+this.text+" times";
    }
    else
    {
        nodeinfotspan1.firstChild.nodeValue = "The two entities Mutual Information is "+this.text;
    }    
    
    var nodeinfotspan2 = doc.getElementById("nodeinfotspan2");
    nodeinfotspan2.setAttribute('x', startpointX + doc.defaultView.innerWidth/2);
    nodeinfotspan2.firstChild.nodeValue = "";

//    if( (info.style.posLeft+121) > doc.offsetWidth)
//    {
//        info.style.posLeft -= 210;
//    }
//    if(info.style.posTop+58 > doc.offsetHeight)
//    {
//        info.style.posTop -= info.offsetHeight;
//    }
//    info.style.textAlign="left";             
    
}
SVG_LP.Remove=function(graph)
{
    var discardLine=graph.children(this.id);
    var discardLine1=graph.children(this.id+"lineText");    
    graph.removeChild(discardLine);
    graph.removeChild(discardLine1);
    var discardLineText=graph.children(this.id+"lineNewText");  
    graph.removeChild(discardLineText);
}

SVG_LP.ChangeArrow=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var line=doc.getElementById(this.id);
}

SVG_LP.Render=function(graph)
{
   if (!this.rendered)
   {
       this.rendered=true;
       var startpointX=this.fromNode.left*60;
       var startpointY=this.fromNode.top*60;
       var endpointX = this.toNode.left*60;
       var endpointY = this.toNode.top*60;


        xmlns="http://www.w3.org/2000/svg";
        var svgDoc = document.getElementById('svgGraph');
        var doc = svgDoc.getSVGDocument();
        var newLine = doc.createElementNS(xmlns, "line");
        newLine.setAttribute('id', this.id);
        newLine.setAttribute('x1', startpointX);
        newLine.setAttribute('y1', startpointY);
        newLine.setAttribute('x2', endpointX);
        newLine.setAttribute('y2', endpointY);
        newLine.setAttribute('fill', "blue");
        newLine.setAttribute('stroke-width', 1);
        newLine.setAttribute('stroke', "blue");
        graph.appendChild(newLine);
        var newLine1 = doc.createElementNS(xmlns, "line");
        newLine1.setAttribute('id', this.id + "lineText");
        newLine1.setAttribute('x1', startpointX);
        newLine1.setAttribute('y1', startpointY);
        newLine1.setAttribute('x2', endpointX);
        newLine1.setAttribute('y2', endpointY);
        graph.appendChild(newLine1);
        
        var newText = doc.createElementNS(xmlns, "text");
        newText.setAttribute('id', this.id + "lineNewText");
        newText.setAttribute('x', (startpointX + endpointX)/2);
        newText.setAttribute('y', (startpointY + endpointY)/2);
        newText.setAttribute('font-size', "14");
        newText.setAttribute('fill', "black");
        newText.setAttribute('text-align', "center");
        newText.setAttribute('font-weight', "bold");
        newText.setAttribute('text-anchor', "middle");
        
        var content;
        if(this.text.length>10)
        {
            content= this.text.substring(0,9)+"...";
        }
        else
        {
            content= this.text.replace("<","<<");
        }
        var nodeContent = doc.createTextNode(content);
        nodeContent.innerHTML+="<br />";
        nodeContent.innerHTML += this.count;
        newText.appendChild(nodeContent);
        graph.appendChild(newText);
   }
   else if (this.arrowFlag==2)
   {
       this.ChangeArrow();
       return this;
   }
}

SVG_LP.SetStartEnd=function()
{
    var start=this.fromNode;
    var end=this.toNode;
    var r1=start.width/2;
    var r2=start.height/2;
    var x1=start.left+r1;
    var y1=start.top+r2;
    var x2=end.left+r1;
    var y2=end.top+r2;
    var tx=x2-x1;
    var ty=y2-y1;
    var c=ty/tx;
    var tls=r1*r1*c*c+r2*r2;
    var tl=Math.sqrt(tls);
    var dl=r1*r2/tl;
    var dt=dl*c;
    if(tx<0)
    {
        x1-=dl;   x2+=dl;
        y1-=dt;   y2+=dt;
    }
    else
    {
        x1+=dl;   x2-=dl;
        y1+=dt;   y2-=dt;
    }
    
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var domline=doc.getElementById(this.id);
    var domline1=doc.getElementById(this.id+"lineText");

    var startpointX=this.fromNode.left;
    var startpointY=this.fromNode.top;
    var endpointX = this.toNode.left;
    var endpointY = this.toNode.top;
    
    if(x1)
    {
        domline.setAttribute('x1', startpointX);
        domline.setAttribute('y1', startpointY);
        domline.setAttribute('x2', endpointX);
        domline.setAttribute('y2',endpointY);
        
        domline1.setAttribute('x1', startpointX);
        domline1.setAttribute('y1', startpointY);
        domline1.setAttribute('x2', endpointX);
        domline1.setAttribute('y2', endpointY);
    }
    var lineNewText=doc.getElementById(this.id + "lineNewText");
    lineNewText.setAttribute('x', (startpointX + endpointX)/2);
    lineNewText.setAttribute('y', (startpointY + endpointY)/2);
}

SVG_LP.SetDashType=function(dashType)
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var line=doc.getElementById(this.id);
    line.stroke.dashStyle=dashType;
}

SVG_LP.SetStrokecolor=function(color)
{
    this.color=color;
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var line=doc.getElementById(this.id);
    line.stroke.color=this.color;
}

SVG_LP.SetWeight=function()
{
    var svgDoc = document.getElementById('svgGraph');
    var doc = svgDoc.getSVGDocument();
    var line=doc.getElementById(this.id);
    line.stroke.weight=this.lineWeight+"pt";
    
}


//////////////////////////-------------------Layout--------------------////////////////////////////////////

function SVG_Layout(graph) 
{
    this.graph = graph;
    this.iterations = 300;
    this.maxRepulsiveForceDistance = 6;
    this.k = 2;
    this.c = 0.01;
    this.maxVertexMovement = 0.5;
}


SVG_Layout.prototype.layoutIteration=function() 
{
    var tmp={};
    for (var key in this.graph.nodes) 
    {
        var node1 = this.graph.nodes[key];
        tmp[key] = true;
        for (var key2 in this.graph.nodes) 
        {
            if (!tmp[key2])
            {
                var node2 = this.graph.nodes[key2];                
                this.layoutRepulsive(node1, node2);
            }
        }
    }
        
        
    for (var key in this.graph.lines) {
            var edge = this.graph.lines[key];
            this.layoutAttractive(edge);             
        }
       

    for (var key in this.graph.nodes) 
    {
        var node = this.graph.nodes[key];
        var xmove = this.c * node.layoutForceX;
        var ymove = this.c * node.layoutForceY;

        var max = this.maxVertexMovement;
        if(xmove > max) xmove = max;
        if(xmove < -max) xmove = -max;
        if(ymove > max) ymove = max;
        if(ymove < -max) ymove = -max;
       
        node.left += xmove;
        node.top += ymove;
        node.layoutForceX = 0;
        node.layoutForceY = 0;
    }
},



SVG_Layout.prototype.layoutRepulsive=function(node1, node2) 
{
    var dx = node2.left - node1.left;
    var dy = node2.top - node1.top;
    var d2 = dx * dx + dy * dy;
    if(d2 < 0.01) 
    {
            dx = 0.1 * Math.random() + 0.1;
            dy = 0.1 * Math.random() + 0.1;
            var d2 = dx * dx + dy * dy;
    }
    var d = Math.sqrt(d2);
    if(d < this.maxRepulsiveForceDistance) 
   {
        var repulsiveForce = this.k * this.k / d;
        node2.layoutForceX += repulsiveForce * dx / d;
        node2.layoutForceY += repulsiveForce * dy / d;
        node1.layoutForceX -= repulsiveForce * dx / d;
        node1.layoutForceY -= repulsiveForce * dy / d;
   }
}

SVG_Layout.prototype.Layout=function() {
    this.layoutPrepare();
    for (var i = 0; i < this.iterations; i++) 
    {
            this.layoutIteration();
    }
    this.layoutCalcBounds();
},

SVG_Layout.prototype.layoutPrepare=function() {

    for (var key in this.graph.nodes) 
    {
        var node = this.graph.nodes[key];
        node.left = 0;
        node.top = 0;
        node.layoutForceX = 0;
        node.layoutForceY = 0;
    }               
},

SVG_Layout.prototype.layoutCalcBounds=function() 
{
    var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;

    for (var key in this.graph.nodes) 
    {
        var x = this.graph.nodes[key].left;
        var y = this.graph.nodes[key].top;
                               
        if(x > maxx) maxx = x;
        if(x < minx) minx = x;
        if(y > maxy) maxy = y;
        if(y < miny) miny = y;
    }

    this.graph.layoutMinX = minx;
    this.graph.layoutMaxX = maxx;
    this.graph.layoutMinY = miny;
    this.graph.layoutMaxY = maxy;
}

SVG_Layout.prototype.layoutAttractive=function(edge) {
        var node1 = edge.fromNode;
        var node2 = edge.toNode;
        var dx = node2.left - node1.left;
        var dy = node2.top - node1.top;
        var d2 = dx * dx + dy * dy;
        if(d2 < 0.01) {
                dx = 0.1 * Math.random() + 0.1;
                dy = 0.1 * Math.random() + 0.1;
                var d2 = dx * dx + dy * dy;
        }
        var d = Math.sqrt(d2);
        if(d > this.maxRepulsiveForceDistance) {
                d = this.maxRepulsiveForceDistance;
                d2 = d * d;
        }
        var attractiveForce = (d2 - this.k * this.k) / this.k;
        if(edge.weight == undefined || edge.weight < 1) edge.weight = 1;
        attractiveForce *= Math.log(edge.weight) * 0.5 + 1;
        node2.layoutForceX -= attractiveForce * dx / d;
        node2.layoutForceY -= attractiveForce * dy / d;
        node1.layoutForceX += attractiveForce * dx / d;
        node1.layoutForceY += attractiveForce * dy / d;
}

//-------rule------//
function SVG_Rule(FromId,FromText,ToId,ToText,FromCount,ToCount,Probability,ProbabilityVal,FromRuleCount,ToRuleCount,db)
{
    this.FromRuleCount=FromRuleCount;
    this.ToRuleCount=ToRuleCount;
    this.FromId=FromId;
    this.FromText=FromText;
    this.FromCount=FromCount;
    this.ToId=ToId;
    this.ToText=ToText;
    this.ToCount=ToCount;
    this.Probability=Probability;
    this.ProbabilityVal=ProbabilityVal;
    this.Database=db;
}