Completed
Push — master ( 7e0621...e07260 )
by Chris
01:17
created

jsondash.handlers.handleC3   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 74

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
cc 2
dl 0
loc 74
rs 9.0335
c 3
b 1
f 1
nc 1
nop 2

3 Functions

Rating   Name   Duplication   Size   Complexity  
B 0 28 5
A 0 5 1
A 0 20 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 sigma.js specifications
67
 */
68
jsondash.handlers.handleSigma = 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
    // Sigmajs just assumes an ID for the querySelector, so we need to add one
74
    // to the child container.
75
    var new_id = 'sigma-' + jsondash.util.guid();
76
    var width = (_width - 10) + 'px';
77
    var height = (config.height - titlebar_offset) + 'px';
78
    container
79
        .select('.chart-container')
80
        .attr('id', new_id)
81
        .style({
82
        width: width,
83
        height: height
84
    });
85
    jsondash.getJSON(container, config.dataSource, function(error, data){
86
        var sig = new sigma({
0 ignored issues
show
Bug introduced by
The variable sigma seems to be never declared. If this is a global, consider adding a /** global: sigma */ 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...
Coding Style Best Practice introduced by
By convention, constructors like sigma should be capitalized.
Loading history...
Unused Code introduced by
The variable sig seems to be never used. Consider removing it.
Loading history...
87
          graph: data,
88
          width: width,
89
          height: height,
90
          container: new_id
91
        });
92
        // Look for callbacks potentially registered for third party code.
93
        jsondash.api.runCallbacks(container, config);
94
        jsondash.unload(container);
95
    });
96
};
97
98
/**
99
 * Handler for all cytoscape specifications
100
 */
101
jsondash.handlers.handleCytoscape = function(container, config) {
102
    'use strict';
103
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
104
    // Titlebar + padding + a bit extra to account for the bottom.
105
    var titlebar_offset = jsondash.getTitleBarHeight(container) * 1.2;
106
    container
107
        .select('.chart-container')
108
        .style({
109
        width: (_width - 10) + 'px',
110
        height: (config.height - titlebar_offset) + 'px'
111
    });
112
    jsondash.getJSON(container, config.dataSource, function(error, cyspec){
113
        // the `document.getElementByID` declaration in the cytoscape
114
        // spec is not serializable so we will ignore anything user
115
        // sent and just drop our selector in place of it.
116
        var override = {
117
            container: document.querySelector('[data-guid="' + config.guid + '"] .chart-container'),
118
            // We intentionally override w/h with null values,
119
            // so the graph is forced to be
120
            // constrained to the parent dimensions.
121
            layout: {
122
                width: null,
123
                height: null
124
            },
125
        };
126
        var spec = $.extend(cyspec, override);
127
        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...
128
        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...
129
        // Look for callbacks potentially registered for third party code.
130
        jsondash.api.runCallbacks(container, config);
131
        jsondash.unload(container);
132
    });
133
};
134
135
/**
136
 * Handler for all vega-lite specifications
137
 */
138
jsondash.handlers.handleVegaLite = function(container, config) {
139
    'use strict';
140
    jsondash.getJSON(container, config.dataSource, function(error, vlspec){
141
        var SCALE_FACTOR = 0.7; // very important to get sizing jusst right.
142
        var selector = '[data-guid="' + config.guid + '"] .chart-container';
143
        var width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
144
        var size = d3.max([config.height, width]);
145
        var overrides = {
146
            width: ~~(size * SCALE_FACTOR),
147
            height: ~~(config.height * SCALE_FACTOR)
148
        };
149
        var embedSpec = {
150
            mode: 'vega-lite',
151
            spec: $.extend({}, vlspec, overrides)
152
        };
153
        vg.embed(selector, embedSpec, function(error, result) {
0 ignored issues
show
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...
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...
154
            // Callback receiving the View instance and parsed Vega spec
155
            // result.view is the View, which resides under the '#vis' element
156
            if(error) {
157
                throw new Error('Error loading chart: ' + error);
158
            }
159
            // Change look of default buttons
160
            container.select('.vega-actions')
161
                .classed({'btn-group': true})
162
                .selectAll('a')
163
                .classed({'btn btn-xs btn-default': true});
164
            // Look for callbacks potentially registered for third party code.
165
            jsondash.api.runCallbacks(container, config);
166
            jsondash.unload(container);
167
        });
168
    });
169
};
170
171
/**
172
 * Handlers for various widget types. The method signatures are always the same,
173
 * but each handler can handle them differently.
174
 */
