Completed
Push — master ( 50957d...a8f21c )
by Chris
01:22
created

jsondash.handlers.handleSparkline   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 11 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 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
            type: config.type,
304
            url: config.dataSource,
305
            mimeType: 'json'
306
        },
307
        onrendered: function(){
308
            // Look for callbacks potentially registered for third party code.
309
            jsondash.api.runCallbacks(container, config);
310
            jsondash.unload(container);
311
        }
312
    };
313
    if(jsondash.util.isOverride(config)) {
314
        // Just use the raw payload for this widgets' options.
315
        jsondash.getJSON(container, config.dataSource, function(error, data){
316
            // Keep existing options if not specified.
317
            config = $.extend(init_config, data);
318
            c3.generate(init_config);
319
        });
320
        return;
321
    }
322
    if(config.type === 'timeseries') {
323
        init_config.axis = {
324
            x: {type: 'timeseries'}
325
        };
326
        // Map the corresponding data key and list of dates
327
        // to the `x` property.
328
        init_config.data.x = 'dates';
329
    }
330
    c3.generate(init_config);
331
};
332
333
jsondash.handlers.handleD3 = function(container, config) {
334
    'use strict';
335
    // Handle specific types.
336
    if(config.type === 'radial-dendrogram') { return jsondash.handlers.handleRadialDendrogram(container, config); }
337
    if(config.type === 'dendrogram') { return jsondash.handlers.handleDendrogram(container, config); }
338
    if(config.type === 'voronoi') { return jsondash.handlers.handleVoronoi(container, config); }
339
    if(config.type === 'treemap') { return jsondash.handlers.handleTreemap(container, config); }
340
    if(config.type === 'circlepack') { return jsondash.handlers.handleCirclePack(container, config); }
341
    throw new Error('Unknown type: ' + config.type);
342
};
343
344
jsondash.handlers.handleCirclePack = function(container, config) {
345
    'use strict';
346
    // Adapted from https://bl.ocks.org/mbostock/4063530
347
    var margin = jsondash.config.WIDGET_MARGIN_Y;
348
    var diameter = jsondash.getDiameter(container, config) - margin;
349
    var format = d3.format(',d');
350
    var pack = d3.layout.pack()
351
        .size([diameter, diameter])
352
        .value(function(d) { return d.size; });
353
    var svg = container
354
        .select('.chart-container')
355
        .append('svg')
356
        .attr('width', diameter)
357
        .attr('height', diameter)
358
        .append('g');
359
360
    jsondash.getJSON(container, config.dataSource, function(error, data) {
361
        var node = svg.datum(data).selectAll('.node')
362
        .data(pack.nodes)
363
        .enter().append('g')
364
        .attr('class', function(d) { return d.children ? 'node' : 'leaf node'; })
365
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
366
367
        node.append('title')
368
        .text(function(d) { return d.name + (d.children ? '' : ': ' + format(d.size)); });
369
370
        node.append('circle')
371
        .attr('r', function(d) { return d.r; });
372
373
        node.filter(function(d) { return !d.children; }).append('text')
374
        .attr('dy', '.3em')
375
        .style('text-anchor', 'middle')
376
        .text(function(d) { return d.name.substring(0, d.r / 3); });
377
        // Look for callbacks potentially registered for third party code.
378
        jsondash.api.runCallbacks(container, config);
379
        jsondash.unload(container);
380
    });
381
    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...
382
};
383
384
jsondash.handlers.handleTreemap = function(container, config) {
385
    'use strict';
386
    // Adapted from http://bl.ocks.org/mbostock/4063582
387
    var margin = {
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
388
        top: jsondash.config.WIDGET_MARGIN_Y / 2,
389
        bottom: jsondash.config.WIDGET_MARGIN_Y / 2,
390
        left: jsondash.config.WIDGET_MARGIN_X / 2,
391
        right: jsondash.config.WIDGET_MARGIN_X / 2
392
    };
393
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
394
    var width = _width - jsondash.config.WIDGET_MARGIN_X;
395
    var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
396
    var color = d3.scale.category20c();
397
    var treemap = d3.layout.treemap()
398
        .size([width, height])
399
        .sticky(true)
400
        .value(function(d) { return d.size; });
401
    var div = container
402
        .select('.chart-container')
403
        .append('div')
404
        .classed({treemap: true, 'chart-centered': true})
405
        .style('position', 'relative')
406
        .style('width', width + 'px')
407
        .style('height', height + 'px');
408
409
    jsondash.getJSON(container, config.dataSource, function(error, root) {
410
        var node = div.datum(root).selectAll('.node')
411
            .data(treemap.nodes)
412
            .enter().append('div')
413
            .attr('class', 'node')
414
            .call(position)
415
            .style('border', '1px solid white')
416
            .style('font', '10px sans-serif')
417
            .style('line-height', '12px')
418
            .style('overflow', 'hidden')
419
            .style('position', 'absolute')
420
            .style('text-indent', '2px')
421
            .style('background', function(d) {
422
                return d.children ? color(d.name) : null;
423
            })
424
            .text(function(d) {
425
                return d.children ? null : d.name;
426
            });
427
        d3.selectAll('input').on('change', function change() {
428
            var value = this.value === 'count'
429
            ? function() { return 1; }
430
            : function(d) { return d.size;};
431
            node
432
            .data(treemap.value(value).nodes)
433
            .transition()
434
            .duration(1500)
435
            .call(position);
436
        });
437
        // Look for callbacks potentially registered for third party code.
438
        jsondash.api.runCallbacks(container, config);
439
        jsondash.unload(container);
440
    });
441
442
    function position() {
443
        this.style('left', function(d) { return d.x + 'px'; })
444
            .style('top', function(d) { return d.y + 'px'; })
445
            .style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; })
