@cryptotaxi247 / netdata-1 / commits / fd309379c

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">&nbsp;</span><br/><span class="netdata-legend-title-time">' + state.chart.name + '</span><br/><span class="netdata-legend-title-units">&nbsp;</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'>&nbsp;</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