Completed
Push — master ( b22ebf...3b8f97 )
by Chris
41s
created

jsondash.handlers.handleDataTable   A

Complexity

Conditions 1
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 1
c 4
b 1
f 0
dl 0
loc 23
rs 9.0856
nc 2
nop 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 20 2
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
        .classed(jsondash.util.getCSSClasses(config))
82
        .style({
83
        width: width,
84
        height: height
85
    });
86
    jsondash.getJSON(container, config.dataSource, function(error, data){
87
        var sig = new sigma({
0 ignored issues
show
Unused Code introduced by
The variable sig seems to be never used. Consider removing it.
Loading history...
Coding Style Best Practice introduced by
By convention, constructors like sigma should be capitalized.
Loading history...
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...
88
          graph: data,
89
          width: width,
90
          height: height,
91
          container: new_id
92
        });
93
        // Look for callbacks potentially registered for third party code.
94
        jsondash.api.runCallbacks(container, config);
95
        jsondash.unload(container);
96
    });
97
};
98
99
/**
100
 * Handler for all cytoscape specifications
101
 */
102
jsondash.handlers.handleCytoscape = function(container, config) {
103
    'use strict';
104
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
105
    // Titlebar + padding + a bit extra to account for the bottom.
106
    var titlebar_offset = jsondash.getTitleBarHeight(container) * 1.2;
107
    container
108
        .select('.chart-container')
109
        .classed(jsondash.util.getCSSClasses(config))
110
        .style({
111
        width: (_width - 10) + 'px',
112
        height: (config.height - titlebar_offset) + 'px'
113
    });
114
    jsondash.getJSON(container, config.dataSource, function(error, cyspec){
115
        // the `document.getElementByID` declaration in the cytoscape
116
        // spec is not serializable so we will ignore anything user
117
        // sent and just drop our selector in place of it.
118
        var override = {
119
            container: document.querySelector('[data-guid="' + config.guid + '"] .chart-container'),
120
            // We intentionally override w/h with null values,
121
            // so the graph is forced to be
122
            // constrained to the parent dimensions.
123
            layout: {
124
                width: null,
125
                height: null
126
            },
127
        };
128
        var spec = $.extend(cyspec, override);
129
        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...
130
        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...
131
        // Look for callbacks potentially registered for third party code.
132
        jsondash.api.runCallbacks(container, config);
133
        jsondash.unload(container);
134
    });
135
};
136
137
/**
138
 * Handler for all vega-lite specifications
139
 */
140
jsondash.handlers.handleVegaLite = function(container, config) {
141
    'use strict';
142
    jsondash.getJSON(container, config.dataSource, function(error, vlspec){
143
        var SCALE_FACTOR = 0.7; // very important to get sizing jusst right.
144
        var selector = '[data-guid="' + config.guid + '"] .chart-container';
145
        var width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
146
        var size = d3.max([config.height, width]);
147
        var overrides = {
148
            width: ~~(size * SCALE_FACTOR),
149
            height: ~~(config.height * SCALE_FACTOR)
150
        };
151
        var embedSpec = {
152
            mode: 'vega-lite',
153
            spec: $.extend({}, vlspec, overrides)
154
        };
155
        d3.select(selector).classed(jsondash.util.getCSSClasses(config))
156
        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...
157
            // Callback receiving the View instance and parsed Vega spec
158
            // result.view is the View, which resides under the '#vis' element
159
            if(error) {
160
                throw new Error('Error loading chart: ' + error);
161
            }
162
            // Change look of default buttons
163
            container.select('.vega-actions')
164
                .classed({'btn-group': true})
165
                .selectAll('a')
166
                .classed({'btn btn-xs btn-default': true});
167
            // Look for callbacks potentially registered for third party code.
168
            jsondash.api.runCallbacks(container, config);
169
            jsondash.unload(container);
170
        });
171
    });
172
};
173
174
/**
175
 * Handlers for various widget types. The method signatures are always the same,
176
 * but each handler can handle them differently.
177
 */
178
jsondash.handlers.handleYoutube = function(container, config) {
179
    // Clean up all previous.
180
    'use strict';
181
    function getAttr(prop, props) {
182
        // Return the propery from a list of properties for the iframe.
183
        // e.g. getAttr('width', ["width="900""]) --> "900"
184
        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...
185
            return k.startsWith(prop);
186
        })[0];
