Completed
Push — master ( 43650d...3e5f45 )
by Chris
01:14
created

jsondash.handlers.handleRadialDendrogram   B

Complexity

Conditions 2
Paths 4

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
c 2
b 0
f 0
nc 4
nop 2
dl 0
loc 24
rs 8.9713
1
/** global: jsondash */
2
/** global: c3 */
3
/** global: d3 */
4
/** global: venn */
5
/** global: Plotly */
6
7
jsondash.getJSON = function(url, callback) {
8
    return d3.json(url, callback);
9
};
10
11
/**
12
 * Handlers for various widget types. The method signatures are always the same,
13
 * but each handler can handle them differently.
14
 */
15
16
jsondash.handlers.handleYoutube = function(container, config) {
17
    // Clean up all previous.
18
    'use strict';
19
    container.selectAll('iframe').remove();
20
21
    function getAttr(prop, props) {
22
        // Return the propery from a list of properties for the iframe.
23
        // e.g. getAttr('width', ["width="900""]) --> "900"
24
        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...
25
            return k.startsWith(prop);
26
        })[0];
27
    }
28
29
    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...
30
    var parts = config.dataSource.split(' ');
31
    var height = parseInt(getAttr('height', parts).split('=')[1].replace(/"/gi, ''), 10);
32
    var width = parseInt(getAttr('width', parts).split('=')[1].replace(/"/gi, ''), 10);
33
    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 29. 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...
34
35
    // In the case of YouTube, we have to override the config dimensions
36
    // as this will be wonky when the aspect ratio is calculated. We will
37
    // defer to YouTube calculations instead.
38
    container.append('iframe')
39
        .attr('width', width)
40
        .attr('height', height)
41
        .attr('src', url)
42
        .attr('allowfullscreen', true)
43
        .attr('frameborder', 0);
44
    // Look for callbacks potentially registered for third party code.
45
    jsondash.api.runCallbacks(container, config);
46
    jsondash.unload(container);
47
};
48
49
/**
50
 * [handleGraph creates graphs using the dot format
51
 * spec with d3 and dagre-d3]
52
 */
53
jsondash.handlers.handleGraph = function(container, config) {
54
    'use strict';
55
    jsondash.getJSON(config.dataSource, function(error, data){
56
        if(error) {
57
            jsondash.unload(container);
58
            throw new Error("Could not load url: " + config.dataSource);
59
        }
60
        container.selectAll('.chart-graph').remove();
61
        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...
62
        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...
63
        var svg = container.append('svg').classed({'chart-graph': true});
64
        var svg_group = svg.append('g');
65
        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...
66
        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...
67
        // Create the renderer
68
        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...
69
        render(svg_group, g);
70
        bbox = svg.node().getBBox();
71
        svg.attr('width', bbox.width)
72
            .attr('height', bbox.height);
73
        // Look for callbacks potentially registered for third party code.
74
        jsondash.api.runCallbacks(container, config);
75
        jsondash.unload(container);
76
    });
77
};
78
79
jsondash.handlers.handleC3 = function(container, config) {
80
    'use strict';
81
    var init_config = {
82
        bindto: '[data-guid="' + config.guid + '"] .chart-container',
83
        legend: {
84
            show: true
85
        },
86
        size: {
87
            height: config.height - jsondash.config.WIDGET_MARGIN_Y,
88
            width: config.width - jsondash.config.WIDGET_MARGIN_X
89
        },
90
        data: {
91
            type: config.type,
92
            url: config.dataSource,
93
            mimeType: 'json'
94
        },
95
        onrendered: function(){
96
            // Look for callbacks potentially registered for third party code.
97
            jsondash.api.runCallbacks(container, config);
98
            jsondash.unload(container);
99
        }
100
    };
101
    if(jsondash.util.isOverride(config)) {
102
        // Just use the raw payload for this widgets' options.
103
        jsondash.getJSON(config.dataSource, function(error, data){
104
            if(error) { throw new Error("Could not load url: " + config.dataSource); }
105
            // Keep existing options if not specified.
106
            config = $.extend(init_config, data);
107
            c3.generate(init_config);
108
        });
109
        return;
110
    }
111
    if(config.type === 'timeseries') {
112
        init_config.axis = {
113
            x: {type: 'timeseries'}
114
        };
115
        // Map the corresponding data key and list of dates
116
        // to the `x` property.
117
        init_config.data.x = 'dates';
118
    }
119
    c3.generate(init_config);
120
};
121
122
jsondash.handlers.handleD3 = function(container, config) {
123
    'use strict';
124
    // Clean up all D3 charts in one step.
125
    container.selectAll('svg').remove();
126
    // Handle specific types.
127
    if(config.type === 'radial-dendrogram') { return jsondash.handlers.handleRadialDendrogram(container, config); }
128
    if(config.type === 'dendrogram') { return jsondash.handlers.handleDendrogram(container, config); }
129
    if(config.type === 'voronoi') { return jsondash.handlers.handleVoronoi(container, config); }
130
    if(config.type === 'treemap') { return jsondash.handlers.handleTreemap(container, config); }
131
    if(config.type === 'circlepack') { return jsondash.handlers.handleCirclePack(container, config); }
132
    throw new Error('Unknown type: ' + config.type);
133
};
134
135
jsondash.handlers.handleCirclePack = function(container, config) {
136
    'use strict';
137
    // Adapted from https://bl.ocks.org/mbostock/4063530
138
    var margin = jsondash.config.WIDGET_MARGIN_Y;
139
    var diameter = d3.max([config.width, config.height]) - margin;
140
    var format = d3.format(',d');
141
142
    var pack = d3.layout.pack()
143
        .size([diameter, diameter])
144
        .value(function(d) { return d.size; });
145
146
    var svg = container
147
        .append('svg')
148
        .attr('width', diameter)
149
        .attr('height', diameter)
150
        .append('g');
151
152
    jsondash.getJSON(config.dataSource, function(error, data) {
153
        if(error) { throw new Error("Could not load url: " + config.dataSource); }
154
155
        var node = svg.datum(data).selectAll('.node')
156
        .data(pack.nodes)
157
        .enter().append('g')
158
        .attr('class', function(d) { return d.children ? 'node' : 'leaf node'; })
159
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
160
161
        node.append('title')
162
        .text(function(d) { return d.name + (d.children ? '' : ': ' + format(d.size)); });
163
164
        node.append('circle')
165
        .attr('r', function(d) { return d.r; });
166
167
        node.filter(function(d) { return !d.children; }).append('text')
168
        .attr('dy', '.3em')
169
        .style('text-anchor', 'middle')
170
        .text(function(d) { return d.name.substring(0, d.r / 3); });
171
        // Look for callbacks potentially registered for third party code.
172
        jsondash.api.runCallbacks(container, config);
173
        jsondash.unload(container);
174
    });
175
176
    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...
177
};
178
179
jsondash.handlers.handleTreemap = function(container, config) {
180
    'use strict';
181
    // Adapted from http://bl.ocks.org/mbostock/4063582
182
    var margin = {
0 ignored issues
show
Unused Code introduced by
The variable margin seems to be never used. Consider removing it.
Loading history...
183
        top: jsondash.config.WIDGET_MARGIN_Y / 2,
184
        bottom: jsondash.config.WIDGET_MARGIN_Y / 2,
185
        left: jsondash.config.WIDGET_MARGIN_X / 2,
186
        right: jsondash.config.WIDGET_MARGIN_X / 2
187
    };
188
    var width = config.width - jsondash.config.WIDGET_MARGIN_X;
189
    var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
190
    var color = d3.scale.category20c();
191
    var treemap = d3.layout.treemap()
192
        .size([width, height])
193
        .sticky(true)
194
        .value(function(d) { return d.size; });
195
    // Cleanup
196
    container.selectAll('.treemap').remove();
197
    var div = container
198
        .append('div')
199
        .classed({treemap: true, 'chart-centered': true})
200
        .style('position', 'relative')
201
        .style('width', width + 'px')
202
        .style('height', height + 'px');
203
204
    jsondash.getJSON(config.dataSource, function(error, root) {
205
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
206
        var node = div.datum(root).selectAll('.node')
207
            .data(treemap.nodes)
208
            .enter().append('div')
209
            .attr('class', 'node')
210
            .call(position)
211
            .style('border', '1px solid white')
212
            .style('font', '10px sans-serif')
213
            .style('line-height', '12px')
214
            .style('overflow', 'hidden')
215
            .style('position', 'absolute')
216
            .style('text-indent', '2px')
217
            .style('background', function(d) {
218
                return d.children ? color(d.name) : null;
219
            })
220
            .text(function(d) {
221
                return d.children ? null : d.name;
222
            });
223
        d3.selectAll('input').on('change', function change() {
224
            var value = this.value === 'count'
225
            ? function() { return 1; }
226
            : function(d) { return d.size;};
227
            node
228
            .data(treemap.value(value).nodes)
229
            .transition()
230
            .duration(1500)
231
            .call(position);
232
        });
233
        // Look for callbacks potentially registered for third party code.
234
        jsondash.api.runCallbacks(container, config);
235
        jsondash.unload(container);
236
    });
237
238
    function position() {
239
        this.style('left', function(d) { return d.x + 'px'; })
240
            .style('top', function(d) { return d.y + 'px'; })
241
            .style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; })
242
            .style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; });
243
    }
