Completed
Push — master ( de7136...b8e623 )
by Chris
01:25
created

jsondash.handlers.handleCytoscape   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
dl 0
loc 34
rs 8.8571
c 1
b 0
f 0
nc 1
nop 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 21 1
1
/** global: jsondash */
2
/** global: c3 */
3
/** global: d3 */
4
/** global: venn */
5
/** global: Plotly */
6
7
jsondash.getJSON = function(container, url, callback) {
8
    if(!url) throw new Error('Invalid URL: ' + url);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
9
    var err_msg = null;
10
    d3.json(url, function(error, data){
11
        if(error) {
12
            jsondash.unload(container);
13
            err_msg = 'Error: ' + error.status + ' ' + error.statusText;
14
        }
15
        else if(!data) {
16
            jsondash.unload(container);
17
            err_msg = 'No data was found (invalid response).';
18
        }
19
        if(error || !data) {
20
            container.classed({error: true});
21
            container.select('.error-overlay')
22
                .classed({hidden: false})
23
                .select('.alert')
24
                .text(err_msg);
25
            jsondash.unload(container);
26
            return;
27
        }
28
        callback(error, data);
29
    });
30
};
31
32
33
/**
34
 * [getTitleBarHeight Return the height for a chart containers titlebar,
35
 *     plus any other computed box model properties.
36
 */
37
jsondash.getTitleBarHeight = function(container) {
38
    var titlebar = container.select('.widget-title');
39
    var titlebar_height = titlebar.node().getBoundingClientRect().height;
40
    var titlebar_padding = parseInt(titlebar.style('padding-bottom').replace('px', ''), 10);
41
    return titlebar_height + titlebar_padding;
42
};
43
44
/**
45
 * [getDynamicWidth Return the width for a container that has no specified width
46
 * (e.g. grid mode)]
47
 */
48
jsondash.getDynamicWidth = function(container, config) {
49
    if(isNaN(config.width)) {
50
        return d3.round(container.node().getBoundingClientRect().width);
51
    }
52
    return parseInt(config.width, 10);
53
};
54
55
56
/**
57
 * [getDiameter Calculate a valid diameter for a circular widget,
58
 * based on width/height to ensure the size never goes out of the container bounds.]
59
 */
60
jsondash.getDiameter = function(container, config) {
61
    var width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
62
    return d3.min([d3.round(width), config.height]);
63
};
64
65
/**
66
 * Handler for all cytoscape specifications
67
 */
68
jsondash.handlers.handleCytoscape = function(container, config) {
69
    'use strict';
70
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
71
    // Titlebar + padding + a bit extra to account for the bottom.
72
    var titlebar_offset = jsondash.getTitleBarHeight(container) * 1.2;
73
    container.selectAll('.chart-container').remove();
74
    container.append('div')
75
        .classed({'chart-container': true})
76
        .style({
77
        width: (_width - 10) + 'px',
78
        height: (config.height - titlebar_offset) + 'px'
79
    });
80
    jsondash.getJSON(container, config.dataSource, function(error, cyspec){
81
        // the `document.getElementByID` declaration in the cytoscape
82
        // spec is not serializable so we will ignore anything user
83
        // sent and just drop our selector in place of it.
84
        var override = {
85
            container: document.querySelector('[data-guid="' + config.guid + '"] .chart-container'),
86
            // We intentionally override w/h with null values,
87
            // so the graph is forced to be
88
            // constrained to the parent dimensions.
89
            layout: {
90
                width: null,
91
                height: null
92
            },
93
        };
94
        var spec = $.extend(cyspec, override);
95
        console.log(spec);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
96
        var cy = cytoscape(spec);
0 ignored issues
show
Unused Code introduced by
The variable cy seems to be never used. Consider removing it.
Loading history...
97
        // Look for callbacks potentially registered for third party code.
98
        jsondash.api.runCallbacks(container, config);
99
        jsondash.unload(container);
100
    });
101
};
102
103
/**
104
 * Handler for all vega-lite specifications
105
 */