175
jsondash.handlers.handleYoutube = function(container, config) {
176
    // Clean up all previous.
177
    'use strict';
178
    function getAttr(prop, props) {
179
        // Return the propery from a list of properties for the iframe.
180
        // e.g. getAttr('width', ["width="900""]) --> "900"
181
        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...
182
            return k.startsWith(prop);
183
        })[0];
184
    }
185
186
187
    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...
188
    var parts = config.dataSource.split(' ');
189
    var yt_width = parseInt(getAttr('width', parts).split('=')[1].replace(/"/gi, ''), 10);
190
    var height = parseInt(getAttr('height', parts).split('=')[1].replace(/"/gi, ''), 10);
191
    var width = isNaN(config.width) ? '100%' : yt_width;
192
    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 187. 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...
193
194
    // In the case of YouTube, we have to override the config dimensions
195
    // as this will be wonky when the aspect ratio is calculated. We will
196
    // defer to YouTube calculations instead.
197
    container
198
        .select('.chart-container')
199
        .append('iframe')
200
        .attr('width', width)
201
        .attr('height', height)
202
        .attr('src', url)
203
        .attr('allowfullscreen', true)
204
        .attr('frameborder', 0);
205
    // Look for callbacks potentially registered for third party code.
206
    jsondash.api.runCallbacks(container, config);
207
    jsondash.unload(container);
208
};
209
210
/**
211
 * [handleGraph creates graphs using the dot format
212
 * spec with d3 and dagre-d3]
213
 */
214
jsondash.handlers.handleGraph = function(container, config) {
215
    'use strict';
216
    jsondash.getJSON(container, config.dataSource, function(error, data){
217
        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...
218
        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...
219
        var svg = container
220
            .select('.chart-container')
221
            .append('svg')
222
            .classed({'chart-graph': true});
223
        var svg_group = svg.append('g');
224
        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...
225
        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...
226
        // Create the renderer
227
        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...
228
        render(svg_group, g);
229
        bbox = svg.node().getBBox();
230
        svg.attr('width', bbox.width)
231
            .attr('height', bbox.height);
232
        // Look for callbacks potentially registered for third party code.
233
        jsondash.api.runCallbacks(container, config);
234
        jsondash.unload(container);
235
    });
236
};
237
238
/**
239
 * [handleWordCloud create word clouds using the d3-cloud extension.]
240
 */
241
jsondash.handlers.handleWordCloud = function(container, config) {
242
    'use strict';
243
    jsondash.getJSON(container, config.dataSource, function(error, data){
244
        var h     = config.height - jsondash.config.WIDGET_MARGIN_Y;
245
        var w     = config.width - jsondash.config.WIDGET_MARGIN_X;
246
        var svg   = container
247
            .select('.chart-container')
248
            .append('svg')
249
            .classed({'wordcloud': true});
250
        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...
251
        var cloud = d3.layout.cloud;
252
        var words = data.map(function(d) {
253
            return {text: d.text, size: d.size};
254
        });
255
        var layout = cloud()
256
            .size([w, h])
257
            .words(words)
258
            .padding(4)
259
            .rotate(function() {return ~~(Math.random() * 1) * 90;})
260
            .font('Arial')
261
            .fontSize(function(d) {return d.size;})
262
            .on('end', draw);
263
264
        layout.start();
265
266
        function draw(words) {
267
          svg
268
              .attr('width', layout.size()[0])
269
              .attr('height', layout.size()[1])
270
            .append('g')
271
              .attr('transform', 'translate(' + layout.size()[0] / 2 + ',' + layout.size()[1] / 2 + ')')
272
            .selectAll('text').data(words)
273
            .enter().append('text')
274
              .style('font-size', function(d) { return d.size + 'px'; })
275
              .style('font-family', 'arial')
276
              .style('fill', function(d, i) { return "#000"; })
0 ignored issues
show
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...
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...
277
              .attr('text-anchor', 'middle')
278
              .attr('transform', function(d) {
279
                return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
280
              })
281
              .text(function(d) { return d.text; });
282
        }
283
284
        // Look for callbacks potentially registered for third party code.
285
        jsondash.api.runCallbacks(container, config);
286
        jsondash.unload(container);
287
    });
288
};
289
290
jsondash.handlers.handleC3 = function(container, config) {
291
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
292
    'use strict';
293
    var init_config = {
294
        bindto: '[data-guid="' + config.guid + '"] .chart-container',
295
        legend: {
296
            show: true
297
        },
298
        size: {
299
            height: config.height - jsondash.config.WIDGET_MARGIN_Y,
300
            width: _width - jsondash.config.WIDGET_MARGIN_X
301
        },
302
        data: {},
303
        onrendered: function(){
304
            // Look for callbacks potentially registered for third party code.
305
            jsondash.api.runCallbacks(container, config);
306
            jsondash.unload(container);
307
        }
308
    };
309
310
    /**
311
     * [normalizeData Transform data from a standardized jsondash
312
     *     format into one suitable for c3.]
313
     */
314
    function normalizeData(data, type) {
315
        // For most cases, we build out N columns into ['label', 0, 1, 2, 3] format
316
        // from data in format: {'foo': [1, 2]} or format {'foo': 1}
317
        var cols = [];
318
        if(type === 'donut' || type === 'gauge' || type === 'pie') {
319
            $.each(data, function(label, val){
320
                cols.push([label, val]);
321
            });
322
            return cols;
323
        }
324
        if(type === 'timeseries') {
325
            var dates = ['x'];
326
            data.dates.map(function(date, _){
0 ignored issues
show
Unused Code introduced by
The parameter _ 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...
327
                dates.push(date);
328
            });
329
            cols.push(dates);
330
        }
331
        $.each(data, function(label, vals){
332
            if(label !== 'dates') {
333
                var newarr = [label];
334
                vals.map(function(val, _){
0 ignored issues
show
Unused Code introduced by
The parameter _ 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...
335
                    newarr.push(val);
336
                });
337
                cols.push(newarr);
338
            }
339
        });
340
        return cols;
341
    }
342
343
    jsondash.getJSON(container, config.dataSource, function(error, data){
344
        if(jsondash.util.isOverride(config)) {
345
            // Just use the raw payload for this widgets' options.
346
            // Keep existing options if not specified.
347
            init_config = $.extend(init_config, data);
348
        } else {
349
            if(config.type === 'timeseries') {
350
                // Map the corresponding data key and list of dates
351
                // to the `x` property.
352
                init_config.axis = {
353
                    x: {type: 'timeseries'}
354
                };
355
                init_config.data.x = 'x';
356
            } else {
357
                init_config.data.type = config.type;
358
            }
359
            init_config.data.columns = normalizeData(data, config.type);
360
        }
361
        c3.generate(init_config);
362
    });
363
};
364
365
jsondash.handlers.handleD3 = function(container, config) {
366
    'use strict';
367
    // Handle specific types.
368
    if(config.type === 'radial-dendrogram') { return jsondash.handlers.handleRadialDendrogram(container, config); }
369
    if(config.type === 'dendrogram') { return jsondash.handlers.handleDendrogram(container, config); }
370
    if(config.type === 'voronoi') { return jsondash.handlers.handleVoronoi(container, config); }
371
    if(config.type === 'treemap') { return jsondash.handlers.handleTreemap(container, config); }
372
    if(config.type === 'circlepack') { return jsondash.handlers.handleCirclePack(container, config); }
373
    throw new Error('Unknown type: ' + config.type);
374
};
375
376
jsondash.handlers.handleCirclePack = function(container, config) {
377
    'use strict';
378
    // Adapted from https://bl.ocks.org/mbostock/4063530
379
    var margin = jsondash.config.WIDGET_MARGIN_Y;
380
    var diameter = jsondash.getDiameter(container, config) - margin;
381
    var format = d3.format(',d');
382
    var pack = d3.layout.pack()
383
        .size([diameter, diameter])
384
        .value(function(d) { return d.size; });
385
    var svg = container
386
        .select('.chart-container')
387
        .append('svg')
388
        .attr('width', diameter)
389
        .attr('height', diameter)
390
        .append('g');
391
392
    jsondash.getJSON(container, config.dataSource, function(error, data) {
393
        var node = svg.datum(data).selectAll('.node')
394
        .data(pack.nodes)
395
        .enter().append('g')
396
        .attr('class', function(d) { return d.children ? 'node' : 'leaf node'; })
397
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
398
399
        node.append('title')
400
        .text(function(d) { return d.name + (d.children ? '' : ': ' + format(d.size)); });
401
402
        node.append('circle')
403
        .attr('r', function(d) { return d.r; });
404
405
        node.filter(function(d) { return !d.children; }).append('text')
406
        .attr('dy', '.3em')
407
        .style('text-anchor', 'middle')
408
        .text(function(d) { return d.name.substring(0, d.r / 3); });
409
        // Look for callbacks potentially registered for third party code.
410
        jsondash.api.runCallbacks(container, config);
411
        jsondash.unload(container);
412
    });
413
    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...
414
};
415
416
jsondash.handlers.handleTreemap = function(container, config) {
417
    'use strict';
418
    // Adapted from http://bl.ocks.org/mbostock/4063582
419
    var margin = {
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
420
        top: jsondash.config.WIDGET_MARGIN_Y / 2,
421
        bottom: jsondash.config.WIDGET_MARGIN_Y / 2,
422
        left: jsondash.config.WIDGET_MARGIN_X / 2,
423
        right: jsondash.config.WIDGET_MARGIN_X / 2
424
    };
425
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
426
    var width = _width - jsondash.config.WIDGET_MARGIN_X;
427
    var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
428
    var color = d3.scale.category20c();
429
    var treemap = d3.layout.treemap()
430
        .size([width, height])
431
        .sticky(true)
432
        .value(function(d) { return d.size; });
433
    var div = container
434
        .select('.chart-container')
435
        .append('div')
436
        .classed({treemap: true, 'chart-centered': true})
437
        .style('position', 'relative')
438
        .style('width', width + 'px')
439
        .style('height', height + 'px');
440
441
    jsondash.getJSON(container, config.dataSource, function(error, root) {
442
        var node = div.datum(root).selectAll('.node')
443
            .data(treemap.nodes)
444
            .enter().append('div')
445
            .attr('class', 'node')
446
            .call(position)
447
            .style('border', '1px solid white')
448
            .style('font', '10px sans-serif')
449
            .style('line-height', '12px')
450
            .style('overflow', 'hidden')
451
            .style('position', 'absolute')
452
            .style('text-indent', '2px')
453
            .style('background', function(d) {
454
                return d.children ? color(d.name) : null;
455
            })
456
            .text(function(d) {
457
                return d.children ? null : d.name;
458
            });
459
        d3.selectAll('input').on('change', function change() {
460
            var value = this.value === 'count'
461
            ? function() { return 1; }
462
            : function(d) { return d.size;};
463
            node
464
            .data(treemap.value(value).nodes)
465
            .transition()
466
            .duration(1500)
467
            .call(position);
468
        });
469
        // Look for callbacks potentially registered for third party code.
470
        jsondash.api.runCallbacks(container, config);
471
        jsondash.unload(container);
472
    });
473
474
    function position() {
475
        this.style('left', function(d) { return d.x + 'px'; })
476
            .style('top', function(d) { return d.y + 'px'; })
477
            .style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; })
478
            .style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; });
479
    }