244
};
245
246
jsondash.handlers.handleRadialDendrogram = function(container, config) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
247
    'use strict';
248
    container.selectAll('svg').remove();
249
    // Code taken (and refactored for use here) from:
250
    // https://bl.ocks.org/mbostock/4339607
251
    var padding = 50;
252
    var radius = (config.width > config.height ? config.width : config.height) - padding;
253
    var cluster = d3.layout.cluster()
254
        .size([360, radius / 2 - 150]); // reduce size relative to `radius`
255
    var diagonal = d3.svg.diagonal.radial()
256
        .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
257
    var svg = container.append('svg')
258
        .attr('width', radius)
259
        .attr('height', radius);
260
    var g = svg.append('g');
261
    g.attr('transform', 'translate(' + radius / 2 + ',' + radius / 2 + ')');
262
263
    jsondash.getJSON(config.dataSource, function(error, root) {
264
        if (error) { throw error; }
265
        var nodes = cluster.nodes(root);
266
        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...
267
            .data(cluster.links(nodes))
268
            .enter().append('path')
269
            .attr('class', 'link')
270
            .attr('d', diagonal);
271
        var node = g.selectAll('g.node')
272
            .data(nodes)
273
            .enter().append('g')
274
            .attr('class', 'node')
275
            .attr('transform', function(d) { return 'rotate(' + (d.x - 90) + ')translate(' + d.y + ')'; });
276
        node.append('circle')
277
            .attr('r', 4.5);
278
        node.append('text')
279
            .attr('dy', '.31em')
280
            .attr('text-anchor', function(d) { return d.x < 180 ? 'start' : 'end'; })
281
            .attr('transform', function(d) { return d.x < 180 ? 'translate(8)' : 'rotate(180)translate(-8)'; })
282
            .text(function(d) { return d.name; });
283
        // Look for callbacks potentially registered for third party code.
284
        jsondash.api.runCallbacks(container, config);
285
        jsondash.unload(container);
286
    });
