Project

General

Profile

Revision 926b0cfc

Added by shye0000 about 9 years ago

Module dataset Explorer D3

View differences:

Module_DatasetExplorerD3_sitools2v3/DatasetExplorerD3.js
1
Ext.namespace('sitools.user.modules');
2

  
3
Ext.define( 'sitools.user.modules.DatasetExplorerD3', {
4
    extend: 'sitools.user.core.Module',
5

  
6

  
7
    init : function (moduleModel) {
8
        var view = Ext.create('sitools.user.view.modules.datasetExplorerD3.DatasetExplorerD3');
9
        this.setViewCmp(view);
10

  
11
        this.show(this.getViewCmp());
12

  
13
        this.callParent(arguments);
14
    },
15

  
16
    /**
17
     * method called when trying to save preference
18
     * 
19
     * @returns
20
     */
21
    _getSettings : function () {
22
        return {
23
            preferencesPath : "/modules",
24
            preferencesFileName : this.id
25
        };
26

  
27
    }
28

  
29
});
Module_DatasetExplorerD3_sitools2v3/DatasetExplorerD3View.js
1
Ext.namespace('sitools.user.view.modules.datasetExplorerD3');
2
/**
3
 * ProjectDescription Module
4
 * @class sitools.user.modules.projectDescription
5
 * @extends Ext.Panel
6
 */