446
            .style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; });
447
    }
448
};
449
450
jsondash.handlers.handleRadialDendrogram = function(container, config) {
451
    'use strict';
452
    // Code taken (and refactored for use here) from:
453
    // https://bl.ocks.org/mbostock/4339607
454
    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...
455
    var radius = jsondash.getDiameter(container, config);
456
    var cluster = d3.layout.cluster()
457
        .size([360, radius / 2 - 150]); // reduce size relative to `radius`
458
    var diagonal = d3.svg.diagonal.radial()
459
        .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
460
    var svg = container
461
        .select('.chart-container')
462
        .append('svg')
463
        .attr('width', radius)
464
        .attr('height', radius);
465
    var g = svg.append('g');
466
    g.attr('transform', 'translate(' + radius / 2 + ',' + radius / 2 + ')');
467
468
    jsondash.getJSON(container, config.dataSource, function(error, root) {
469
        if (error) { throw error; }
470
        var nodes = cluster.nodes(root);
471
        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...
472
            .data(cluster.links(nodes))
473
            .enter().append('path')
474
            .attr('class', 'link')
475
            .attr('d', diagonal);
476
        var node = g.selectAll('g.node')
477
            .data(nodes)
478
            .enter().append('g')
479
            .attr('class', 'node')
480
            .attr('transform', function(d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y + ')'; });
481
        node.append('circle')
482
            .attr('r', 4.5);
483
        node.append('text')
484
            .attr('dy', '.31em')
485
            .attr('text-anchor', function(d) { return d.x < 180 ? 'start' : 'end'; })
486
            .attr('transform', function(d) { return d.x < 180 ? 'translate(8)' : 'rotate(180)translate(-8)'; })
487
            .text(function(d) { return d.name; });
488
        // Look for callbacks potentially registered for third party code.
489
        jsondash.api.runCallbacks(container, config);
490
        jsondash.unload(container);
491
    });
492
    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...
493
};
494
495
jsondash.handlers.handleDendrogram = function(container, config) {
496
    'use strict';
497
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
498
    // A general padding for the svg inside of the widget.
499
    // The cluster dendrogram will also need to have padding itself, so
500
    // the bounds are not clipped in the svg.
501
    var svg_pad = 20;
502
    var width = _width - svg_pad;
503
    var height = config.height - svg_pad;
504
    var PADDING = width / 4;
505
    var cluster = d3.layout.cluster()
506
        .size([height * 0.85, width - PADDING]);
507
    var diagonal = d3.svg.diagonal()
508
        .projection(function(d) { return [d.y, d.x]; });
509
    var svg = container
510
        .select('.chart-container')
511
        .append('svg')
512
        .attr('width', width)
513
        .attr('height', height);
514
    var g = svg.append('g')
515
        .attr('transform', 'translate(40, 0)');
516
517
    jsondash.getJSON(container, config.dataSource, function(error, root) {
518
        var nodes = cluster.nodes(root);
519
        var links = cluster.links(nodes);
520
        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...
521
        .data(links)
522
        .enter().append('path')
523
        .attr('class', 'link')
524
        .attr('d', diagonal);
525
526
        var node = g.selectAll('.node')
527
        .data(nodes)
528
        .enter().append('g')
529
        .attr('class', 'node')
530
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
531
532
        node.append('circle').attr('r', 4.5);
533
        node.append('text')
534
        .attr('dx', function(d) { return d.children ? -8 : 8; })
535
        .attr('dy', 3)
536
        .style('text-anchor', function(d) { return d.children ? 'end' : 'start'; })
537
        .text(function(d) { return d.name; });
538
539
        // Look for callbacks potentially registered for third party code.
540
        jsondash.api.runCallbacks(container, config);
541
        jsondash.unload(container);
542
    });
543
};
544
545
jsondash.handlers.handleVoronoi = function(container, config) {
546
    'use strict';
547
    jsondash.getJSON(container, config.dataSource, function(error, data){
548
        var _width   = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
549
        var width    = _width - jsondash.config.WIDGET_MARGIN_X;
550
        var height   = config.height - jsondash.config.WIDGET_MARGIN_Y;
551
        var vertices = data;
552
        var voronoi  = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]);
553
        var svg = container
554
            .select('.chart-container')
555
            .append('svg')
556
            .attr('width', width)
557
            .attr('height', height);
558
        var path = svg.append('g').selectAll('path');
559
        svg.selectAll('circle')
560
            .data(vertices.slice(1))
561
            .enter().append('circle')
562
            .attr('transform', function(d) { return 'translate(' + d + ')'; })
563
            .attr('r', 1.5);
564
            redraw();
565
566
        function redraw() {
567
            path = path.data(voronoi(vertices), jsondash.util.polygon);
568
            path.exit().remove();
569
            path.enter().append('path')
570
            .attr('class', function(d, i) { return 'q' + (i % 9) + '-9'; })
571
            .attr('d', jsondash.util.polygon);
572
            path.order();
573
        }
574
        // Look for callbacks potentially registered for third party code.
575
        jsondash.api.runCallbacks(container, config);
576
        jsondash.unload(container);
577
    });