480
};
481
482
jsondash.handlers.handleRadialDendrogram = function(container, config) {
483
    'use strict';
484
    // Code taken (and refactored for use here) from:
485
    // https://bl.ocks.org/mbostock/4339607
486
    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...
487
    var radius = jsondash.getDiameter(container, config);
488
    var cluster = d3.layout.cluster()
489
        .size([360, radius / 2 - 150]); // reduce size relative to `radius`
490
    var diagonal = d3.svg.diagonal.radial()
491
        .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
492
    var svg = container
493
        .select('.chart-container')
494
        .append('svg')
495
        .attr('width', radius)
496
        .attr('height', radius);
497
    var g = svg.append('g');
498
    g.attr('transform', 'translate(' + radius / 2 + ',' + radius / 2 + ')');
499
500
    jsondash.getJSON(container, config.dataSource, function(error, root) {
501
        if (error) { throw error; }
502
        var nodes = cluster.nodes(root);
503
        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...
504
            .data(cluster.links(nodes))
505
            .enter().append('path')
506
            .attr('class', 'link')
507
            .attr('d', diagonal);
508
        var node = g.selectAll('g.node')
509
            .data(nodes)
510
            .enter().append('g')
511
            .attr('class', 'node')
512
            .attr('transform', function(d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y + ')'; });
513
        node.append('circle')
514
            .attr('r', 4.5);
515
        node.append('text')
516
            .attr('dy', '.31em')
517
            .attr('text-anchor', function(d) { return d.x < 180 ? 'start' : 'end'; })
518
            .attr('transform', function(d) { return d.x < 180 ? 'translate(8)' : 'rotate(180)translate(-8)'; })
519
            .text(function(d) { return d.name; });
520
        // Look for callbacks potentially registered for third party code.
521
        jsondash.api.runCallbacks(container, config);
522
        jsondash.unload(container);
523
    });
524
    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...
525
};
526
527
jsondash.handlers.handleDendrogram = function(container, config) {
528
    'use strict';
529
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
530
    // A general padding for the svg inside of the widget.
531
    // The cluster dendrogram will also need to have padding itself, so
532
    // the bounds are not clipped in the svg.
533
    var svg_pad = 20;
534
    var width = _width - svg_pad;
535
    var height = config.height - svg_pad;
536
    var PADDING = width / 4;
537
    var cluster = d3.layout.cluster()
538
        .size([height * 0.85, width - PADDING]);
539
    var diagonal = d3.svg.diagonal()
540
        .projection(function(d) { return [d.y, d.x]; });
541
    var svg = container
542
        .select('.chart-container')
543
        .append('svg')
544
        .attr('width', width)
545
        .attr('height', height);
546
    var g = svg.append('g')
547
        .attr('transform', 'translate(40, 0)');
548
549
    jsondash.getJSON(container, config.dataSource, function(error, root) {
550
        var nodes = cluster.nodes(root);
551
        var links = cluster.links(nodes);
552
        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...
553
        .data(links)
554
        .enter().append('path')
555
        .attr('class', 'link')
556
        .attr('d', diagonal);
557
558
        var node = g.selectAll('.node')
559
        .data(nodes)
560
        .enter().append('g')
561
        .attr('class', 'node')
562
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
563
564
        node.append('circle').attr('r', 4.5);
565
        node.append('text')
566
        .attr('dx', function(d) { return d.children ? -8 : 8; })
567
        .attr('dy', 3)
568
        .style('text-anchor', function(d) { return d.children ? 'end' : 'start'; })
569
        .text(function(d) { return d.name; });
570
571
        // Look for callbacks potentially registered for third party code.
572
        jsondash.api.runCallbacks(container, config);
573
        jsondash.unload(container);
574
    });
575
};
576
577
jsondash.handlers.handleVoronoi = function(container, config) {
578
    'use strict';
579
    jsondash.getJSON(container, config.dataSource, function(error, data){
580
        var _width   = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
581
        var width    = _width - jsondash.config.WIDGET_MARGIN_X;
582
        var height   = config.height - jsondash.config.WIDGET_MARGIN_Y;
583
        var vertices = data;
584
        var voronoi  = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]);
585
        var svg = container
586
            .select('.chart-container')
587
            .append('svg')
588
            .attr('width', width)
589
            .attr('height', height);
590
        var path = svg.append('g').selectAll('path');
591
        svg.selectAll('circle')
592
            .data(vertices.slice(1))
593
            .enter().append('circle')
594
            .attr('transform', function(d) { return 'translate(' + d + ')'; })
595
            .attr('r', 1.5);
596
            redraw();
597
598
        function redraw() {
599
            path = path.data(voronoi(vertices), jsondash.util.polygon);
600
            path.exit().remove();
601
            path.enter().append('path')
602
            .attr('class', function(d, i) { return 'q' + (i % 9) + '-9'; })
603
            .attr('d', jsondash.util.polygon);
604
            path.order();
605
        }
606
        // Look for callbacks potentially registered for third party code.
607
        jsondash.api.runCallbacks(container, config);
608
        jsondash.unload(container);
609
    });
