Project

General

Profile

Download (7.14 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: 40, bottom: 20, left: 40},
11
    width = 740 - margin.right - margin.left,
12
    height = 600 - 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
                xend: function(d) { return d.y; },
40
            },
41
            "bottomtop": {
42
                size: [width, height],
43
                x: function(d) { return d.x; },
44
                y: function(d) { return height - d.y; }
45
            },
46
            "leftright": {
47
                size: [height, width],
48
                x: function(d) { return d.y; },
49
                y: function(d) { return d.x; },
50
                xend: function(d) { return width - d.y; },
51
            }
52
    };
53
    // default setting is left-right
54
    var orientation = orientations.rightleft;    
55
    var tAnchorToTaxon = "start";
56
    var tAnchorConceptR = "end";
57
    var tAnchorFromTaxon = "start";
58
    var dirMult = 1;
59
    this.onStateChange = function() {
60
        crTree = this.getState().conceptRelationshipTree;
61
       
62
        if(crTree) {
63
            root = JSON.parse(connector.getState().conceptRelationshipTree);
64
                        
65
            if(root.direction === "left-right") {               
66
                orientation = orientations.leftright;       
67
                tAnchorToTaxon = "start";
68
                tAnchorConceptR = "end";
69
                tAnchorFromTaxon = "start";
70
                dirMult = 1;
71
            }
72
            if(root.direction === "right-left") {                
73
                orientation = orientations.rightleft;      
74
                tAnchorToTaxon = "end";
75
                tAnchorConceptR = "start";
76
                tAnchorFromTaxon = "end";
77
                dirMult = -1;
78
            }
79
                        
80
            diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });                
81
            tree = d3.layout.tree().size(orientation.size);
82
            update(root);
83
            d3.select(self.frameElement).style("height", "800px");
84
        }       
85
    }
86

    
87
    
88
    function update(source) {
89

    
90
        // Compute the new tree layout.
91
        var nodes = tree.nodes(root).reverse(),
92
        links = tree.links(nodes);
93

    
94
        // Normalize for fixed-depth.
95
        nodes.forEach(function(d) { d.y = d.depth * 180; });
96

    
97
        // Update the nodes…
98
        var node = svg.selectAll("g.node")
99
        .data(nodes, function(d) { return d.id || (d.id = ++i); });
100

    
101

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

    
108
        nodeEnter.append("circle")
109
        .attr("r", function(d) { return d.type === "ftaxon" || d.type === "ttaxon" ? 5 : d.type === "conceptr" ? 10 : 0; })
110
        .style("fill", function(d) { return d === selectedNode && d.type === "conceptr" ? "#DF7401" : "#fff"; });
111
        
112
        nodeEnter.append("text")
113
        .attr("x", function(d) { 
114
            if(d.type === "conceptr") { 
115
                return dirMult*50;
116
            } else {
117
                return d.type === "ttaxon" ? 1*dirMult*10 : -dirMult*40; 
118
            }
119
        })
120
        .attr("y", function(d) { return d.type === "conceptr" ? -20 : d.type === "ftaxon" ? 20: 0; })
121
        .attr("dy", ".35em")
122
        .attr("text-anchor",function(d) { 
123
            if(d.type === "ftaxon") {
124
                return tAnchorFromTaxon;
125
            }; 
126
            if(d.type === "conceptr") {
127
                return tAnchorConceptR;
128
            };
129
            if(d.type === "ttaxon") {
130
                return tAnchorToTaxon;
131
            };             
132
        })
133
        
134
        .text(function(d) { return d.name; })
135
        .style("font-style", function(d){return d.type === "conceptr" ? "normal" : "italic"})
136
        .style("font-weight", function(d){return d.type === "conceptr" ? "bold" : "normal"})
137
        .style("fill", function(d){return d.type === "conceptr" ? "#000000" : "#005C5C"})
138
        .style("fill-opacity", 1e-6);
139

    
140
        
141
        // Transition nodes to their new position.
142
        var nodeUpdate = node.transition()
143
        .duration(duration)
144
        .attr("transform", function(d) { 
145
            if(d.type === "conceptr") {
146
                return "translate(" + (orientation.x(d) + 20)  + "," + orientation.y(d) + ")";
147
            } else {
148
                return "translate(" + orientation.x(d)  + "," + orientation.y(d) + ")";
149
            }
150
        });
151

    
152
        nodeUpdate.select("circle")
153
        .attr("r", function(d) { return d.type === "ftaxon" || d.type === "ttaxon" ? 5 : d.type === "conceptr" ? 10 : 0; })
154
        .style("fill", function(d) { return d === selectedNode && d.type === "conceptr" ? "#DF7401" : "#fff"; });
155

    
156
        nodeUpdate.select("text")
157
        .style("fill-opacity", 1);
158

    
159
        // Transition exiting nodes to the parent's new position.
160
        var nodeExit = node.exit().transition()
161
            .duration(duration)
162
            .attr("transform", function(d) { return "translate(" + orientation.xend(source) + "," + orientation.y(source) + ")"; })
163
            .remove();
164

    
165
        nodeExit.select("circle")
166
            .attr("r", 1e-6);
167

    
168
        nodeExit.select("text")
169
            .style("fill-opacity", 1e-6);
170
        
171
        // Update the links…
172
        var link = svg.selectAll("path.link")
173
        .data(links, function(d) { return d.target.id; });
174

    
175
        // Remove links without transition
176
        link.exit().remove();
177
        
178
        // Enter any new links at the parent's previous position.
179
        link.enter().insert("path", "g")
180
        .attr("class", "link")
181
        .attr("d", function(d) {
182
            var o = {x: source.x, y: source.y};
183
            return diagonal({source: o, target: o});
184
        });
185

    
186
        // Transition links to their new position.
187
        link.transition()
188
        .duration(duration)
189
        .attr("d", diagonal);
190

    
191

    
192
    }
193

    
194
//  Toggle children on click.
195
    function click(d) {
196
        //root.children.forEach(collapse);
197

    
198
        if(d.type === "conceptr") {
199
            connector.select(d.uuid);
200
        }
201

    
202
        selectedNode = d;
203
        update(d);
204
    }
205
}
    (1-1/1)