187
    }
188
189
190
    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...
191
    var parts = config.dataSource.split(' ');
192
    var yt_width = parseInt(getAttr('width', parts).split('=')[1].replace(/"/gi, ''), 10);
193
    var height = parseInt(getAttr('height', parts).split('=')[1].replace(/"/gi, ''), 10);
194
    var width = isNaN(config.width) ? '100%' : yt_width;
195
    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 190. 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...
196
197
    // In the case of YouTube, we have to override the config dimensions
198
    // as this will be wonky when the aspect ratio is calculated. We will
199
    // defer to YouTube calculations instead.
200
    container
201
        .select('.chart-container')
202
        .append('iframe')
203
        .classed(jsondash.util.getCSSClasses(config))
204
        .attr('width', width)
205
        .attr('height', height)
206
        .attr('src', url)
207
        .attr('allowfullscreen', true)
208
        .attr('frameborder', 0);
209
    // Look for callbacks potentially registered for third party code.
210
    jsondash.api.runCallbacks(container, config);
211
    jsondash.unload(container);
212
};
213
214
/**
215
 * [handleGraph creates graphs using the dot format
216
 * spec with d3 and dagre-d3]
217
 */
218
jsondash.handlers.handleGraph = function(container, config) {
219
    'use strict';
220
    jsondash.getJSON(container, config.dataSource, function(error, data){
221
        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...
222
        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...
223
        var svg = container
224
            .select('.chart-container')
225
            .append('svg')
226
            .classed(jsondash.util.getCSSClasses(config))
227
            .classed({'chart-graph': true});
228
        var svg_group = svg.append('g');
229
        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...
230
        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...
231
        // Create the renderer
232
        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...
233
        render(svg_group, g);
234
        bbox = svg.node().getBBox();
235
        svg.attr('width', bbox.width)
236
            .attr('height', bbox.height);
237
        // Look for callbacks potentially registered for third party code.
238
        jsondash.api.runCallbacks(container, config);
239
        jsondash.unload(container);
240
    });
241
};
242
243
/**
244
 * [handleWordCloud create word clouds using the d3-cloud extension.]
245
 */
246
jsondash.handlers.handleWordCloud = function(container, config) {
247
    'use strict';
248
    jsondash.getJSON(container, config.dataSource, function(error, data){
249
        var h     = config.height - jsondash.config.WIDGET_MARGIN_Y;
250
        var w     = config.width - jsondash.config.WIDGET_MARGIN_X;
251
        var svg   = container
252
            .select('.chart-container')
253
            .append('svg')
254
            .classed(jsondash.util.getCSSClasses(config))
255
            .classed({'wordcloud': true});
256
        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...
257
        var cloud = d3.layout.cloud;
258
        var words = data.map(function(d) {
259
            return {text: d.text, size: d.size};
260
        });
261
        var layout = cloud()
262
            .size([w, h])
263
            .words(words)
264
            .padding(4)
265
            .rotate(function() {return ~~(Math.random() * 1) * 90;})
266
            .font('Arial')
267
            .fontSize(function(d) {return d.size;})
268
            .on('end', draw);
269
270
        layout.start();
271
272
        function draw(words) {
273
          svg
274
              .attr('width', layout.size()[0])
275
              .attr('height', layout.size()[1])
276
            .append('g')
277
              .attr('transform', 'translate(' + layout.size()[0] / 2 + ',' + layout.size()[1] / 2 + ')')
278
            .selectAll('text').data(words)
279
            .enter().append('text')
280
              .style('font-size', function(d) { return d.size + 'px'; })
281
              .style('font-family', 'arial')
282
              .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...
283
              .attr('text-anchor', 'middle')
284
              .attr('transform', function(d) {
285
                return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
286
              })
287
              .text(function(d) { return d.text; });
288
        }
289
290
        // Look for callbacks potentially registered for third party code.
291
        jsondash.api.runCallbacks(container, config);
292
        jsondash.unload(container);
293
    });
294
};
295
296
jsondash.handlers.handleC3 = function(container, config) {
297
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
298
    'use strict';
299
    var init_config = {
300
        bindto: '[data-guid="' + config.guid + '"] .chart-container',
301
        legend: {
302
            show: true
303
        },
304
        size: {
305
            height: config.height - jsondash.config.WIDGET_MARGIN_Y,
306
            width: _width - jsondash.config.WIDGET_MARGIN_X
307
        },
308
        data: {},
309
        onrendered: function(){
310
            // Look for callbacks potentially registered for third party code.
311
            jsondash.api.runCallbacks(container, config);
312
            jsondash.unload(container);
313
        }
314
    };
315
316
    container
317
        .select('.chart-container')
318
        .classed(jsondash.util.getCSSClasses(config))
319
320
    /**
321
     * [normalizeData Transform data from a standardized jsondash
322
     *     format into one suitable for c3.]
323
     */
324
    function normalizeData(data, type) {
325
        // For most cases, we build out N columns into ['label', 0, 1, 2, 3] format
326
        // from data in format: {'foo': [1, 2]} or format {'foo': 1}
327
        var cols = [];
328
        if(type === 'donut' || type === 'gauge' || type === 'pie') {
329
            $.each(data, function(label, val){
330
                cols.push([label, val]);
331
            });
332
            return cols;
333
        }
334
        if(type === 'timeseries') {
335
            var dates = ['x'];
336
            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...
337
                dates.push(date);
338
            });
339
            cols.push(dates);
340
        }
341
        $.each(data, function(label, vals){
342
            if(label !== 'dates') {
343
                var newarr = [label];
344
                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...
345
                    newarr.push(val);
346
                });
347
                cols.push(newarr);
348
            }
349
        });
350
        return cols;
351
    }
