aboutsummaryrefslogblamecommitdiffstats
path: root/html/js/git-deps-graph.js
blob: 6fdac689a8c400a4517851223198e3495cd62862 (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                                                                      




                                  
                           
 

            



                    





                                                     
                        
                                         

                                
 



                                    
                                                             
 
                         
 
                                                  


                               


                                          

                                               
                                                  


                                          

                                    




                                        
                                        



                                     
                                        
                                  
                                    
                                      
                                   
 


                                                                  

                                                
 



                                         
                                                  

                                       







                                                                              


                                                      
 
                                                                      


                                                                      

                       




                                                                  
 

                               
                                       













                                                                      
 


                                                                     
                                         
                                                                             



                                          


                                                                      





                                                                             
               
           
 
                                        
 
                                                            

                                            


                                                    

                                             
               
              


       



                               



























                                                                                              
                  




                                                                                         
var WIDTH   = 960,
    HEIGHT  = 500,
    MARGIN  = 14,   // space in between <rects>
    PADDING =  5,   // space in between <text> label and <rect> border
    EDGE_ROUTING_MARGIN = 3;

var color = d3.scale.category20();

var d3cola = cola.d3adaptor()
    .avoidOverlaps(true)
    .size([WIDTH, HEIGHT]);

var svg, fg;

jQuery(function () {
    draw_graph();
});

function redraw_on_zoom () {
    fg.attr("transform",
            "translate(" + d3.event.translate + ")" +
            " scale(" + d3.event.scale + ")");
}

function draw_graph () {
    svg = d3.select("body").append("svg")
        .attr("width", WIDTH)
        .attr("height", HEIGHT);

    svg.append('rect')
        .attr('class', 'background')
        .attr('width', "100%")
        .attr('height', "100%")
        .call(d3.behavior.zoom().on("zoom", redraw_on_zoom));

    fg = svg.append('g');

    d3.json("test.json", function (error, graph) {
        d3cola
            .nodes(graph.nodes)
            .links(graph.links)
            .flowLayout("y", 150)
            .symmetricDiffLinkLengths(30);
            //.jaccardLinkLengths(100);

        // define arrow markers for graph links
        fg.append('svg:defs').append('svg:marker')
            .attr('id', 'end-arrow')
            .attr('viewBox', '0 -5 10 10')
            .attr('refX', 6)
            .attr('markerWidth', 8)
            .attr('markerHeight', 8)
            .attr('orient', 'auto')
          .append('svg:path')
            .attr('d', 'M0,-5L10,0L0,5')
            .attr('fill', '#000');

        var path = fg.selectAll(".link")
            .data(graph.links)
          .enter().append('svg:path')
            .attr('class', 'link');

        var node = fg.selectAll(".node")
                .data(graph.nodes)
                .enter().append("g")
                .attr("class", "node")
                .call(d3cola.drag);

        // Initialize tooltip
        var tip = d3.tip().attr('class', 'd3-tip').html(tip_html);
        fg.call(tip);
        // Hide tooltip when we start dragging
        d3cola.drag().on('dragstart', tip.hide);

        var rect = node.append("rect")
            .attr("rx", 5).attr("ry", 5);

        var label = node.append("text")
            .text(function (d) { return d.name; })
            .each(function (d) {
                var b = this.getBBox();
                // Calculate width/height of rectangle from text bounding box.
                d.rect_width  = b.width  + 2 * PADDING;
                d.rect_height = b.height + 2 * PADDING;
                // Now set the node width/height as used by cola for
                // positioning.  This has to include the margin
                // outside the rectangle.
                d.width  = d.rect_width  + 2 * MARGIN;
                d.height = d.rect_height + 2 * MARGIN;
            });
        // label.append("title")
        //     .text(function (d) { return d.name; });

        rect.attr('width',  function (d, i) { return d.rect_width;  })
            .attr('height', function (d, i) { return d.rect_height; })
            .on('mouseover', tip.show)
            .on('mouseout',  tip.hide);

        // Centre label
        label
            .attr("x", function (d) { return d.rect_width  / 2; })
            .attr("y", function (d) { return d.rect_height / 2; })
            .on('mouseover', tip.show)
            .on('mouseout',  tip.hide);

        d3cola.start(10,20,20);

        d3cola.on("tick", function () {
            node.each(function (d) {
                // cola sets the bounds property which is a Rectangle
                // representing the space which other nodes should not
                // overlap.  The innerBounds property seems to tell
                // cola the Rectangle which is the visible part of the
                // node, minus any blank margin.
                d.innerBounds = d.bounds.inflate(-MARGIN);
            });

            node.attr("transform", function (d) {
                return "translate(" +
                    d.innerBounds.x + "," +
                    d.innerBounds.y + ")";
            });

            path.each(function (d) {
                if (isIE()) this.parentNode.insertBefore(this, this);
            });
            path.attr("d", function (d) {
                // Undocumented: https://github.com/tgdwyer/WebCola/issues/52
                cola.vpsc.makeEdgeBetween(
                    d,
                    d.source.innerBounds,
                    d.target.innerBounds,
                    // This value is related to but not equal to the
                    // distance of arrow tip from object it points at:
                    5
                );
                var lineData = [
                    { x: d.sourceIntersection.x, y: d.sourceIntersection.y },
                    { x: d.arrowStart.x, y: d.arrowStart.y }
                ];
                return lineFunction(lineData);
            });
        });

        // d3cola.on("end", routeEdges);

        // turn on overlap avoidance after first convergence
        // d3cola.on("end", function () {
        //    if (!d3cola.avoidOverlaps()) {
        //        graph.nodes.forEach(function (v) {
        //            v.width = v.height = 10;
        //        });
        //        d3cola.avoidOverlaps(true);
        //        d3cola.start();
        //    }
        // });
    });
}

function tip_html (d) {
    return d.describe || d.sha;
}

var lineFunction = d3.svg.line()
    .x(function (d) { return d.x; })
    .y(function (d) { return d.y; })
    .interpolate("linear");

var routeEdges = function () {
    d3cola.prepareEdgeRouting(EDGE_ROUTING_MARGIN);
    path.attr("d", function (d) {
        return lineFunction(d3cola.routeEdge(d)
            // // show visibility graph
            //, function (g) {
            //    if (d.source.id === 10 && d.target.id === 11) {
            //        g.E.forEach(function (e) {
            //            vis.append("line").attr("x1", e.source.p.x).attr("y1", e.source.p.y)
            //                .attr("x2", e.target.p.x).attr("y2", e.target.p.y)
            //                .attr("stroke", "green");
            //        });
            //    }
            // }));
        );
    });
    if (isIE()) {
        path.each(function (d) {
            this.parentNode.insertBefore(this, this);
        });
    }
};

function isIE () {
    return (navigator.appName == 'Microsoft Internet Explorer') ||
            ((navigator.appName == 'Netscape') &&
             (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent)
              != null));
}