@cryptotaxi247 / netdata-1 / commits / 236150e1c

new resizable dashboard; all charts can now have relative width; more code cleanups

Costa Tsaousis (ktsaou) committed Dec 2, 2015 at 02:14 UTC 236150e1c9beaf153cbd06a50d354453c632469f
2 files changed +471 -409
web/dashboard.html
+259 -242
@@ -1,6 +1,16 @@
1 -<html>
1 +<!DOCTYPE html>
2 +<html lang="en">
3 <head>
4 <title>NetData Dashboard</title>
5 +
6 + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7 + <meta charset="utf-8">
8 + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9 + <meta name="viewport" content="width=device-width, initial-scale=1">
10 + <meta name="apple-mobile-web-app-capable" content="yes">
11 + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
12 + <meta name="author" content="costa@tsaousis.gr">
13 +
14 <style type="text/css">
15 html{font-family:sans-serif;}
16 </style>
@@ -12,7 +22,16 @@
22 This is a template for building custom dashboards. To build a dashboard you just do this:
23
24 <pre>
15 -&lt;html>
25 +&lt;!DOCTYPE html>
26 +&lt;html lang="en">
27 +&lt;head>
28 + &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">
29 + &lt;meta charset="utf-8">
30 + &lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
31 + &lt;meta name="viewport" content="width=device-width, initial-scale=1">
32 + &lt;meta name="apple-mobile-web-app-capable" content="yes">
33 + &lt;meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
34 +&lt;/head>
35 &lt;body>
36 &lt;div data-netdata="system.processes"
37 data-chart-library="dygraph"
@@ -35,246 +54,244 @@ This is a template for building custom dashboards. To build a dashboard you just
54 <li>Depending on the width of the chart and <b>data-after</b> attribute, netdata will automatically refresh the chart when it needs to be updated. For example giving 600 pixels for width for -600 seconds of data, using a chart library that needs 3 pixels per point, will yeld in a chart updated once every 3 seconds.</li>
55 </ul>
56
38 - <table border="0" cellpadding="5" cellspacing="5">
39 - <tr>
40 - <th width="600">
41 - System Processes - Line Chart
42 - </th>
43 - <th width="600">
44 - System ipv4 - Area Chart
45 - </th>
46 - <th width="600">
47 - System CPU - Stacked Area Chart
48 - </th>
49 - </tr>
50 - <tr><td colspan="3">&nbsp;</td></tr>
51 - <tr><th colspan="3"><hr>Peity Charts</th></tr>
52 - <tr><td colspan="3">
53 - Peity charts do not support 'NULL' values, so the charts cannot indicate that values are missing.
54 - Peity charts cannot have multiple dimensions on the charts - so netdata will use 'min2max' to show
55 - the total of all dimensions.
56 - </td></tr>
57 - <tr>
58 - <td width="600">
59 - <div data-netdata="system.processes"
60 - data-chart-library="peity"
61 - data-width="600"
62 - data-height="30"
63 - data-after="-600"
64 - data-dt-element-name="time11"
65 - </div>
66 - </td>
67 - <td width="600">
68 - <div data-netdata="system.ipv4"
69 - data-chart-library="peity"
70 - data-width="600"
71 - data-height="30"
72 - data-after="-600"
73 - data-dt-element-name="time12"
74 - </div>
75 - </td>
76 - <td width="600">
77 - <div data-netdata="system.cpu"
78 - data-chart-library="peity"
79 - data-width="600"
80 - data-height="30"
81 - data-after="-600"
82 - data-dt-element-name="time13"
83 - </div>
84 - </td>
85 - </tr>
86 - <tr>
87 - <td>rendered in <span id="time11">X</span> ms</td>
88 - <td>rendered in <span id="time12">X</span> ms</td>
89 - <td>rendered in <span id="time13">X</span> ms</td>
90 - </tr>
91 - <tr><td colspan="3">&nbsp;</td></tr>
92 - <tr><th colspan="3"><hr>Sparkline Charts</th></tr>
93 - <tr><td colspan="3">
94 - Sparkline charts support 'NULL' values, so the charts can indicate that values are missing.
95 - Sparkline charts stretch the values to show the variations between values in more detail.
96 - They also have mouse-hover support.
97 - <br/>
98 - Sparklines are fantastic. You can inline charts in text. For example this
99 - <div data-netdata="system.cpu"
100 - data-chart-library="sparkline"
101 - data-width="60"
102 - data-height="20"
103 - data-after="-30"
104 - ></div> is my current cpu usage,
105 - <br/>
106 - while this
107 - <div data-netdata="netdata.net"
108 - data-dimensions="out"
109 - data-chart-library="sparkline"
110 - data-width="60"
111 - data-height="20"
112 - data-after="-30"
113 - ></div> is the bandwidth my netdata server is currently transmitting and this
114 -
115 - <div data-netdata="netdata.requests"
116 - data-chart-library="sparkline"
117 - data-width="360"
118 - data-height="20"
119 - data-after="-180"
120 - ></div> is the requests/sec it serves.
121 - </td></tr>
122 - <tr>
123 - <td width="600">
124 - <div data-netdata="system.processes"
125 - data-chart-library="sparkline"
126 - data-width="600"
127 - data-height="30"
128 - data-after="-600"
129 - data-dt-element-name="time21"
130 - ></div>
131 - </td>
132 - <td width="600">
133 - <div data-netdata="system.ipv4"
134 - data-chart-library="sparkline"
135 - data-width="600"
136 - data-height="30"
137 - data-after="-600"
138 - data-dt-element-name="time22"
139 - ></div>
140 - </td>
141 - <td width="600">
142 - <div data-netdata="system.cpu"
143 - data-chart-library="sparkline"
144 - data-width="600"
145 - data-height="30"
146 - data-after="-600"
147 - data-dt-element-name="time23"
148 - ></div>
149 - </td>
150 - </tr>
151 - <tr>
152 - <td>rendered in <span id="time21">X</span> ms</td>
153 - <td>rendered in <span id="time22">X</span> ms</td>
154 - <td>rendered in <span id="time23">X</span> ms</td>
155 - </tr>
156 - <tr><td colspan="3">&nbsp;</td></tr>
157 - <tr><th colspan="3"><hr>Dygraph Charts</th></tr>
158 - <tr><td colspan="3">
159 - The fastest charting engine that can chart complete charts (not just sparklines).
160 - The charts are zoomable (drag their contents to zoom-in, double click to zoom-out).
161 - For the moment zooming is just on the presentation layer (the data do not become more detailed when you zoom).
162 - </td></tr>
163 - <tr>
164 - <td width="600">
165 - <div data-netdata="system.processes"
166 - data-chart-library="dygraph"
167 - data-width="600"
168 - data-height="200"
169 - data-after="-600"
170 - data-dt-element-name="time31"
171 - ></div>
172 - </td>
173 - <td width="600">
174 - <div data-netdata="system.ipv4"
175 - data-chart-library="dygraph"
176 - data-width="600"
177 - data-height="200"
178 - data-after="-600"
179 - data-dt-element-name="time32"
180 - ></div>
181 - </td>
182 - <td width="600">
183 - <div data-netdata="system.cpu"
184 - data-chart-library="dygraph"
185 - data-width="600"
186 - data-height="200"
187 - data-after="-600"
188 - data-dt-element-name="time33"
189 - ></div>
190 - </td>
191 - </tr>
192 - <tr>
193 - <td>rendered in <span id="time31">X</span> ms</td>
194 - <td>rendered in <span id="time32">X</span> ms</td>
195 - <td>rendered in <span id="time33">X</span> ms</td>
196 - </tr>
197 - <tr><td colspan="3">&nbsp;</td></tr>
198 - <tr><th colspan="3"><hr>Google Charts</th></tr>
199 - <tr><td colspan="3">
200 - NetData was originaly developed with Google Charts.
201 - NetData is a complete Google Visualization API provider.
202 - </td></tr>
203 - <tr>
204 - <td width="600">
205 - <div data-netdata="system.processes"
206 - data-chart-library="google"
207 - data-width="600"
208 - data-height="200"
209 - data-after="-600"
210 - data-dt-element-name="time51"
211 - ></div>
212 - </td>
213 - <td width="600">
214 - <div data-netdata="system.ipv4"
215 - data-chart-library="google"
216 - data-width="600"
217 - data-height="200"
218 - data-after="-600"
219 - data-dt-element-name="time52"
220 - ></div>
221 - </td>
222 - <td width="600">
223 - <div data-netdata="system.cpu"
224 - data-chart-library="google"
225 - data-width="600"
226 - data-height="200"
227 - data-after="-600"
228 - data-dt-element-name="time53"
229 - ></div>
230 - </td>
231 - </tr>
232 - <tr>
233 - <td>rendered in <span id="time51">X</span> ms</td>
234 - <td>rendered in <span id="time52">X</span> ms</td>
235 - <td>rendered in <span id="time53">X</span> ms</td>
236 - </tr>
237 - <tr><td colspan="3">&nbsp;</td></tr>
238 - <tr><th colspan="3"><hr>Morris Charts</th></tr>
239 - <tr><td colspan="3">
240 - Unfortunatelly, Morris Charts are veeeeeeeeeeeeeeeery slow! We force them to lower their detail to get acceptable results.
241 - And they have issues with negative numbers in area charts...
242 - </td></tr>
243 - <tr>
244 - <td width="600">
245 - <div data-netdata="system.processes"
246 - data-chart-library="morris"
247 - data-width="600"
248 - data-height="200"
249 - data-after="-600"
250 - data-dt-element-name="time41"
251 - ></div>
252 - </td>
253 - <td width="600">
254 - <div data-netdata="system.ipv4"
255 - data-chart-library="morris"
256 - data-width="600"
257 - data-height="200"
258 - data-after="-600"
259 - data-dt-element-name="time42"
260 - ></div>
261 - </td>
262 - <td width="600">
263 - <div data-netdata="system.cpu"
264 - data-chart-library="morris"
265 - data-width="600"
266 - data-height="200"
267 - data-after="-600"
268 - data-dt-element-name="time43"
269 - ></div>
270 - </td>
271 - </tr>
272 - <tr>
273 - <td>rendered in <span id="time41">X</span> ms</td>
274 - <td>rendered in <span id="time42">X</span> ms</td>
275 - <td>rendered in <span id="time43">X</span> ms</td>
276 - </tr>
277 - </table>
57 +
58 +<hr>
59 +<h1>Sparkline Charts</h1>
60 +Sparkline charts support 'NULL' values, so the charts can indicate that values are missing.
61 +Sparkline charts stretch the values to show the variations between values in more detail.
62 +They also have mouse-hover support.
63 +<br/>
64 +<b>Sparklines are fantastic</b>. You can inline charts in text. For example this
65 + <div data-netdata="system.cpu"
66 + data-chart-library="sparkline"
67 + data-width="5%"
68 + data-height="20"
69 + data-after="-30"
70 + ></div> is my current cpu usage (last 30 seconds),
71 + while this
72 + <div data-netdata="netdata.net"
73 + data-dimensions="out"
74 + data-chart-library="sparkline"
75 + data-width="10%"
76 + data-height="20"
77 + data-after="-60"
78 + ></div> is the bandwidth my netdata server is currently transmitting (last minute)
79 + and this
80 + <div data-netdata="netdata.requests"
81 + data-chart-library="sparkline"
82 + data-width="20%"
83 + data-height="20"
84 + data-after="-180"
85 + ></div> is the requests/sec it serves (last 3 minutes).
86 +
87 +<br/>
88 +<div style="width: 32%; display: inline-block;">
89 + <div data-netdata="system.processes"
90 + data-chart-library="sparkline"
91 + data-width="100%"
92 + data-height="30"
93 + data-after="-600"
94 + data-dt-element-name="time101"
95 + ></div>
96 + <br/>
97 + <small>rendered in <span id="time101">X</span> ms</small>
98 +</div>
99 +<div style="width: 32%; display: inline-block;">
100 + <div data-netdata="system.ipv4"
101 + data-chart-library="sparkline"
102 + data-width="100%"
103 + data-height="30"
104 + data-after="-600"
105 + data-dt-element-name="time102"
106 + ></div>
107 + <br/>
108 + <small>rendered in <span id="time102">X</span> ms</small>
109 +</div>
110 +<div style="width: 32%; display: inline-block;">
111 + <div data-netdata="system.cpu"
112 + data-chart-library="sparkline"
113 + data-width="100%"
114 + data-height="30"
115 + data-after="-600"
116 + data-dt-element-name="time103"
117 + ></div>
118 + <br/>
119 + <small>rendered in <span id="time103">X</span> ms</small>
120 +</div>
121 +
122 +
123 +
124 +<hr>
125 +<h1>Peity Charts</h1>
126 +Peity charts do not support 'NULL' values, so the charts cannot indicate that values are missing.
127 +Peity charts cannot have multiple dimensions on the charts - so netdata will use 'min2max' to show
128 +the total of all dimensions.
129 +<br/>
130 +<div style="width: 32%; display: inline-block;">
131 + <div data-netdata="system.processes"
132 + data-chart-library="peity"
133 + data-width="100%"
134 + data-height="30"
135 + data-after="-600"
136 + data-dt-element-name="time001"
137 + ></div>
138 + <br/>
139 + <small>rendered in <span id="time001">X</span> ms</small>
140 +</div>
141 +<div style="width: 32%; display: inline-block;">
142 + <div data-netdata="system.ipv4"
143 + data-chart-library="peity"
144 + data-width="100%"
145 + data-height="30"
146 + data-after="-600"
147 + data-dt-element-name="time002"
148 + ></div>
149 + <br/>
150 + <small>rendered in <span id="time002">X</span> ms</small>
151 +</div>
152 +<div style="width: 32%; display: inline-block;">
153 + <div data-netdata="system.cpu"
154 + data-chart-library="peity"
155 + data-width="100%"
156 + data-height="30"
157 + data-after="-600"
158 + data-dt-element-name="time003"
159 + ></div>
160 + <br/>
161 + <small>rendered in <span id="time003">X</span> ms</small>
162 +</div>
163 +
164 +
165 +
166 +
167 +<hr>
168 +<h1>Dygraph Charts</h1>
169 +The fastest charting engine that can chart complete charts (not just sparklines).
170 +The charts are zoomable (drag their contents to zoom-in, double click to zoom-out).
171 +For the moment zooming is just on the presentation layer (the data do not become more detailed when you zoom).
172 +<br/>
173 +<div style="width: 32%; display: inline-block;">
174 + <div data-netdata="system.processes"
175 + data-chart-library="dygraph"
176 + data-width="100%"
177 + data-height="200"
178 + data-after="-600"
179 + data-dt-element-name="time201"
180 + ></div>
181 + <br/>
182 + <small>rendered in <span id="time201">X</span> ms</small>
183 +</div>
184 +<div style="width: 32%; display: inline-block;">
185 + <div data-netdata="system.ipv4"
186 + data-chart-library="dygraph"
187 + data-width="100%"
188 + data-height="200"
189 + data-after="-600"
190 + data-dt-element-name="time202"
191 + ></div>
192 + <br/>
193 + <small>rendered in <span id="time202">X</span> ms</small>
194 +</div>
195 +<div style="width: 32%; display: inline-block;">
196 + <div data-netdata="system.cpu"
197 + data-chart-library="dygraph"
198 + data-width="100%"
199 + data-height="200"
200 + data-after="-600"
201 + data-dt-element-name="time203"
202 + ></div>
203 + <br/>
204 + <small>rendered in <span id="time203">X</span> ms</small>
205 +</div>
206 +
207 +
208 +
209 +
210 +<hr>
211 +<h1>Google Charts</h1>
212 +NetData was originaly developed with Google Charts.
213 +NetData is a complete Google Visualization API provider.
214 +<br/>
215 +<div style="width: 32%; display: inline-block;">
216 + <div data-netdata="system.processes"
217 + data-chart-library="google"
218 + data-width="100%"
219 + data-height="200"
220 + data-after="-600"
221 + data-dt-element-name="time301"
222 + ></div>
223 + <br/>
224 + <small>rendered in <span id="time301">X</span> ms</small>
225 +</div>
226 +<div style="width: 32%; display: inline-block;">
227 + <div data-netdata="system.ipv4"
228 + data-chart-library="google"
229 + data-width="100%"
230 + data-height="200"
231 + data-after="-600"
232 + data-dt-element-name="time302"
233 + ></div>
234 + <br/>
235 + <small>rendered in <span id="time302">X</span> ms</small>
236 +</div>
237 +<div style="width: 32%; display: inline-block;">
238 + <div data-netdata="system.cpu"
239 + data-chart-library="google"
240 + data-width="100%"
241 + data-height="200"
242 + data-after="-600"
243 + data-dt-element-name="time303"
244 + ></div>
245 + <br/>
246 + <small>rendered in <span id="time303">X</span> ms</small>
247 +</div>
248 +
249 +
250 +
251 +
252 +
253 +
254 +<hr>
255 +<h1>Morris Charts</h1>
256 +Unfortunatelly, Morris Charts are veeeeeeeeeeeeeeeery slow! We force them to lower their detail to get acceptable results.
257 +<br/>
258 +<div style="width: 32%; display: inline-block;">
259 + <div data-netdata="system.processes"
260 + data-chart-library="morris"
261 + data-width="100%"
262 + data-height="200"
263 + data-after="-600"
264 + data-dt-element-name="time401"
265 + ></div>
266 + <br/>
267 + <small>rendered in <span id="time401">X</span> ms</small>
268 +</div>
269 +<div style="width: 32%; display: inline-block;">
270 + <div data-netdata="system.ipv4"
271 + data-chart-library="morris"
272 + data-width="100%"
273 + data-height="200"
274 + data-after="-600"
275 + data-dt-element-name="time402"
276 + ></div>
277 + <br/>
278 + <small>rendered in <span id="time402">X</span> ms</small>
279 +</div>
280 +<div style="width: 32%; display: inline-block;">
281 + <div data-netdata="system.cpu"
282 + data-chart-library="morris"
283 + data-width="100%"
284 + data-height="200"
285 + data-after="-600"
286 + data-dt-element-name="time403"
287 + ></div>
288 + <br/>
289 + <small>rendered in <span id="time403">X</span> ms</small>
290 +</div>
291 +
292 +
293 +
294 +
295
296 </body>
297 </html>
web/dashboard.js
+212 -167
@@ -16,6 +16,9 @@
16
17 (function(window)
18 {
19 + // fix IE bug with console
20 + if(!window.console){ window.console = {log: function(){} }; }
21 +
22 var NETDATA = window.NETDATA || {};
23
24 // ----------------------------------------------------------------------------------------------------------------
@@ -76,25 +79,26 @@
79
80 NETDATA.chartDefaults = {
81 host: NETDATA.serverDefault, // the server to get data from
79 - width: 100, // the chart width
80 - height: 20, // the chart height
81 - library: 'peity', // the graphing library to use
82 + width: '100%', // the chart width
83 + height: '100%', // the chart height
84 + library: 'dygraph', // the graphing library to use
85 method: 'average', // the grouping method
86 before: 0, // panning
87 after: -600, // panning
85 - pixels_per_point: 1, // the detail of the chart
88 + pixels_per_point: 1 // the detail of the chart
89 }
90
91 NETDATA.options = {
89 - targets: null,
92 + targets: null,
93 updated_dom: 1,
94 debug: 1,
95 + last_paused: 0,
96
97 current: {
98 pixels_per_point: 1,
95 - idle_between_charts: 50,
96 - idle_between_loops: 100,
97 - debug: 1
99 + idle_between_charts: 100,
100 + idle_between_loops: 500,
101 + fast_render_timeframe: 200 // render continously for these many ms
102 }
103 }
104
@@ -108,12 +112,12 @@
112 100: { message: "Cannot load chart library", alert: true },
113 101: { message: "Cannot load jQuery", alert: true },
114 402: { message: "Chart library not found", alert: false },
111 - 404: { message: "Chart not found", alert: false },
115 + 404: { message: "Chart not found", alert: false }
116 };
117 NETDATA.errorLast = {
118 code: 0,
119 message: "",
116 - datetime: 0,
120 + datetime: 0
121 };
122
123 NETDATA.error = function(code, msg) {
@@ -133,19 +137,18 @@
137 NETDATA.errorLast.datetime = 0;
138 }
139
136 - NETDATA.chartContainer = function(element, width, height) {
140 + NETDATA.messageInABox = function(element, message) {
141 self = $(element);
138 - self.css('width', width)
139 - .css('height', height)
140 - .css('display', 'inline-block')
141 - .css('overflow', 'hidden');
142 - }
142
144 - NETDATA.messageInABox = function(element, width, height, message) {
145 - NETDATA.chartContainer(element, width, height);
146 - element.innerHTML = '<div style="overflow: hidden; border: 0px; background-color: lightgrey; width: ' + width + '; height: ' + height + ';"><small>'
143 + bgcolor = ""
144 + if(NETDATA.options.debug)
145 + bgcolor = " background-color: lightgrey;";
146 +
147 + element.innerHTML = '<div style="overflow: hidden;' + bgcolor + ' width: 100%; height: 100%;"><small>'
148 + message
149 + '</small></div>';
150 +
151 + self.data('created', false);
152 }
153
154 // ----------------------------------------------------------------------------------------------------------------
@@ -171,63 +174,77 @@
174 callback();
175 }
176
174 - NETDATA.generateChartDataURL = function(options) {
177 + NETDATA.generateChartDataURL = function() {
178 + self = $(this);
179 +
180 + var chart = self.data('chart');
181 + var host = self.data('host') || NETDATA.chartDefaults.host;
182 + var width = self.width();
183 + var height = self.height();
184 + var method = self.data('method') || NETDATA.chartDefaults.method;
185 + var after = self.data('after') || NETDATA.chartDefaults.after;
186 + var before = self.data('before') || NETDATA.chartDefaults.before;
187 + var library = self.data('chart-library') || NETDATA.chartDefaults.library;
188 + var dimensions = self.data('dimensions') || null;
189 + var pixels_per_point = self.data('pixels-per-point') || NETDATA.chartLibraries[library].pixels_per_point;
190 +
191 + // force an options provided detail
192 + if(pixels_per_point < NETDATA.options.current.pixels_per_point)
193 + pixels_per_point = NETDATA.options.current.pixels_per_point
194 +
195 + var points = self.data('points') || Math.round(width / pixels_per_point);
196 +
197 // build the data URL
176 - var url = options.host + options.url;
177 - url += "&points=";
178 - url += options.points.toString();
179 - url += "&group=";
180 - url += options.method;
181 - url += "&after=";
182 - url += options.after || "0";
183 - url += "&before=";
184 - url += options.before || "0";
185 - url += "&options=" + NETDATA.chartLibraries[options.library].options + '|';
186 - url += (options.non_zero)?"nonzero":"";
187 - url += "&format=" + NETDATA.chartLibraries[options.library].format;
188 -
189 - if(options.dimensions)
190 - url += "&dimensions=" + options.dimensions;
191 -
192 - if(NETDATA.options.debug) console.log('generateChartDataURL(' + options + ') = ' + url );
198 + var url = host + chart.data_url;
199 + url += "&format=" + NETDATA.chartLibraries[library].format;
200 + url += "&points=" + points.toString();
201 + url += "&options=" + NETDATA.chartLibraries[library].options;
202 + url += "&group=" + method;
203 +
204 + if(after)
205 + url += "&after=" + after.toString();
206 +
207 + if(before)
208 + url += "&before=" + before.toString();
209 +
210 + if(dimensions)
211 + url += "&dimensions=" + dimensions;
212 +
213 + self.data('calculated-width', width)
214 + .data('calculated-height', height)
215 + .data('calculated-points', points)
216 + .data('calculated-url', url);
217 +
218 + if(NETDATA.options.debug) console.log('generateChartDataURL(): ' + url + ' WxH:' + width + 'x' + height + ' points: ' + points + ' library: ' + library);
219 return url;
220 }
221
196 - NETDATA.parseDomCharts = function(targets, index, callback) {
197 - if(NETDATA.options.debug) console.log('parseDomCharts() working on ' + index);
222 + NETDATA.validateDomCharts = function(targets, index, callback) {
223 + if(NETDATA.options.debug) console.log('validateDomCharts() working on ' + index);
224
225 var target = targets.get(index);
226 if(target == null) {
201 - if(NETDATA.options.debug) console.log('parseDomCharts(): all ' + (index - 1) + ' charts parsed.');
227 + if(NETDATA.options.debug) console.log('validateDomCharts(): all ' + (index - 1) + ' charts parsed.');
228 if(typeof callback == 'function') callback();
229 }
230 else {
231 var self = $(target);
232 if(!self.data('prepared')) {
207 - self.data('prepared', true);
233 + self.data('prepared', true)
234 + .data('updated', 0)
235 + .data('created', false)
236 + .data('enabled', false);
237
238 var id = self.data('netdata');
239 var host = self.data('host') || NETDATA.chartDefaults.host;
211 - var width = self.data('width') || NETDATA.chartDefaults.width;
212 - var height = self.data('height') || NETDATA.chartDefaults.height;
213 - var method = self.data('method') || NETDATA.chartDefaults.method;
214 - var after = self.data('after') || NETDATA.chartDefaults.after;
215 - var before = self.data('before') || NETDATA.chartDefaults.before;
240 var library = self.data('chart-library') || NETDATA.chartDefaults.library;
217 - var dimensions = self.data('dimensions') || null;
241
219 - NETDATA.chartContainer(target, width, height);
220 - if(NETDATA.options.debug) console.log('parseDomCharts() parsing ' + id + ' of type ' + library);
242 + if(NETDATA.options.debug) console.log('validateDomCharts() parsing ' + id + ' of type ' + library);
243
244 if(typeof NETDATA.chartLibraries[library] == 'undefined') {
223 - self.data('created', false)
224 - .data('updated', 0)
225 - .data('enabled', false);
226 -
245 NETDATA.error(402, library);
228 - NETDATA.messageInABox(target, width, height, 'chart library "' + library + '" is not found');
229 -
230 - NETDATA.parseDomCharts(targets, ++index, callback);
246 + NETDATA.messageInABox(target, 'chart library "' + library + '" is not found');
247 + NETDATA.validateDomCharts(targets, ++index, callback);
248 }
249 else {
250 var url = host + "/api/v1/chart?chart=" + id;
@@ -237,93 +254,96 @@
254 crossDomain: true
255 })
256 .done(function(chart) {
240 - var pixels_per_point = self.data('point-width') || NETDATA.chartLibraries[library].pixels_per_point;
241 - var points = self.data('points') || Math.round(width / pixels_per_point);
242 -
243 - var url = NETDATA.generateChartDataURL({
244 - host: host,
245 - url: chart.data_url,
246 - dimensions: dimensions,
247 - library: library,
248 - method: method,
249 - before: before,
250 - points: points,
251 - after: after,
252 - non_zero: null
253 - });
254 -
255 - // done processing of this DIV
256 - // store the processing result, in
257 - // 'data' sections in the DIV
257 self.data('chart', chart)
259 - .data('chart-url', url)
258 .data('update-every', chart.update_every * 1000)
261 - .data('created', false)
262 - .data('updated', 0)
259 .data('enabled', true)
260 .data('host', host)
265 - .data('width', width)
266 - .data('height', height)
267 - .data('method', method)
268 - .data('after', after)
269 - .data('before', before)
270 - .data('chart-library', library)
271 - .data('dimensions', dimensions)
272 - ;
273 -
274 - NETDATA.messageInABox(target, width, height, 'chart "' + id + '" is loading...');
261 + .data('chart-library', library);
262 })
263 .fail(function() {
277 - self.data('created', false)
278 - .data('enabled', false);
279 -
264 NETDATA.error(404, url);
281 - NETDATA.messageInABox(target, width, height, 'chart "' + id + '" not found on url "' + url + '"');
265 + NETDATA.messageInABox(target, 'chart "' + id + '" not found on url "' + url + '"');
266 })
267 .always(function() {
284 - self.data('updated', 0);
285 - NETDATA.parseDomCharts(targets, ++index, callback);
268 + NETDATA.validateDomCharts(targets, ++index, callback);
269 });
270 }
271 }
272 }
273 }
274
275 + NETDATA.sizeDomCharts = function(targets, index, callback) {
276 + // this is used to quickly size all charts to their size
277 +
278 + if(NETDATA.options.debug) console.log('sizeDomCharts() working on ' + index);
279 +
280 + var target = targets.get(index);
281 + if(target == null) {
282 + if(NETDATA.options.debug) console.log('sizeDomCharts(): all ' + (index - 1) + ' charts sized.');
283 + if(typeof callback == 'function') callback();
284 + }
285 + else {
286 + var self = $(target);
287 +
288 + var id = self.data('netdata');
289 + var width = self.data('width') || NETDATA.chartDefaults.width;
290 + var height = self.data('height') || NETDATA.chartDefaults.height;
291 +
292 + self.css('width', width)
293 + .css('height', height)
294 + .css('display', 'inline-block')
295 + .css('overflow', 'hidden');
296 +
297 + NETDATA.messageInABox(target, 'chart "' + id + '" is loading...');
298 + NETDATA.sizeDomCharts(targets, ++index, callback);
299 + }
300 + }
301 +
302 NETDATA.domUpdated = function(callback) {
303 NETDATA.options.updated_dom = 0;
304
295 - NETDATA.options.targets = $('div[data-netdata]') // .filter(':visible')
305 + NETDATA.options.targets = $('div[data-netdata]').filter(':visible')
306 .bind('create', function(event, data) {
307 var self = $(this);
298 - try {
308 +
309 + if(NETDATA.options.debug)
310 NETDATA.chartLibraries[self.data('chart-library')].create(this, data);
300 - }
301 - catch(err) {
302 - NETDATA.messageInABox(this, self.data('width'), self.data('height'), 'chart "' + id + '" failed to be created as ' + self.data('chart-library'));
311 + else {
312 + try {
313 + NETDATA.chartLibraries[self.data('chart-library')].create(this, data);
314 + }
315 + catch(err) {
316 + NETDATA.messageInABox(this, 'chart "' + self.data('netdata') + '" failed to be created as ' + self.data('chart-library'));
317 + self.data('created', false);
318 + }
319 }
320 })
321 .bind('update', function(event, data) {
322 var self = $(this);
307 - try {
323 + if(NETDATA.options.debug)
324 NETDATA.chartLibraries[self.data('chart-library')].update(this, data);
309 - }
310 - catch(err) {
311 - NETDATA.messageInABox(this, self.data('width'), self.data('height'), 'chart "' + id + '" failed to be updated as ' + self.data('chart-library'));
325 + else {
326 + try {
327 + NETDATA.chartLibraries[self.data('chart-library')].update(this, data);
328 + }
329 + catch(err) {
330 + NETDATA.messageInABox(this, 'chart "' + self.data('netdata') + '" failed to be updated as ' + self.data('chart-library'));
331 + self.data('created', false);
332 + }
333 }
334 });
335
336 if(NETDATA.options.debug)
337 console.log('DOM updated - there are ' + NETDATA.options.targets.length + ' charts on page.');
338
318 - NETDATA.parseDomCharts(NETDATA.options.targets, 0, callback);
339 + NETDATA.sizeDomCharts(NETDATA.options.targets, 0, function() {
340 + NETDATA.validateDomCharts(NETDATA.options.targets, 0, callback);
341 + });
342 }
343
344 NETDATA.init = function() {
345 + // this should be called only once
346 NETDATA.domUpdated(function() {
323 - // done processing all netdata DIVs in this page
324 - // call the refresh handler
325 -
326 - // FIXME
347 NETDATA.chartRefresher(0);
348 });
349 }
@@ -358,7 +378,7 @@
378 else {
379 console.log(self.data('netdata') + ' is visible, downloading data...');
380 $.ajax( {
361 - url: self.data('chart-url'),
381 + url: NETDATA.generateChartDataURL.call(element), // self.data('chart-url'),
382 crossDomain: true
383 })
384 .then(function(data) {
@@ -391,7 +411,7 @@
411 }
412 })
413 .fail(function() {
394 - NETDATA.messageInABox(element, self.data('width'), self.data('height'), 'cannot download chart "' + self.data('netdata') + '" values from url "' + self.data('chart-url') + '"');
414 + NETDATA.messageInABox(element, 'cannot download chart "' + self.data('netdata') + '" values from url "' + self.data('chart-url') + '"');
415 })
416 .always(function() {
417 if(typeof callback == 'function') callback();
@@ -402,6 +422,8 @@
422 NETDATA.chartRefresher = function(index) {
423 // if(NETDATA.options.debug) console.log('NETDATA.chartRefresher(<targets, ' + index + ')');
424
425 + now = new Date().getTime();
426 +
427 if(NETDATA.options.updated_dom) {
428 NETDATA.domUpdated(function() {
429 NETDATA.chartRefresher(0);
@@ -410,9 +432,9 @@
432 else {
433 var target = NETDATA.options.targets.get(index);
434 if(target == null) {
413 - console.log('waiting to restart main loop...');
435 + if(NETDATA.options.debug) console.log('waiting to restart main loop...');
436 + NETDATA.options.last_paused = now;
437
415 - // finished, restart
438 setTimeout(function() {
439 NETDATA.chartRefresher(0);
440 }, NETDATA.options.current.idle_between_loops);
@@ -423,11 +445,23 @@
445 NETDATA.chartRefresher(++index);
446 }
447 else {
426 - setTimeout(function() {
448 + if(now - NETDATA.options.last_paused < NETDATA.options.current.fast_render_timeframe) {
449 + if(NETDATA.options.debug) console.log('fast rendering...');
450 +
451 NETDATA.chartValuesDownloader(target, function() {
452 NETDATA.chartRefresher(++index);
453 });
430 - }, NETDATA.options.current.idle_between_charts);
454 + }
455 + else {
456 + if(NETDATA.options.debug) console.log('waiting for next refresh...');
457 + NETDATA.options.last_paused = now;
458 +
459 + setTimeout(function() {
460 + NETDATA.chartValuesDownloader(target, function() {
461 + NETDATA.chartRefresher(++index);
462 + });
463 + }, NETDATA.options.current.idle_between_charts);
464 + }
465 }
466 }
467 }
@@ -466,21 +500,39 @@
500
501 NETDATA.peityChartUpdate = function(element, data) {
502 var self = $(element);
469 - var instance = self.html(data).not('[data-created]');
470 - instance.change();
503 + var instance = self.data('peity-instance');
504 + var ins = $(instance);
505 + ins.html(data);
506 +
507 + // peity.change() does not accept options
508 + // to pass width and height
509 + //ins.change();
510 + ins.peity('line', { width: self.data('calculated-width'), height: self.data('calculated-height') })
511 }
512
513 NETDATA.peityChartCreate = function(element, data) {
514 var self = $(element);
475 - var width = self.data('width') || NETDATA.chartDefaults.width;
476 - var height = self.data('height') || NETDATA.chartDefaults.height;
477 - var instance = self.html(data).not('[data-created]');
515
479 - instance.peity('line', {
480 - width: width,
481 - height: height
482 - })
483 - .data('created', true);
516 + if(!NETDATA.chartLibraries.peity.initialized) {
517 + if(!NETDATA.chartLibraries.peity.enabled) {
518 + NETDATA.messageInABox(element, 'peity is disabled.');
519 + }
520 + else {
521 + NETDATA.messageInABox(element, 'peity is initializing...');
522 +
523 + }
524 + }
525 +
526 + var uuid = NETDATA.guid();
527 + element.innerHTML = '<div id="' + uuid + '">' + data + '</div>';
528 + var instance = document.getElementById(uuid);
529 + var ins = $(instance);
530 +
531 + ins.peity('line', { width: self.data('calculated-width'), height: self.data('calculated-height') })
532 +
533 + self.data('peity-uuid', uuid)
534 + .data('peity-instance', instance)
535 + .data('created', true);
536 }
537
538 // ----------------------------------------------------------------------------------------------------------------
@@ -507,14 +559,14 @@
559 NETDATA.sparklineChartUpdate = function(element, data) {
560 var self = $(element);
561 var options = self.data('sparkline-options');
562 + options.width = self.data('calculated-width');
563 + options.height = self.data('calculated-height');
564 self.sparkline(data, options);
565 }
566
567 NETDATA.sparklineChartCreate = function(element, data) {
568 var self = $(element);
569 var chart = self.data('chart');
516 - var width = self.data('width') || NETDATA.chartDefaults.width;
517 - var height = self.data('height') || NETDATA.chartDefaults.height;
570 var type = self.data('sparkline-type') || 'line';
571 var lineColor = self.data('sparkline-lineColor') || undefined;
572 var fillColor = self.data('sparkline-fillColor') || (chart.chart_type == 'line')?'#FFF':undefined;
@@ -609,8 +661,8 @@
661 numberDecimalMark: numberDecimalMark,
662 numberDigitGroupCount: numberDigitGroupCount,
663 animatedZooms: animatedZooms,
612 - width: width,
613 - height: height
664 + width: self.data('calculated-width'),
665 + height: self.data('calculated-height')
666 };
667
668 var uuid = NETDATA.guid();
@@ -674,7 +726,11 @@
726
727 if(dygraph != null) {
728 console.log('updating dygraphs');
677 - dygraph.updateOptions( { 'file': data.data, 'labels': data.labels } );
729 + dygraph.updateOptions({
730 + file: data.data,
731 + labels: data.labels,
732 + labelsDivWidth: self.width() - 70
733 + });
734 }
735 else
736 console.log('not updating dygraphs');
@@ -682,8 +738,6 @@
738
739 NETDATA.dygraphChartCreate = function(element, data) {
740 var self = $(element);
685 - var width = self.data('width') || NETDATA.chartDefaults.width;
686 - var height = self.data('height') || NETDATA.chartDefaults.height;
741 var chart = self.data('chart');
742 var title = self.data('dygraph-title') || chart.title;
743 var titleHeight = self.data('dygraph-titleHeight') || 20;
@@ -695,8 +749,9 @@
749 var hideOverlayOnMouseOut = self.data('dygraph-hideOverlayOnMouseOut') || true;
750 var fillGraph = self.data('dygraph-fillGraph') || (chart.chart_type == 'area')?true:false;
751 var drawPoints = self.data('dygraph-drawPoints') || false;
698 - var labelsDivStyles = self.data('dygraph-labelsDivStyles') || { 'fontSize':'10' };
699 - var labelsDivWidth = self.data('dygraph-labelsDivWidth') || 250;
752 + var labelsDivStyles = self.data('dygraph-labelsDivStyles') || { 'fontSize':'10px' };
753 + // var labelsDivWidth = self.data('dygraph-labelsDivWidth') || 250;
754 + var labelsDivWidth = self.width() - 70;
755 var labelsSeparateLines = self.data('dygraph-labelsSeparateLines') || false;
756 var labelsShowZeroValues = self.data('dygraph-labelsShowZeroValues') || true;
757 var legend = self.data('dygraph-legend') || 'onmouseover';
@@ -780,8 +835,6 @@
835 showRoller: showRoller,
836 valueFormatter: valueFormatter,
837 rightGap: rightGap,
783 - width: width,
784 - height: height,
838 labels: data.labels,
839 axes: {
840 x: {
@@ -796,21 +849,21 @@
849 }
850 },
851 y: {
799 - pixelsPerLabel: 15,
852 + pixelsPerLabel: 15
853 }
854 }
855 };
856
857 var uuid = NETDATA.guid();
805 - self.html('<div id="' + uuid + '"></div>');
858 + self.html('<div id="' + uuid + '" style="width: 100%; height: 100%;"></div>');
859
860 var dchart = new Dygraph(document.getElementById(uuid),
861 data.data, options);
862
863 self.data('dygraph-instance', dchart)
811 - .data('dygraph-options', options)
812 - .data('uuid', uuid)
813 - .data('created', true);
864 + .data('dygraph-options', options)
865 + .data('uuid', uuid)
866 + .data('created', true);
867
868 //NETDATA.dygraphAllCharts.push(dchart);
869 //if(NETDATA.dygraphAllCharts.length > 1)
@@ -848,8 +901,6 @@
901
902 NETDATA.morrisChartUpdate = function(element, data) {
903 var self = $(element);
851 - var width = self.data('width') || NETDATA.chartDefaults.width;
852 - var height = self.data('height') || NETDATA.chartDefaults.height;
904 var morris = self.data('morris-instance');
905
906 if(typeof data.update_every != 'undefined')
@@ -865,17 +916,16 @@
916
917 NETDATA.morrisChartCreate = function(element, data) {
918 var self = $(element);
868 - var width = self.data('width') || NETDATA.chartDefaults.width;
869 - var height = self.data('height') || NETDATA.chartDefaults.height;
919 var chart = self.data('chart');
920
872 - self.html('<div id="morris-' + chart.id + '" style="width: ' + width + 'px; height: ' + height + 'px;"></div>');
921 + var uuid = NETDATA.guid();
922 + self.html('<div id="' + uuid + '" style="width: ' + self.data('calculated-width') + 'px; height: ' + self.data('calculated-height') + 'px;"></div>');
923
924 // remove the 'time' element from the labels
925 data.labels.splice(0, 1);
926
927 var options = {
878 - element: 'morris-' + chart.id,
928 + element: uuid,
929 data: data.data,
930 xkey: 'time',
931 ykeys: data.labels,
@@ -886,9 +936,7 @@
936 hideHover: 'auto',
937 parseTime: true,
938 continuousLine: false,
889 - behaveLikeLine: false,
890 - width: width,
891 - height: height
939 + behaveLikeLine: false
940 };
941
942 var morris;
@@ -929,23 +977,19 @@
977
978 NETDATA.raphaelChartUpdate = function(element, data) {
979 var self = $(element);
932 - var width = self.data('width') || NETDATA.chartDefaults.width;
933 - var height = self.data('height') || NETDATA.chartDefaults.height;
980
981 self.raphael(data, {
936 - width: width,
937 - height: height
982 + width: self.data('calculated-width'),
983 + height: self.data('calculated-height')
984 })
985 };
986
987 NETDATA.raphaelChartCreate = function(element, data) {
988 var self = $(element);
943 - var width = self.data('width') || NETDATA.chartDefaults.width;
944 - var height = self.data('height') || NETDATA.chartDefaults.height;
989
990 self.raphael(data, {
947 - width: width,
948 - height: height
991 + width: self.data('calculated-width'),
992 + height: self.data('calculated-height')
993 })
994 .data('created', true);
995 };
@@ -965,8 +1009,6 @@
1009
1010 NETDATA.googleChartUpdate = function(element, data) {
1011 var self = $(element);
968 - var width = self.data('width') || NETDATA.chartDefaults.width;
969 - var height = self.data('height') || NETDATA.chartDefaults.height;
1012 var gchart = self.data('google-instance');
1013 var options = self.data('google-options');
1014
@@ -980,16 +1022,15 @@
1022
1023 NETDATA.googleChartCreate = function(element, data) {
1024 var self = $(element);
983 - var width = self.data('width') || NETDATA.chartDefaults.width;
984 - var height = self.data('height') || NETDATA.chartDefaults.height;
1025 var chart = self.data('chart');
1026
1027 var datatable = new google.visualization.DataTable(data);
1028 var gchart;
1029
1030 var options = {
991 - width: width,
992 - height: height,
1031 + // do not set width, height - the chart resizes itself
1032 + //width: self.data('calculated-width'),
1033 + //height: self.data('calculated-height'),
1034 lineWidth: 1,
1035 title: chart.title,
1036 fontSize: 11,
@@ -1046,10 +1087,13 @@
1087 isStacked: false
1088 };
1089
1090 + var uuid = NETDATA.guid();
1091 + self.html('<div id="' + uuid + '" style="width: 100%; height: 100%;"></div>');
1092 +
1093 switch(chart.chart_type) {
1094 case "area":
1095 options.vAxis.viewWindowMode = 'maximized';
1052 - gchart = new google.visualization.AreaChart(element);
1096 + gchart = new google.visualization.AreaChart(document.getElementById(uuid));
1097 break;
1098
1099 case "stacked":
@@ -1058,21 +1102,22 @@
1102 options.vAxis.viewWindowMode = 'maximized';
1103 options.vAxis.minValue = null;
1104 options.vAxis.maxValue = null;
1061 - gchart = new google.visualization.AreaChart(element);
1105 + gchart = new google.visualization.AreaChart(document.getElementById(uuid));
1106 break;
1107
1108 default:
1109 case "line":
1110 options.lineWidth = 2;
1067 - gchart = new google.visualization.LineChart(element);
1111 + gchart = new google.visualization.LineChart(document.getElementById(uuid));
1112 break;
1113 }
1114
1115 gchart.draw(datatable, options);
1116
1117 self.data('google-instance', gchart)
1074 - .data('google-options', options)
1075 - .data('created', true);
1118 + .data('google-options', options)
1119 + .data('uuid', uuid)
1120 + .data('created', true);
1121 };
1122
1123 // ----------------------------------------------------------------------------------------------------------------