578
};
579
580
jsondash.handlers.handleSparkline = function(container, config) {
581
    'use strict';
582
    var sparkline_type = config.type.split('-')[1];
583
    var spark = container
584
        .select('.chart-container')
585
        .append('div')
586
        .classed({
587
            'sparkline-container': true,
588
            'text-center': true
589
        });
590
    spark = $(spark[0]);
591
    jsondash.getJSON(container, config.dataSource, function(data){
592
        var opts = {
593
            type: sparkline_type,
594
            width: config.width - jsondash.config.WIDGET_MARGIN_X,
595
            height: config.height - jsondash.config.WIDGET_MARGIN_Y
596
        };
597
        spark.sparkline(data, opts);
598
        // Look for callbacks potentially registered for third party code.
599
        jsondash.api.runCallbacks(container, config);
600
        jsondash.unload(container);
601
    });
602
};
603
604
jsondash.handlers.handleDataTable = function(container, config) {
605
    'use strict';
606
    jsondash.getJSON(container, config.dataSource, function(error, res) {
607
        var keys = d3.keys(res[0]).map(function(d){
608
            return {data: d, title: d};
609
        });
610
        container
611
            .select('.chart-container')
612
            .append('table')
613
            .classed({
614
                table: true,
615
                'table-striped': true,
616
                'table-bordered': true,
617
                'table-condensed': true
618
            });
619
        var opts = config.override ? res : {data: res, columns: keys};
620
        $(container.select('table')[0]).dataTable(opts).css({width: 'auto'});
621
        // Look for callbacks potentially registered for third party code.
622
        jsondash.api.runCallbacks(container, config);
623
        jsondash.unload(container);
624
    });
625
};
626
627
jsondash.handlers.handleSingleNum = function(container, config) {
628
    'use strict';
629
    jsondash.getJSON(container, config.dataSource, function(error, res){
630
        var data = res.data.data ? res.data.data : res.data;
631
        var num = container
632
            .select('.chart-container')
633
            .append('div')
634
            .classed({singlenum: true})
635
            .text(data);
636
        data = String(data);
637
        // Add red or green, depending on if the number appears to be pos/neg.
638
        if(!res.noformat) {
639
            num.classed({
640
                'text-danger': data.startsWith('-'),
641
                'text-success': !data.startsWith('-')
642
            });
643
        }
644
        // Allow custom colors.
645
        if(res.color && res.noformat) {
646
            num.style('color', res.color);
647
        }
648
        // Get title height to offset box.
649
        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...
650
            .select('.widget-title')
651
            .node()
652
            .getBoundingClientRect()
653
            .height;
654
        var h = config.height - jsondash.config.WIDGET_MARGIN_Y;
655
        num.style({
656
            'line-height': h + 'px',
657
            height: h + 'px',
658
            width: config.width - jsondash.config.WIDGET_MARGIN_X
659
        });
660
        var digits = String(data).length;
661
        var size = jsondash.util.getDigitSize()(digits);
662
        num.style('font-size', size + 'px');
663
        // Look for callbacks potentially registered for third party code.
664
        jsondash.api.runCallbacks(container, config);
665
        jsondash.unload(container);
666
    });
667
};
668
669
jsondash.handlers.handleTimeline = function(container, config) {
670
    'use strict';
671
    jsondash.getJSON(container, config.dataSource, function(data){
672
        container.append('div').attr('id', 'widget-' + config.guid);
673
        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...
674
        // Look for callbacks potentially registered for third party code.
675
        jsondash.api.runCallbacks(container, config);
676
        jsondash.unload(container);
677
    });
678
};
679
680
/**
681
 * [handleImage Embed an image src directly.]
682
 */