287
    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...
288
};
289
290
jsondash.handlers.handleDendrogram = function(container, config) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
291
    'use strict';
292
    container.selectAll('svg').remove();
293
    // A general padding for the svg inside of the widget.
294
    // The cluster dendrogram will also need to have padding itself, so
295
    // the bounds are not clipped in the svg.
296
    var svg_pad = 20;
297
    var width = config.width - svg_pad;
298
    var height = config.height - svg_pad;
299
    var PADDING = width / 4;
300
    var cluster = d3.layout.cluster()
301
        .size([height * 0.85, width - PADDING]);
302
    var diagonal = d3.svg.diagonal()
303
        .projection(function(d) { return [d.y, d.x]; });
304
    var svg = container
305
        .append('svg')
306
        .attr('width', width)
307
        .attr('height', height);
308
    var g = svg.append('g')
309
        .attr('transform', 'translate(40, 0)');
310
311
    jsondash.getJSON(config.dataSource, function(error, root) {
312
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
313
314
        var nodes = cluster.nodes(root);
315
        var links = cluster.links(nodes);
316
        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...
317
        .data(links)
318
        .enter().append('path')
319
        .attr('class', 'link')
320
        .attr('d', diagonal);
321
322
        var node = g.selectAll('.node')
323
        .data(nodes)
324
        .enter().append('g')
325
        .attr('class', 'node')
326
        .attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
327
328
        node.append('circle').attr('r', 4.5);
329
        node.append('text')
330
        .attr('dx', function(d) { return d.children ? -8 : 8; })
331
        .attr('dy', 3)
332
        .style('text-anchor', function(d) { return d.children ? 'end' : 'start'; })
333
        .text(function(d) { return d.name; });
334
335
        // Look for callbacks potentially registered for third party code.
336
        jsondash.api.runCallbacks(container, config);
337
        jsondash.unload(container);
338
    });