610
};
611
612
jsondash.handlers.handleSparkline = function(container, config) {
613
    'use strict';
614
    var sparkline_type = config.type.split('-')[1];
615
    var spark = container
616
        .select('.chart-container')
617
        .append('div')
618
        .classed({
619
            'sparkline-container': true,
620
            'text-center': true
621
        });
622
    spark = $(spark[0]);
623
    jsondash.getJSON(container, config.dataSource, function(data){
624
        var opts = {
625
            type: sparkline_type,
626
            width: config.width - jsondash.config.WIDGET_MARGIN_X,
627
            height: config.height - jsondash.config.WIDGET_MARGIN_Y
628
        };
629
        spark.sparkline(data, opts);
630
        // Look for callbacks potentially registered for third party code.
631
        jsondash.api.runCallbacks(container, config);
632
        jsondash.unload(container);
633
    });
634
};
635
636
jsondash.handlers.handleDataTable = function(container, config) {
637
    'use strict';
638
    jsondash.getJSON(container, config.dataSource, function(error, res) {
639
        var keys = d3.keys(res[0]).map(function(d){
640
            return {data: d, title: d};
641
        });
642
        container
643
            .select('.chart-container')
644
            .append('table')
645
            .classed({
646
                table: true,
647
                'table-striped': true,
648
                'table-bordered': true,
649
                'table-condensed': true
650
            });
651
        var opts = config.override ? res : {data: res, columns: keys};
652
        $(container.select('table')[0]).dataTable(opts).css({width: 'auto'});
653
        // Look for callbacks potentially registered for third party code.
654
        jsondash.api.runCallbacks(container, config);
655
        jsondash.unload(container);
656
    });
657
};
658
659
jsondash.handlers.handleSingleNum = function(container, config) {
660
    'use strict';
661
    jsondash.getJSON(container, config.dataSource, function(error, res){
662
        var data = res.data.data ? res.data.data : res.data;
663
        var num = container
664
            .select('.chart-container')
665
            .append('div')
666
            .classed({singlenum: true})
667
            .text(data);
668
        data = String(data);
669
        // Add red or green, depending on if the number appears to be pos/neg.
670
        if(!res.noformat) {
671
            num.classed({
672
                'text-danger': data.startsWith('-'),
673
                'text-success': !data.startsWith('-')
674
            });
675
        }
676
        // Allow custom colors.
677
        if(res.color && res.noformat) {
678
            num.style('color', res.color);
679
        }
680
        // Get title height to offset box.
681
        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...
682
            .select('.widget-title')
683
            .node()
684
            .getBoundingClientRect()
685
            .height;
686
        var h = config.height - jsondash.config.WIDGET_MARGIN_Y;
687
        num.style({
688
            'line-height': h + 'px',
689
            height: h + 'px',
690
            width: config.width - jsondash.config.WIDGET_MARGIN_X
691
        });
692
        var digits = String(data).length;
693
        var size = jsondash.util.getDigitSize()(digits);
694
        num.style('font-size', size + 'px');
695
        // Look for callbacks potentially registered for third party code.
696
        jsondash.api.runCallbacks(container, config);
697
        jsondash.unload(container);
698
    });
699
};
700
701
jsondash.handlers.handleTimeline = function(container, config) {
702
    'use strict';
703
    jsondash.getJSON(container, config.dataSource, function(data){
704
        container.append('div').attr('id', 'widget-' + config.guid);
705
        var timeline = new TL.Timeline('widget-' + config.guid, data);
0 ignored issues
show
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...
Unused Code introduced by
The variable timeline seems to be never used. Consider removing it.
Loading history...
706
        // Look for callbacks potentially registered for third party code.
707
        jsondash.api.runCallbacks(container, config);
708
        jsondash.unload(container);
709
    });
710
};
711
712
/**
713
 * [handleImage Embed an image src directly.]
714
 */
