Project

General

Profile

Download (6.32 KB) Statistics
| Branch: | Tag: | Revision:
1

    
2
/**
3
 * D3 Layout Tree (inspired by http://bl.ocks.org/mbostock/4339083)
4
 * which displays a list concept relationships between a 'from' taxon 
5
 * and a number of 'to' taxon
6
 */
7
window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function() {
8
    var connector = this;
9
    var diagramElement = connector.getElement();
10
    var margin = {top: 20, right: 120, bottom: 20, left: 120},
11
    width = 960 - margin.right - margin.left,
12
    height = 800 - margin.top - margin.bottom;
13

    
14
    var i = 0,
15
    duration = 750,
16
    root;
17

    
18
    var tree;
19
    var diagonal;
20

    
21
    var svg = d3.select(diagramElement).append("svg")
22
    .attr("width", width + margin.right + margin.left)
23
    .attr("height", height + margin.top + margin.bottom)
24
    .append("g")
25
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
26

    
27
    var selectedNode;
28
    
29
    var orientations = {
30
            "topbottom": {
31
                size: [width, height],
32
                x: function(d) { return d.x; },
33
                y: function(d) { return d.y; }
34
            },
35
            "rightleft": {
36
                size: [height, width],
37
                x: function(d) { return width - d.y; },
38
                y: function(d) { return d.x; }
39
            },
40
            "bottomtop": {
41
                size: [width, height],
42
                x: function(d) { return d.x; },
43
                y: function(d) { return height - d.y; }
44
            },
45
            "leftright": {
46
                size: [height, width],
47
                x: function(d) { return d.y; },
48
                y: function(d) { return d.x; }
49
            }
50
    };
51
    // default setting is left-right
52
    var orientation = orientations.rightleft;    
53
    var tAnchorWithChildren = "end";
54
    var tAnchorWithoutChildren = "start";
55
    var dirMult = 1;
56
    this.onStateChange = function() {
57
        crTree = this.getState().conceptRelationshipTree;
58

    
59
        if(crTree) {
60
            root = JSON.parse(connector.getState().conceptRelationshipTree);
61
                        
62
            if(root.direction === "left-right") {               
63
                orientation = orientations.leftright;       
64
                tAnchorWithChildren = "end";
65
                tAnchorWithoutChildren = "start";
66
                dirMult = 1;
67
            }
68
            if(root.direction === "right-left") {                
69
                orientation = orientations.rightleft;      
70
                tAnchorWithChildren = "start";
71
                tAnchorWithoutChildren = "end";
72
                dirMult = -1;
73
            }
74
                        
75
            diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });                
76
            tree = d3.layout.tree().size(orientation.size);
77
            update(root);
78
            d3.select(self.frameElement).style("height", "800px");
79
        }           
80
    }
81

    
82
    
83
    function update(source) {
84

    
85
        // Compute the new tree layout.
86
        var nodes = tree.nodes(root).reverse(),
87
        links = tree.links(nodes);
88

    
89
        // Normalize for fixed-depth.
90
        nodes.forEach(function(d) { d.y = d.depth * 180; });
91

    
92
        // Update the nodes…
93
        var node = svg.selectAll("g.node")
94
        .data(nodes, function(d) { return d.id || (d.id = ++i); });
95

    
96

    
97
        // Enter any new nodes at the parent's previous position.
98
        var nodeEnter = node.enter().append("g")
99
        .attr("class", "node")
100
        .attr("transform", function(d) { return "translate(" + orientation.x(source) + "," + orientation.y(source) + ")"; })
101
        .on("click", click);
102

    
103
        nodeEnter.append("circle")
104
        .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
105
        .style("fill", function(d) { return d === source && d.type === "conceptr" ? "#DF7401" : "#fff"; });
106
        
107
        nodeEnter.append("text")
108
        .attr("x", function(d) { 
109
            if(d.type === "conceptr") { 
110
                return dirMult*50;
111
            } else {
112
                return d.children || d._children ? -1*dirMult*10 : dirMult*10; 
113
            }
114
        })
115
        .attr("y", function(d) { return d.type === "conceptr" ? -20 : 0; })
116
        .attr("dy", ".35em")
117
        .attr("text-anchor", function(d) { return d.children || d._children ? tAnchorWithChildren : tAnchorWithoutChildren; })
118
        .text(function(d) { return d.name; })
119
        .style("fill-opacity", 1e-6);
120

    
121
        // Transition nodes to their new position.
122
        var nodeUpdate = node.transition()
123
        .duration(duration)
124
        .attr("transform", function(d) { return "translate(" + orientation.x(d) + "," + orientation.y(d) + ")"; });
125

    
126
        nodeUpdate.select("circle")
127
        .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
128
        .style("fill", function(d) { return d === selectedNode && d.type === "conceptr" ? "#DF7401" : "#fff"; });
129

    
130
        nodeUpdate.select("text")
131
        .style("fill-opacity", 1);
132

    
133
        // Transition exiting nodes to the parent's new position.
134
        var nodeExit = node.exit().transition()
135
            .duration(duration)
136
            .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
137
            .remove();
138

    
139
        nodeExit.select("circle")
140
            .attr("r", 1e-6);
141

    
142
        nodeExit.select("text")
143
            .style("fill-opacity", 1e-6);
144
        
145
        // Update the links…
146
        var link = svg.selectAll("path.link")
147
        .data(links, function(d) { return d.target.id; });
148

    
149
        // Transition exiting nodes to the parent's new position.
150
        link.exit().transition()
151
            .duration(duration)
152
            .attr("d", function(d) {
153
              var o = {x: source.x, y: source.y};
154
              return diagonal({source: o, target: o});
155
            })
156
            .remove();
157
        
158
        // Enter any new links at the parent's previous position.
159
        link.enter().insert("path", "g")
160
        .attr("class", "link")
161
        .attr("d", function(d) {
162
            var o = {x: source.x, y: source.y};
163
            return diagonal({source: o, target: o});
164
        });
165

    
166
        // Transition links to their new position.
167
        link.transition()
168
        .duration(duration)
169
        .attr("d", diagonal);
170

    
171

    
172
    }
173

    
174
//  Toggle children on click.
175
    function click(d) {
176
        //root.children.forEach(collapse);
177

    
178
        if(d.type === "conceptr") {
179
            connector.select(d.uuid);
180
        }
181

    
182
        selectedNode = d;
183
        update(d);
184
    }
185
}
    (1-1/1)