352
353
    jsondash.getJSON(container, config.dataSource, function(error, data){
354
        if(jsondash.util.isOverride(config)) {
355
            // Just use the raw payload for this widgets' options.
356
            // Keep existing options if not specified.
357
            init_config = $.extend(init_config, data);
358
        } else {
359
            if(config.type === 'timeseries') {
360
                // Map the corresponding data key and list of dates
361
                // to the `x` property.
362
                init_config.axis = {
363
                    x: {type: 'timeseries'}
364
                };
365
                init_config.data.x = 'x';
366
            } else {
367
                init_config.data.type = config.type;
368
            }
369
            init_config.data.columns = normalizeData(data, config.type);
370
        }
371
        c3.generate(init_config);
372
    });
373
};
374
375
jsondash.handlers.handleBasic = function(container, config) {
376
    'use strict';
377
    if(config.type === 'number') { return jsondash.handlers.handleSingleNum(container, config); }
378
    if(config.type === 'iframe') { return jsondash.handlers.handleIframe(container, config); }
379
    if(config.type === 'image') { return jsondash.handlers.handleImage(container, config); }
380
    if(config.type === 'youtube') { return jsondash.handlers.handleYoutube(container, config); }
381
    if(config.type === 'custom') { return jsondash.handlers.handleCustom(container, config); }
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if config.type === "custom" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
382
};
383
384
jsondash.handlers.handleD3 = function(container, config) {
385
    'use strict';
386
    // Handle specific types.
387
    if(config.type === 'radial-dendrogram') { return jsondash.handlers.handleRadialDendrogram(container, config); }
388
    if(config.type === 'dendrogram') { return jsondash.handlers.handleDendrogram(container, config); }
389
    if(config.type === 'voronoi') { return jsondash.handlers.handleVoronoi(container, config); }
390
    if(config.type === 'treemap') { return jsondash.handlers.handleTreemap(container, config); }
391
    if(config.type === 'circlepack') { return jsondash.handlers.handleCirclePack(container, config); }
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if config.type === "circlepack" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
392
};
393
394
jsondash.handlers.handleCirclePack = function(container, config) {
395
    'use strict';
396
    // Adapted from https://bl.ocks.org/mbostock/4063530
397
    var margin = jsondash.config.WIDGET_MARGIN_Y;
398
    var diameter = jsondash.getDiameter(container, config) - margin;
399
    var format = d3.format(',d');
400
    var pack = d3.layout.pack()
401
        .size([diameter, diameter])
402
        .value(function(d) { return d.size; });
403
    var svg = container
404
        .select('.chart-container')
405
        .append('svg')
406
        .classed(jsondash.util.getCSSClasses(config))
407
        .attr('width', diameter)
408
        .attr('height', diameter)
409
        .append('g');
410
411
    jsondash.getJSON(container, config.dataSource, function(error, data) {
412
        var node = svg.datum(data).selectAll('.node')
413
        .data(pack.nodes)
414
        .enter().append('g')
415
        .attr('class', function(d) { return d.children ? 'node' : 'leaf node'; })
416
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
417
418
        node.append('title')
419
        .text(function(d) { return d.name + (d.children ? '' : ': ' + format(d.size)); });
420
421
        node.append('circle')
422
        .attr('r', function(d) { return d.r; });
423
424
        node.filter(function(d) { return !d.children; }).append('text')
425
        .attr('dy', '.3em')
426
        .style('text-anchor', 'middle')
427
        .text(function(d) { return d.name.substring(0, d.r / 3); });
428
        // Look for callbacks potentially registered for third party code.
429
        jsondash.api.runCallbacks(container, config);
430
        jsondash.unload(container);
431
    });
432
    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...
433
};
434
435
jsondash.handlers.handleTreemap = function(container, config) {
436
    'use strict';
437
    // Adapted from http://bl.ocks.org/mbostock/4063582
438
    var margin = {
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
439
        top: jsondash.config.WIDGET_MARGIN_Y / 2,
440
        bottom: jsondash.config.WIDGET_MARGIN_Y / 2,
441
        left: jsondash.config.WIDGET_MARGIN_X / 2,
442
        right: jsondash.config.WIDGET_MARGIN_X / 2
443
    };
444
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
445
    var width = _width - jsondash.config.WIDGET_MARGIN_X;
446
    var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
447
    var color = d3.scale.category20c();
448
    var treemap = d3.layout.treemap()
449
        .size([width, height])
450
        .sticky(true)
451
        .value(function(d) { return d.size; });
452
    var div = container
453
        .select('.chart-container')
454
        .append('div')
455
        .classed(jsondash.util.getCSSClasses(config))
456
        .classed({treemap: true, 'chart-centered': true})
457
        .style('position', 'relative')
458
        .style('width', width + 'px')
459
        .style('height', height + 'px');
460
461
    jsondash.getJSON(container, config.dataSource, function(error, root) {
462
        var node = div.datum(root).selectAll('.node')
463
            .data(treemap.nodes)
464
            .enter().append('div')
465
            .attr('class', 'node')
466
            .call(position)
467
            .style('border', '1px solid white')
468
            .style('font', '10px sans-serif')
469
            .style('line-height', '12px')
470
            .style('overflow', 'hidden')
471
            .style('position', 'absolute')
472
            .style('text-indent', '2px')
473
            .style('background', function(d) {
474
                return d.children ? color(d.name) : null;
475
            })
476
            .text(function(d) {
477
                return d.children ? null : d.name;
478
            });
479
        d3.selectAll('input').on('change', function change() {
480
            var value = this.value === 'count'
481
            ? function() { return 1; }
482
            : function(d) { return d.size;};
483
            node
484
            .data(treemap.value(value).nodes)
485
            .transition()
486
            .duration(1500)
487
            .call(position);
488
        });
489
        // Look for callbacks potentially registered for third party code.
490
        jsondash.api.runCallbacks(container, config);
491
        jsondash.unload(container);
492
    });
493
494
    function position() {
495
        this.style('left', function(d) { return d.x + 'px'; })
496
            .style('top', function(d) { return d.y + 'px'; })
497
            .style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; })