339
};
340
341
jsondash.handlers.handleVoronoi = function(container, config) {
342
    'use strict';
343
    jsondash.getJSON(config.dataSource, function(error, data){
344
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
345
        var width = config.width - jsondash.config.WIDGET_MARGIN_X;
346
        var height = config.height - jsondash.config.WIDGET_MARGIN_Y;
347
        var vertices = data;
348
        var voronoi = d3.geom.voronoi().clipExtent([[0, 0], [width, height]]);
349
        // Cleanup
350
        var svg = container
351
        .append('svg')
352
        .attr('width', width)
353
        .attr('height', height);
354
        var path = svg.append('g').selectAll('path');
355
        svg.selectAll('circle')
356
        .data(vertices.slice(1))
357
        .enter().append('circle')
358
        .attr('transform', function(d) { return 'translate(' + d + ')'; })
359
        .attr('r', 1.5);
360
        redraw();
361
362
        function redraw() {
363
            path = path.data(voronoi(vertices), jsondash.util.polygon);
364
            path.exit().remove();
365
            path.enter().append('path')
366
            .attr('class', function(d, i) { return 'q' + (i % 9) + '-9'; })
367
            .attr('d', jsondash.util.polygon);
368
            path.order();
369
        }
370
        // Look for callbacks potentially registered for third party code.
371
        jsondash.api.runCallbacks(container, config);
372
        jsondash.unload(container);
373
    });
374
};
375
376
jsondash.handlers.handleSparkline = function(container, config) {
377
    'use strict';
378
    // Clean up old canvas elements
379
    container.selectAll('.sparkline-container').remove();
380
    var sparkline_type = config.type.split('-')[1];
381
    var spark = container
382
        .append('div')
383
        .classed({
384
            'sparkline-container': true,
385
            'text-center': true
386
        });
387
    spark = $(spark[0]);
388
    jsondash.getJSON(config.dataSource, function(data){
389
        var opts = {
390
            type: sparkline_type,
391
            width: config.width - jsondash.config.WIDGET_MARGIN_X,
392
            height: config.height - jsondash.config.WIDGET_MARGIN_Y
393
        };
394
        spark.sparkline(data, opts);
395
        // Look for callbacks potentially registered for third party code.
396
        jsondash.api.runCallbacks(container, config);
397
        jsondash.unload(container);
398
    });
399
};
400
401
jsondash.handlers.handleDataTable = function(container, config) {
402
    'use strict';
403
    // Clean up old tables if they exist, during reloading.
404
    container.selectAll('.dataTables_wrapper').remove();
405
    jsondash.getJSON(config.dataSource, function(error, res) {
406
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
407
        var keys = d3.keys(res[0]).map(function(d){
408
            return {data: d, title: d};
409
        });
410
        container
411
            .append('table')
412
            .classed({
413
                table: true,
414
                'table-striped': true,
415
                'table-bordered': true,
416
                'table-condensed': true
417
            });
418
        var opts = config.override ? res : {data: res, columns: keys};
419
        $(container.select('table')[0]).dataTable(opts).css({width: 'auto'});
420
        // Look for callbacks potentially registered for third party code.
421
        jsondash.api.runCallbacks(container, config);
422
        jsondash.unload(container);
423
    });
424
};
425
426
jsondash.handlers.handleSingleNum = function(container, config) {
427
    'use strict';
428
    container.selectAll('.singlenum').remove();
429
    jsondash.getJSON(config.dataSource, function(resp){
430
        var data = resp.data.data ? resp.data.data : resp.data;
431
        var num = container.append('div')
432
            .classed({singlenum: true})
433
            .text(data);
434
        data = String(data);
435
        // Add red or green, depending on if the number appears to be pos/neg.
436
        if(!resp.noformat) {
437
            num.classed({
438
                'text-danger': data.startsWith('-'),
439
                'text-success': !data.startsWith('-')
440
            });
441
        }
442
        // Allow custom colors.
443
        if(resp.color && resp.noformat) {
444
            num.style('color', resp.color);
445
        }
446
        // Get title height to offset box.
447
        var title_h = container
448
            .select('.widget-title')
449
            .node()
450
            .getBoundingClientRect()
451
            .height;
452
        var inner_box_height = config.height - title_h; // factor in rough height of title.
453
        num.style({
454
            'line-height': inner_box_height + 'px',
455
            height: inner_box_height + 'px'
456
        });
457
        var digits = String(data).length;
458
        var size = jsondash.util.getDigitSize()(digits);
459
        num.style('font-size', size + 'px');
460
        // Look for callbacks potentially registered for third party code.
461
        jsondash.api.runCallbacks(container, config);
462
        jsondash.unload(container);
463
    });
464
};
465
466
jsondash.handlers.handleTimeline = function(container, config) {
467
    'use strict';
468
    jsondash.getJSON(config.dataSource, function(data){
469
        container.append('div').attr('id', 'widget-' + config.guid);
470
        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...
471
        // Look for callbacks potentially registered for third party code.
472
        jsondash.api.runCallbacks(container, config);
473
        jsondash.unload(container);
474
    });
475
};
476
477
jsondash.handlers.handleIframe = function(container, config) {
478
    'use strict';
479
    container.selectAll('iframe').remove();
480
    var iframe = container.append('iframe');
481
    iframe.attr({
482
        border: 0,
483
        src: config.dataSource,
484
        height: '100%',
485
        width: '100%'
486
    });
487
    // Look for callbacks potentially registered for third party code.
488
    jsondash.api.runCallbacks(container, config);
489
    jsondash.unload(container);
490
};
491
492
jsondash.handlers.handleCustom = function(container, config) {
493
    'use strict';
494
    container.selectAll('.custom-container').remove();
495
    $.get(config.dataSource, function(html){
496
        container.append('div').classed({'custom-container': true}).html(html);
497
        // Look for callbacks potentially registered for third party code.
498
        jsondash.api.runCallbacks(container, config);
499
        jsondash.unload(container);
500
    });
501
};
502
503
jsondash.handlers.handleVenn = function(container, config) {
504
    'use strict';
505
    container.selectAll('.venn').remove();
506
    jsondash.getJSON(config.dataSource, function(error, data){
507
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
508
        var chart = venn.VennDiagram();
509
        var cont = container
510
            .append('div')
511
            .classed({venn: true});
512
        cont.datum(data).call(chart);
513
        cont.select('svg')
514
            .attr('width', config.width - jsondash.config.WIDGET_MARGIN_X)
515
            .attr('height', config.height - jsondash.config.WIDGET_MARGIN_Y);
516
        // Look for callbacks potentially registered for third party code.
517
        jsondash.api.runCallbacks(container, config);
518
        jsondash.unload(container);
519
    });
520
};
521
522
jsondash.handlers.handlePlotly = function(container, config) {
523
    'use strict';
524
    var id = 'plotly-' + config.guid;
525
    container.selectAll('.plotly-container').remove();
526
    container.append('div')
527
        .classed({'plotly-container': true})
528
        .attr('id', id);
529
    jsondash.getJSON(config.dataSource, function(error, data){
530
        if(error) { throw new Error('Could not load url: ' + config.dataSource); }
531
        if(config.override) {
532
            if(data.layout && data.layout.margin) {
533
                // Remove margins, they mess up the
534
                // layout and are already accounted for.
535
                delete data.layout['margin'];
536
            }
537
            Plotly.plot(id, data.data, data.layout || {}, data.options || {});
538
        } else {
539
            Plotly.plot(id, data);
540
        }
541
        d3.select('#' + id).select('.svg-container').style({'margin': '0 auto'})
542
        // Look for callbacks potentially registered for third party code.
543
        jsondash.api.runCallbacks(container, config);
544
        jsondash.unload(container);
545
    });
546
};
547