added support for empty charts; now the javascript tracks colors per dimension to assign the same color on any instance of the chart; various optimizations; nonzero option is now properly supported
Costa Tsaousis (ktsaou) committed
Dec 16, 2015 at 04:32 UTC
810f14d024d8926d823f52c84e9ea0eab4f665f7
4 files changed
+438
-209
src/rrd2json.c
+68
-16
@@ -425,8 +425,34 @@ void rrdr_buffer_print_format(BUFFER *wb, uint32_t format)
425
}
426
}
427
428
+uint32_t rrdr_check_options(RRDR *r, uint32_t options)
429
+{
430
+ if(options & RRDR_OPTION_NONZERO) {
431
+ long c, i;
432
+ RRDDIM *rd;
433
+
434
+ // find how many dimensions are not zero
435
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ; c++, rd = rd->next) {
436
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
437
+ if(unlikely(!(r->od[c] & RRDR_NONZERO))) continue;
438
+ i++;
439
+ }
440
+
441
+ // if with nonzero we get i = 0
442
+ // but c != 0, then disable nonzero
443
+ // to show all dimensions
444
+ if(!i) options &= ~RRDR_OPTION_NONZERO;
445
+ }
446
+
447
+ return options;
448
+}
449
+
450
void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value)
451
{
452
+ int rows = rrdr_rows(r);
453
+ long c, i;
454
+ RRDDIM *rd;
455
+
456
//info("JSONWRAPPER(): %s: BEGIN", r->st->id);
457
char kq[2] = "", // key quote
458
sq[2] = ""; // string quote
@@ -441,13 +467,15 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
467
}
468
469
buffer_sprintf(wb, "{\n"
470
+ " %sapi%s: 1,\n"
471
" %sid%s: %s%s%s,\n"
472
" %sname%s: %s%s%s,\n"
473
" %sview_update_every%s: %d,\n"
474
" %supdate_every%s: %d,\n"
448
- " %sfirst_entry_t%s: %u, \n"
449
- " %slast_entry_t%s: %u, \n"
475
+ " %sfirst_entry_t%s: %u,\n"
476
+ " %slast_entry_t%s: %u,\n"
477
" %smin%s: "
478
+ , kq, kq
479
, kq, kq, sq, r->st->id, sq
480
, kq, kq, sq, r->st->name, sq
481
, kq, kq, r->update_every
@@ -467,10 +495,7 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
495
, kq, kq, r->after
496
, kq, kq);
497
470
-
471
- long c, i;
472
- RRDDIM *rd;
473
- for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
498
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
499
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
500
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
501
@@ -480,11 +505,18 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
505
buffer_strcat(wb, sq);
506
i++;
507
}
508
+ if(!i) {
509
+ rows = 0;
510
+ buffer_strcat(wb, sq);
511
+ buffer_strcat(wb, "no data");
512
+ buffer_strcat(wb, sq);
513
+ }
514
+
515
buffer_sprintf(wb, "],\n"
516
" %sdimension_ids%s: ["
517
, kq, kq);
518
487
- for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
519
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
520
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
521
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
522
@@ -494,11 +526,18 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
526
buffer_strcat(wb, sq);
527
i++;
528
}
529
+ if(!i) {
530
+ rows = 0;
531
+ buffer_strcat(wb, sq);
532
+ buffer_strcat(wb, "no data");
533
+ buffer_strcat(wb, sq);
534
+ }
535
+
536
buffer_sprintf(wb, "],\n"
537
" %slatest_values%s: ["
538
, kq, kq);
539
501
- for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
540
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
541
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
542
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
543
@@ -512,12 +551,18 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
551
else
552
buffer_rrd_value(wb, unpack_storage_number(n));
553
}
554
+ if(!i) {
555
+ rows = 0;
556
+ buffer_strcat(wb, "null");
557
+ }
558
+
559
buffer_sprintf(wb, "],\n"
560
" %sresult_latest_values%s: ["
561
, kq, kq);
562
519
- if(rrdr_rows(r)) {
520
- for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
563
+ i = 0;
564
+ if(rows) {
565
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
566
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
567
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
568
@@ -533,12 +578,17 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
578
buffer_rrd_value(wb, cn[c]);
579
}
580
}
581
+ if(!i) {
582
+ rows = 0;
583
+ buffer_strcat(wb, "null");
584
+ }
585
+
586
buffer_sprintf(wb, "],\n"
587
" %sdimensions%s: %d,\n"
588
" %spoints%s: %d,\n"
589
" %sformat%s: %s"
590
, kq, kq, i
541
- , kq, kq, rrdr_rows(r)
591
+ , kq, kq, rows
592
, kq, kq, sq
593
);
594
@@ -661,7 +711,7 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
711
RRDDIM *rd;
712
713
// print the header lines
664
- for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
714
+ for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
715
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
716
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
717
@@ -747,7 +797,7 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
797
}
798
799
// for each dimension
750
- for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
800
+ for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) {
801
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
802
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
803
@@ -786,7 +836,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
836
RRDDIM *d;
837
838
// print the csv header
789
- for(c = 0, i = 0, d = r->st->dimensions; d ;c++, d = d->next) {
839
+ for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
840
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
841
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
842
@@ -835,7 +885,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
885
}
886
887
// for each dimension
838
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
888
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
889
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
890
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
891
@@ -884,7 +934,7 @@ static void rrdr2ssv(RRDR *r, BUFFER *wb, uint32_t options, const char *prefix,
934
int all_null = 1, init = 1;
935
936
// for each dimension
887
- for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) {
937
+ for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) {
938
if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
939
if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
940
@@ -1333,6 +1383,8 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
1383
return 500;
1384
}
1385
1386
+ options = rrdr_check_options(r, options);
1387
+
1388
if(dimensions)
1389
rrdr_disable_not_selected_dimensions(r, buffer_tostring(dimensions));
1390
web/dashboard.html
+11
@@ -326,6 +326,17 @@ Sparklines using dygraphs
326
<br/>
327
<small>rendered in <span id="time208">X</span> ms</small>
328
</div>
329
+<div style="width: 33%; display: inline-block;">
330
+ <div data-netdata="net.gstag0"
331
+ data-chart-library="dygraph"
332
+ data-width="100%"
333
+ data-height="200"
334
+ data-after="-300"
335
+ data-dt-element-name="time209"
336
+ ></div>
337
+ <br/>
338
+ <small>rendered in <span id="time209">X</span> ms</small>
339
+</div>
340
341
342
web/dashboard.js
+358
-192
@@ -5,6 +5,8 @@
5
// var netdataNoPeitys = true; // do not use peity
6
// var netdataNoGoogleCharts = true; // do not use google
7
// var netdataNoMorris = true; // do not use morris
8
+// var netdataNoEasyPieChart = true; // do not use easy pie chart
9
+// var netdataNoBootstrap = true; // do not load bootstrap
10
// var netdataDontStart = true; // do not start the thread to process the charts
11
//
12
// You can also set the default netdata server, using the following.
@@ -13,7 +15,7 @@
15
// var netdataServer = "http://yourhost:19999"; // set your NetData server
16
17
//(function(window, document, undefined) {
16
- // fix IE bug with console
18
+ // fix IE issue with console
19
if(!window.console){ window.console = {log: function(){} }; }
20
21
// global namespace
@@ -161,15 +163,17 @@
163
164
idle_between_charts: 100, // ms - how much time to wait between chart updates
165
164
- fast_render_timeframe: 100, // ms - render continously until this time of continious
166
+ fast_render_timeframe: 200, // ms - render continously until this time of continious
167
// rendering has been reached
168
// this setting is used to make it render e.g. 10
169
// charts at once, sleep idle_between_charts time
170
// and continue for another 10 charts.
171
170
- idle_between_loops: 200, // ms - if all charts have been updated, wait this
172
+ idle_between_loops: 500, // ms - if all charts have been updated, wait this
173
// time before starting again.
174
175
+ idle_parallel_loops: 100, // ms - the time between parallel refresher updates
176
+
177
idle_lost_focus: 500, // ms - when the window does not have focus, check
178
// if focus has been regained, every this time
179
@@ -193,6 +197,8 @@
197
198
destroy_on_hide: false, // destroy charts when they are not visible
199
200
+ eliminate_zero_dimensions: true, // do not show dimensions with just zeros
201
+
202
color_fill_opacity: {
203
line: 1.0,
204
area: 0.2,
@@ -223,6 +229,7 @@
229
230
window.onscroll = function(event) {
231
NETDATA.options.last_page_scroll = new Date().getTime();
232
+ if(NETDATA.options.targets === null) return;
233
234
// when the user scrolls he sees that we have
235
// hidden all the not-visible charts
@@ -453,6 +460,8 @@
460
library: null, // object - the chart library used
461
462
colors: null,
463
+ colors_assigned: {},
464
+ colors_available: null,
465
466
element: element, // the element already created by the user
467
element_message: null,
@@ -889,7 +898,7 @@
898
}
899
900
chartState.prototype.legendFormatValue = function(value) {
892
- if(value === null) return '-';
901
+ if(value === null || value === 'undefined') return '-';
902
if(typeof value !== 'number') return value;
903
904
var abs = Math.abs(value);
@@ -915,7 +924,7 @@
924
925
chartState.prototype.legendSetDate = function(ms) {
926
if(typeof ms !== 'number') {
918
- this.legendUndefined();
927
+ this.legendShowUndefined();
928
return;
929
}
930
@@ -931,7 +940,7 @@
940
this.element_legend_childs.title_units.innerHTML = this.chart.units;
941
}
942
934
- chartState.prototype.legendUndefined = function() {
943
+ chartState.prototype.legendShowUndefined = function() {
944
if(this.element_legend_childs.title_date)
945
this.element_legend_childs.title_date.innerHTML = ' ';
946
@@ -959,7 +968,7 @@
968
if(this.selected) return;
969
970
if(this.current.data === null || this.element_legend_childs.series === null) {
962
- this.legendUndefined();
971
+ this.legendShowUndefined();
972
return;
973
}
974
@@ -968,7 +977,7 @@
977
show_undefined = false;
978
979
if(show_undefined)
971
- this.legendUndefined();
980
+ this.legendShowUndefined();
981
else
982
this.legendSetDate(this.current.data.before * 1000);
983
@@ -991,28 +1000,51 @@
1000
this.legendShowLatestValues();
1001
}
1002
1003
+ // this should be called just ONCE per dimension per chart
1004
+ chartState.prototype._chartDimensionColor = function(label) {
1005
+ if(this.colors === null)
1006
+ this.chartColors();
1007
+
1008
+ if(typeof this.colors_assigned[label] === 'undefined') {
1009
+ if(this.colors_available.length === 0) {
1010
+ for(var i = 0, len = NETDATA.colors.length; i < len ; i++)
1011
+ this.colors_available.push(NETDATA.colors[i]);
1012
+ }
1013
+
1014
+ this.colors_assigned[label] = this.colors_available.shift();
1015
+ if(this.debug) this.log('label "' + label + '" got color "' + this.colors_assigned[label]);
1016
+ }
1017
+ else {
1018
+ if(this.debug) this.log('label "' + label + '" already has color "' + this.colors_assigned[label] + '"');
1019
+ }
1020
+
1021
+ this.colors.push(this.colors_assigned[label]);
1022
+ return this.colors_assigned[label];
1023
+ }
1024
+
1025
chartState.prototype.chartColors = function() {
1026
if(this.colors !== null) return this.colors;
1027
997
- this.colors = $(this.element).data('colors');
998
- if(typeof this.colors === 'undefined' || this.colors === null)
999
- this.colors = NETDATA.colors;
1000
- else {
1001
- // console.log(this.colors);
1002
- var s = this.colors;
1003
- if(typeof s === 'string') s = s.split(' ');
1028
+ this.colors = new Array();
1029
1005
- this.colors = new Array();
1006
- var self = this;
1007
- $.each(s, function(i, c) {
1008
- self.colors.push(c);
1009
- });
1030
+ if(this.colors_available === null) {
1031
+ this.colors_available = new Array();
1032
1011
- // push the default colors too
1012
- var self = this;
1013
- $.each(NETDATA.colors, function(i, c) {
1014
- self.colors.push(c);
1015
- });
1033
+ var c = $(this.element).data('colors');
1034
+ if(typeof c !== 'undefined' && c !== null) {
1035
+ if(typeof c !== 'string') {
1036
+ this.log('invalid color given: ' + c + ' (give a space separated list of colors)');
1037
+ }
1038
+ else {
1039
+ c = c.split(' ');
1040
+ for(var i = 0, len = c.length; i < len ; i++)
1041
+ this.colors_available.push(c[i]);
1042
+ }
1043
+ }
1044
+
1045
+ // push all the standard colors too
1046
+ for(var i = 0, len = NETDATA.colors.length; i < len ; i++)
1047
+ this.colors_available.push(NETDATA.colors[i]);
1048
}
1049
1050
return this.colors;
@@ -1030,31 +1062,47 @@
1062
// this.log('the chart does not have any data - requesting legend update');
1063
needed = true;
1064
}
1065
+ else if(typeof this.element_legend_childs.series.labels_key === 'undefined') {
1066
+ needed = true;
1067
+ }
1068
else {
1034
- // this.log('checking existing legend');
1035
- var labels = this.current.data.dimension_names;
1036
- var i = labels.length;
1037
- while(i--) {
1038
- var name = labels[i];
1039
- if(typeof this.element_legend_childs.series[name] === 'undefined') {
1040
- // this.log('legend is incosistent - missing dimension:' + name);
1041
- needed = true;
1042
- break;
1043
- }
1044
- else if(Math.abs(this.current.data.last_entry_t - this.current.data.before) <= this.current.data.view_update_every) {
1045
- // this.log('setting legend of ' + name + ' to ' + this.current.data.latest_values[i]);
1046
- this.legendSetLabelValue(name, this.current.data.latest_values[i]);
1047
- }
1069
+ var labels = this.current.data.dimension_names.toString();
1070
+ if(labels !== this.element_legend_childs.series.labels_key) {
1071
+ needed = true;
1072
+ if(this.debug) this.log('NEW LABELS: "' + labels + '" NOT EQUAL OLD LABELS: "' + this.element_legend_childs.series.labels_key + '"');
1073
}
1074
}
1075
1051
- if(!needed) return;
1076
+ if(!needed) {
1077
+ // make sure there are colors available
1078
+ if(this.colors === null) this.colors = NETDATA.colors;
1079
+
1080
+ // do we have to update the current values?
1081
+ // we do this, only when the visible chart is current
1082
+ if(Math.abs(this.current.data.last_entry_t - this.current.data.before) <= this.current.data.view_update_every) {
1083
+ if(this.debug) this.log('chart in running... updating values on legend...');
1084
+ var labels = this.current.data.dimension_names;
1085
+ var i = labels.length;
1086
+ while(i--)
1087
+ this.legendSetLabelValue(labels[i], this.current.data.latest_values[i]);
1088
+ }
1089
+ return;
1090
+ }
1091
+ if(this.colors === null) {
1092
+ // this is the first time we update the chart
1093
+ // let's assign colors to all dimensions
1094
+ if(this.library.track_colors() === true)
1095
+ for(var dim in this.chart.dimensions)
1096
+ this._chartDimensionColor(this.chart.dimensions[dim].name);
1097
+ }
1098
+ // we will re-generate the colors for the chart
1099
+ this.colors = null;
1100
1101
if(this.debug) this.log('updating Legend DOM');
1102
1103
self = $(this.element);
1104
var genLabel = function(state, parent, name, count) {
1057
- var c = count % state.chartColors().length;
1105
+ var color = state._chartDimensionColor(name);
1106
1107
var user_element = null;
1108
var user_id = self.data('show-value-of-' + name + '-at') || null;
@@ -1078,7 +1126,7 @@
1126
label.name.title = name;
1127
label.value.title = name;
1128
1081
- var rgb = NETDATA.colorHex2Rgb(state.chartColors()[c]);
1129
+ var rgb = NETDATA.colorHex2Rgb(color);
1130
label.name.innerHTML = '<table class="netdata-legend-name-table-'
1131
+ state.chart.chart_type
1132
+ '" style="background-color: '
@@ -1088,8 +1136,8 @@
1136
var text = document.createTextNode(' ' + name);
1137
label.name.appendChild(text);
1138
1091
- label.name.style.color = state.chartColors()[c];
1092
- label.value.style.color = state.chartColors()[c];
1139
+ label.name.style.color = color;
1140
+ label.value.style.color = color;
1141
1142
if(count > 0)
1143
parent.appendChild(document.createElement('br'));
@@ -1154,16 +1202,21 @@
1202
}
1203
1204
if(this.current.data) {
1157
- var me = this;
1158
- $.each(me.current.data.dimension_names, function(i, d) {
1159
- genLabel(me, content, d, i);
1160
- });
1205
+ this.element_legend_childs.series.labels_key = this.current.data.dimension_names.toString();
1206
+ if(this.debug) this.log('SET DATA LABELS: "' + this.element_legend_childs.series.labels_key + '"');
1207
+
1208
+ for(var i = 0, len = this.current.data.dimension_names.length; i < len ;i++) {
1209
+ genLabel(this, content, this.current.data.dimension_names[i], i);
1210
+ }
1211
}
1212
else {
1163
- var me = this;
1164
- $.each(me.chart.dimensions, function(i, d) {
1165
- genLabel(me, content, d.name, i);
1166
- });
1213
+ var tmp = new Array();
1214
+ for(var dim in this.chart.dimensions) {
1215
+ tmp.push(this.chart.dimensions[dim].name);
1216
+ genLabel(this, content, this.chart.dimensions[dim].name, i);
1217
+ }
1218
+ this.element_legend_childs.series.labels_key = tmp.toString();
1219
+ if(this.debug) this.log('SET DEFAULT LABELS: "' + this.element_legend_childs.series.labels_key + '"');
1220
}
1221
1222
// create a hidden div to be used for hidding
@@ -1291,6 +1344,9 @@
1344
this.current.url += "&options=" + this.library.options();
1345
this.current.url += '|jsonwrap';
1346
1347
+ if(NETDATA.options.current.eliminate_zero_dimensions === true)
1348
+ this.current.url += '|nonzero';
1349
+
1350
if(after)
1351
this.current.url += "&after=" + after.toString();
1352
@@ -1306,8 +1362,10 @@
1362
chartState.prototype.updateChartWithData = function(data) {
1363
if(this.debug) this.log('got data from netdata server');
1364
this.current.data = data;
1365
+ this.updates_counter++;
1366
1310
- var started = this.tm.last_updated = new Date().getTime();
1367
+ var started = new Date().getTime();
1368
+ this.tm.last_updated = started;
1369
1370
// if the result is JSON, find the latest update-every
1371
if(typeof data === 'object') {
@@ -1332,8 +1390,6 @@
1390
data.state = this;
1391
}
1392
1335
- this.updates_counter++;
1336
-
1393
if(this.debug) {
1394
this.log('UPDATE No ' + this.updates_counter + ' COMPLETED');
1395
@@ -1347,6 +1403,11 @@
1403
this.log('STATUS: points : ' + (this.current.points).toString() + ', min step: ' + (this._minPanOrZoomStep() / 1000).toString());
1404
}
1405
1406
+ if(data.points === 0) {
1407
+ this.noData();
1408
+ return;
1409
+ }
1410
+
1411
// this may force the chart to be re-created
1412
this.resizeChart();
1413
@@ -1403,8 +1464,12 @@
1464
// forced to be updated with global PanAndZoom
1465
if(NETDATA.globalPanAndZoom.isActive())
1466
this.current.last_autorefreshed = 0;
1406
- else
1407
- this.current.last_autorefreshed = now;
1467
+ else {
1468
+ //if(NETDATA.options.current.parallel_refresher === true)
1469
+ // this.current.last_autorefreshed = Math.round(now / 1000) * 1000;
1470
+ //else
1471
+ this.current.last_autorefreshed = now;
1472
+ }
1473
1474
this.refresh_dt_ms = now - started;
1475
NETDATA.options.auto_refresher_fast_weight += this.refresh_dt_ms;
@@ -1429,9 +1494,16 @@
1494
}
1495
1496
if(this.library.initialized === false) {
1432
- var self = this;
1433
- this.library.initialize(function() { self.updateChart(callback); });
1434
- return;
1497
+ if(this.library.enabled === true) {
1498
+ var self = this;
1499
+ this.library.initialize(function() { self.updateChart(callback); });
1500
+ return;
1501
+ }
1502
+ else {
1503
+ this.error('chart library "' + this.library_name + '" is not available.');
1504
+ if(typeof callback === 'function') callback();
1505
+ return false;
1506
+ }
1507
}
1508
1509
this.clearSelection();
@@ -1462,6 +1534,8 @@
1534
}
1535
1536
chartState.prototype.destroyChart = function() {
1537
+ if(this.debug === true) this.log('destroying chart');
1538
+
1539
this.current.last_autorefreshed = new Date().getTime();
1540
1541
if(this.element_message !== null) {
@@ -1528,6 +1602,8 @@
1602
1603
chartState.prototype.unhideChart = function() {
1604
if(typeof this.___isHidden___ !== 'undefined' && this.enabled === true) {
1605
+ if(this.debug === true) this.log('unhiding chart');
1606
+
1607
this.element_message.style.display = 'none';
1608
if(this.element_chart !== null) this.element_chart.style.display = 'inline-block';
1609
if(this.element_legend !== null) this.element_legend.style.display = 'inline-block';
@@ -1548,6 +1624,7 @@
1624
if(NETDATA.options.current.destroy_on_hide === true)
1625
this.destroyChart();
1626
1627
+ if(this.debug === true) this.log('hiding chart');
1628
this.element_message.style.display = 'inline-block';
1629
if(this.element_chart !== null) this.element_chart.style.display = 'none';
1630
if(this.element_legend !== null) this.element_legend.style.display = 'none';
@@ -1561,6 +1638,8 @@
1638
1639
chartState.prototype.hideLoading = function() {
1640
if(typeof this.___showsLoading___ !== 'undefined' && this.enabled === true) {
1641
+ if(this.debug === true) this.log('hide loading...');
1642
+
1643
this.element_message.style.display = 'none';
1644
if(this.element_chart !== null) this.element_chart.style.display = 'inline-block';
1645
if(this.element_legend !== null) this.element_legend.style.display = 'inline-block';
@@ -1573,6 +1652,8 @@
1652
1653
chartState.prototype.showLoading = function() {
1654
if(typeof this.___showsLoading___ === 'undefined' && this.tm.last_created === 0 && this.enabled === true) {
1655
+ if(this.debug === true) this.log('show loading...');
1656
+
1657
this.element_message.style.display = 'none';
1658
if(this.element_chart !== null) this.element_chart.style.display = 'none';
1659
if(this.element_legend !== null) this.element_legend.style.display = 'none';
@@ -1586,8 +1667,10 @@
1667
1668
chartState.prototype.isVisible = function() {
1669
// this.log('last_visible_check: ' + this.tm.last_visible_check + ', last_page_scroll: ' + NETDATA.options.last_page_scroll);
1589
- if(this.tm.last_visible_check > NETDATA.options.last_page_scroll)
1670
+ if(this.tm.last_visible_check > NETDATA.options.last_page_scroll) {
1671
+ if(this.debug === true) this.log('isVisible: ' + this.___isVisible___);
1672
return this.___isVisible___;
1673
+ }
1674
1675
this.tm.last_visible_check = new Date().getTime();
1676
@@ -1609,12 +1692,14 @@
1692
// the chart is too far
1693
this.___isVisible___ = false;
1694
if(this.tm.last_created !== 0) this.hideChart();
1695
+ if(this.debug === true) this.log('isVisible: ' + this.___isVisible___);
1696
return this.___isVisible___;
1697
}
1698
else {
1699
// the chart is inside or very close
1700
this.___isVisible___ = true;
1701
this.unhideChart();
1702
+ if(this.debug === true) this.log('isVisible: ' + this.___isVisible___);
1703
return this.___isVisible___;
1704
}
1705
}
@@ -1757,13 +1842,20 @@
1842
$(this.element).css('min-width', NETDATA.chartDefaults.min_width);
1843
}
1844
1845
+ chartState.prototype.noData = function() {
1846
+ if(this.tm.last_created === 0) {
1847
+ this.createChartDOM();
1848
+ this.tm.last_created = new Date().getTime();
1849
+ }
1850
+
1851
+ this.current.last_autorefreshed = new Date().getTime();
1852
+ this.current.view_update_every = 30 * 1000;
1853
+ }
1854
+
1855
// show a message in the chart
1856
chartState.prototype.message = function(type, msg) {
1857
this.hideChart();
1858
this.element_message.innerHTML = msg;
1764
-
1765
- // reset the creation datetime
1766
- // since we overwrote the whole element
1859
if(this.debug) this.log(msg);
1860
}
1861
@@ -1941,10 +2033,12 @@
2033
2034
// ----------------------------------------------------------------------------------------------------------------
2035
2036
+ // this is purely sequencial charts refresher
2037
+ // it is meant to be autonomous
2038
NETDATA.chartRefresherNoParallel = function(index) {
2039
if(NETDATA.options.debug.mail_loop) console.log('NETDATA.chartRefresherNoParallel(' + index + ')');
2040
1947
- if(NETDATA.options.updated_dom) {
2041
+ if(NETDATA.options.updated_dom === true) {
2042
// the dom has been updated
2043
// get the dom parts again
2044
NETDATA.parseDom(NETDATA.chartRefresher);
@@ -1981,8 +2075,14 @@
2075
}
2076
}
2077
1984
- NETDATA.chartRefresher_sequencial = function() {
1985
- if(NETDATA.options.updated_dom) {
2078
+ // this is part of the parallel refresher
2079
+ // its cause is to refresh sequencially all the charts
2080
+ // that depend on chart library initialization
2081
+ // it will call the parallel refresher back
2082
+ // as soon as it sees a chart that its chart library
2083
+ // is initialized
2084
+ NETDATA.chartRefresher_unitialized = function() {
2085
+ if(NETDATA.options.updated_dom === true) {
2086
// the dom has been updated
2087
// get the dom parts again
2088
NETDATA.parseDom(NETDATA.chartRefresher);
@@ -1993,18 +2093,28 @@
2093
NETDATA.chartRefresher();
2094
else {
2095
var state = NETDATA.options.sequencial.pop();
1996
- if(state.library.initialized)
2096
+ if(state.library.initialized === true)
2097
NETDATA.chartRefresher();
2098
else
1999
- state.autoRefresh(NETDATA.chartRefresher_sequencial);
2099
+ state.autoRefresh(NETDATA.chartRefresher_unitialized);
2100
}
2101
}
2102
2103
+ NETDATA.chartRefresherWaitTime = function() {
2104
+ return NETDATA.options.current.idle_parallel_loops;
2105
+ }
2106
+
2107
+ // the default refresher
2108
+ // it will create 2 sets of charts:
2109
+ // - the ones that can be refreshed in parallel
2110
+ // - the ones that depend on something else
2111
+ // the first set will be executed in parallel
2112
+ // the second will be given to NETDATA.chartRefresher_unitialized()
2113
NETDATA.chartRefresher = function() {
2004
- if(NETDATA.options.pause) {
2114
+ if(NETDATA.options.pause === true) {
2115
// console.log('auto-refresher is paused');
2116
setTimeout(NETDATA.chartRefresher,
2007
- NETDATA.options.current.idle_between_loops);
2117
+ NETDATA.chartRefresherWaitTime());
2118
return;
2119
}
2120
@@ -2013,50 +2123,60 @@
2123
NETDATA.options.pause = true;
2124
NETDATA.options.pauseCallback();
2125
NETDATA.chartRefresher();
2126
+ return;
2127
}
2128
2018
- if(!NETDATA.options.current.parallel_refresher) {
2129
+ if(NETDATA.options.current.parallel_refresher === false) {
2130
NETDATA.chartRefresherNoParallel(0);
2131
return;
2132
}
2133
2023
- if(NETDATA.options.updated_dom) {
2134
+ if(NETDATA.options.updated_dom === true) {
2135
// the dom has been updated
2136
// get the dom parts again
2137
NETDATA.parseDom(NETDATA.chartRefresher);
2138
return;
2139
}
2140
2030
- NETDATA.options.parallel = new Array();
2031
- NETDATA.options.sequencial = new Array();
2032
-
2141
+ var parallel = new Array();
2142
var targets = NETDATA.options.targets;
2143
var len = targets.length;
2144
while(len--) {
2145
+ if(!targets[len].isVisible()) continue;
2146
+
2147
var state = targets[len];
2148
+ if(state.library.initialized === false) {
2149
+ if(state.library.enabled === true) {
2150
+ state.library.initialize(NETDATA.chartRefresher);
2151
+ return;
2152
+ }
2153
+ else {
2154
+ state.error('chart library "' + state.library_name + '" is not enabled.');
2155
+ state.enabled = false;
2156
+ }
2157
+ }
2158
2038
- if(!state.library.initialized)
2039
- NETDATA.options.sequencial.push(state);
2040
- else
2041
- NETDATA.options.parallel.push(state);
2159
+ parallel.unshift(state);
2160
}
2161
2044
- if(NETDATA.options.parallel.length > 0) {
2045
- NETDATA.options.parallel_jobs = NETDATA.options.parallel.length;
2162
+ if(parallel.length > 0) {
2163
+ var parallel_jobs = parallel.length;
2164
2047
- $(NETDATA.options.parallel).each(function() {
2165
+ // this will execute the jobs in parallel
2166
+ $(parallel).each(function() {
2167
this.autoRefresh(function() {
2049
- NETDATA.options.parallel_jobs--;
2050
- if(NETDATA.options.parallel_jobs === 0) {
2051
- setTimeout(NETDATA.chartRefresher_sequencial,
2052
- NETDATA.options.current.idle_between_charts);
2168
+ parallel_jobs--;
2169
+
2170
+ if(parallel_jobs === 0) {
2171
+ setTimeout(NETDATA.chartRefresher,
2172
+ NETDATA.chartRefresherWaitTime());
2173
}
2174
});
2175
})
2176
}
2177
else {
2058
- setTimeout(NETDATA.chartRefresher_sequencial,
2059
- NETDATA.options.current.idle_between_charts);
2178
+ setTimeout(NETDATA.chartRefresher,
2179
+ NETDATA.chartRefresherWaitTime());
2180
}
2181
}
2182
@@ -2114,16 +2234,17 @@
2234
cache: true,
2235
dataType: "script"
2236
})
2117
- .done(function() {
2118
- NETDATA.registerChartLibrary('peity', NETDATA.peity_js);
2119
- })
2120
- .fail(function() {
2121
- NETDATA.error(100, NETDATA.peity_js);
2122
- })
2123
- .always(function() {
2124
- if(typeof callback === "function")
2125
- callback();
2126
- })
2237
+ .done(function() {
2238
+ NETDATA.registerChartLibrary('peity', NETDATA.peity_js);
2239
+ })
2240
+ .fail(function() {
2241
+ NETDATA.chartLibraries.peity.enabled = false;
2242
+ NETDATA.error(100, NETDATA.peity_js);
2243
+ })
2244
+ .always(function() {
2245
+ if(typeof callback === "function")
2246
+ callback();
2247
+ });
2248
}
2249
else {
2250
NETDATA.chartLibraries.peity.enabled = false;
@@ -2133,19 +2254,33 @@
2254
};
2255
2256
NETDATA.peityChartUpdate = function(state, data) {
2136
- $(state.peity_instance).html(data.result);
2137
- // $(state.element_chart).change() does not accept options
2138
- // to pass width and height
2139
- //$(state.peity_instance).change();
2140
- $(state.peity_instance).peity('line', { width: state.chartWidth(), height: state.chartHeight() });
2257
+ state.peity_instance.innerHTML = data.result;
2258
+
2259
+ if(state.peity_options.stroke !== state.chartColors()[0]) {
2260
+ state.peity_options.stroke = state.chartColors()[0];
2261
+ if(state.chart.chart_type === 'line')
2262
+ state.peity_options.fill = '#FFF';
2263
+ else
2264
+ state.peity_options.fill = NETDATA.colorLuminance(state.chartColors()[0], NETDATA.chartDefaults.fill_luminance);
2265
+ }
2266
+
2267
+ $(state.peity_instance).peity('line', state.peity_options);
2268
}
2269
2270
NETDATA.peityChartCreate = function(state, data) {
2271
state.peity_instance = document.createElement('div');
2272
state.element_chart.appendChild(state.peity_instance);
2273
2147
- $(state.peity_instance).html(data.result);
2148
- $(state.peity_instance).peity('line', { width: state.chartWidth(), height: state.chartHeight() });
2274
+ var self = $(state.element);
2275
+ state.peity_options = {
2276
+ stroke: '#000',
2277
+ strokeWidth: self.data('peity-strokewidth') || 1,
2278
+ width: state.chartWidth(),
2279
+ height: state.chartHeight(),
2280
+ fill: '#000'
2281
+ };
2282
+
2283
+ NETDATA.peityChartUpdate(state, data);
2284
}
2285
2286
// ----------------------------------------------------------------------------------------------------------------
@@ -2158,16 +2293,17 @@
2293
cache: true,
2294
dataType: "script"
2295
})
2161
- .done(function() {
2162
- NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js);
2163
- })
2164
- .fail(function() {
2165
- NETDATA.error(100, NETDATA.sparkline_js);
2166
- })
2167
- .always(function() {
2168
- if(typeof callback === "function")
2169
- callback();
2170
- })
2296
+ .done(function() {
2297
+ NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js);
2298
+ })
2299
+ .fail(function() {
2300
+ NETDATA.chartLibraries.sparkline.enabled = false;
2301
+ NETDATA.error(100, NETDATA.sparkline_js);
2302
+ })
2303
+ .always(function() {
2304
+ if(typeof callback === "function")
2305
+ callback();
2306
+ });
2307
}
2308
else {
2309
NETDATA.chartLibraries.sparkline.enabled = false;
@@ -2300,7 +2436,7 @@
2436
state.dygraph_instance.setSelection(r);
2437
else {
2438
state.dygraph_instance.clearSelection();
2303
- state.legendUndefined();
2439
+ state.legendShowUndefined();
2440
}
2441
}
2442
@@ -2320,15 +2456,18 @@
2456
cache: true,
2457
dataType: "script"
2458
})
2323
- .done(function() {
2324
- NETDATA.dygraph.smooth = true;
2325
- smoothPlotter.smoothing = 0.3;
2326
- })
2327
- .always(function() {
2328
- if(typeof callback === "function")
2329
- callback();
2330
- })
2331
- };
2459
+ .done(function() {
2460
+ NETDATA.dygraph.smooth = true;
2461
+ smoothPlotter.smoothing = 0.3;
2462
+ })
2463
+ .fail(function() {
2464
+ NETDATA.dygraph.smooth = false;
2465
+ })
2466
+ .always(function() {
2467
+ if(typeof callback === "function")
2468
+ callback();
2469
+ });
2470
+ }
2471
2472
NETDATA.dygraphInitialize = function(callback) {
2473
if(typeof netdataNoDygraphs === 'undefined' || !netdataNoDygraphs) {
@@ -2337,15 +2476,19 @@
2476
cache: true,
2477
dataType: "script"
2478
})
2340
- .done(function() {
2341
- NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js);
2479
+ .done(function() {
2480
+ NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js);
2481
+ })
2482
+ .fail(function() {
2483
+ NETDATA.chartLibraries.dygraph.enabled = false;
2484
+ NETDATA.error(100, NETDATA.dygraph_js);
2485
+ })
2486
+ .always(function() {
2487
+ if(NETDATA.chartLibraries.dygraph.enabled === true)
2488
NETDATA.dygraphSmoothInitialize(callback);
2343
- })
2344
- .fail(function() {
2345
- NETDATA.error(100, NETDATA.dygraph_js);
2346
- if(typeof callback === "function")
2347
- callback();
2348
- })
2489
+ else if(typeof callback === "function")
2490
+ callback();
2491
+ });
2492
}
2493
else {
2494
NETDATA.chartLibraries.dygraph.enabled = false;
@@ -2369,6 +2512,7 @@
2512
if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartUpdate() loose update');
2513
dygraph.updateOptions({
2514
file: data.result.data,
2515
+ colors: state.chartColors(),
2516
labels: data.result.labels,
2517
labelsDivWidth: state.chartWidth() - 70
2518
});
@@ -2377,6 +2521,7 @@
2521
if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartUpdate() strict update');
2522
dygraph.updateOptions({
2523
file: data.result.data,
2524
+ colors: state.chartColors(),
2525
labels: data.result.labels,
2526
labelsDivWidth: state.chartWidth() - 70,
2527
dateWindow: null,
@@ -2406,9 +2551,6 @@
2551
var highlightCircleSize = (NETDATA.chartLibraries.dygraph.isSparkline(state))?3:4;
2552
2553
2409
- //if(state.id == 'system.cpu')
2410
- // console.log(data);
2411
-
2554
state.dygraph_options = {
2555
colors: self.data('dygraph-colors') || state.chartColors(),
2556
@@ -2420,7 +2562,6 @@
2562
title: self.data('dygraph-title') || state.chart.title,
2563
titleHeight: self.data('dygraph-titleheight') || 19,
2564
2423
-// legend: self.data('dygraph-legend') || NETDATA.chartLibraries.dygraph.legend(state)?'always':'never', // 'onmouseover',
2565
legend: self.data('dygraph-legend') || 'always', // 'onmouseover',
2566
labels: data.result.labels,
2567
labelsDiv: self.data('dygraph-labelsdiv') || state.element_legend_childs.hidden,
@@ -2657,7 +2798,7 @@
2798
2799
// http://dygraphs.com/gallery/interaction-api.js
2800
var normal = (event.detail) ? event.detail * -1 : event.wheelDelta / 40;
2660
- var percentage = normal / 25;
2801
+ var percentage = normal / 10;
2802
2803
var before_old = state.current.before_ms;
2804
var after_old = state.current.after_ms;
@@ -2709,8 +2850,7 @@
2850
state.dygraph_options.rightGap = 0;
2851
}
2852
2712
- if(smooth === true && typeof smoothPlotter === 'function')
2713
- state.dygraph_options.plotter = smoothPlotter;
2853
+ if(smooth === true) state.dygraph_options.plotter = smoothPlotter;
2854
2855
state.dygraph_instance = new Dygraph(state.element_chart,
2856
data.result.data, state.dygraph_options);
@@ -2745,16 +2885,17 @@
2885
cache: true,
2886
dataType: "script"
2887
})
2748
- .done(function() {
2749
- NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
2750
- })
2751
- .fail(function() {
2752
- NETDATA.error(100, NETDATA.morris_js);
2753
- })
2754
- .always(function() {
2755
- if(typeof callback === "function")
2756
- callback();
2757
- })
2888
+ .done(function() {
2889
+ NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
2890
+ })
2891
+ .fail(function() {
2892
+ NETDATA.chartLibraries.morris.enabled = false;
2893
+ NETDATA.error(100, NETDATA.morris_js);
2894
+ })
2895
+ .always(function() {
2896
+ if(typeof callback === "function")
2897
+ callback();
2898
+ });
2899
}
2900
}
2901
else {
@@ -2800,22 +2941,23 @@
2941
// raphael
2942
2943
NETDATA.raphaelInitialize = function(callback) {
2803
- if(typeof netdataStopRaphael === 'undefined') {
2944
+ if(typeof netdataStopRaphael === 'undefined' || !netdataStopRaphael) {
2945
$.ajax({
2946
url: NETDATA.raphael_js,
2947
cache: true,
2948
dataType: "script"
2949
})
2809
- .done(function() {
2810
- NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js);
2811
- })
2812
- .fail(function() {
2813
- NETDATA.error(100, NETDATA.raphael_js);
2814
- })
2815
- .always(function() {
2816
- if(typeof callback === "function")
2817
- callback();
2818
- })
2950
+ .done(function() {
2951
+ NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js);
2952
+ })
2953
+ .fail(function() {
2954
+ NETDATA.chartLibraries.raphael.enabled = false;
2955
+ NETDATA.error(100, NETDATA.raphael_js);
2956
+ })
2957
+ .always(function() {
2958
+ if(typeof callback === "function")
2959
+ callback();
2960
+ });
2961
}
2962
else {
2963
NETDATA.chartLibraries.raphael.enabled = false;
@@ -2848,19 +2990,19 @@
2990
cache: true,
2991
dataType: "script"
2992
})
2851
- .done(function() {
2852
- NETDATA.registerChartLibrary('google', NETDATA.google_js);
2853
-
2854
- google.load('visualization', '1.1', {
2855
- 'packages': ['corechart', 'controls'],
2856
- 'callback': callback
2857
- });
2858
- })
2859
- .fail(function() {
2860
- NETDATA.error(100, NETDATA.google_js);
2861
- if(typeof callback === "function")
2862
- callback();
2863
- })
2993
+ .done(function() {
2994
+ NETDATA.registerChartLibrary('google', NETDATA.google_js);
2995
+ google.load('visualization', '1.1', {
2996
+ 'packages': ['corechart', 'controls'],
2997
+ 'callback': callback
2998
+ });
2999
+ })
3000
+ .fail(function() {
3001
+ NETDATA.chartLibraries.google.enabled = false;
3002
+ NETDATA.error(100, NETDATA.google_js);
3003
+ if(typeof callback === "function")
3004
+ callback();
3005
+ });
3006
}
3007
else {
3008
NETDATA.chartLibraries.google.enabled = false;
@@ -2966,7 +3108,7 @@
3108
// easy-pie-chart
3109
3110
NETDATA.easypiechartInitialize = function(callback) {
2969
- if(typeof netdataStopEasypiechart === 'undefined') {
3111
+ if(typeof netdataNoEasyPieChart === 'undefined' || !netdataNoEasyPieChart) {
3112
$.ajax({
3113
url: NETDATA.easypiechart_js,
3114
cache: true,
@@ -3041,6 +3183,7 @@
3183
},
3184
autoresize: function(state) { return true; },
3185
max_updates_to_recreate: function(state) { return 5000; },
3186
+ track_colors: function(state) { return true; },
3187
pixels_per_point: function(state) {
3188
if(!this.isSparkline(state))
3189
return 3;
@@ -3072,6 +3215,7 @@
3215
legend: function(state) { return null; },
3216
autoresize: function(state) { return false; },
3217
max_updates_to_recreate: function(state) { return 5000; },
3218
+ track_colors: function(state) { return false; },
3219
pixels_per_point: function(state) { return 3; }
3220
},
3221
"peity": {
@@ -3087,6 +3231,7 @@
3231
legend: function(state) { return null; },
3232
autoresize: function(state) { return false; },
3233
max_updates_to_recreate: function(state) { return 5000; },
3234
+ track_colors: function(state) { return false; },
3235
pixels_per_point: function(state) { return 3; }
3236
},
3237
"morris": {
@@ -3102,6 +3247,7 @@
3247
legend: function(state) { return null; },
3248
autoresize: function(state) { return false; },
3249
max_updates_to_recreate: function(state) { return 50; },
3250
+ track_colors: function(state) { return false; },
3251
pixels_per_point: function(state) { return 15; }
3252
},
3253
"google": {
@@ -3117,6 +3263,7 @@
3263
legend: function(state) { return null; },
3264
autoresize: function(state) { return false; },
3265
max_updates_to_recreate: function(state) { return 300; },
3266
+ track_colors: function(state) { return false; },
3267
pixels_per_point: function(state) { return 4; }
3268
},
3269
"raphael": {
@@ -3132,6 +3279,7 @@
3279
legend: function(state) { return null; },
3280
autoresize: function(state) { return false; },
3281
max_updates_to_recreate: function(state) { return 5000; },
3282
+ track_colors: function(state) { return false; },
3283
pixels_per_point: function(state) { return 3; }
3284
},
3285
"easypiechart": {
@@ -3147,6 +3295,7 @@
3295
legend: function(state) { return null; },
3296
autoresize: function(state) { return false; },
3297
max_updates_to_recreate: function(state) { return 5000; },
3298
+ track_colors: function(state) { return false; },
3299
pixels_per_point: function(state) { return 3; }
3300
}
3301
};
@@ -3169,8 +3318,12 @@
3318
isAlreadyLoaded: function() {
3319
if(typeof $().emulateTransitionEnd == 'function')
3320
return true;
3172
- else
3173
- return false;
3321
+ else {
3322
+ if(typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap)
3323
+ return true;
3324
+ else
3325
+ return false;
3326
+ }
3327
}
3328
},
3329
{
@@ -3180,9 +3333,19 @@
3333
];
3334
3335
NETDATA.requiredCSS = [
3183
- NETDATA.serverDefault + 'css/bootstrap.min.css',
3184
- //NETDATA.serverDefault + 'css/bootstrap-theme.min.css',
3185
- NETDATA.dashboard_css
3336
+ {
3337
+ url: NETDATA.serverDefault + 'css/bootstrap.min.css',
3338
+ isAlreadyLoaded: function() {
3339
+ if(typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap)
3340
+ return true;
3341
+ else
3342
+ return false;
3343
+ }
3344
+ },
3345
+ {
3346
+ url: NETDATA.dashboard_css,
3347
+ isAlreadyLoaded: function() { return false; }
3348
+ }
3349
];
3350
3351
NETDATA.loadRequiredJs = function(index, callback) {
@@ -3216,25 +3379,28 @@
3379
if(index >= NETDATA.requiredCSS.length)
3380
return;
3381
3219
- if(NETDATA.options.debug.main_loop) console.log('loading ' + NETDATA.requiredCSS[index]);
3220
- NETDATA._loadCSS(NETDATA.requiredCSS[index]);
3382
+ if(NETDATA.requiredCSS[index].isAlreadyLoaded()) {
3383
+ NETDATA.loadRequiredCSS(++index);
3384
+ return;
3385
+ }
3386
+
3387
+ if(NETDATA.options.debug.main_loop) console.log('loading ' + NETDATA.requiredCSS[index].url);
3388
+ NETDATA._loadCSS(NETDATA.requiredCSS[index].url);
3389
NETDATA.loadRequiredCSS(++index);
3390
}
3391
3392
NETDATA.errorReset();
3393
NETDATA.loadRequiredCSS(0);
3394
+
3395
NETDATA._loadjQuery(function() {
3396
NETDATA.loadRequiredJs(0, function() {
3228
- //NETDATA.chartRegistry.downloadAll(NETDATA.serverDefault, function() {
3229
- // NETDATA._loadCSS(NETDATA.dashboard_css);
3230
- if(typeof netdataDontStart === 'undefined' || !netdataDontStart) {
3231
- if(NETDATA.options.debug.main_loop) console.log('starting chart refresh thread');
3232
- NETDATA.start();
3233
- }
3397
+ if(typeof netdataDontStart === 'undefined' || !netdataDontStart) {
3398
+ if(NETDATA.options.debug.main_loop) console.log('starting chart refresh thread');
3399
+ NETDATA.start();
3400
+ }
3401
3235
- if(typeof NETDATA.options.readyCallback === 'function')
3236
- NETDATA.options.readyCallback();
3237
- //});
3402
+ if(typeof NETDATA.options.readyCallback === 'function')
3403
+ NETDATA.options.readyCallback();
3404
});
3405
});
3406
web/dashboard_full.html
+1
-1
@@ -274,7 +274,7 @@ var options = {
274
};
275
276
var messages = {
277
- 'system.cpu': 'The current CPU utilization of the system is below.<br/>Keep an eye on iowait <div data-netdata="system.cpu" data-after="-60" data-width="15%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="iowait" data-colors="' + NETDATA.colors[8] + '" data-show-value-of-iowait-at="system.cpu.iowait.1"></div> (<span id="system.cpu.iowait.1" style="display: inline-block; min-width: 40px; text-align: right;">X</span>%). If it is constantly high, your disks are a bottleneck and they slow your system down.'
277
+ 'system.cpu': 'The current CPU utilization of the system is below.<br/>Keep an eye on iowait <div data-netdata="system.cpu" data-after="-60" data-width="15%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="iowait" data-show-value-of-iowait-at="system.cpu.iowait.1"></div> (<span id="system.cpu.iowait.1" style="display: inline-block; min-width: 40px; text-align: right;">X</span>%). If it is constantly high, your disks are a bottleneck and they slow your system down.'
278
};
279
280
function screenWidth() {