498
            .style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; });
499
    }
500
};
501
502
jsondash.handlers.handleRadialDendrogram = function(container, config) {
503
    'use strict';
504
    // Code taken (and refactored for use here) from:
505
    // https://bl.ocks.org/mbostock/4339607
506
    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...
507
    var radius = jsondash.getDiameter(container, config);
508
    var cluster = d3.layout.cluster()
509
        .size([360, radius / 2 - 150]); // reduce size relative to `radius`
510
    var diagonal = d3.svg.diagonal.radial()
511
        .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
512
    var svg = container
513
        .select('.chart-container')
514
        .append('svg')
515
        .classed(jsondash.util.getCSSClasses(config))
516
        .attr('width', radius)
517
        .attr('height', radius);
518
    var g = svg.append('g');
519
    g.attr('transform', 'translate(' + radius / 2 + ',' + radius / 2 + ')');
520
521
    jsondash.getJSON(container, config.dataSource, function(error, root) {
522
        if (error) { throw error; }
523
        var nodes = cluster.nodes(root);
524
        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...
525
            .data(cluster.links(nodes))
526
            .enter().append('path')
527
            .attr('class', 'link')
528
            .attr('d', diagonal);
529
        var node = g.selectAll('g.node')
530
            .data(nodes)
531
            .enter().append('g')
532
            .attr('class', 'node')
533
            .attr('transform', function(d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y + ')'; });
534
        node.append('circle')
535
            .attr('r', 4.5);
536
        node.append('text')
537
            .attr('dy', '.31em')
538
            .attr('text-anchor', function(d) { return d.x < 180 ? 'start' : 'end'; })
539
            .attr('transform', function(d) { return d.x < 180 ? 'translate(8)' : 'rotate(180)translate(-8)'; })
540
            .text(function(d) { return d.name; });
541
        // Look for callbacks potentially registered for third party code.
542
        jsondash.api.runCallbacks(container, config);
543
        jsondash.unload(container);
544
    });
545
    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...
546
};
547
548
jsondash.handlers.handleDendrogram = function(container, config) {
549
    'use strict';
550
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
551
    // A general padding for the svg inside of the widget.
552
    // The cluster dendrogram will also need to have padding itself, so
553
    // the bounds are not clipped in the svg.
554
    var svg_pad = 20;
555
    var width = _width - svg_pad;
556
    var height = config.height - svg_pad;
557
    var PADDING = width / 4;
558
    var cluster = d3.layout.cluster()
559
        .size([height * 0.85, width - PADDING]);
560
    var diagonal = d3.svg.diagonal()
561
        .projection(function(d) { return [d.y, d.x]; });
562
    var svg = container
563
        .select('.chart-container')
564
        .append('svg')
565
        .classed(jsondash.util.getCSSClasses(config))
566
        .attr('width', width)
567
        .attr('height', height);
568
    var g = svg.append('g')
569
        .attr('transform', 'translate(40, 0)');
570
571
    jsondash.getJSON(container, config.dataSource, function(error, root) {
572
        var nodes = cluster.nodes(root);
573
        var links = cluster.links(nodes);
574
        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...
575
        .data(links)
576
        .enter().append('path')
577
        .attr('class', 'link')
578
        .attr('d', diagonal);
579
580
        var node = g.selectAll('.node')
581
        .data(nodes)
582
        .enter().append('g')
583
        .attr('class', 'node')
584
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
585
586
        node.append('circle').attr('r', 4.5);
587
        node.append('text')
588
        .attr('dx', function(d) { return d.children ? -8 : 8; })
589
        .attr('dy', 3)
590
        .style('text-anchor', function(d) { return d.children ? 'end' : 'start'; })
591
        .text(function(d) { return d.name; });
592
593
        // Look for callbacks potentially registered for third party code.
594
        jsondash.api.runCallbacks(container, config);
595
        jsondash.unload(container);
596
    });
597
};
598
599
jsondash.handlers.handleVoronoi = function(container, config) {
600
    'use strict';
601
    jsondash.getJSON(container, config.dataSource, function(error, data){
602
        var _width   = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
603
        var width    = _width - jsondash.config.WIDGET_MARGIN_X;
604
        var height   = config.height - jsondash.config.WIDGET_MARGIN_Y;
605
        var vertices = data;
606
        var voronoi  = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]);
607
        var svg = container
608
            .select('.chart-container')
609
            .append('svg')
610
            .classed(jsondash.util.getCSSClasses(config))
611
            .attr('width', width)
612
            .attr('height', height);
613
        var path = svg.append('g').selectAll('path');
614
        svg.selectAll('circle')
615
            .data(vertices.slice(1))
616
            .enter().append('circle')
617
            .attr('transform', function(d) { return 'translate(' + d + ')'; })
618
            .attr('r', 1.5);
619
            redraw();
620
621
        function redraw() {
622
            path = path.data(voronoi(vertices), jsondash.util.polygon);
623
            path.exit().remove();
624
            path.enter().append('path')
625
            .attr('class', function(d, i) { return 'q' + (i % 9) + '-9'; })
626
            .attr('d', jsondash.util.polygon);
627
            path.order();
628
        }
629
        // Look for callbacks potentially registered for third party code.
630
        jsondash.api.runCallbacks(container, config);
631
        jsondash.unload(container);
632
    });