106
jsondash.handlers.handleVegaLite = function(container, config) {
107
    'use strict';
108
    container.selectAll('.chart-container').remove();
109
    container.append('div').classed({'chart-container': true});
110
111
    jsondash.getJSON(container, config.dataSource, function(error, vlspec){
112
        var SCALE_FACTOR = 0.7; // very important to get sizing jusst right.
113
        var selector = '[data-guid="' + config.guid + '"] .chart-container';
114
        var width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
115
        var size = d3.max([config.height, width]);
116
        var overrides = {
117
            width: ~~(size * SCALE_FACTOR),
118
            height: ~~(config.height * SCALE_FACTOR)
119
        };
120
        var embedSpec = {
121
            mode: 'vega-lite',
122
            spec: $.extend({}, vlspec, overrides)
123
        };
124
        vg.embed(selector, embedSpec, function(error, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Bug introduced by
The variable vg seems to be never declared. If this is a global, consider adding a /** global: vg */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
125
            // Callback receiving the View instance and parsed Vega spec
126
            // result.view is the View, which resides under the '#vis' element
127
            if(error) {
128
                throw new Error('Error loading chart: ' + error);
129
            }
130
            // Change look of default buttons
131
            container.select('.vega-actions')
132
                .classed({'btn-group': true})
133
                .selectAll('a')
134
                .classed({'btn btn-xs btn-default': true});
135
136
            // Look for callbacks potentially registered for third party code.
137
            jsondash.api.runCallbacks(container, config);
138
            jsondash.unload(container);
139
        });
140
    });
141
};
142
143
/**
144
 * Handlers for various widget types. The method signatures are always the same,
145
 * but each handler can handle them differently.
146
 */