715
jsondash.handlers.handleImage = function(container, config) {
716
    'use strict';
717
    var img = container.select('.chart-container').append('img');
718
    var height = (config.height - jsondash.config.WIDGET_MARGIN_Y) + 'px';
719
    img.attr({
720
        src: config.dataSource,
721
        height: height
722
    });
723
    img.classed({img: true});
724
    // Look for callbacks potentially registered for third party code.
725
    jsondash.api.runCallbacks(container, config);
726
    jsondash.unload(container);
727
};
728
729
jsondash.handlers.handleIframe = function(container, config) {
730
    'use strict';
731
    var iframe = container
732
        .select('.chart-container')
733
        .append('iframe');
734
    iframe.attr({
735
        border: 0,
736
        src: config.dataSource,
737
        height: config.height - jsondash.config.WIDGET_MARGIN_Y,
738
        width: isNaN(config.width) ? '100%' : config.width - jsondash.config.WIDGET_MARGIN_X
739
    });
740
    // Look for callbacks potentially registered for third party code.
741
    jsondash.api.runCallbacks(container, config);
742
    jsondash.unload(container);
743
};
744
745
jsondash.handlers.handleCustom = function(container, config) {
746
    'use strict';
747
    $.get(config.dataSource, function(html){
748
        container
749
            .select('.chart-container')
750
            .append('div')
751
            .classed({'custom-container': true})
752
            .html(html);
753
        // Look for callbacks potentially registered for third party code.
754
        jsondash.api.runCallbacks(container, config);
755
        jsondash.unload(container);
756
    });
757
};
758
759
jsondash.handlers.handleVenn = function(container, config) {
760
    'use strict';
761
    jsondash.getJSON(container, config.dataSource, function(error, data){
762
        var chart = venn.VennDiagram();
763
        var cont = container
764
            .select('.chart-container')
765
            .append('div')
766
            .classed({venn: true});
767
        cont.datum(data).call(chart);
768
        cont.select('svg')
769
            .attr('width', config.width - jsondash.config.WIDGET_MARGIN_X)
770
            .attr('height', config.height - jsondash.config.WIDGET_MARGIN_Y);
771
        // Look for callbacks potentially registered for third party code.
772
        jsondash.api.runCallbacks(container, config);
773
        jsondash.unload(container);
774
    });
775
};
776
777
jsondash.handlers.handlePlotly = function(container, config) {
778
    'use strict';
779
    var id = 'plotly-' + config.guid;
780
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
781
    container
782
        .select('.chart-container')
783
        .append('div')
784
        .classed({'plotly-container': true})
785
        .attr('id', id);
786
    jsondash.getJSON(container, config.dataSource, function(error, data){
787
        var plotly_wrapper =  d3.select('#' + id);
788
        delete data.layout.height;
789
        delete data.layout.width;
790
        data.layout.margin = {l: 20, r: 20, b: 20, t: 50};
791
        if(config.override) {
792
            Plotly.plot(id, data.data, data.layout || {}, data.options || {});
793
        } else {
794
            Plotly.plot(id, data);
795
        }
796
       plotly_wrapper.select('.svg-container').style({
797
            'margin': '0 auto',
798
            'width': isNaN(config.width) ? '100%' : config.width,
799
            'height': config.height
800
        });
801
        plotly_wrapper.select('#scene').style({
802
            'width': _width,
803
            'height': config.height
804
        });
805
        // Look for callbacks potentially registered for third party code.
806
        jsondash.api.runCallbacks(container, config);
807
        jsondash.unload(container);
808
    });
809
};
810