633
};
634
635
jsondash.handlers.handleSparkline = function(container, config) {
636
    'use strict';
637
    var sparkline_type = config.type.split('-')[1];
638
    var spark = container
639
        .select('.chart-container')
640
        .append('div')
641
        .classed(jsondash.util.getCSSClasses(config))
642
        .classed({
643
            'sparkline-container': true,
644
            'text-center': true
645
        });
646
    spark = $(spark[0]);
647
    jsondash.getJSON(container, config.dataSource, function(data){
648
        var opts = {
649
            type: sparkline_type,
650
            width: config.width - jsondash.config.WIDGET_MARGIN_X,
651
            height: config.height - jsondash.config.WIDGET_MARGIN_Y
652
        };
653
        spark.sparkline(data, opts);
654
        // Look for callbacks potentially registered for third party code.
655
        jsondash.api.runCallbacks(container, config);
656
        jsondash.unload(container);
657
    });
658
};
659
660
jsondash.handlers.handleDataTable = function(container, config) {
661
    'use strict';
662
    jsondash.getJSON(container, config.dataSource, function(error, res) {
663
        var keys = d3.keys(res[0]).map(function(d){
664
            return {data: d, title: d};
665
        });
666
        var titlebar_offset = jsondash.getTitleBarHeight(container) * 2.5;
0 ignored issues
show
Unused Code introduced by
The variable titlebar_offset seems to be never used. Consider removing it.
Loading history...
667
        var table_class_defaults = ['table', 'table-bordered', 'table-striped'];
668
        var classes = jsondash.util.getCSSClasses(config, table_class_defaults);
669
        container
670
            .select('.chart-container')
671
            .append('table')
672
            .classed(classes);
673
        var opts = config.override ? res : {data: res, columns: keys};
674
        $(container.select('table')[0])
675
            .dataTable(opts).css({
676
                width: 'auto',
677
        });
678
        // Look for callbacks potentially registered for third party code.
679
        jsondash.api.runCallbacks(container, config);
680
        jsondash.unload(container);
681
    });
682
};
683
684
jsondash.handlers.handleSingleNum = function(container, config) {
685
    'use strict';
686
    jsondash.getJSON(container, config.dataSource, function(error, res){
687
        var data = res.data.data ? res.data.data : res.data;
688
        var num = container
689
            .select('.chart-container')
690
            .append('div')
691
            .classed({singlenum: true})
692
            .classed(jsondash.util.getCSSClasses(config))
693
            .text(data);
694
        data = String(data);
695
        // Add red or green, depending on if the number appears to be pos/neg.
696
        if(!res.noformat) {
697
            num.classed({
698
                'text-danger': data.startsWith('-'),
699
                'text-success': !data.startsWith('-')
700
            });
701
        }
702
        // Allow custom colors.
703
        if(res.color && res.noformat) {
704
            num.style('color', res.color);
705
        }
706
        // Get title height to offset box.
707
        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...
708
            .select('.widget-title')
709
            .node()
710
            .getBoundingClientRect()
711
            .height;
712
        var h = config.height - jsondash.config.WIDGET_MARGIN_Y;
713
        num.style({
714
            'line-height': h + 'px',
715
            height: h + 'px',
716
            width: config.width - jsondash.config.WIDGET_MARGIN_X
717
        });
718
        var digits = String(data).length;
719
        var size = jsondash.util.getDigitSize()(digits);
720
        num.style('font-size', size + 'px');
721
        // Look for callbacks potentially registered for third party code.
722
        jsondash.api.runCallbacks(container, config);
723
        jsondash.unload(container);
724
    });
725
};
726
727
jsondash.handlers.handleTimeline = function(container, config) {
728
    'use strict';
729
    jsondash.getJSON(container, config.dataSource, function(data){
730
        container
731
            .append('div')
732
            .classed(jsondash.util.getCSSClasses(config))
733
            .attr('id', 'widget-' + config.guid);
734
        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...
735
        // Look for callbacks potentially registered for third party code.
736
        jsondash.api.runCallbacks(container, config);
737
        jsondash.unload(container);
738
    });
739
};
740
741
/**
742
 * [handleImage Embed an image src directly.]
743
 */