147
jsondash.handlers.handleYoutube = function(container, config) {
148
    // Clean up all previous.
149
    'use strict';
150
    container.selectAll('iframe').remove();
151
152
    function getAttr(prop, props) {
153
        // Return the propery from a list of properties for the iframe.
154
        // e.g. getAttr('width', ["width="900""]) --> "900"
155
        return props.filter(function(k, v){
0 ignored issues
show
Unused Code introduced by
The parameter v is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
156
            return k.startsWith(prop);
157
        })[0];
158
    }
159
160
161
    var url = config.dataSource;
0 ignored issues
show
Unused Code introduced by
The assignment to variable url seems to be never used. Consider removing it.
Loading history...
162
    var parts = config.dataSource.split(' ');
163
    var yt_width = parseInt(getAttr('width', parts).split('=')[1].replace(/"/gi, ''), 10);
164
    var height = parseInt(getAttr('height', parts).split('=')[1].replace(/"/gi, ''), 10);
165
    var width = isNaN(config.width) ? '100%' : yt_width;
166
    var url = getAttr('src', parts).replace('src=', '').replace(/"/gi, '');
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable url already seems to be declared on line 161. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
167
168
    // In the case of YouTube, we have to override the config dimensions
169
    // as this will be wonky when the aspect ratio is calculated. We will
170
    // defer to YouTube calculations instead.
171
    container.append('iframe')
172
        .attr('width', width)
173
        .attr('height', height)
174
        .attr('src', url)
175
        .attr('allowfullscreen', true)
176
        .attr('frameborder', 0);
177
    // Look for callbacks potentially registered for third party code.
178
    jsondash.api.runCallbacks(container, config);
179
    jsondash.unload(container);
180
};
181
182
/**
183
 * [handleGraph creates graphs using the dot format
184
 * spec with d3 and dagre-d3]
185
 */
186
jsondash.handlers.handleGraph = function(container, config) {
187
    'use strict';
188
    jsondash.getJSON(container, config.dataSource, function(error, data){
189
        container.selectAll('.chart-graph').remove();
190
        var h = config.height - jsondash.config.WIDGET_MARGIN_Y;
0 ignored issues
show
Unused Code introduced by
The variable h seems to be never used. Consider removing it.
Loading history...
191
        var w = config.width - jsondash.config.WIDGET_MARGIN_X;
0 ignored issues
show
Unused Code introduced by
The variable w seems to be never used. Consider removing it.
Loading history...
192
        var svg = container.append('svg').classed({'chart-graph': true});
193
        var svg_group = svg.append('g');
194
        var g = graphlibDot.read(data.graph);
0 ignored issues
show
Bug introduced by
The variable graphlibDot seems to be never declared. If this is a global, consider adding a /** global: graphlibDot */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
195
        var bbox = null;
0 ignored issues
show
Unused Code introduced by
The assignment to bbox seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
196
        // Create the renderer
197
        var render = new dagreD3.render();
0 ignored issues
show
Bug introduced by
The variable dagreD3 seems to be never declared. If this is a global, consider adding a /** global: dagreD3 */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
198
        render(svg_group, g);
199
        bbox = svg.node().getBBox();
200
        svg.attr('width', bbox.width)
201
            .attr('height', bbox.height);
202
        // Look for callbacks potentially registered for third party code.
203
        jsondash.api.runCallbacks(container, config);
204
        jsondash.unload(container);
205
    });
206
};
207
208
/**
209
 * [handleWordCloud create word clouds using the d3-cloud extension.]
210
 */
211
jsondash.handlers.handleWordCloud = function(container, config) {
212
    'use strict';
213
    jsondash.getJSON(container, config.dataSource, function(error, data){
214
        container.selectAll('.wordcloud').remove();
215
        var h     = config.height - jsondash.config.WIDGET_MARGIN_Y;
216
        var w     = config.width - jsondash.config.WIDGET_MARGIN_X;
217
        var svg   = container.append('svg').classed({'wordcloud': true});
218
        var fill  = d3.scale.category20();
0 ignored issues
show
Unused Code introduced by
The variable fill seems to be never used. Consider removing it.
Loading history...
219
        var cloud = d3.layout.cloud;
220
        var words = data.map(function(d) {
221
            return {text: d.text, size: d.size};
222
        });
223
        var layout = cloud()
224
            .size([w, h])
225
            .words(words)
226
            .padding(4)
227
            .rotate(function() {return ~~(Math.random() * 1) * 90;})
228
            .font('Arial')
229
            .fontSize(function(d) {return d.size;})
230
            .on('end', draw);
231
232
        layout.start();
233
234
        function draw(words) {
235
          svg
236
              .attr('width', layout.size()[0])
237
              .attr('height', layout.size()[1])
238
            .append('g')
239
              .attr('transform', 'translate(' + layout.size()[0] / 2 + ',' + layout.size()[1] / 2 + ')')
240
            .selectAll('text').data(words)
241
            .enter().append('text')
242
              .style('font-size', function(d) { return d.size + 'px'; })
243
              .style('font-family', 'arial')
244
              .style('fill', function(d, i) { return "#000"; })
0 ignored issues
show
Unused Code introduced by
The parameter d is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
245
              .attr('text-anchor', 'middle')
246
              .attr('transform', function(d) {
247
                return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
248
              })
249
              .text(function(d) { return d.text; });
250
        }
251
252
        // Look for callbacks potentially registered for third party code.
253
        jsondash.api.runCallbacks(container, config);
254
        jsondash.unload(container);
255
    });
256
};
257
258
jsondash.handlers.handleC3 = function(container, config) {
259
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
260
    'use strict';
261
    var init_config = {
262
        bindto: '[data-guid="' + config.guid + '"] .chart-container',
263
        legend: {
264
            show: true
265
        },
266
        size: {
267
            height: config.height - jsondash.config.WIDGET_MARGIN_Y,
268
            width: _width - jsondash.config.WIDGET_MARGIN_X
269
        },
270
        data: {
271
            type: config.type,
272
            url: config.dataSource,
273
            mimeType: 'json'
274
        },
275
        onrendered: function(){
276
            // Look for callbacks potentially registered for third party code.
277
            jsondash.api.runCallbacks(container, config);
278
            jsondash.unload(container);
279
        }
280
    };
281
    if(jsondash.util.isOverride(config)) {
282
        // Just use the raw payload for this widgets' options.
283
        jsondash.getJSON(container, config.dataSource, function(error, data){
284
            // Keep existing options if not specified.
285
            config = $.extend(init_config, data);
286
            c3.generate(init_config);
287
        });
288
        return;
289
    }
290
    if(config.type === 'timeseries') {
291
        init_config.axis = {
292
            x: {type: 'timeseries'}
293
        };
294
        // Map the corresponding data key and list of dates
295
        // to the `x` property.
296
        init_config.data.x = 'dates';
297
    }
298
    c3.generate(init_config);
299
};
300
301
jsondash.handlers.handleD3 = function(container, config) {
302
    'use strict';
303
    // Clean up all D3 charts in one step.
304
    container.selectAll('svg').remove();
305
    // Handle specific types.
306
    if(config.type === 'radial-dendrogram') { return jsondash.handlers.handleRadialDendrogram(container, config); }
307
    if(config.type === 'dendrogram') { return jsondash.handlers.handleDendrogram(container, config); }
308
    if(config.type === 'voronoi') { return jsondash.handlers.handleVoronoi(container, config); }
309
    if(config.type === 'treemap') { return jsondash.handlers.handleTreemap(container, config); }
310
    if(config.type === 'circlepack') { return jsondash.handlers.handleCirclePack(container, config); }
311
    throw new Error('Unknown type: ' + config.type);
312
};
313
314
jsondash.handlers.handleCirclePack = function(container, config) {
315
    'use strict';
316
    // Adapted from https://bl.ocks.org/mbostock/4063530
317
    var margin = jsondash.config.WIDGET_MARGIN_Y;
318
    var diameter = jsondash.getDiameter(container, config) - margin;
319
    var format = d3.format(',d');
320
    var pack = d3.layout.pack()
321
        .size([diameter, diameter])
322
        .value(function(d) { return d.size; });
323
324
    var svg = container
325
        .append('svg')
326
        .attr('width', diameter)
327
        .attr('height', diameter)
328
        .append('g');
329
330
    jsondash.getJSON(container, config.dataSource, function(error, data) {
331
        var node = svg.datum(data).selectAll('.node')
332
        .data(pack.nodes)
333
        .enter().append('g')
334
        .attr('class', function(d) { return d.children ? 'node' : 'leaf node'; })
335
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
336
337
        node.append('title')
338
        .text(function(d) { return d.name + (d.children ? '' : ': ' + format(d.size)); });
339
340
        node.append('circle')
341
        .attr('r', function(d) { return d.r; });
342
343
        node.filter(function(d) { return !d.children; }).append('text')
344
        .attr('dy', '.3em')
345
        .style('text-anchor', 'middle')
346
        .text(function(d) { return d.name.substring(0, d.r / 3); });
347
        // Look for callbacks potentially registered for third party code.
348
        jsondash.api.runCallbacks(container, config);
349
        jsondash.unload(container);
350
    });
351
    d3.select(self.frameElement).style("height", diameter + "px");
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
352
};
353
354
jsondash.handlers.handleTreemap = function(container, config) {
355
    'use strict';
356
    // Adapted from http://bl.ocks.org/mbostock/4063582
357
    var margin = {
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
358
        top: jsondash.config.WIDGET_MARGIN_Y / 2,
359
        bottom: jsondash.config.WIDGET_MARGIN_Y / 2,
360
        left: jsondash.config.WIDGET_MARGIN_X / 2,
361
        right: jsondash.config.WIDGET_MARGIN_X / 2
362
    };
363
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
364
    var width = _width - jsondash.config.WIDGET_MARGIN_X;
365
    var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
366
    var color = d3.scale.category20c();
367
    var treemap = d3.layout.treemap()
368
        .size([width, height])
369
        .sticky(true)
370
        .value(function(d) { return d.size; });
371
    // Cleanup
372
    container.selectAll('.treemap').remove();
373
    var div = container
374
        .append('div')
375
        .classed({treemap: true, 'chart-centered': true})
376
        .style('position', 'relative')
377
        .style('width', width + 'px')
378
        .style('height', height + 'px');
379
380
    jsondash.getJSON(container, config.dataSource, function(error, root) {
381
        var node = div.datum(root).selectAll('.node')
382
            .data(treemap.nodes)
383
            .enter().append('div')
384
            .attr('class', 'node')
385
            .call(position)
386
            .style('border', '1px solid white')
387
            .style('font', '10px sans-serif')
388
            .style('line-height', '12px')
389
            .style('overflow', 'hidden')
390
            .style('position', 'absolute')
391
            .style('text-indent', '2px')
392
            .style('background', function(d) {
393
                return d.children ? color(d.name) : null;
394
            })
395
            .text(function(d) {
396
                return d.children ? null : d.name;
397
            });
398
        d3.selectAll('input').on('change', function change() {
399
            var value = this.value === 'count'
400
            ? function() { return 1; }
401
            : function(d) { return d.size;};
402
            node
403
            .data(treemap.value(value).nodes)
404
            .transition()
405
            .duration(1500)
406
            .call(position);
407
        });
408
        // Look for callbacks potentially registered for third party code.
409
        jsondash.api.runCallbacks(container, config);
410
        jsondash.unload(container);
411
    });
412
413
    function position() {
414
        this.style('left', function(d) { return d.x + 'px'; })
415
            .style('top', function(d) { return d.y + 'px'; })
416
            .style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; })
417
            .style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; });
418
    }
419
};
420
421
jsondash.handlers.handleRadialDendrogram = function(container, config) {
422
    'use strict';
423
    // Code taken (and refactored for use here) from:
424
    // https://bl.ocks.org/mbostock/4339607
425
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
0 ignored issues
show
Unused Code introduced by
The variable _width seems to be never used. Consider removing it.
Loading history...
426
    var radius = jsondash.getDiameter(container, config);
427
    var cluster = d3.layout.cluster()
428
        .size([360, radius / 2 - 150]); // reduce size relative to `radius`
429
    var diagonal = d3.svg.diagonal.radial()
430
        .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
431
    var svg = container.append('svg')
432
        .attr('width', radius)
433
        .attr('height', radius);
434
    var g = svg.append('g');
435
    g.attr('transform', 'translate(' + radius / 2 + ',' + radius / 2 + ')');
436
437
    jsondash.getJSON(container, config.dataSource, function(error, root) {
438
        if (error) { throw error; }
439
        var nodes = cluster.nodes(root);
440
        var link = g.selectAll('path.link')
0 ignored issues
show
Unused Code introduced by
The variable link seems to be never used. Consider removing it.
Loading history...
441
            .data(cluster.links(nodes))
442
            .enter().append('path')
443
            .attr('class', 'link')
444
            .attr('d', diagonal);
445
        var node = g.selectAll('g.node')
446
            .data(nodes)
447
            .enter().append('g')
448
            .attr('class', 'node')
449
            .attr('transform', function(d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y + ')'; });
450
        node.append('circle')
451
            .attr('r', 4.5);
452
        node.append('text')
453
            .attr('dy', '.31em')
454
            .attr('text-anchor', function(d) { return d.x < 180 ? 'start' : 'end'; })
455
            .attr('transform', function(d) { return d.x < 180 ? 'translate(8)' : 'rotate(180)translate(-8)'; })
456
            .text(function(d) { return d.name; });
457
        // Look for callbacks potentially registered for third party code.
458
        jsondash.api.runCallbacks(container, config);
459
        jsondash.unload(container);
460
    });
461
    d3.select(self.frameElement).style('height', radius * 2 + 'px');
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
462
};
463
464
jsondash.handlers.handleDendrogram = function(container, config) {
465
    'use strict';
466
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
467
    // A general padding for the svg inside of the widget.
468
    // The cluster dendrogram will also need to have padding itself, so
469
    // the bounds are not clipped in the svg.
470
    var svg_pad = 20;
471
    var width = _width - svg_pad;
472
    var height = config.height - svg_pad;
473
    var PADDING = width / 4;
474
    var cluster = d3.layout.cluster()
475
        .size([height * 0.85, width - PADDING]);
476
    var diagonal = d3.svg.diagonal()
477
        .projection(function(d) { return [d.y, d.x]; });
478
    var svg = container
479
        .append('svg')
480
        .attr('width', width)
481
        .attr('height', height);
482
    var g = svg.append('g')
483
        .attr('transform', 'translate(40, 0)');
484
485
    jsondash.getJSON(container, config.dataSource, function(error, root) {
486
        var nodes = cluster.nodes(root);
487
        var links = cluster.links(nodes);
488
        var link = g.selectAll('.link')
0 ignored issues
show
Unused Code introduced by
The variable link seems to be never used. Consider removing it.
Loading history...
489
        .data(links)
490
        .enter().append('path')
491
        .attr('class', 'link')
492
        .attr('d', diagonal);
493
494
        var node = g.selectAll('.node')
495
        .data(nodes)
496
        .enter().append('g')
497
        .attr('class', 'node')
498
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
499
500
        node.append('circle').attr('r', 4.5);
501
        node.append('text')
502
        .attr('dx', function(d) { return d.children ? -8 : 8; })
503
        .attr('dy', 3)
504
        .style('text-anchor', function(d) { return d.children ? 'end' : 'start'; })
505
        .text(function(d) { return d.name; });
506
507
        // Look for callbacks potentially registered for third party code.
508
        jsondash.api.runCallbacks(container, config);
509
        jsondash.unload(container);
510
    });
511
};
512
513
jsondash.handlers.handleVoronoi = function(container, config) {
514
    'use strict';
515
    jsondash.getJSON(container, config.dataSource, function(error, data){
516
        var _width   = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
517
        var width    = _width - jsondash.config.WIDGET_MARGIN_X;
518
        var height   = config.height - jsondash.config.WIDGET_MARGIN_Y;
519
        var vertices = data;
520
        var voronoi  = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]);
521
        // Cleanup
522
        container.selectAll('svg').remove();
523
        var svg = container
524
            .append('svg')
525
            .attr('width', width)
526
            .attr('height', height);
527
        var path = svg.append('g').selectAll('path');
528
        svg.selectAll('circle')
529
            .data(vertices.slice(1))
530
            .enter().append('circle')
531
            .attr('transform', function(d) { return 'translate(' + d + ')'; })
532
            .attr('r', 1.5);
533
            redraw();
534
535
        function redraw() {
536
            path = path.data(voronoi(vertices), jsondash.util.polygon);
537
            path.exit().remove();
538
            path.enter().append('path')
539
            .attr('class', function(d, i) { return 'q' + (i % 9) + '-9'; })
540
            .attr('d', jsondash.util.polygon);
541
            path.order();
542
        }
543
        // Look for callbacks potentially registered for third party code.
544
        jsondash.api.runCallbacks(container, config);
545
        jsondash.unload(container);
546
    });