683
jsondash.handlers.handleImage = function(container, config) {
684
    'use strict';
685
    var img = container
686
        .select('.chart-container')
687
        .append('div')
688
        .append('img');
689
    var width = isNaN(config.width) ? '100%' : config.width - jsondash.config.WIDGET_MARGIN_X;
690
    var height = (config.height - jsondash.config.WIDGET_MARGIN_Y) + 'px';
691
    img.attr({
692
        src: config.dataSource,
693
        height: height,
694
        width: width
695
    });
696
    img.classed({img: true});
697
    // Look for callbacks potentially registered for third party code.
698
    jsondash.api.runCallbacks(container, config);
699
    jsondash.unload(container);
700
};
701
702
jsondash.handlers.handleIframe = function(container, config) {
703
    'use strict';
704
    var iframe = container
705
        .select('.chart-container')
706
        .append('iframe');
707
    iframe.attr({
708
        border: 0,
709
        src: config.dataSource,
710
        height: config.height - jsondash.config.WIDGET_MARGIN_Y,
711
        width: isNaN(config.width) ? '100%' : config.width - jsondash.config.WIDGET_MARGIN_X
712
    });
713
    // Look for callbacks potentially registered for third party code.
714
    jsondash.api.runCallbacks(container, config);
715
    jsondash.unload(container);
716
};
717
718
jsondash.handlers.handleCustom = function(container, config) {
719
    'use strict';
720
    $.get(config.dataSource, function(html){
721
        container
722
            .select('.chart-container')
723
            .append('div')
724
            .classed({'custom-container': true})
725
            .html(html);
726
        // Look for callbacks potentially registered for third party code.
727
        jsondash.api.runCallbacks(container, config);
728
        jsondash.unload(container);
729
    });
730
};
731
732
jsondash.handlers.handleVenn = function(container, config) {
733
    'use strict';
734
    jsondash.getJSON(container, config.dataSource, function(error, data){
735
        var chart = venn.VennDiagram();
736
        var cont = container
737
            .select('.chart-container')
738
            .append('div')
739
            .classed({venn: true});
740
        cont.datum(data).call(chart);
741
        cont.select('svg')
742
            .attr('width', config.width - jsondash.config.WIDGET_MARGIN_X)
743
            .attr('height', config.height - jsondash.config.WIDGET_MARGIN_Y);
744
        // Look for callbacks potentially registered for third party code.
745
        jsondash.api.runCallbacks(container, config);
746
        jsondash.unload(container);
747
    });
748
};
749
750
jsondash.handlers.handlePlotly = function(container, config) {
751
    'use strict';
752
    var id = 'plotly-' + config.guid;
753
    var _width = isNaN(config.width) ? jsondash.getDynamicWidth(container, config) : config.width;
754
    container
755
        .select('.chart-container')
756
        .append('div')
757
        .classed({'plotly-container': true})
758
        .attr('id', id);
759
    jsondash.getJSON(container, config.dataSource, function(error, data){
760
        var plotly_wrapper =  d3.select('#' + id);
761
        delete data.layout.height;
762
        delete data.layout.width;
763
        data.layout.margin = {l: 20, r: 20, b: 20, t: 50};
764
        if(config.override) {
765
            Plotly.plot(id, data.data, data.layout || {}, data.options || {});
766
        } else {
767
            Plotly.plot(id, data);
768
        }
769
       plotly_wrapper.select('.svg-container').style({
770
            'margin': '0 auto',
771
            'width': isNaN(config.width) ? '100%' : config.width,
772
            'height': config.height
773
        });
774
        plotly_wrapper.select('#scene').style({
775
            'width': _width,
776
            'height': config.height
777
        });
778
        // Look for callbacks potentially registered for third party code.
779
        jsondash.api.runCallbacks(container, config);
780
        jsondash.unload(container);
781
    });
782
};
783