744
jsondash.handlers.handleImage = function(container, config) {
745
    'use strict';
746
    var img = container.select('.chart-container').append('img');
747
    var height = (config.height - jsondash.config.WIDGET_MARGIN_Y) + 'px';
748
    img.attr({
749
        src: config.dataSource,
750
        height: height
751
    });
752
    img.classed({img: true});
753
    img.classed(jsondash.util.getCSSClasses(config));
754
    // Look for callbacks potentially registered for third party code.
755
    jsondash.api.runCallbacks(container, config);
756
    jsondash.unload(container);
757
};
758
759
jsondash.handlers.handleIframe = function(container, config) {
760
    'use strict';
761
    var iframe = container
762
        .select('.chart-container')
763
        .append('iframe');
764
    iframe.attr({
765
        border: 0,
766
        src: config.dataSource,
767
        height: config.height - jsondash.config.WIDGET_MARGIN_Y,
768
        width: isNaN(config.width) ? '100%' : config.width - jsondash.config.WIDGET_MARGIN_X
769
    });
770
    iframe.classed(jsondash.util.getCSSClasses(config));
771
    // Look for callbacks potentially registered for third party code.
772
    jsondash.api.runCallbacks(container, config);
773
    jsondash.unload(container);
774
};
775
776
jsondash.handlers.handleCustom = function(container, config) {
777
    'use strict';
778
    $.get(config.dataSource, function(html){
779
        container
780
            .select('.chart-container')
781
            .append('div')
782
            .classed({'custom-container': true})
783
            .classed(jsondash.util.getCSSClasses(config))
784
            .html(html);
785
        // Look for callbacks potentially registered for third party code.
786
        jsondash.api.runCallbacks(container, config);
787
        jsondash.unload(container);
788
    });
789
};
790
791
jsondash.handlers.handleVenn = function(container, config) {
792
    'use strict';
793
    jsondash.getJSON(container, config.dataSource, function(error, data){
794
        var chart = venn.VennDiagram();
795
        var cont = container
796
            .select('.chart-container')
797
            .append('div')
798
            .classed(jsondash.util.getCSSClasses(config))
799
            .classed({venn: true});
800
        cont.datum(data).call(chart);
801
        cont.select('svg')
802
            .attr('width', config.width - jsondash.config.WIDGET_MARGIN_X)
803
            .attr('height', config.height - jsondash.config.WIDGET_MARGIN_Y);
804
        // Look for callbacks potentially registered for third party code.
805
        jsondash.api.runCallbacks(container, config);
806
        jsondash.unload(container);
807
    });
808
};
809
810
jsondash.handlers.handlePlotly = function(container, config) {
811
    'use strict';
812
    var id = 'plotly-' + config.guid;
813
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
814
    container
815
        .select('.chart-container')
816
        .append('div')
817
        .classed(jsondash.util.getCSSClasses(config))
818
        .classed({'plotly-container': true})
819
        .attr('id', id);
820
    jsondash.getJSON(container, config.dataSource, function(error, data){
821
        var plotly_wrapper =  d3.select('#' + id);
822
        delete data.layout.height;
823
        delete data.layout.width;
824
        data.layout.margin = {l: 20, r: 20, b: 20, t: 50};
825
        if(config.override) {
826
            Plotly.plot(id, data.data, data.layout || {}, data.options || {});
827
        } else {
828
            Plotly.plot(id, data);
829
        }
830
       plotly_wrapper.select('.svg-container').style({
831
            'margin': '0 auto',
832
            'width': isNaN(config.width) ? '100%' : config.width,
833
            'height': config.height
834
        });
835
        plotly_wrapper.select('#scene').style({
836
            'width': _width,
837
            'height': config.height
838
        });
839
        // Look for callbacks potentially registered for third party code.
840
        jsondash.api.runCallbacks(container, config);
841
        jsondash.unload(container);
842
    });
843
};
844