547
};
548
549
jsondash.handlers.handleSparkline = function(container, config) {
550
    'use strict';
551
    // Clean up old canvas elements
552
    container.selectAll('.sparkline-container').remove();
553
    var sparkline_type = config.type.split('-')[1];
554
    var spark = container
555
        .append('div')
556
        .classed({
557
            'sparkline-container': true,
558
            'text-center': true
559
        });
560
    spark = $(spark[0]);
561
    jsondash.getJSON(container, config.dataSource, function(data){
562
        var opts = {
563
            type: sparkline_type,
564
            width: config.width - jsondash.config.WIDGET_MARGIN_X,
565
            height: config.height - jsondash.config.WIDGET_MARGIN_Y
566
        };
567
        spark.sparkline(data, opts);
568
        // Look for callbacks potentially registered for third party code.
569
        jsondash.api.runCallbacks(container, config);
570
        jsondash.unload(container);
571
    });
572
};
573
574
jsondash.handlers.handleDataTable = function(container, config) {
575
    'use strict';
576
    // Clean up old tables if they exist, during reloading.
577
    container.selectAll('.dataTables_wrapper').remove();
578
    jsondash.getJSON(container, config.dataSource, function(error, res) {
579
        var keys = d3.keys(res[0]).map(function(d){
580
            return {data: d, title: d};
581
        });
582
        container
583
            .append('table')
584
            .classed({
585
                table: true,
586
                'table-striped': true,
587
                'table-bordered': true,
588
                'table-condensed': true
589
            });
590
        var opts = config.override ? res : {data: res, columns: keys};
591
        $(container.select('table')[0]).dataTable(opts).css({width: 'auto'});
592
        // Look for callbacks potentially registered for third party code.
593
        jsondash.api.runCallbacks(container, config);
594
        jsondash.unload(container);
595
    });
596
};
597
598
jsondash.handlers.handleSingleNum = function(container, config) {
599
    'use strict';
600
    container.selectAll('.singlenum').remove();
601
    jsondash.getJSON(container, config.dataSource, function(error, res){
602
        var data = res.data.data ? res.data.data : res.data;
603
        var num = container.select('.chart-container').append('div')
604
            .classed({singlenum: true})
605
            .text(data);
606
        data = String(data);
607
        // Add red or green, depending on if the number appears to be pos/neg.
608
        if(!res.noformat) {
609
            num.classed({
610
                'text-danger': data.startsWith('-'),
611
                'text-success': !data.startsWith('-')
612
            });
613
        }
614
        // Allow custom colors.
615
        if(res.color && res.noformat) {
616
            num.style('color', res.color);
617
        }
618
        // Get title height to offset box.
619
        var title_h = container
0 ignored issues
show
Unused Code introduced by
The variable title_h seems to be never used. Consider removing it.
Loading history...
620
            .select('.widget-title')
621
            .node()
622
            .getBoundingClientRect()
623
            .height;
624
        var h = config.height - jsondash.config.WIDGET_MARGIN_Y;
625
        num.style({
626
            'line-height': h + 'px',
627
            height: h + 'px',
628
            width: config.width - jsondash.config.WIDGET_MARGIN_X
629
        });
630
        var digits = String(data).length;
631
        var size = jsondash.util.getDigitSize()(digits);
632
        num.style('font-size', size + 'px');
633
        // Look for callbacks potentially registered for third party code.
634
        jsondash.api.runCallbacks(container, config);
635
        jsondash.unload(container);
636
    });
637
};
638
639
jsondash.handlers.handleTimeline = function(container, config) {
640
    'use strict';
641
    jsondash.getJSON(container, config.dataSource, function(data){
642
        container.append('div').attr('id', 'widget-' + config.guid);
643
        var timeline = new TL.Timeline('widget-' + config.guid, data);
0 ignored issues
show
Unused Code introduced by
The variable timeline seems to be never used. Consider removing it.
Loading history...
Bug introduced by
The variable TL seems to be never declared. If this is a global, consider adding a /** global: TL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
644
        // Look for callbacks potentially registered for third party code.
645
        jsondash.api.runCallbacks(container, config);
646
        jsondash.unload(container);
647
    });
648
};
649
650
jsondash.handlers.handleIframe = function(container, config) {
651
    'use strict';
652
    container.selectAll('iframe').remove();
653
    var iframe = container.append('iframe');
654
    iframe.attr({
655
        border: 0,
656
        src: config.dataSource,
657
        height: config.height - jsondash.config.WIDGET_MARGIN_Y,
658
        width: isNaN(config.width) ? '100%' : config.width - jsondash.config.WIDGET_MARGIN_X
659
    });
660
    // Look for callbacks potentially registered for third party code.
661
    jsondash.api.runCallbacks(container, config);
662
    jsondash.unload(container);
663
};
664
665
jsondash.handlers.handleCustom = function(container, config) {
666
    'use strict';
667
    container.selectAll('.custom-container').remove();
668
    $.get(config.dataSource, function(html){
669
        container.append('div').classed({'custom-container': true}).html(html);
670
        // Look for callbacks potentially registered for third party code.
671
        jsondash.api.runCallbacks(container, config);
672
        jsondash.unload(container);
673
    });
674
};
675
676
jsondash.handlers.handleVenn = function(container, config) {
677
    'use strict';
678
    container.selectAll('.venn').remove();
679
    jsondash.getJSON(container, config.dataSource, function(error, data){
680
        var chart = venn.VennDiagram();
681
        var cont = container
682
            .append('div')
683
            .classed({venn: true});
684
        cont.datum(data).call(chart);
685
        cont.select('svg')
686
            .attr('width', config.width - jsondash.config.WIDGET_MARGIN_X)
687
            .attr('height', config.height - jsondash.config.WIDGET_MARGIN_Y);
688
        // Look for callbacks potentially registered for third party code.
689
        jsondash.api.runCallbacks(container, config);
690
        jsondash.unload(container);
691
    });
692
};
693
694
jsondash.handlers.handlePlotly = function(container, config) {
695
    'use strict';
696
    var id = 'plotly-' + config.guid;
697
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
698
    container.selectAll('.plotly-container').remove();
699
    container.append('div')
700
        .classed({'plotly-container': true})
701
        .attr('id', id);
702
    jsondash.getJSON(container, config.dataSource, function(error, data){
703
        var plotly_wrapper =  d3.select('#' + id);
704
        delete data.layout.height;
705
        delete data.layout.width;
706
        data.layout.margin = {l: 20, r: 20, b: 20, t: 50};
707
        if(config.override) {
708
            Plotly.plot(id, data.data, data.layout || {}, data.options || {});
709
        } else {
710
            Plotly.plot(id, data);
711
        }
712
       plotly_wrapper.select('.svg-container').style({
713
            'margin': '0 auto',
714
            'width': isNaN(config.width) ? '100%' : config.width,
715
            'height': config.height
716
        });
717
        plotly_wrapper.select('#scene').style({
718
            'width': _width,
719
            'height': config.height
720
        });
721
        // Look for callbacks potentially registered for third party code.
722
        jsondash.api.runCallbacks(container, config);
723
        jsondash.unload(container);
724
    });
725
};
726