Project

General

Profile

Download (6.23 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 = 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 tAnchorWithChildren = "end";
56
    var tAnchorWithoutChildren = "start";
57
    var dirMult = 1;
58
    this.onStateChange = function() {
59
        crTree = this.getState().conceptRelationshipTree;
60

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

    
84
    
85
    function update(source) {
86

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

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

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

    
98

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

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

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

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

    
132
        nodeUpdate.select("text")
133
        .style("fill-opacity", 1);
134

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

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

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

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

    
162
        // Transition links to their new position.
163
        link.transition()
164
        .duration(duration)
165
        .attr("d", diagonal);
166

    
167

    
168
    }
169

    
170
//  Toggle children on click.
171
    function click(d) {
172
        //root.children.forEach(collapse);
173

    
174
        if(d.type === "conceptr") {
175
            connector.select(d.uuid);
176
        }
177

    
178
        selectedNode = d;
179
        update(d);
180
    }
181
}
    (1-1/1)