7
Ext.define('sitools.user.view.modules.datasetExplorerD3.DatasetExplorerD3', {
8
    extend : 'Ext.panel.Panel',
9
    layout : 'fit',
10
    id : 'ds',
11
    border : false,
12
    bodyBorder : false,
13
    listeners: {
14
        //afterrender:function(){console.log( 'afterrender ' +this.getHeight())},
15
        boxready: function() {
16
            //alert(this.getHeight()+' '+this.getWidth());
17
            var me = this;
18
            //me.doc = Ext.getDoc();
19
            //me.callParent(arguments);
20
            me.drawMap();
21
                 },
22
        resize: function() {
23
            //alert(this.getHeight()+' '+this.getWidth());
24
            var me = this;
25
            d3.select("#vis").remove();
26
            //me.doc = Ext.getDoc();
27
            //me.callParent(arguments);
28
            me.drawMap();
29
        }
30
    },
31
    initComponent : function () {
32
        this.callParent(arguments);
33

  
34
    },
35

  
36
    drawMap : function() {
37
        if (Math.min(this.getHeight(),this.getWidth()) < 400) var fontSize = '0px';
38
        else if (Math.min(this.getHeight(),this.getWidth()) > 800) var fontSize = '14px';
39
        else var fontSize = (Math.round(Math.min(this.getHeight(),this.getWidth()).toFixed(1)/100)+Math.floor(Math.min(this.getHeight(),this.getWidth()).toFixed(1)/100)-2).toString()+'px';
40

  
41
        me = this;
42
        var project = Ext.getStore('ProjectStore').getProject();
43
        var d = document,
44
            g = d.getElementById('ds');
45
        if (this.getHeight() > this.getWidth()) {
46
        var width = this.getWidth()/1.02,
47
            height = width;
48
        } else {
49
            var height = this.getHeight()/1.05 ,
50
            width = height;
51
        }
52
        function t(n, e) {
53
            return n === e ? !0 : n.children ? n.children.some(function(n) {
54
                return t(n, e)
55
            }) : !1
56
        }
57

  
58
        function n(t) {
59
            if (t.children) {
60
                var e = t.children.map(n),
61
                r = d3.hsl(e[0]),
62
                a = d3.hsl(e[1]);
63
                return d3.hsl((r.h + a.h) / 2, 1.2 * r.s, r.l / 1.2)
64
            }
65
            return t.colour || "#fff"
66
        }
67

  
68
        function e(t) {
69
            var n = r(t),
70
                e = d3.interpolate(d.domain(), [t.x, t.x + t.dx]),
71
                a = d3.interpolate(u.domain(), [t.y, n]),
72
                i = d3.interpolate(u.range(), [t.y ? 20 : 0, o]);
73
            return function(t) {
74
                return function(n) {
75
                        return d.domain(e(n)), u.domain(a(n)).range(i(n)), x(t)
76
                }
77
            }
78
        }
79

  
80
        function r(t) {
81
            return t.children ? Math.max.apply(Math, t.children.map(r)) : t.y + t.dy
82
        }
83

  
84
        function a(t) {
85
            return .299 * t.r + .587 * t.g + .114 * t.b
86
        }
87
        var radius = width / 2,
88
            x = d3.scale.linear().range([0, 2 * Math.PI]),
89
            y = d3.scale.pow().exponent(1.3).domain([0, 1]).range([0, radius]),
90
            padding = 5,
91
            duration = 500;
92

  
93
        var color = d3.scale.category20c();
94

  
95
        var ds = d3.select("#ds");
96
        var div = ds.append("div").attr("id","vis");
97
        var vis = div.append("svg")
98
            .attr("width", width + padding * 2)
99
            .attr("height", height + padding * 2)
100
            .append("g")
101
            .attr("id", "container")
102
            .attr("transform", "translate(" + [radius + padding, radius + padding] + ")");
103
        var partition = d3.layout.partition()
104
            .sort(null)
105
            .value(function(d) {
106
                //console.log(Math.sqrt(d.nbRecord));
107
                return 5.8-d.depth;
108
            });
109

  
110
        var arc = d3.svg.arc()
111
            .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
112
            .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
113
            .innerRadius(function(d) { return Math.max(0, d.y ? y(d.y) : d.y); })
114
            .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
115
        //d3.json("graph.json", function(error, json) {
116
        d3.json(project.get('sitoolsAttachementForUsers')+"/graph?media=json", function(error, json) {
117
            d3.select("#container").on("mouseleave", mouseleave);
118
            //d3.select("#container").on("touchend", mouseleave);
119
            json.graph.text = 'Solar';
120
            json.graph.children = json.graph.nodeList;
121
            var nodes = partition.nodes({children: json.graph.children[0].children})
122
            /*.filter(function(d) {
123
                return (d.dx > 0.05); // 0.005 radians = 0.29 degrees
124
            })*/;
125
            var path = vis.selectAll("path").data(nodes);
126
            var pathEnter = path.enter().append("path")
127
            .attr("id", function(d, i) { return "path-" + i; })
128
            .attr("class", "pathSolarProject")
129
            .attr("d", arc)
130
            .attr("fill-rule", "evenodd")
131
            .style("fill", function(d, i) { if (i==0) return d.color = '#FDB813'; else return d.color = color((d.children ? d : d.parent).text);})
132
            .on("mouseover", mouseover)
133
            //.on("touchenter", mouseover)
134
            //.on("touchstart", mouseover)
135
            .on("click", click);
136
            var tooltips= pathEnter
137
                .append("title")
138
                .text(function(d, i) { if (i != 0) return d.description? d.description : d.text.split('<br/>')[0]; });
139

  
140
            var text = vis.selectAll("text").data(nodes);
141
            var textEnter = text.enter().append("text")
142
                .attr("class", "pathSolarProject")
143
                .style("fill-opacity", 1)
144
                .style("fill", function(d) {
145
                    return brightness(d3.rgb(d.color)) < 125 ? "#fff" : "#000";
146
                })
147
                .attr("text-anchor", function(d, i) {
148
                    if (i == 0) {
149
                        return "middle";
150
                    }
151
                    return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
152
                })
153
                .attr("dy", ".3em")
154
                .attr("dx", function(d, i){
155
                    if (i == 0) return 0;
156
                    return x(d.x + d.dx / 2) > Math.PI ? "-1.5em" : "1.5em";
157
                })
158
                .attr("transform", function(d, i) {
159
                    if (i == 0) {
160
                        return null;
161
                    }
162
                    var multiline = (d.text || "").split(" ").length > 1,
163
                    angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
164
                    rotate = angle + (multiline ? -.5 : 0);
165
                    return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
166
                })
167
                .on("click", click);
168
            textEnter.append("title")
169
                .attr("class", "pathSolarProject")
170
                .text(function(d, i) { if (i != 0) return d.description? d.description : d.text.split('<br/>')[0]; });
171
            var image = vis.selectAll("image").data(nodes);
172
            imageEnter = image.enter().append("image")
173
                .attr("class","dataIconImg pathSolarProject")
174
                .attr("xlink:href",function(d, i){
175
                    if (i == 0) return "";
176
                    else {
177
                        if (d.type == "node") {
178
                            if (d.text.search("Query form") > -1)
179
                                return brightness(d3.rgb(d.color)) < 125 ? "/sitools/upload/search-white.png" : "/sitools/upload/search-black.png";
180
                            else if (d.text.search("Display data") > -1)
181
                                return brightness(d3.rgb(d.color)) < 125 ? "/sitools/upload/database-white.png" : "/sitools/upload/database-black.png";
182
                            else
183
                                return "";
184
                        }
185
                        else return brightness(d3.rgb(d.color)) < 125 ? "/sitools/upload/database-white.png" : "/sitools/upload/database-black.png";
186
                    }
187
                })
188
                .attr('width', "1em")
189
                .attr('height', "1em")
190
                .style("fill-opacity", 1)
191
                .style("fill", function(d) {
192
                    return brightness(d3.rgb(d.color)) < 125 ? "#fff" : "#000";
193
                })
194
                .style('cursor','pointer')
195
                .attr("y", "-0.5em")
196
                .attr("x", function(d){
197
                    return x(d.x + d.dx / 2) > Math.PI ? "-1.2em" : "0.2em";
198
                })
199
                .attr("transform", function(d, i) {
200
                    if (i == 0) {
201
                        return null;
202
                    }
203
                    var multiline = (d.text || "").split(" ").length > 1,
204
                    angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
205
                    rotate = angle + (multiline ? -.5 : 0);
206
                    return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
207
                })
208
                .on("click", function(d,i) {
209
                    if (i == 0){
210
                        return false;
211
                    }
212
                    if (d.type == "node" && (d.text.search("Query form")>-1))
213
                        sitools.user.utils.DatasetUtils.clickDatasetIcone(d.text.split("clickDatasetIcone('")[1].split(", 'forms'")[0], 'forms');
214
                    if (d.type == "node" && (d.text.search("Display data")>-1))
215
                        sitools.user.utils.DatasetUtils.clickDatasetIcone(d.text.split("clickDatasetIcone('")[1].split("', 'data'")[0], 'data');
216
                    if (d.type == "dataset")
217
                        sitools.user.utils.DatasetUtils.clickDatasetIcone(d.url, 'data');
218
                    return false;
219
                })
220
                .on("mouseover", iconhover);
221
            function iconhover(d,i) {
222
                imageEnter.attr("width", function(e){
223
                        if (d.text == e.text) {
224
                            return "1.1em";
225
                        } else {
226
                            return "1em";
227
                        }
228
                    })
229
                    .attr("height", function(e){
230
                        if (d.text == e.text) {
231
                            return "1.1em";
232
                        } else {
233
                            return "1em";
234
                        }
235
                    });
236
            }
237
            image.append("svg:title")
238
                .text(function(d, i) {
239
                  if (i == 0) return "";
240
                    else {
241
                        if (d.type == "node") {
242
                            if (d.text.search("Query form") > -1)
243
                                return "Query form";
244
                            else if (d.text.search("Display data") > -1)
245
                                return "Display data";
246
                            else
247
                                return "";
248
                        }
249
                        else return "Display data";
250
                    }
251
            });
252
            if (Math.min(me.getHeight(), me.getWidth()) >= 400){
253
                var tspan = textEnter.append("tspan")
254
                    .attr("x", 0)
255
                    .style("font-weight", function(d, i) { return i == 0 ? "bold" : ""; })
256
                    .style("font-size", function(d, i) { return fontSize; })
257
                    .text(function(d, i) { if (i == 0) { return 'SOLAR'; } return d.depth ? d.text.split("<br/>")[0] : ""; });
258
            }
259
            function click(d) {
260
                d3.select("#container").on("mouseleave", null);
261
                d3.selectAll(".pathSolarProject").on("mouseover", null);
262
                path.transition()
263
                    .duration(duration)
264
                    .attrTween("d", arcTween(d));
265
                    d3.selectAll(".pathSolarProject")
266
                    .style("opacity", 1);
267
                setTimeout(function(){
268
                    d3.select("#container").on("mouseleave", mouseleave);
269
                    d3.selectAll(".pathSolarProject").on("mouseover", mouseover);
270
                        //.on("touchstart", mouseover)
271
                        //.on("touchenter", mouseover);
272
                }, duration);
273

  
274
                // Somewhat of a hack as we rely on arcTween updating the scales.
275
                text.style("visibility", function(e) {
276
                    return isParentOf(d, e) ? null : d3.select(this).style("visibility");
277
                })
278
                    .transition()
279
                    .duration(duration)
280
                    .attrTween("text-anchor", function(d, i) {
281
                        if (i == 0) {
282
                            return null;
283
                        }
284
                        return function() {
285
                            return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
286
                        };
287
                    })
288
                    .attr("dx", function(d, i){
289
                        if (i == 0) return 0;
290
                        else return x(d.x + d.dx / 2) > Math.PI ? "-1.5em" : "1.5em";
291
                    })
292
                    .attrTween("transform", function(d, i) {
293
                        if (i == 0) {
294
                            return null;
295
                        }
296
                        var multiline = (d.text || "").split(" ").length > 1;
297
                        return function() {
298
                            var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
299
                            rotate = angle + (multiline ? -.5 : 0);
300
                            return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
301
                        };
302
                    })
303
                    .style("fill-opacity", function(e) { return isParentOf(d, e) ? 1 : 1e-6; })
304
                    .each("end", function(e) {
305
                        d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
306
                    });
307
                setTimeout(function(){
308
                    text.attr("dx", function(d, i){
309
                        if (i == 0) return 0;
310
                        else return x(d.x + d.dx / 2) > Math.PI ? "-1.5em" : "1.5em";
311
                    });
312
                }, duration+20);
313
                image.style("visibility", function(e) {
314
                    return isParentOf(d, e) ? null : d3.select(this).style("visibility");
315
                })
316
                    .transition()
317
                    .duration(duration)
318
                    .attr("y", "-0.5em")
319
                    .attr("x", function(d){
320
                        return x(d.x + d.dx / 2) > Math.PI ? "-1.2em" : "0.2em";
321
                    })
322
                    .attrTween("transform", function(d, i) {
323
                        if (i == 0) {
324
                            return null;
325
                        }
326
                        var multiline = (d.text || "").split(" ").length > 1;
327
                        return function() {
328
                            var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
329
                            rotate = angle + (multiline ? -.5 : 0);
330
                            return "rotate(" + rotate + ")translate(" + (y(d.y) + padding) + ")rotate(" + (angle > 90 ? -180 : 0) + ")";
331
                        };
332
                    })
333
                    .style("fill-opacity", function(e) { return isParentOf(d, e) ? 1 : 1e-6; })
334
                    .each("end", function(e) {
335
                        d3.select(this).style("visibility", isParentOf(d, e) ? null : "hidden");
336
                    });
337
                setTimeout(function(){
338
                    image.attr("x", function(d){
339
                        return x(d.x + d.dx / 2) > Math.PI ? "-1.2em" : "0.2em";;
340
                    });
341
                }, duration+20);
342
            }
343
            function mouseleave(d) {
344
                // Hide the breadcrumb trail
345
                //d3.select("#trail")
346
                //  .style("visibility", "hidden");
347

  
348
                // Deactivate all segments during transition.
349
                d3.selectAll(".pathSolarProject").on("mouseover", null);
350

  
351
                // Transition each segment to full opacity and then reactivate it.
352
                d3.selectAll(".pathSolarProject")
353
                    .transition()
354
                    .duration(500)
355
                    .style("opacity", 1)
356
                    .each("end", function() {
357
                        d3.select(this).on("mouseover", mouseover);
358
                        //d3.select(this).on("touchstart", mouseover);
359
                        //d3.select(this).on("touchenter", mouseover);
360
                    });
361
            }
362

  
363
            function mouseover(d) {
364
                var sequenceArray = getAncestors(d);
365
                //updateBreadcrumbs(sequenceArray, percentageString);
366

  
367
                // Fade all the segments.
368
                d3.selectAll(".pathSolarProject")
369
                    .style("opacity", 0.4);
370
                // Then highlight only those that are an ancestor of the current segment.
371
                vis.selectAll(".pathSolarProject")
372
                    .filter(function(node) {
373
                        return (sequenceArray.indexOf(node) >= 0);
374
                    })
375
                    .style("opacity", 1);
376
                vis.selectAll("text")
377
                    .filter(function(node) {
378
                        return (sequenceArray.indexOf(node) >= 0);
379
                    })
380
                    .style("opacity", 1);
381
                vis.selectAll("image")
382
                    .filter(function(node) {
383
                        return (sequenceArray.indexOf(node) >= 0);
384
                    })
385
                    .style("opacity", 1);
386
            }
387
            function isParentOf(p, c) {
388
                if (p === c) return true;
389
                if (p.children) {
390
                    return p.children.some(function(d) {
391
                        return isParentOf(d, c);
392
                    });
393
                }
394
                return false;
395
            }
396

  
397
            function getAncestors(node) {
398
                var path = [];
399
                var current = node;
400
                while (current.parent) {
401
                    path.unshift(current);
402
                    current = current.parent;
403
                }
404
                path.unshift(current);
405
                return path;
406
            }
407

  
408
            // Interpolate the scales!
409
            function arcTween(d) {
410
                var my = maxY(d),
411
                    xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
412
                    yd = d3.interpolate(y.domain(), [d.y, my]),
413
                    yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
414
                return function(d) {
415
                    return function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
416
                };
417
            }
418

  
419
            function maxY(d) {
420
                return d.children ? Math.max.apply(Math, d.children.map(maxY)) : d.y + d.dy;
421
            }
422

  
423
            // http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
424
            function brightness(rgb) {
425
                return rgb.r * .299 + rgb.g * .587 + rgb.b * .114;
426
            }
427

  
428
        });
429
    },
430
    /**
431
     * method called when trying to save preference
432
     * @returns
433
     */
434
    _getSettings : function () {
435
        return {
436
            preferencesPath : "/modules",
437
            preferencesFileName : this.id,
438
            xtype : this.$className
439
        };
440

  
441
    }
442
});
Module_DatasetExplorerD3_sitools2v3/style.css
1
svg {
2
	position: absolute;
3
	top: 10px;
4
	left: 0;
5
	right: 0;
6
	margin-left: auto;
7
	margin-right: auto;
8
}
9
path {
10
    cursor: pointer;
11
    stroke: #fff;
12
    stroke-width: 1;
13
}
14
text {
15
    cursor: pointer;
16
    font-family: Arial, Helvetica, sans-serif;
17
}
18
#vis {
19
  border-radius: 50%;
20
}

Also available in: Unified diff