legend now is rendered independently of the charting library; code cleanups
Costa Tsaousis (ktsaou) committed
Dec 10, 2015 at 23:03 UTC
fd309379c88a88514124a213d0ad18d5e8c99eac
3 files changed
+215
-137
web/dashboard.css
+31
-5
@@ -67,7 +67,6 @@ html {
67
}
68
.netdata-legend-series {
69
position: absolute;
70
- display: block;
70
width: 100%;
71
height: calc(100% - 50px);
72
/*background-color: Gray;*/
@@ -80,15 +79,42 @@ html {
79
font-size: 10px;
80
margin-top: 0px;
81
}
82
+.netdata-legend-name-table-line {
83
+ display: inline-block;
84
+ width: 13px;
85
+ height: 3px;
86
+ border-width: 0px;
87
+ border-bottom-width: 2px;
88
+ border-bottom-style: solid;
89
+ border-bottom-color: white;
90
+}
91
+.netdata-legend-name-table-area {
92
+ display: inline-block;
93
+ width: 13px;
94
+ height: 5px;
95
+ border-width: 1px;
96
+ border-top-width: 1px;
97
+ border-top-style: solid;
98
+ border-top-color: inherit;
99
+}
100
+.netdata-legend-name-table-stacked {
101
+ display: inline-block;
102
+ width: 13px;
103
+ height: 5px;
104
+ border-width: 1px;
105
+ border-top-width: 1px;
106
+ border-top-style: solid;
107
+ border-top-color: inherit;
108
+}
109
+.netdata-legend-name-tr {
110
+}
111
+.netdata-legend-name-td {
112
+}
113
.netdata-legend-name {
84
- position: absolute;
85
- left: 0px;
86
- float: left;
114
text-align: left;
115
font-size: 10px;
116
font-weight: bold;
117
vertical-align: bottom;
91
- background-color: White;
118
margin-top: 0px;
119
z-index: 9;
120
padding: 0px;
web/dashboard.html
+45
-3
@@ -172,7 +172,7 @@ Sparklines using dygraphs
172
data-dygraph-theme="sparkline"
173
data-legend="no"
174
data-width="15%"
175
- data-height="30"
175
+ data-height="20"
176
data-after="-300"
177
></div>
178
are also possible! This
@@ -181,7 +181,7 @@ Sparklines using dygraphs
181
data-dygraph-theme="sparkline"
182
data-legend="no"
183
data-width="15%"
184
- data-height="30"
184
+ data-height="20"
185
data-after="-300"
186
></div>
187
is an area chart, while this
@@ -190,9 +190,51 @@ Sparklines using dygraphs
190
data-dygraph-theme="sparkline"
191
data-legend="no"
192
data-width="15%"
193
- data-height="30"
193
+ data-height="20"
194
data-after="-300"
195
></div> is a stacked area chart!
196
+
197
+
198
+<br/>
199
+<div style="width: 32%; display: inline-block;">
200
+ <div data-netdata="system.processes"
201
+ data-chart-library="dygraph"
202
+ data-dygraph-theme="sparkline"
203
+ data-width="100%"
204
+ data-height="30"
205
+ data-after="-300"
206
+ data-dt-element-name="time501"
207
+ ></div>
208
+ <br/>
209
+ <small>rendered in <span id="time501">X</span> ms</small>
210
+</div>
211
+<div style="width: 32%; display: inline-block;">
212
+ <div data-netdata="system.ipv4"
213
+ data-chart-library="dygraph"
214
+ data-dygraph-theme="sparkline"
215
+ data-width="100%"
216
+ data-height="30"
217
+ data-after="-300"
218
+ data-dt-element-name="time502"
219
+ ></div>
220
+ <br/>
221
+ <small>rendered in <span id="time502">X</span> ms</small>
222
+</div>
223
+<div style="width: 32%; display: inline-block;">
224
+ <div data-netdata="system.cpu"
225
+ data-chart-library="dygraph"
226
+ data-dygraph-theme="sparkline"
227
+ data-width="100%"
228
+ data-height="30"
229
+ data-after="-300"
230
+ data-dt-element-name="time503"
231
+ ></div>
232
+ <br/>
233
+ <small>rendered in <span id="time503">X</span> ms</small>
234
+</div>
235
+
236
+
237
+
238
<br/>
239
<div style="width: 32%; display: inline-block;">
240
<div data-netdata="system.processes"
web/dashboard.js
+139
-129
@@ -17,6 +17,7 @@
17
// fix IE bug with console
18
if(!window.console){ window.console = {log: function(){} }; }
19
20
+ // global namespace
21
var NETDATA = window.NETDATA || {};
22
23
// ----------------------------------------------------------------------------------------------------------------
@@ -170,7 +171,13 @@
171
172
sync_pan_and_zoom: true, // enable or disable pan and zoom sync
173
173
- update_only_visible: true // enable or disable visibility management
174
+ update_only_visible: true, // enable or disable visibility management
175
+
176
+ color_fill_opacity: {
177
+ line: 1.0,
178
+ area: 0.2,
179
+ stacked: 0.8
180
+ }
181
},
182
183
debug: {
@@ -706,49 +713,52 @@
713
el.className += "netdata-legend-series";
714
this.element_legend.appendChild(el);
715
716
+ var genLabel = function(state, parent, name, count) {
717
+ var c = count % NETDATA.colors.length;
718
+
719
+ state.element_legend_childs.series[name] = {
720
+ name: document.createElement('span'),
721
+ value: document.createElement('span')
722
+ };
723
+
724
+ var label = state.element_legend_childs.series[name];
725
+
726
+ label.name.className += 'netdata-legend-name';
727
+ label.value.className += 'netdata-legend-value';
728
+ label.value.title = name;
729
+
730
+ var table = document.createElement('table');
731
+ table.innerHTML = '<tr class="netdata-legend-name-tr"><td class="netdata-legend-name-td"></td></tr>';
732
+ table.className += 'netdata-legend-name-table-' + state.chart.chart_type;
733
+
734
+ var rgb = NETDATA.colorHex2Rgb(NETDATA.colors[c]);
735
+ table.style.backgroundColor = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + NETDATA.options.current.color_fill_opacity[state.chart.chart_type] + ')';
736
+
737
+ var text = document.createTextNode(' ' + name);
738
+
739
+ label.name.appendChild(table);
740
+ label.name.appendChild(text);
741
+
742
+ label.name.style.color = NETDATA.colors[c];
743
+ label.value.style.color = NETDATA.colors[c];
744
+
745
+ if(count > 0)
746
+ parent.appendChild(document.createElement('br'));
747
+
748
+ parent.appendChild(label.name);
749
+ parent.appendChild(label.value);
750
+ };
751
+
752
if(this.current.data) {
753
var me = this;
754
$.each(me.current.data.dimension_names, function(i, d) {
712
- me.element_legend_childs.series[d] = {
713
- name: document.createElement('span'),
714
- value: document.createElement('span')
715
- };
716
- me.element_legend_childs.series[d].name.className += 'netdata-legend-name';
717
- me.element_legend_childs.series[d].value.className += 'netdata-legend-value';
718
- me.element_legend_childs.series[d].value.title = d;
719
-
720
- var c = i % NETDATA.colors.length;
721
- me.element_legend_childs.series[d].name.style.color = NETDATA.colors[c];
722
- me.element_legend_childs.series[d].value.style.color = NETDATA.colors[c];
723
-
724
- if(i > 0)
725
- el.appendChild(document.createElement('br'));
726
-
727
- el.appendChild(me.element_legend_childs.series[d].name);
728
- el.appendChild(me.element_legend_childs.series[d].value);
755
+ genLabel(me, el, d, i);
756
});
757
}
758
else {
759
var me = this;
760
$.each(me.chart.dimensions, function(i, d) {
734
- me.element_legend_childs.series[d.name] = {
735
- name: document.createElement('span'),
736
- value: document.createElement('span')
737
- };
738
- me.element_legend_childs.series[d.name].name.className += 'netdata-legend-name';
739
- me.element_legend_childs.series[d.name].value.className += 'netdata-legend-value';
740
- me.element_legend_childs.series[d.name].value.title = d;
741
-
742
- var c = i;
743
- while(c >= NETDATA.colors.length) c -= NETDATA.colors.length;
744
- me.element_legend_childs.series[d.name].name.style.color = NETDATA.colors[c];
745
- me.element_legend_childs.series[d.name].value.style.color = NETDATA.colors[c];
746
-
747
- if(i > 0)
748
- el.appendChild(document.createElement('br'));
749
-
750
- el.appendChild(me.element_legend_childs.series[d.name].name);
751
- el.appendChild(me.element_legend_childs.series[d.name].value);
761
+ genLabel(me, el, d.name, i);
762
});
763
}
764
@@ -801,7 +811,7 @@
811
hasLegend: function() {
812
if(this.element_legend) return true;
813
804
- if(this.library && this.library.legend == 'right-side') {
814
+ if(this.library && this.library.legend(this) == 'right-side') {
815
var legend = $(this.element).data('legend') || 'yes';
816
if(legend == 'no') return false;
817
return true;
@@ -830,8 +840,8 @@
840
// force an options provided detail
841
var px = this.pixels_per_point;
842
833
- if(this.library && px < this.library.pixels_per_point)
834
- px = this.library.pixels_per_point;
843
+ if(this.library && px < this.library.pixels_per_point(this))
844
+ px = this.library.pixels_per_point(this);
845
846
if(px < NETDATA.options.current.pixels_per_point)
847
px = NETDATA.options.current.pixels_per_point;
@@ -840,7 +850,7 @@
850
},
851
852
needsResize: function() {
843
- return (this.library && !this.library.autoresize && this.last_resized < NETDATA.options.last_resized);
853
+ return (this.library && !this.library.autoresize() && this.last_resized < NETDATA.options.last_resized);
854
},
855
856
resizeChart: function() {
@@ -872,11 +882,11 @@
882
883
// build the data URL
884
this.current.url = this.chart.data_url;
875
- this.current.url += "&format=" + this.library.format;
885
+ this.current.url += "&format=" + this.library.format();
886
this.current.url += "&points=" + this.current.points.toString();
887
this.current.url += "&group=" + this.method;
878
- this.current.url += "&options=" + this.library.options;
879
- if(this.library.jsonWrapper) this.current.url += '|jsonwrap';
888
+ this.current.url += "&options=" + this.library.options();
889
+ this.current.url += '|jsonwrap';
890
891
if(after)
892
this.current.url += "&after=" + after.toString();
@@ -897,7 +907,7 @@
907
var started = new Date().getTime();
908
909
// if the result is JSON, find the latest update-every
900
- if(typeof data == 'object' && this.library.jsonWrapper) {
910
+ if(typeof data == 'object') {
911
if(typeof data.view_update_every != 'undefined')
912
this.current.view_update_every = data.view_update_every * 1000;
913
@@ -937,7 +947,7 @@
947
// this may force the chart to be re-created
948
this.resizeChart();
949
940
- if(this.updates_since_last_creation >= this.library.max_updates_to_recreate) {
950
+ if(this.updates_since_last_creation >= this.library.max_updates_to_recreate()) {
951
if(this.debug) this.log('max updates of ' + this.updates_since_last_creation.toString() + ' reached. Forcing re-generation.');
952
this.created_ms = 0;
953
}
@@ -1284,7 +1294,22 @@
1294
document.getElementsByTagName("head")[0].appendChild(fileref);
1295
}
1296
1287
- NETDATA.ColorLuminance = function(hex, lum) {
1297
+ NETDATA.colorHex2Rgb = function(hex) {
1298
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
1299
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
1300
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
1301
+ return r + r + g + g + b + b;
1302
+ });
1303
+
1304
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
1305
+ return result ? {
1306
+ r: parseInt(result[1], 16),
1307
+ g: parseInt(result[2], 16),
1308
+ b: parseInt(result[3], 16)
1309
+ } : null;
1310
+ }
1311
+
1312
+ NETDATA.colorLuminance = function(hex, lum) {
1313
// validate hex string
1314
hex = String(hex).replace(/[^0-9a-f]/gi, '');
1315
if (hex.length < 6)
@@ -1495,7 +1520,7 @@
1520
var self = $(state.element);
1521
var type = self.data('sparkline-type') || 'line';
1522
var lineColor = self.data('sparkline-linecolor') || NETDATA.colors[0];
1498
- var fillColor = self.data('sparkline-fillcolor') || (state.chart.chart_type == 'line')?'#FFF':NETDATA.ColorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1523
+ var fillColor = self.data('sparkline-fillcolor') || (state.chart.chart_type == 'line')?'#FFF':NETDATA.colorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1524
var chartRangeMin = self.data('sparkline-chartrangemin') || undefined;
1525
var chartRangeMax = self.data('sparkline-chartrangemax') || undefined;
1526
var composite = self.data('sparkline-composite') || undefined;
@@ -1905,7 +1930,7 @@
1930
1931
for (var i = 0; i < data.series.length; i++) {
1932
var series = data.series[i];
1908
- elements.series[series.label].name.innerHTML = series.dashHTML + ' ' + series.labelHTML;
1933
+ //elements.series[series.label].name.innerHTML = series.dashHTML + ' ' + series.labelHTML;
1934
elements.series[series.label].value.innerHTML = '';
1935
}
1936
}
@@ -1922,31 +1947,7 @@
1947
}
1948
}
1949
1925
- return 'nothing interesting here';
1926
-/*
1927
- if (typeof(data.x) === 'undefined') {
1928
- html = '<span class="netdata-legend-title-date"> </span><br/><span class="netdata-legend-title-time">' + state.chart.name + '</span><br/><span class="netdata-legend-title-units"> </span>';
1929
- for (var i = 0; i < data.series.length; i++) {
1930
- var series = data.series[i];
1931
- if (!series.isVisible) continue;
1932
-
1933
- html += '<br/>';
1934
- html += "<span class='netdata-legend-series' style='color: " + series.color + ";'>" + series.dashHTML + " " + series.labelHTML + "</span>"
1935
- html += "<span class='netdata-legend-value'> </span>";
1936
- }
1937
- return html;
1938
- }
1939
-
1940
- html = data.xHTML + '<br/><span class="netdata-legend-title-units">' + state.chart.units + '</span>';
1941
- for (var i = 0; i < data.series.length; i++) {
1942
- var series = data.series[i];
1943
- if (!series.isVisible) continue;
1944
- html += '<br/>';
1945
- html += "<span class='netdata-legend-series' style='color: " + series.color + ";'>" + series.dashHTML + " " + series.labelHTML + "</span>"
1946
- html += "<span class='netdata-legend-value' style='color: " + series.color + ";'>" + series.yHTML + "</span>";
1947
- }
1948
- return html;
1949
-*/
1950
+ return 'hidden original dygraph legend';
1951
},
1952
drawCallback: function(dygraph, is_initial) {
1953
if(state.current.name != 'auto') {
@@ -2100,14 +2101,7 @@
2101
}
2102
};
2103
2103
- // smooth lines patch
2104
- if(NETDATA.dygraph.smooth && state.chart.chart_type == 'line') {
2105
- state.dygraph_options.plotter = smoothPlotter;
2106
- state.dygraph_options.strokeWidth = 1.5;
2107
- }
2108
-
2109
- var theme = self.data('dygraph-theme') || null;
2110
- if(theme == 'sparkline') {
2104
+ if(NETDATA.chartLibraries.dygraph.isSparkline(state)) {
2105
state.dygraph_options.drawGrid = false;
2106
state.dygraph_options.drawAxis = false;
2107
state.dygraph_options.title = undefined;
@@ -2120,9 +2114,16 @@
2114
state.dygraph_options.labelsSeparateLines = true;
2115
state.dygraph_options.highlightCircleSize = 3;
2116
state.dygraph_options.rightGap = 0;
2117
+ state.dygraph_options.strokeWidth = 1.0;
2118
+ }
2119
+ else if(NETDATA.dygraph.smooth && state.chart.chart_type == 'line') {
2120
+ // smooth lines patch
2121
+ state.dygraph_options.plotter = smoothPlotter;
2122
+ state.dygraph_options.strokeWidth = 1.5;
2123
}
2124
2125
2126
+
2127
state.dygraph_instance = new Dygraph(state.element_chart,
2128
data.result.data, state.dygraph_options);
2129
};
@@ -2383,14 +2384,33 @@
2384
clearSelection: NETDATA.dygraphClearSelection,
2385
initialized: false,
2386
enabled: true,
2386
- format: 'json',
2387
- options: 'ms|flip',
2388
- jsonWrapper: true,
2389
- legend: 'right-side',
2390
- autoresize: true,
2391
- max_updates_to_recreate: 5000,
2392
- pixels_per_point: 3,
2393
- detects_dimensions_on_update: false
2387
+ format: function(state) { return 'json'; },
2388
+ options: function(state) { return 'ms|flip'; },
2389
+ legend: function(state) {
2390
+ if(!this.isSparkline(state))
2391
+ return 'right-side';
2392
+ else
2393
+ return null;
2394
+ },
2395
+ autoresize: function(state) { return true; },
2396
+ max_updates_to_recreate: function(state) { return 5000; },
2397
+ pixels_per_point: function(state) {
2398
+ if(!this.isSparkline(state))
2399
+ return 3;
2400
+ else
2401
+ return 2;
2402
+ },
2403
+
2404
+ isSparkline: function(state) {
2405
+ if(typeof state.dygraph_sparkline == 'undefined') {
2406
+ var t = $(state.element).data('dygraph-theme');
2407
+ if(t == 'sparkline')
2408
+ state.dygraph_sparkline = true;
2409
+ else
2410
+ state.dygraph_sparkline = false;
2411
+ }
2412
+ return state.dygraph_sparkline;
2413
+ }
2414
},
2415
"sparkline": {
2416
initialize: NETDATA.sparklineInitialize,
@@ -2400,14 +2420,12 @@
2420
clearSelection: null,
2421
initialized: false,
2422
enabled: true,
2403
- format: 'array',
2404
- options: 'flip|abs',
2405
- jsonWrapper: true,
2406
- legend: 'none',
2407
- autoresize: false,
2408
- max_updates_to_recreate: 5000,
2409
- pixels_per_point: 3,
2410
- detects_dimensions_on_update: false
2423
+ format: function(state) { return 'array'; },
2424
+ options: function(state) { return 'flip|abs'; },
2425
+ legend: function(state) { return null; },
2426
+ autoresize: function(state) { return false; },
2427
+ max_updates_to_recreate: function(state) { return 5000; },
2428
+ pixels_per_point: function(state) { return 3; }
2429
},
2430
"peity": {
2431
initialize: NETDATA.peityInitialize,
@@ -2417,14 +2435,12 @@
2435
clearSelection: null,
2436
initialized: false,
2437
enabled: true,
2420
- format: 'ssvcomma',
2421
- options: 'null2zero|flip|abs',
2422
- jsonWrapper: true,
2423
- legend: 'none',
2424
- autoresize: false,
2425
- max_updates_to_recreate: 5000,
2426
- pixels_per_point: 3,
2427
- detects_dimensions_on_update: false
2438
+ format: function(state) { return 'ssvcomma'; },
2439
+ options: function(state) { return 'null2zero|flip|abs'; },
2440
+ legend: function(state) { return null; },
2441
+ autoresize: function(state) { return false; },
2442
+ max_updates_to_recreate: function(state) { return 5000; },
2443
+ pixels_per_point: function(state) { return 3; }
2444
},
2445
"morris": {
2446
initialize: NETDATA.morrisInitialize,
@@ -2434,14 +2450,12 @@
2450
clearSelection: null,
2451
initialized: false,
2452
enabled: true,
2437
- format: 'json',
2438
- options: 'objectrows|ms',
2439
- jsonWrapper: true,
2440
- legend: 'none',
2441
- autoresize: false,
2442
- max_updates_to_recreate: 50,
2443
- pixels_per_point: 15,
2444
- detects_dimensions_on_update: false
2453
+ format: function(state) { return 'json'; },
2454
+ options: function(state) { return 'objectrows|ms'; },
2455
+ legend: function(state) { return null; },
2456
+ autoresize: function(state) { return false; },
2457
+ max_updates_to_recreate: function(state) { return 50; },
2458
+ pixels_per_point: function(state) { return 15; }
2459
},
2460
"google": {
2461
initialize: NETDATA.googleInitialize,
@@ -2451,14 +2465,12 @@
2465
clearSelection: null,
2466
initialized: false,
2467
enabled: true,
2454
- format: 'datatable',
2455
- options: '',
2456
- jsonWrapper: true,
2457
- legend: 'none',
2458
- autoresize: false,
2459
- max_updates_to_recreate: 300,
2460
- pixels_per_point: 4,
2461
- detects_dimensions_on_update: true
2468
+ format: function(state) { return 'datatable'; },
2469
+ options: function(state) { return ''; },
2470
+ legend: function(state) { return null; },
2471
+ autoresize: function(state) { return false; },
2472
+ max_updates_to_recreate: function(state) { return 300; },
2473
+ pixels_per_point: function(state) { return 4; }
2474
},
2475
"raphael": {
2476
initialize: NETDATA.raphaelInitialize,
@@ -2468,14 +2480,12 @@
2480
clearSelection: null,
2481
initialized: false,
2482
enabled: true,
2471
- format: 'json',
2472
- options: '',
2473
- jsonWrapper: true,
2474
- legend: 'none',
2475
- autoresize: false,
2476
- max_updates_to_recreate: 1000,
2477
- pixels_per_point: 1,
2478
- detects_dimensions_on_update: false
2483
+ format: function(state) { return 'json'; },
2484
+ options: function(state) { return ''; },
2485
+ legend: function(state) { return null; },
2486
+ autoresize: function(state) { return false; },
2487
+ max_updates_to_recreate: function(state) { return 5000; },
2488
+ pixels_per_point: function(state) { return 3; }
2489
}
2490
};
2491