@cryptotaxi247 / netdata-1 / commits / 24ac530ed

optimized for loading speed

Costa Tsaousis (ktsaou) committed Apr 25, 2014 at 01:09 UTC 24ac530edb39ef0b5387b153ccc3b9e1258dcced
2 files changed +955 -1000
web/index.html
+20 -1000
@@ -12,982 +12,9 @@
12
13 <title>NetData</title>
14
15 - <!-- Google AJAX API -->
16 - <script type="text/javascript" src="https://www.google.com/jsapi"></script>
17 - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
18 -
19 - <!-- Bootstrap -->
15 + <!-- Bootstrap CSS -->
16 <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
21 - <!-- <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> -->
22 - <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
17 <link href="/file/theme.css" rel="stylesheet">
24 -
25 - <!-- NetData -->
26 - <script type="text/javascript" src="/file/netdata.js"></script>
27 - <script type="text/javascript" src="/file/jquery.visible.js"></script>
28 - <script type="text/javascript">
29 -
30 - // Set a callback to run when the Google Visualization API is loaded.
31 - google.setOnLoadCallback(initCharts);
32 -
33 - var TARGET_THUMB_GRAPH_WIDTH = 500; // thumb charts width will range from 0.5 to 1.5 of that
34 - var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that
35 - var TARGET_THUMB_GRAPH_HEIGHT = 220; // the height of the thumb charts
36 - var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
37 -
38 - var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?
39 - var MAINCHART_POINTS_DIVISOR = 10; // how much detailed will the main chart be by default? 1 = finest, higher is faster
40 - var MAINCHART_CONTROL_HEIGHT = 75; // how tall the control chart will be
41 - var MAINCHART_CONTROL_DIVISOR = 2; // how much detailed will the control chart be? 1 = finest, higher is faster
42 -
43 - var MODE_THUMBS = 1;
44 - var MODE_MAIN = 2;
45 - var MODE_GROUP_THUMBS = 3;
46 - var mode; // one of the MODE_* values
47 -
48 - var mycharts = new Array();
49 - var mainchart;
50 -
51 - // html for the main menu
52 - var mainmenu = "";
53 -
54 -
55 - // ------------------------------------------------------------------------
56 - // common HTML generation
57 -
58 - function chartIsLoadingHTML(name, width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading " + name + "<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
59 -
60 - function showChartIsLoading(id, name, width, height) {
61 - //mylog('adding loading chart html in div with id ' + id);
62 - document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
63 - }
64 -
65 - function thumbChartActions(i, c, nogroup) {
66 - var name = c.name;
67 - if(!nogroup) name = c.group_tag;
68 -
69 - var refinfo = "the chart is drawing ";
70 - if(c.group == 1) refinfo += "every single point collected.";
71 - else refinfo += ((c.group_method == "average")?"the average":"the max") + " value for every " + (c.group * c.update_every) + " seconds of data";
72 -
73 - var html = "<div class=\"btn-group btn-group\" data-toggle=\"tooltip\" title=\"" + refinfo + "\">"
74 - + "<button type=\"button\" class=\"btn btn-default\" onclick=\"javascript: return;\"><span class=\"glyphicon glyphicon-info-sign\"></span></button>"
75 - + "</div>"
76 - + "<div class=\"btn-group btn-group\"><button type=\"button\" class=\"btn btn-default disabled\"><small>&nbsp;&nbsp; " + name + "</small></button>";
77 -
78 - if(!nogroup) {
79 - var ingroup = 0;
80 - var ingroup_detail = 0;
81 -
82 - $.each(mycharts, function(i, d) {
83 - if(d.group_tag == c.group_tag) {
84 - ingroup++;
85 - if(d.isdetail) ingroup_detail++;
86 - }
87 - });
88 -
89 - var hidden = "";
90 - if(ingroup_detail) hidden = ", including " + ingroup_detail + " charts not shown now";
91 -
92 - html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"Show all " + ingroup + " charts in group '" + c.group_tag + "'" + hidden + "\" class=\"btn btn-default\" onclick=\"initGroupGraphs('" + c.group_tag +"');\"><span class=\"glyphicon glyphicon-th-large\"></span></button>";
93 - }
94 -
95 - html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"show chart '" + c.name + "' in fullscreen\" class=\"btn btn-default\" onclick=\"initMainChartIndex(" + i +");\"><span class=\"glyphicon glyphicon-resize-full\"></span></button>"
96 - + "<button type=\"button\" data-toggle=\"tooltip\" title=\"set options for chart '" + c.name + "'\" class=\"btn btn-default disabled\" onclick=\"alert('Not implemented yet!');\"><span class=\"glyphicon glyphicon-cog\"></span></button>"
97 - + "<button type=\"button\" data-toggle=\"tooltip\" title=\"ignore chart '" + c.name + "'\" class=\"btn btn-default\" onclick=\"disableChart(" + i + ");\"><span class=\"glyphicon glyphicon-trash\"></span></button>"
98 - + "</div>";
99 -
100 - return html;
101 - }
102 -
103 - function mylog(txt) {
104 - console.log(txt);
105 - }
106 -
107 - function chartssort(a, b) {
108 - if(a.userpriority < b.userpriority) return -1;
109 - return 1;
110 - }
111 -
112 -
113 - // ------------------------------------------------------------------------
114 - // MAINGRAPH = fullscreen view of 1 graph
115 -
116 - function calculateChartGroup(c, divisor, maxtime, group) {
117 - var before = c.before?c.before:new Date().getTime() / 1000;
118 - var after = c.after?c.after:c.first_entry_t;
119 -
120 - var dt = before - after;
121 - if(dt > c.entries * c.update_every) dt = c.entries * c.update_every;
122 -
123 - if(maxtime) dt = maxtime;
124 -
125 - var data_points = Math.round(dt / c.update_every);
126 - var screen_points = Math.round(c.chartOptions.width / divisor);
127 - //mylog('screen = ' + screen_points + ', data = ' + data_points + ', divisor = ' + divisor);
128 -
129 - if(group <= 0) {
130 - if(screen_points > data_points) {
131 - c.group = 1;
132 - c.points_to_show = data_points;
133 - //mylog("rendering at full detail");
134 - }
135 - else {
136 - c.group = Math.round(data_points / screen_points);
137 -
138 - if(group >= 0) {
139 - if(c.group > 60) c.group = 60;
140 - else if(c.group > 45) c.group = 45;
141 - else if(c.group > 30) c.group = 30;
142 - else if(c.group > 20) c.group = 20;
143 - else if(c.group > 15) c.group = 15;
144 - else if(c.group > 10) c.group = 10;
145 - else if(c.group > 5) c.group = 5;
146 - else if(c.group > 2) c.group = 2;
147 - else c.group = 1;
148 - }
149 -
150 - c.points_to_show = Math.round(data_points / c.group);
151 - //mylog("rendering adaptive");
152 - }
153 - }
154 - else {
155 - c.group = group;
156 - c.points_to_show = Math.round(data_points / group);
157 - //mylog("rendering with given group");
158 - }
159 - //mylog('group = ' + c.group + ', points = ' + c.points_to_show);
160 -
161 - if(mainchart.chartType == 'LineChart') {
162 - if(mainchart.group <= 2) mainchart.chartOptions.lineWidth = 1;
163 - else mainchart.chartOptions.lineWidth = 2;
164 - }
165 - }
166 -
167 - // copy the chart c to mainchart
168 - // switch to main graphs screen
169 - function initMainChart(c) {
170 - if(mainchart) cleanThisChart(mainchart);
171 -
172 - mainchart = $.extend(true, {}, c);
173 - mainchart.refreshCount = 0;
174 - mainchart.last_updated = 0;
175 - mainchart.chartOptions.explorer = null;
176 - mainchart.chart = null;
177 -
178 - mainchart.chartOptions.width = screenWidth();
179 - mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
180 - if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
181 - //mainchart.chartOptions.chartArea = {'width': '80%'};
182 -
183 - mainchart.div = 'maingraph';
184 - calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
185 -
186 - // copy it to the hidden chart
187 - mainchart.hiddenchart = $.extend(true, {}, mainchart);
188 - mainchart.hiddenchart.chartOptions.height = MAINCHART_CONTROL_HEIGHT;
189 - mainchart.hiddenchart.div = 'maingraph_control';
190 -
191 - // initialize the div
192 - showChartIsLoading(mainchart.div, mainchart.name, mainchart.chartOptions.width, mainchart.chartOptions.height);
193 -
194 - // set the radio buttons
195 - setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
196 - setMainChartMax('normal');
197 -
198 - $('#group' + mainchart.group).trigger('click');
199 - setMainChartGroup(mainchart.group, 'no-refresh');
200 -
201 - switchToMainGraph();
202 - }
203 -
204 - function refreshHiddenChart(doNext) {
205 - if(refresh_mode == REFRESH_PAUSED && mainchart.hiddenchart.last_updated != 0) {
206 - if(typeof doNext == "function") doNext();
207 - return;
208 - }
209 -
210 - // is it too soon for a refresh?
211 - var now = new Date().getTime();
212 - if((now - mainchart.hiddenchart.last_updated) < (mainchart.hiddenchart.group * mainchart.hiddenchart.update_every * 1000)) {
213 - if(typeof doNext == "function") doNext();
214 - return;
215 - }
216 -
217 - if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {
218 - mainchart.dashboard.clear();
219 - mainchart.control_wrapper.clear();
220 - mainchart.hidden_wrapper.clear();
221 -
222 - mainchart.dashboard = null;
223 - mainchart.control_wrapper = null;
224 - mainchart.hidden_wrapper = null;
225 - mainchart.hiddenchart.last_updated = 0;
226 - }
227 -
228 - if(!mainchart.dashboard) {
229 - var controlopts = $.extend(true, {}, mainchart.chartOptions, {
230 - lineWidth: 1,
231 - height: mainchart.hiddenchart.chartOptions.height,
232 - chartArea: {'width': '98%'},
233 - hAxis: {'baselineColor': 'none'},
234 - vAxis: {'title': null},
235 - });
236 -
237 - mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
238 - mainchart.control_wrapper = new google.visualization.ControlWrapper({
239 - controlType: 'ChartRangeFilter',
240 - containerId: 'maingraph_control',
241 - options: {
242 - filterColumnIndex: 0,
243 - ui: {
244 - chartType: mainchart.chartType,
245 - chartOptions: controlopts,
246 - minRangeSize: (MAINCHART_MAX_TIME_TO_SHOW * 1000 * mainchart.update_every) / MAINCHART_POINTS_DIVISOR,
247 - }
248 - },
249 - });
250 - mainchart.hidden_wrapper = new google.visualization.ChartWrapper({
251 - chartType: mainchart.chartType,
252 - containerId: 'maingraph_hidden',
253 - options: {
254 - isStacked: mainchart.chartOptions.isStacked,
255 - width: mainchart.hiddenchart.chartOptions.width,
256 - height: mainchart.hiddenchart.chartOptions.height,
257 - //chartArea: {'height': '80%', 'width': '100%'},
258 - //hAxis: {'slantedText': false},
259 - //legend: {'position': 'none'}
260 - },
261 - });
262 -
263 - mainchart.hiddenchart.refreshCount = 0;
264 - }
265 -
266 - // load the data for the control and the hidden wrappers
267 - // calculate the group and points to show for the control chart
268 - calculateChartGroup(mainchart.hiddenchart, MAINCHART_CONTROL_DIVISOR, 0, -1);
269 -
270 - $.ajax({
271 - url: generateChartURL(mainchart.hiddenchart),
272 - dataType:"json",
273 - cache: false
274 - })
275 - .done(function(jsondata) {
276 - if(!jsondata || jsondata.length == 0) return;
277 -
278 - mainchart.control_data = new google.visualization.DataTable(jsondata);
279 -
280 - if(mainchart.hiddenchart.last_updated == 0) {
281 - google.visualization.events.addListener(mainchart.control_wrapper, 'ready', mainchartControlReadyEvent);
282 - mainchart.dashboard.bind(mainchart.control_wrapper, mainchart.hidden_wrapper);
283 - }
284 - if(refresh_mode != REFRESH_PAUSED)
285 - mainchart.control_wrapper.setState({range: {
286 - start: new Date((Math.round(new Date().getTime() / 1000) - MAINCHART_MAX_TIME_TO_SHOW) * 1000),
287 - end: new Date()
288 - }});
289 -
290 - mainchart.dashboard.draw(mainchart.control_data);
291 - mainchart.hiddenchart.last_updated = new Date().getTime();
292 - mainchart.hiddenchart.refreshCount++;
293 - })
294 - .always(function() {
295 - if(typeof doNext == "function") doNext();
296 - });
297 - }
298 -
299 - function mainchartControlReadyEvent() {
300 - google.visualization.events.addListener(mainchart.control_wrapper, 'statechange', mainchartControlStateHandler);
301 - //mylog(mainchart);
302 - }
303 -
304 - function mainchartControlStateHandler() {
305 - // setMainChartPlay('pause');
306 -
307 - var state = mainchart.control_wrapper.getState();
308 - mainchart.after = Math.round(state.range.start.getTime() / 1000);
309 - mainchart.before = Math.round(state.range.end.getTime() / 1000);
310 -
311 - calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, 0, 0);
312 - //mylog('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
313 -
314 - $('#group' + mainchart.group).trigger('click');
315 - mainchart.last_updated = 0;
316 -
317 - if(refresh_mode != REFRESH_PAUSED) pauseGraphs();
318 - }
319 -
320 - function initMainChartIndex(i) {
321 - if(mode == MODE_GROUP_THUMBS)
322 - initMainChart(group_charts[i]);
323 -
324 - else if(mode == MODE_THUMBS)
325 - initMainChart(mycharts[i]);
326 - }
327 -
328 - var last_main_chart_max='normal';
329 - function setMainChartMax(m) {
330 - if(!mainchart) return;
331 -
332 - if(m == 'toggle') {
333 - if(last_main_chart_max == 'maximized') m = 'normal';
334 - else m = 'maximized';
335 - }
336 -
337 - if(m == "maximized") {
338 - mainchart.chartOptions.theme = 'maximized';
339 - //mainchart.chartOptions.axisTitlesPosition = 'in';
340 - //mainchart.chartOptions.legend = {position: 'none'};
341 - //mainchart.chartOptions.hAxis.title = null;
342 - mainchart.chartOptions.hAxis.viewWindowMode = 'maximized';
343 - mainchart.chartOptions.vAxis.viewWindowMode = 'maximized';
344 - }
345 - else {
346 - mainchart.chartOptions.theme = null;
347 - mainchart.chartOptions.hAxis.viewWindowMode = null;
348 - mainchart.chartOptions.vAxis.viewWindowMode = null;
349 - }
350 - $('.mainchart_max_button').button(m);
351 - last_main_chart_max = m;
352 - mainchart.last_updated = 0;
353 - }
354 -
355 - function setMainChartGroup(g, norefresh) {
356 - if(!mainchart) return;
357 -
358 - mainchart.group = g;
359 -
360 - if(!mainchart.before && !mainchart.after)
361 - calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, mainchart.group);
362 - else
363 - calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, 0, mainchart.group);
364 -
365 - if(!norefresh) {
366 - mainchart.last_updated = 0;
367 - }
368 - }
369 -
370 - var last_main_chart_avg = null;
371 - function setMainChartGroupMethod(g, norefresh) {
372 - if(!mainchart) return;
373 -
374 - if(g == 'toggle') {
375 - if(last_main_chart_avg == 'max') g = 'average';
376 - else g = 'max';
377 - }
378 -
379 - mainchart.group_method = g;
380 -
381 - $('.mainchart_avg_button').button(g);
382 -
383 - if(!norefresh) {
384 - mainchart.last_updated = 0;
385 - }
386 -
387 - last_main_chart_avg = g;
388 - }
389 -
390 - function setMainChartPlay(p) {
391 - if(!mainchart) return;
392 -
393 - if(p == 'toggle') {
394 - if(refresh_mode != REFRESH_ALWAYS) p = 'play';
395 - else p = 'pause';
396 - }
397 -
398 - if(p == 'play') {
399 - //mainchart.chartOptions.explorer = null;
400 - mainchart.after = 0;
401 - mainchart.before = 0;
402 - calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
403 - $('#group' + mainchart.group).trigger('click');
404 - mainchart.last_updated = 0;
405 - mainchart.hiddenchart.last_updated = 0;
406 - playGraphs();
407 - }
408 - else {
409 - //mainchart.chartOptions.explorer = {
410 - // 'axis': 'horizontal',
411 - // 'maxZoomOut': 1,
412 - //};
413 - //mainchart.last_updated = 0;
414 -
415 - //if(!refreshChart(mainchart, pauseGraphs))
416 - pauseGraphs();
417 - }
418 - }
419 -
420 -
421 - // ------------------------------------------------------------------------
422 - // Chart resizing
423 -
424 - function screenWidth() {
425 - return (($(window).width() * 0.95) - 50);
426 - }
427 -
428 - // calculate the proper width for the thumb charts
429 - function thumbWidth() {
430 - var cwidth = screenWidth();
431 - var items = Math.round(cwidth / TARGET_THUMB_GRAPH_WIDTH);
432 - if(items < 1) items = 1;
433 -
434 - if(items > 1 && (cwidth / items) < MINIMUM_THUMB_GRAPH_WIDTH) items--;
435 -
436 - return Math.round(cwidth / items) - 1;
437 - }
438 -
439 - function groupChartSizes() {
440 - var s = { width: screenWidth() / 2, height: ($(window).height() - 130) / 3 - 10};
441 - if(s.width < MINIMUM_THUMB_GRAPH_WIDTH * 1.5) s.width = screenWidth();
442 -
443 - var count = 0;
444 - if(group_charts) $.each(group_charts, function(i, c) {
445 - if(c.enabled) count++;
446 - });
447 -
448 - if(count == 0) {
449 - s.width = TARGET_THUMB_GRAPH_WIDTH;
450 - s.height = TARGET_THUMB_GRAPH_HEIGHT;
451 - }
452 - if(count < 4) {
453 - s.width = screenWidth();
454 - s.height = ($(window).height() - 130) / count - 10;
455 - }
456 - else if(count == 4) {
457 - s.height = ($(window).height() - 130) / 2 - 10;
458 - }
459 -
460 - if(s.height < TARGET_THUMB_GRAPH_HEIGHT * 1.5)
461 - s.height = TARGET_THUMB_GRAPH_HEIGHT * 1.5;
462 -
463 - return s;
464 - }
465 -
466 - // resize all charts
467 - // if the thumb charts need resize in their width, reset them
468 - function resizeCharts() {
469 - var width = screenWidth();
470 -
471 - if(mainchart) {
472 - mainchart.chartOptions.width = width;
473 - mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
474 - mainchart.last_updated = 0;
475 -
476 - mainchart.hidden_wrapper.setOption('width', width);
477 - mainchart.control_wrapper.setOption('ui.chartOptions.width', width);
478 - mainchart.hiddenchart.chartOptions.width = width;
479 - mainchart.hiddenchart.last_updated = 0;
480 - }
481 -
482 - width = thumbWidth();
483 - $.each(mycharts, function(i, c) {
484 - if(c.enabled && c.chartOptions.width != width) {
485 - cleanThisChart(c);
486 - c.chartOptions.width = width;
487 - showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
488 - c.last_updated = 0;
489 - }
490 - });
491 -
492 - if(group_charts) $.each(group_charts, function(i, c) {
493 - var sizes = groupChartSizes();
494 -
495 - if(c.enabled && (c.chartOptions.width != sizes.width || c.chartOptions.height != sizes.height)) {
496 - cleanThisChart(c);
497 - c.chartOptions.width = sizes.width;
498 - c.chartOptions.height = sizes.height;
499 - showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
500 - c.last_updated = 0;
501 - }
502 - });
503 - }
504 -
505 - var resize_request = false;
506 - window.onresize = function(event) {
507 - resize_request = true;
508 - };
509 -
510 -
511 - // ------------------------------------------------------------------------
512 - // Core of the thread refreshing the charts
513 -
514 - var REFRESH_PAUSED = 0;
515 - var REFRESH_ALWAYS = 1;
516 -
517 - var refresh_mode = REFRESH_PAUSED;
518 - var last_refresh = 0;
519 - function playGraphs() {
520 - if(refresh_mode == REFRESH_ALWAYS) return;
521 -
522 - //mylog('PlayGraphs()');
523 - refresh_mode = REFRESH_ALWAYS;
524 - $('.mainchart_play_button').button('play');
525 -
526 - // check if the thread died due to a javascript error
527 - var now = new Date().getTime();
528 - if((now - last_refresh) > 5000) {
529 - // it died or never started
530 - //mylog('It seems the refresh thread died. Restarting it.');
531 - chartsRefresh();
532 - }
533 - }
534 -
535 - function pauseGraphs() {
536 - if(refresh_mode == REFRESH_PAUSED) return;
537 -
538 - //mylog('PauseGraphs()');
539 - refresh_mode = REFRESH_PAUSED;
540 - $('.mainchart_play_button').button('pause');
541 - }
542 -
543 - // refresh the proper chart
544 - // this is an internal function.
545 - // never call it directly, or new javascript threads will be spawn
546 - var timeout;
547 - function chartsRefresh() {
548 - if(resize_request) {
549 - resizeCharts();
550 - resize_request = false;
551 - // refresh_mode = REFRESH_ALWAYS;
552 - }
553 -
554 - last_refresh = new Date().getTime();
555 -
556 - if(refresh_mode == REFRESH_PAUSED) {
557 - if(mode == MODE_MAIN && mainchart.last_updated == 0)
558 - mainChartRefresh();
559 - else
560 - timeout = setTimeout(chartsRefresh, 100);
561 -
562 - return;
563 - }
564 -
565 - if(mode == MODE_THUMBS) thumbChartsRefresh();
566 - else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();
567 - else if(mode == MODE_MAIN) mainChartRefresh();
568 - else timeout = setTimeout(triggerRefresh, 100);
569 - }
570 -
571 - // callback for refreshing the charts later
572 - // this is an internal function.
573 - // never call it directly, or new javascript threads will be spawn
574 - function triggerRefresh() {
575 - //mylog('triggerRefresh()');
576 -
577 - // cleanup has to take place when the charts are not refreshed
578 - // since the refreshing thread is in this function, it means
579 - // nothing is being refreshed.
580 - cleanupCharts();
581 -
582 - if(mode == MODE_THUMBS) timeout = setTimeout(chartsRefresh, 200);
583 - else if(mode == MODE_GROUP_THUMBS) timeout = setTimeout(chartsRefresh, 200);
584 - else if(mode == MODE_MAIN) timeout = setTimeout(chartsRefresh, 200);
585 - else timeout = setTimeout(triggerRefresh, 100);
586 - }
587 -
588 - // refresh the main chart
589 - // make sure we don't loose the refreshing thread
590 - function mainChartRefresh() {
591 - //mylog('mainChartRefresh()');
592 -
593 - if(mode != MODE_MAIN || !mainchart) {
594 - triggerRefresh();
595 - return;
596 - }
597 -
598 - if(!refreshChart(mainchart, hiddenChartRefresh))
599 - hiddenChartRefresh();
600 - }
601 -
602 - function hiddenChartRefresh() {
603 - refreshHiddenChart(triggerRefresh);
604 - }
605 -
606 - function roundRobinRefresh(charts, startat) {
607 - var refreshed = false;
608 -
609 - // find a chart to refresh
610 - var all = charts.length;
611 - var cur = startat;
612 - var count = 0;
613 -
614 - for(count = 0; count < all ; count++, cur++) {
615 - if(cur >= all) cur = 0;
616 -
617 - if(charts[cur].enabled) {
618 - //mylog('going to refresh chart ' + charts[cur].name);
619 - refreshed = refreshChart(charts[cur], chartsRefresh);
620 - if(refreshed) break;
621 - }
622 - }
623 -
624 - if(!refreshed) triggerRefresh();
625 - return cur;
626 - }
627 -
628 - // refresh the thumb charts
629 - // make sure we don't loose the refreshing thread
630 - var last_thumb_updated = 0;
631 - function thumbChartsRefresh() {
632 - //mylog('thumbChartsRefresh()');
633 -
634 - if(mycharts.length == 0 || mode != MODE_THUMBS) {
635 - triggerRefresh();
636 - return;
637 - }
638 -
639 - last_thumb_updated = roundRobinRefresh(mycharts, last_thumb_updated);
640 - }
641 -
642 - // refresh the group charts
643 - // make sure we don't loose the refreshing thread
644 - var last_group_updated = 0;
645 - function groupChartsRefresh() {
646 - //mylog('groupChartsRefresh()');
647 -
648 - if(!group_charts || group_charts.length == 0 || mode != MODE_GROUP_THUMBS) {
649 - //mylog('cannot refresh charts');
650 - triggerRefresh();
651 - return;
652 - }
653 -
654 - last_group_updated = roundRobinRefresh(group_charts, last_group_updated);
655 - }
656 -
657 -
658 - // ------------------------------------------------------------------------
659 - // switch the screen between views
660 - // these should be called only from initXXXX()
661 -
662 - function disableChart(i) {
663 - //mylog('disableChart(' + i + ')');
664 -
665 - var chart = null;
666 -
667 - var count = 0;
668 - if(mode == MODE_GROUP_THUMBS && group_charts) {
669 - $.each(group_charts, function(i, c) {
670 - if(c.enabled) count++;
671 - });
672 -
673 - if(i < group_charts.length) chart = group_charts[i];
674 - }
675 - else if(mode == MODE_THUMBS) {
676 - $.each(mycharts, function(i, c) {
677 - if(c.enabled) count++;
678 - });
679 -
680 - if(i < mycharts.length) chart = mycharts[i];
681 - }
682 -
683 - if(!chart) return;
684 -
685 - if(count <= 1) {
686 - alert('Cannot close the last chart shown.');
687 - return;
688 - }
689 -
690 - if(chart) {
691 - //mylog("disabling chart " + chart.name);
692 - chart.disablethisplease = true;
693 - }
694 - }
695 -
696 - function cleanThisChart(chart, emptydivs) {
697 - //mylog('cleanThisChart(' + chart.name + ', ' + emptydivs +')');
698 -
699 - if(chart.dashboard) {
700 - chart.dashboard.clear();
701 - chart.dashboard = null;
702 -
703 - if(chart.control_wrapper) {
704 - chart.control_wrapper.clear();
705 - chart.control_wrapper = null;
706 - }
707 -
708 - if(chart.hidden_wrapper) {
709 - chart.hidden_wrapper.clear();
710 - chart.hidden_wrapper = null;
711 - }
712 -
713 - chart.control_data = null;
714 - }
715 -
716 - if(chart.chart) chart.chart.clearChart();
717 - chart.chart = null;
718 -
719 - if(emptydivs) {
720 - var div = document.getElementById(chart.div);
721 - if(div) {
722 - div.style.display = 'none';
723 - div.innerHTML = "";
724 - }
725 -
726 - div = document.getElementById(chart.div + "_parent");
727 - if(div) {
728 - div.style.display = 'none';
729 - div.innerHTML = "";
730 - }
731 - }
732 -
733 - //mylog("chart " + chart.name + " cleaned with option " + emptydivs);
734 - }
735 -
736 - // cleanup the previously shown charts
737 - function cleanupCharts() {
738 - //mylog('cleanupCharts()');
739 -
740 - if(mode != MODE_MAIN && mainchart) {
741 - if(mainchart.chart) cleanThisChart(mainchart);
742 - mainchart = null;
743 - }
744 -
745 - if(mode != MODE_GROUP_THUMBS && group_charts) {
746 - clearGroupGraphs();
747 - }
748 -
749 - // cleanup the disabled charts
750 - $.each(mycharts, function(i, c) {
751 - if(c.disablethisplease && c.enabled) {
752 - cleanThisChart(c, 'emptydivs');
753 - c.disablethisplease = false;
754 - c.enabled = false;
755 - resize_request = true;
756 - //mylog("disabled chart " + c.name + " removed");
757 - }
758 - });
759 -
760 - if(group_charts) $.each(group_charts, function(i, c) {
761 - if(c.disablethisplease && c.enabled) {
762 - cleanThisChart(c, 'emptydivs');
763 - c.disablethisplease = false;
764 - c.enabled = false;
765 - resize_request = true;
766 - //mylog("disabled chart " + c.name + " removed");
767 - }
768 - });
769 -
770 - // we never cleanup the thumb charts
771 - }
772 -
773 - function updateUI() {
774 - $('[data-toggle="tooltip"]').tooltip({'placement': 'top', 'container': 'body', 'html': true});
775 -
776 - $('[data-spy="scroll"]').each(function () {
777 - var $spy = $(this).scrollspy('refresh')
778 - })
779 - }
780 -
781 - var thumbsScrollPosition = null;
782 - function switchToMainGraph() {
783 - //mylog('switchToMainGraph()');
784 -
785 - if(!mainchart) return;
786 -
787 - if(!group_charts) thumbsScrollPosition = window.pageYOffset;
788 -
789 - document.getElementById('maingraph_container').style.display = 'block';
790 - document.getElementById('thumbgraphs_container').style.display = 'none';
791 - document.getElementById('groupgraphs_container').style.display = 'none';
792 -
793 - document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + mainchart.title + "</a></li></ul>";
794 -
795 - window.scrollTo(0, 0);
796 -
797 - mode = MODE_MAIN;
798 - playGraphs();
799 - updateUI();
800 - }
801 -
802 - function switchToThumbGraphs() {
803 - //mylog('switchToThumbGraphs()');
804 -
805 - document.getElementById('maingraph_container').style.display = 'none';
806 - document.getElementById('thumbgraphs_container').style.display = 'block';
807 - document.getElementById('groupgraphs_container').style.display = 'none';
808 -
809 - document.getElementById("main_menu_div").innerHTML = mainmenu;
810 -
811 - if(thumbsScrollPosition) window.scrollTo(0, thumbsScrollPosition);
812 -
813 - // switch mode
814 - mode = MODE_THUMBS;
815 - playGraphs();
816 - updateUI();
817 - }
818 -
819 - function switchToGroupGraphs() {
820 - //mylog('switchToGroupGraphs()');
821 -
822 - if(!group_charts) return;
823 -
824 - if(!mainchart) thumbsScrollPosition = window.pageYOffset;
825 -
826 - document.getElementById('maingraph_container').style.display = 'none';
827 - document.getElementById('thumbgraphs_container').style.display = 'none';
828 - document.getElementById('groupgraphs_container').style.display = 'block';
829 -
830 - document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + group_charts[0].group_tag + " charts</a></li></ul>";
831 -
832 - window.scrollTo(0, 0);
833 -
834 - mode = MODE_GROUP_THUMBS;
835 - playGraphs();
836 - updateUI();
837 - }
838 -
839 -
840 - // ------------------------------------------------------------------------
841 - // Group Charts
842 -
843 - var group_charts = null;
844 - function initGroupGraphs(group) {
845 - var count = 0;
846 -
847 - if(group_charts) clearGroupGraphs();
848 - group_charts = new Array();
849 -
850 - var groupbody = "";
851 - $.each(mycharts, function(i, c) {
852 - if(c.group_tag == group) {
853 - group_charts[count] = [];
854 - group_charts[count] = $.extend(true, {}, c);
855 - group_charts[count].div += "_group";
856 - group_charts[count].enabled = true;
857 - group_charts[count].chart = null;
858 - group_charts[count].last_updated = 0;
859 - count++;
860 - }
861 - });
862 - group_charts.sort(chartssort);
863 -
864 - var sizes = groupChartSizes();
865 -
866 - var groupbody = "";
867 - $.each(group_charts, function(i, c) {
868 - c.chartOptions.width = sizes.width;
869 - c.chartOptions.height = sizes.height;
870 -
871 - groupbody += "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
872 - });
873 - groupbody += "";
874 -
875 - document.getElementById("groupgraphs").innerHTML = groupbody;
876 - switchToGroupGraphs();
877 - }
878 -
879 - function clearGroupGraphs() {
880 - if(group_charts && group_charts.length) {
881 - $.each(group_charts, function(i, c) {
882 - cleanThisChart(c, 'emptydivs');
883 - });
884 -
885 - group_charts = null;
886 - }
887 -
888 - document.getElementById("groupgraphs").innerHTML = "";
889 - }
890 -
891 -
892 - // ------------------------------------------------------------------------
893 - // Global entry point
894 - // initialize the thumb charts
895 -
896 - // load the charts from the server
897 - // generate html for the thumbgraphs to support them
898 - function initCharts() {
899 - var width = thumbWidth();
900 - var height = TARGET_THUMB_GRAPH_HEIGHT;
901 -
902 - loadCharts(null, function(c) {
903 - mycharts = c;
904 -
905 - if(mycharts == null || mycharts.length == 0) {
906 - alert("Cannot load data from server.");
907 - return;
908 - }
909 -
910 - var thumbsContainer = document.getElementById("thumbgraphs");
911 - if(!thumbsContainer) {
912 - alert("Cannot find the thumbsContainer");
913 - return;
914 - }
915 -
916 - mycharts.sort(chartssort);
917 -
918 - document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
919 - document.title = mycharts[0].hostname;
920 -
921 - // create an array for grouping all same-type graphs together
922 - var categories = new Array();
923 - $.each(mycharts, function(i, c) {
924 - c.chartOptions.width = width;
925 - c.chartOptions.height = height;
926 -
927 - // calculate how many point to show for each chart
928 - c.points_to_show = Math.round(c.entries / c.group) - 1;
929 -
930 - // show max 10 mins of data
931 - if(c.points_to_show * c.group > THUMBS_MAX_TIME_TO_SHOW) c.points_to_show = THUMBS_MAX_TIME_TO_SHOW / c.group;
932 -
933 - if(c.enabled) {
934 - var j;
935 - var h = "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
936 - + thumbChartActions(i, c)
937 - + "</td></tr></table></div>";
938 -
939 - // find the categories object for this type
940 - for(j = 0; j < categories.length ;j++) {
941 - if(categories[j].name == c.type) {
942 - categories[j].html += h;
943 - categories[j].count++;
944 - break;
945 - }
946 - }
947 -
948 - if(j == categories.length) {
949 - categories.push({name: c.type, title: c.category, description: '', priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
950 - }
951 - }
952 - });
953 -
954 - $.each(categories, function(i, a) {
955 - if(a.name == "system") a.priority = 1;
956 - else if(a.name == "net") a.priority = 2;
957 - else if(a.name == "tc") a.priority = 3;
958 - else if(a.name == "conntrack") a.priority = 4;
959 - else if(a.name == "ipvs") a.priority = 5;
960 - else if(a.name == "ipv4") a.priority = 6;
961 - else if(a.name == "cpu") a.priority = 7;
962 - else if(a.name == "mem") a.priority = 8;
963 - else if(a.name == "disk") a.priority = 9;
964 - else a.priority = 99;
965 -
966 - a.html = "<tr><td id=\"" + a.name + "\"><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> &nbsp; <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
967 - });
968 -
969 - function categoriessort(a, b) {
970 - if(a.priority < b.priority) return -1;
971 - return 1;
972 - }
973 - categories.sort(categoriessort);
974 -
975 - // combine all the htmls into one
976 - var allcategories = "<table width=\"100%\">";
977 - mainmenu = "<ul class=\"nav navbar-nav\"><li><a href=\"#\">Home</a></li>";
978 - $.each(categories, function(i, a) {
979 - allcategories += a.html;
980 - mainmenu += "<li><a href=\"#" + a.name + "\">" + a.title + "</a></li>";
981 - });
982 - allcategories += "</table>";
983 - mainmenu += "</ul>";
984 -
985 - thumbsContainer.innerHTML = allcategories;
986 - switchToThumbGraphs();
987 - });
988 - }
989 -
990 - </script>
18 </head>
19
20 <body role="document" data-spy="scroll" data-target="#main_menu_div">
@@ -1035,17 +62,7 @@
62 <span class="glyphicon glyphicon-signal"></span>
63 </button>
64 </div>
1038 -<!-- <div class="btn-group btn-group" data-toggle="buttons">
1039 - <label class="btn btn-primary" data-toggle="tooltip" title="show the MAX point among all points grouped">
1040 - <input type="radio" name="groupmethod" id="groupmax" onChange="setMainChartGroupMethod('max');">
1041 - <span class="glyphicon glyphicon-signal"></span>
1042 - </label>
1043 - <label class="btn btn-primary" data-toggle="tooltip" title="show the AVERAGE of all points grouped">
1044 - <input type="radio" name="groupmethod" id="groupaverage" onChange="setMainChartGroupMethod('average');">
1045 - <span class="glyphicon glyphicon-align-justify"></span>
1046 - </label>
1047 - </div>
1048 ---> <div class="btn-group btn-group" data-toggle="buttons" >
65 + <div class="btn-group btn-group" data-toggle="buttons" >
66 <label class="btn btn-primary" data-toggle="tooltip" title="do not group points, show the raw data">
67 <input type="radio" name="group" id="group1" onChange="setMainChartGroup(1);">1
68 </label>
@@ -1081,17 +98,7 @@
98 <span class="glyphicon glyphicon-fullscreen"></span>
99 </button>
100 </div>
1084 -<!-- <div class="btn-group btn-group" data-toggle="buttons" >
1085 - <label class="btn btn-primary" data-toggle="tooltip" title="NORMAL chart size">
1086 - <input type="radio" name="chartmax" id="chartnormal" onChange="setMainChartMax('normal');">
1087 - <span class="glyphicon glyphicon-resize-small"></span>
1088 - </label>
1089 - <label class="btn btn-primary" data-toggle="tooltip" title="MAXIMIZED chart size">
1090 - <input type="radio" name="chartmax" id="chartmax" onChange="setMainChartMax('maximized');">
1091 - <span class="glyphicon glyphicon-fullscreen"></span>
1092 - </label>
1093 - </div>
1094 ---> </form>
101 + </form>
102 </div>
103 </td></tr>
104 </table>
@@ -1109,7 +116,7 @@
116 <br/><br/>
117 <span class="glyphicon glyphicon-off"></span>
118 <br/><br/>
1112 - loading charts
119 + loading cosmos
120 <br/><br/>
121 <span class="label label-default">Please wait...</span>
122 </h1>
@@ -1134,20 +141,33 @@
141 (c) 2014 Costa Tsaousis <a href="mailto:costa@tsaousis.gr">costa@tsaousis.gr</a>
142 </div>
143
144 + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
145 + <script type='text/javascript'>
146 + document.getElementById('splash').height = $(window).height();
147 + </script>
148 +
149 + <!-- Bootstrap -->
150 + <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
151 +
152 + <!-- Google AJAX API -->
153 + <script type="text/javascript" src="https://www.google.com/jsapi"></script>
154 +
155 + <!-- NetData -->
156 + <script type="text/javascript" src="/file/netdata.js"></script>
157 + <script type="text/javascript" src="/file/index.js"></script>
158 +
159 <script type='text/javascript'>
160 google.load('visualization', '1.1', {packages: ['controls']});
161
162 $(document).ready(function(){
1141 - document.getElementById('splash').height = $(window).height();
163
164 $(document).on('click','.navbar-collapse.in',function(e) {
165 if( $(e.target).is('a') ) {
166 $(this).collapse('hide');
167 }
168 });
1148 -
169 +
170 $('body').scrollspy({ target: '#main_menu_div' })
171 });
1151 -
172 </script>
173 </html>
web/index.js new
+935
@@ -0,0 +1,935 @@
1 +var TARGET_THUMB_GRAPH_WIDTH = 500; // thumb charts width will range from 0.5 to 1.5 of that
2 +var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that
3 +var TARGET_THUMB_GRAPH_HEIGHT = 220; // the height of the thumb charts
4 +
5 +var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
6 +var THUMBS_POINTS_DIVISOR = 4;
7 +var THUMBS_STACKED_POINTS_DIVISOR = 10;
8 +
9 +var GROUPS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
10 +var GROUPS_POINTS_DIVISOR = 4;
11 +var GROUPS_STACKED_POINTS_DIVISOR = 10;
12 +
13 +var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?
14 +var MAINCHART_POINTS_DIVISOR = 10; // how much detailed will the main chart be by default? 1 = finest, higher is faster
15 +var MAINCHART_STACKED_POINTS_DIVISOR = 20; // how much detailed will the main chart be by default? 1 = finest, higher is faster
16 +
17 +var MAINCHART_CONTROL_HEIGHT = 75; // how tall the control chart will be
18 +var MAINCHART_CONTROL_DIVISOR = 2; // how much detailed will the control chart be? 1 = finest, higher is faster
19 +
20 +var MODE_THUMBS = 1;
21 +var MODE_MAIN = 2;
22 +var MODE_GROUP_THUMBS = 3;
23 +var mode; // one of the MODE_* values
24 +
25 +var mycharts = new Array();
26 +var mainchart;
27 +
28 +// html for the main menu
29 +var mainmenu = "";
30 +
31 +
32 +// ------------------------------------------------------------------------
33 +// common HTML generation
34 +
35 +function chartIsLoadingHTML(name, width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading " + name + "<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
36 +
37 +function showChartIsLoading(id, name, width, height) {
38 + //mylog('adding loading chart html in div with id ' + id);
39 + document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
40 +}
41 +
42 +function thumbChartActions(i, c, nogroup) {
43 + var name = c.name;
44 + if(!nogroup) name = c.group_tag;
45 +
46 + var refinfo = "the chart is drawing ";
47 + if(c.group == 1) refinfo += "every single point collected.";
48 + else refinfo += ((c.group_method == "average")?"the average":"the max") + " value for every " + (c.group * c.update_every) + " seconds of data";
49 +
50 + var html = "<div class=\"btn-group btn-group\" data-toggle=\"tooltip\" title=\"" + refinfo + "\">"
51 + + "<button type=\"button\" class=\"btn btn-default\" onclick=\"javascript: return;\"><span class=\"glyphicon glyphicon-info-sign\"></span></button>"
52 + + "</div>"
53 + + "<div class=\"btn-group btn-group\"><button type=\"button\" class=\"btn btn-default disabled\"><small>&nbsp;&nbsp; " + name + "</small></button>";
54 +
55 + if(!nogroup) {
56 + var ingroup = 0;
57 + var ingroup_detail = 0;
58 +
59 + $.each(mycharts, function(i, d) {
60 + if(d.group_tag == c.group_tag) {
61 + ingroup++;
62 + if(d.isdetail) ingroup_detail++;
63 + }
64 + });
65 +
66 + var hidden = "";
67 + if(ingroup_detail) hidden = ", including " + ingroup_detail + " charts not shown now";
68 +
69 + html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"Show all " + ingroup + " charts in group '" + c.group_tag + "'" + hidden + "\" class=\"btn btn-default\" onclick=\"initGroupGraphs('" + c.group_tag +"');\"><span class=\"glyphicon glyphicon-th-large\"></span></button>";
70 + }
71 +
72 + html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"show chart '" + c.name + "' in fullscreen\" class=\"btn btn-default\" onclick=\"initMainChartIndex(" + i +");\"><span class=\"glyphicon glyphicon-resize-full\"></span></button>"
73 + + "<button type=\"button\" data-toggle=\"tooltip\" title=\"set options for chart '" + c.name + "'\" class=\"btn btn-default disabled\" onclick=\"alert('Not implemented yet!');\"><span class=\"glyphicon glyphicon-cog\"></span></button>"
74 + + "<button type=\"button\" data-toggle=\"tooltip\" title=\"ignore chart '" + c.name + "'\" class=\"btn btn-default\" onclick=\"disableChart(" + i + ");\"><span class=\"glyphicon glyphicon-trash\"></span></button>"
75 + + "</div>";
76 +
77 + return html;
78 +}
79 +
80 +function mylog(txt) {
81 + console.log(txt);
82 +}
83 +
84 +function chartssort(a, b) {
85 + if(a.userpriority < b.userpriority) return -1;
86 + return 1;
87 +}
88 +
89 +
90 +// ------------------------------------------------------------------------
91 +// MAINGRAPH = fullscreen view of 1 graph
92 +
93 +// copy the chart c to mainchart
94 +// switch to main graphs screen
95 +function initMainChart(c) {
96 + if(mainchart) cleanThisChart(mainchart);
97 +
98 + mainchart = $.extend(true, {}, c);
99 + mainchart.refreshCount = 0;
100 + mainchart.last_updated = 0;
101 + mainchart.chartOptions.explorer = null;
102 + mainchart.chart = null;
103 +
104 + mainchart.chartOptions.width = screenWidth();
105 + mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
106 + if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
107 + //mainchart.chartOptions.chartArea = {'width': '80%'};
108 +
109 + mainchart.div = 'maingraph';
110 + calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
111 +
112 + // copy it to the hidden chart
113 + mainchart.hiddenchart = $.extend(true, {}, mainchart);
114 + mainchart.hiddenchart.chartOptions.height = MAINCHART_CONTROL_HEIGHT;
115 + mainchart.hiddenchart.div = 'maingraph_control';
116 +
117 + // initialize the div
118 + showChartIsLoading(mainchart.div, mainchart.name, mainchart.chartOptions.width, mainchart.chartOptions.height);
119 +
120 + // set the radio buttons
121 + setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
122 + setMainChartMax('normal');
123 +
124 + $('#group' + mainchart.group).trigger('click');
125 + setMainChartGroup(mainchart.group, 'no-refresh');
126 +
127 + switchToMainGraph();
128 +}
129 +
130 +function refreshHiddenChart(doNext) {
131 + if(refresh_mode == REFRESH_PAUSED && mainchart.hiddenchart.last_updated != 0) {
132 + if(typeof doNext == "function") doNext();
133 + return;
134 + }
135 +
136 + // is it too soon for a refresh?
137 + var now = new Date().getTime();
138 + if((now - mainchart.hiddenchart.last_updated) < (mainchart.hiddenchart.group * mainchart.hiddenchart.update_every * 1000)) {
139 + if(typeof doNext == "function") doNext();
140 + return;
141 + }
142 +
143 + if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {
144 + mainchart.dashboard.clear();
145 + mainchart.control_wrapper.clear();
146 + mainchart.hidden_wrapper.clear();
147 +
148 + mainchart.dashboard = null;
149 + mainchart.control_wrapper = null;
150 + mainchart.hidden_wrapper = null;
151 + mainchart.hiddenchart.last_updated = 0;
152 + }
153 +
154 + if(!mainchart.dashboard) {
155 + var controlopts = $.extend(true, {}, mainchart.chartOptions, {
156 + lineWidth: 1,
157 + height: mainchart.hiddenchart.chartOptions.height,
158 + chartArea: {'width': '98%'},
159 + hAxis: {'baselineColor': 'none'},
160 + vAxis: {'title': null},
161 + });
162 +
163 + mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
164 + mainchart.control_wrapper = new google.visualization.ControlWrapper({
165 + controlType: 'ChartRangeFilter',
166 + containerId: 'maingraph_control',
167 + options: {
168 + filterColumnIndex: 0,
169 + ui: {
170 + chartType: mainchart.chartType,
171 + chartOptions: controlopts,
172 + minRangeSize: (MAINCHART_MAX_TIME_TO_SHOW * 1000 * mainchart.update_every) / MAINCHART_POINTS_DIVISOR,
173 + }
174 + },
175 + });
176 + mainchart.hidden_wrapper = new google.visualization.ChartWrapper({
177 + chartType: mainchart.chartType,
178 + containerId: 'maingraph_hidden',
179 + options: {
180 + isStacked: mainchart.chartOptions.isStacked,
181 + width: mainchart.hiddenchart.chartOptions.width,
182 + height: mainchart.hiddenchart.chartOptions.height,
183 + //chartArea: {'height': '80%', 'width': '100%'},
184 + //hAxis: {'slantedText': false},
185 + //legend: {'position': 'none'}
186 + },
187 + });
188 +
189 + mainchart.hiddenchart.refreshCount = 0;
190 + }
191 +
192 + // load the data for the control and the hidden wrappers
193 + // calculate the group and points to show for the control chart
194 + calculateChartPointsToShow(mainchart.hiddenchart, MAINCHART_CONTROL_DIVISOR, 0, -1);
195 +
196 + $.ajax({
197 + url: generateChartURL(mainchart.hiddenchart),
198 + dataType:"json",
199 + cache: false
200 + })
201 + .done(function(jsondata) {
202 + if(!jsondata || jsondata.length == 0) return;
203 +
204 + mainchart.control_data = new google.visualization.DataTable(jsondata);
205 +
206 + if(mainchart.hiddenchart.last_updated == 0) {
207 + google.visualization.events.addListener(mainchart.control_wrapper, 'ready', mainchartControlReadyEvent);
208 + mainchart.dashboard.bind(mainchart.control_wrapper, mainchart.hidden_wrapper);
209 + }
210 + if(refresh_mode != REFRESH_PAUSED)
211 + mainchart.control_wrapper.setState({range: {
212 + start: new Date((Math.round(new Date().getTime() / 1000) - MAINCHART_MAX_TIME_TO_SHOW) * 1000),
213 + end: new Date()
214 + }});
215 +
216 + mainchart.dashboard.draw(mainchart.control_data);
217 + mainchart.hiddenchart.last_updated = new Date().getTime();
218 + mainchart.hiddenchart.refreshCount++;
219 + })
220 + .always(function() {
221 + if(typeof doNext == "function") doNext();
222 + });
223 +}
224 +
225 +function mainchartControlReadyEvent() {
226 + google.visualization.events.addListener(mainchart.control_wrapper, 'statechange', mainchartControlStateHandler);
227 + //mylog(mainchart);
228 +}
229 +
230 +function mainchartControlStateHandler() {
231 + // setMainChartPlay('pause');
232 +
233 + var state = mainchart.control_wrapper.getState();
234 + mainchart.after = Math.round(state.range.start.getTime() / 1000);
235 + mainchart.before = Math.round(state.range.end.getTime() / 1000);
236 +
237 + calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, 0, 0);
238 + //mylog('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
239 +
240 + $('#group' + mainchart.group).trigger('click');
241 + mainchart.last_updated = 0;
242 +
243 + if(refresh_mode != REFRESH_PAUSED) pauseGraphs();
244 +}
245 +
246 +function initMainChartIndex(i) {
247 + if(mode == MODE_GROUP_THUMBS)
248 + initMainChart(group_charts[i]);
249 +
250 + else if(mode == MODE_THUMBS)
251 + initMainChart(mycharts[i]);
252 +}
253 +
254 +var last_main_chart_max='normal';
255 +function setMainChartMax(m) {
256 + if(!mainchart) return;
257 +
258 + if(m == 'toggle') {
259 + if(last_main_chart_max == 'maximized') m = 'normal';
260 + else m = 'maximized';
261 + }
262 +
263 + if(m == "maximized") {
264 + mainchart.chartOptions.theme = 'maximized';
265 + //mainchart.chartOptions.axisTitlesPosition = 'in';
266 + //mainchart.chartOptions.legend = {position: 'none'};
267 + //mainchart.chartOptions.hAxis.title = null;
268 + mainchart.chartOptions.hAxis.viewWindowMode = 'maximized';
269 + mainchart.chartOptions.vAxis.viewWindowMode = 'maximized';
270 + }
271 + else {
272 + mainchart.chartOptions.theme = null;
273 + mainchart.chartOptions.hAxis.viewWindowMode = null;
274 + mainchart.chartOptions.vAxis.viewWindowMode = null;
275 + }
276 + $('.mainchart_max_button').button(m);
277 + last_main_chart_max = m;
278 + mainchart.last_updated = 0;
279 +}
280 +
281 +function setMainChartGroup(g, norefresh) {
282 + if(!mainchart) return;
283 +
284 + mainchart.group = g;
285 +
286 + if(!mainchart.before && !mainchart.after)
287 + calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, mainchart.group);
288 + else
289 + calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, 0, mainchart.group);
290 +
291 + if(!norefresh) {
292 + mainchart.last_updated = 0;
293 + }
294 +}
295 +
296 +var last_main_chart_avg = null;
297 +function setMainChartGroupMethod(g, norefresh) {
298 + if(!mainchart) return;
299 +
300 + if(g == 'toggle') {
301 + if(last_main_chart_avg == 'max') g = 'average';
302 + else g = 'max';
303 + }
304 +
305 + mainchart.group_method = g;
306 +
307 + $('.mainchart_avg_button').button(g);
308 +
309 + if(!norefresh) {
310 + mainchart.last_updated = 0;
311 + }
312 +
313 + last_main_chart_avg = g;
314 +}
315 +
316 +function setMainChartPlay(p) {
317 + if(!mainchart) return;
318 +
319 + if(p == 'toggle') {
320 + if(refresh_mode != REFRESH_ALWAYS) p = 'play';
321 + else p = 'pause';
322 + }
323 +
324 + if(p == 'play') {
325 + //mainchart.chartOptions.explorer = null;
326 + mainchart.after = 0;
327 + mainchart.before = 0;
328 + calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
329 + $('#group' + mainchart.group).trigger('click');
330 + mainchart.last_updated = 0;
331 + mainchart.hiddenchart.last_updated = 0;
332 + playGraphs();
333 + }
334 + else {
335 + //mainchart.chartOptions.explorer = {
336 + // 'axis': 'horizontal',
337 + // 'maxZoomOut': 1,
338 + //};
339 + //mainchart.last_updated = 0;
340 +
341 + //if(!refreshChart(mainchart, pauseGraphs))
342 + pauseGraphs();
343 + }
344 +}
345 +
346 +
347 +// ------------------------------------------------------------------------
348 +// Chart resizing
349 +
350 +function screenWidth() {
351 + return (($(window).width() * 0.95) - 50);
352 +}
353 +
354 +// calculate the proper width for the thumb charts
355 +function thumbWidth() {
356 + var cwidth = screenWidth();
357 + var items = Math.round(cwidth / TARGET_THUMB_GRAPH_WIDTH);
358 + if(items < 1) items = 1;
359 +
360 + if(items > 1 && (cwidth / items) < MINIMUM_THUMB_GRAPH_WIDTH) items--;
361 +
362 + return Math.round(cwidth / items) - 1;
363 +}
364 +
365 +function groupChartSizes() {
366 + var s = { width: screenWidth() / 2, height: ($(window).height() - 130) / 3 - 10};
367 + if(s.width < MINIMUM_THUMB_GRAPH_WIDTH * 1.5) s.width = screenWidth();
368 +
369 + var count = 0;
370 + if(group_charts) $.each(group_charts, function(i, c) {
371 + if(c.enabled) count++;
372 + });
373 +
374 + if(count == 0) {
375 + s.width = TARGET_THUMB_GRAPH_WIDTH;
376 + s.height = TARGET_THUMB_GRAPH_HEIGHT;
377 + }
378 + if(count < 4) {
379 + s.width = screenWidth();
380 + s.height = ($(window).height() - 130) / count - 10;
381 + }
382 + else if(count == 4) {
383 + s.height = ($(window).height() - 130) / 2 - 10;
384 + }
385 +
386 + if(s.height < TARGET_THUMB_GRAPH_HEIGHT * 1.5)
387 + s.height = TARGET_THUMB_GRAPH_HEIGHT * 1.5;
388 +
389 + return s;
390 +}
391 +
392 +// resize all charts
393 +// if the thumb charts need resize in their width, reset them
394 +function resizeCharts() {
395 + var width = screenWidth();
396 +
397 + if(mainchart) {
398 + mainchart.chartOptions.width = width;
399 + mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
400 + mainchart.last_updated = 0;
401 +
402 + mainchart.hidden_wrapper.setOption('width', width);
403 + mainchart.control_wrapper.setOption('ui.chartOptions.width', width);
404 + mainchart.hiddenchart.chartOptions.width = width;
405 + mainchart.hiddenchart.last_updated = 0;
406 + }
407 +
408 + width = thumbWidth();
409 + $.each(mycharts, function(i, c) {
410 + if(c.enabled && c.chartOptions.width != width) {
411 + cleanThisChart(c);
412 + c.chartOptions.width = width;
413 + calculateChartPointsToShow(c, c.chartOptions.isStacked?THUMBS_STACKED_POINTS_DIVISOR:THUMBS_POINTS_DIVISOR, THUMBS_MAX_TIME_TO_SHOW, -1);
414 + showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
415 + c.last_updated = 0;
416 + }
417 + });
418 +
419 + if(group_charts) $.each(group_charts, function(i, c) {
420 + var sizes = groupChartSizes();
421 +
422 + if(c.enabled && (c.chartOptions.width != sizes.width || c.chartOptions.height != sizes.height)) {
423 + cleanThisChart(c);
424 + c.chartOptions.width = sizes.width;
425 + c.chartOptions.height = sizes.height;
426 + calculateChartPointsToShow(c, c.chartOptions.isStacked?GROUPS_STACKED_POINTS_DIVISOR:GROUPS_POINTS_DIVISOR, GROUPS_MAX_TIME_TO_SHOW, -1);
427 + showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
428 + c.last_updated = 0;
429 + }
430 + });
431 +}
432 +
433 +var resize_request = false;
434 +window.onresize = function(event) {
435 + resize_request = true;
436 +};
437 +
438 +
439 +// ------------------------------------------------------------------------
440 +// Core of the thread refreshing the charts
441 +
442 +var REFRESH_PAUSED = 0;
443 +var REFRESH_ALWAYS = 1;
444 +
445 +var refresh_mode = REFRESH_PAUSED;
446 +var last_refresh = 0;
447 +function playGraphs() {
448 + if(refresh_mode == REFRESH_ALWAYS) return;
449 +
450 + //mylog('PlayGraphs()');
451 + refresh_mode = REFRESH_ALWAYS;
452 + $('.mainchart_play_button').button('play');
453 +
454 + // check if the thread died due to a javascript error
455 + var now = new Date().getTime();
456 + if((now - last_refresh) > 5000) {
457 + // it died or never started
458 + //mylog('It seems the refresh thread died. Restarting it.');
459 + chartsRefresh();
460 + }
461 +}
462 +
463 +function pauseGraphs() {
464 + if(refresh_mode == REFRESH_PAUSED) return;
465 +
466 + //mylog('PauseGraphs()');
467 + refresh_mode = REFRESH_PAUSED;
468 + $('.mainchart_play_button').button('pause');
469 +}
470 +
471 +var interval = null;
472 +function checkRefreshThread() {
473 + if(interval == null) {
474 + interval = setInterval(checkRefreshThread, 2000);
475 + return;
476 + }
477 +
478 + var now = new Date().getTime();
479 + if(now - last_refresh > 10000) {
480 + mylog('Refresh thread died. Restarting it.');
481 + chartsRefresh();
482 + }
483 +}
484 +
485 +// refresh the proper chart
486 +// this is an internal function.
487 +// never call it directly, or new javascript threads will be spawn
488 +var timeout = null;
489 +function chartsRefresh() {
490 + if(resize_request) {
491 + resizeCharts();
492 + resize_request = false;
493 + // refresh_mode = REFRESH_ALWAYS;
494 + }
495 +
496 + last_refresh = new Date().getTime();
497 +
498 + if(refresh_mode == REFRESH_PAUSED) {
499 + if(mode == MODE_MAIN && mainchart.last_updated == 0) {
500 + mainChartRefresh();
501 + return;
502 + }
503 + }
504 +
505 + if(mode == MODE_THUMBS) thumbChartsRefresh();
506 + else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();
507 + else if(mode == MODE_MAIN) mainChartRefresh();
508 + else timeout = setTimeout(triggerRefresh, 100);
509 +}
510 +
511 +// callback for refreshing the charts later
512 +// this is an internal function.
513 +// never call it directly, or new javascript threads will be spawn
514 +function triggerRefresh() {
515 + //mylog('triggerRefresh()');
516 +
517 + // cleanup has to take place when the charts are not refreshed
518 + // since the refreshing thread is in this function, it means
519 + // nothing is being refreshed.
520 + cleanupCharts();
521 +
522 + if(mode == MODE_THUMBS) timeout = setTimeout(chartsRefresh, 200);
523 + else if(mode == MODE_GROUP_THUMBS) timeout = setTimeout(chartsRefresh, 200);
524 + else if(mode == MODE_MAIN) timeout = setTimeout(chartsRefresh, 200);
525 + else timeout = setTimeout(triggerRefresh, 100);
526 +}
527 +
528 +// refresh the main chart
529 +// make sure we don't loose the refreshing thread
530 +function mainChartRefresh() {
531 + //mylog('mainChartRefresh()');
532 +
533 + if(mode != MODE_MAIN || !mainchart) {
534 + triggerRefresh();
535 + return;
536 + }
537 +
538 + if(!refreshChart(mainchart, hiddenChartRefresh))
539 + hiddenChartRefresh();
540 +}
541 +
542 +function hiddenChartRefresh() {
543 + refreshHiddenChart(triggerRefresh);
544 +}
545 +
546 +function roundRobinRefresh(charts, startat) {
547 + var refreshed = false;
548 +
549 + // find a chart to refresh
550 + var all = charts.length;
551 + var cur = startat;
552 + var count = 0;
553 +
554 + for(count = 0; count < all ; count++, cur++) {
555 + if(cur >= all) cur = 0;
556 +
557 + if(charts[cur].enabled) {
558 + //mylog('going to refresh chart ' + charts[cur].name);
559 + refreshed = refreshChart(charts[cur], chartsRefresh);
560 + if(refreshed) break;
561 + }
562 + }
563 +
564 + if(!refreshed) triggerRefresh();
565 + return cur;
566 +}
567 +
568 +// refresh the thumb charts
569 +// make sure we don't loose the refreshing thread
570 +var last_thumb_updated = 0;
571 +function thumbChartsRefresh() {
572 + //mylog('thumbChartsRefresh()');
573 +
574 + if(mycharts.length == 0 || mode != MODE_THUMBS) {
575 + triggerRefresh();
576 + return;
577 + }
578 +
579 + last_thumb_updated = roundRobinRefresh(mycharts, last_thumb_updated);
580 +}
581 +
582 +// refresh the group charts
583 +// make sure we don't loose the refreshing thread
584 +var last_group_updated = 0;
585 +function groupChartsRefresh() {
586 + //mylog('groupChartsRefresh()');
587 +
588 + if(!group_charts || group_charts.length == 0 || mode != MODE_GROUP_THUMBS) {
589 + //mylog('cannot refresh charts');
590 + triggerRefresh();
591 + return;
592 + }
593 +
594 + last_group_updated = roundRobinRefresh(group_charts, last_group_updated);
595 +}
596 +
597 +
598 +// ------------------------------------------------------------------------
599 +// switch the screen between views
600 +// these should be called only from initXXXX()
601 +
602 +function disableChart(i) {
603 + //mylog('disableChart(' + i + ')');
604 +
605 + var chart = null;
606 +
607 + var count = 0;
608 + if(mode == MODE_GROUP_THUMBS && group_charts) {
609 + $.each(group_charts, function(i, c) {
610 + if(c.enabled) count++;
611 + });
612 +
613 + if(i < group_charts.length) chart = group_charts[i];
614 + }
615 + else if(mode == MODE_THUMBS) {
616 + $.each(mycharts, function(i, c) {
617 + if(c.enabled) count++;
618 + });
619 +
620 + if(i < mycharts.length) chart = mycharts[i];
621 + }
622 +
623 + if(!chart) return;
624 +
625 + if(count <= 1) {
626 + alert('Cannot close the last chart shown.');
627 + return;
628 + }
629 +
630 + if(chart) {
631 + //mylog("disabling chart " + chart.name);
632 + chart.disablethisplease = true;
633 + }
634 +}
635 +
636 +function cleanThisChart(chart, emptydivs) {
637 + //mylog('cleanThisChart(' + chart.name + ', ' + emptydivs +')');
638 +
639 + if(chart.dashboard) {
640 + chart.dashboard.clear();
641 + chart.dashboard = null;
642 +
643 + if(chart.control_wrapper) {
644 + chart.control_wrapper.clear();
645 + chart.control_wrapper = null;
646 + }
647 +
648 + if(chart.hidden_wrapper) {
649 + chart.hidden_wrapper.clear();
650 + chart.hidden_wrapper = null;
651 + }
652 +
653 + chart.control_data = null;
654 + }
655 +
656 + if(chart.chart) chart.chart.clearChart();
657 + chart.chart = null;
658 +
659 + if(emptydivs) {
660 + var div = document.getElementById(chart.div);
661 + if(div) {
662 + div.style.display = 'none';
663 + div.innerHTML = "";
664 + }
665 +
666 + div = document.getElementById(chart.div + "_parent");
667 + if(div) {
668 + div.style.display = 'none';
669 + div.innerHTML = "";
670 + }
671 + }
672 +
673 + //mylog("chart " + chart.name + " cleaned with option " + emptydivs);
674 +}
675 +
676 +// cleanup the previously shown charts
677 +function cleanupCharts() {
678 + //mylog('cleanupCharts()');
679 +
680 + if(mode != MODE_MAIN && mainchart) {
681 + if(mainchart.chart) cleanThisChart(mainchart);
682 + mainchart = null;
683 + }
684 +
685 + if(mode != MODE_GROUP_THUMBS && group_charts) {
686 + clearGroupGraphs();
687 + }
688 +
689 + // cleanup the disabled charts
690 + $.each(mycharts, function(i, c) {
691 + if(c.disablethisplease && c.enabled) {
692 + cleanThisChart(c, 'emptydivs');
693 + c.disablethisplease = false;
694 + c.enabled = false;
695 + resize_request = true;
696 + //mylog("disabled chart " + c.name + " removed");
697 + }
698 + });
699 +
700 + if(group_charts) $.each(group_charts, function(i, c) {
701 + if(c.disablethisplease && c.enabled) {
702 + cleanThisChart(c, 'emptydivs');
703 + c.disablethisplease = false;
704 + c.enabled = false;
705 + resize_request = true;
706 + //mylog("disabled chart " + c.name + " removed");
707 + }
708 + });
709 +
710 + // we never cleanup the thumb charts
711 +}
712 +
713 +function updateUI() {
714 + $('[data-toggle="tooltip"]').tooltip({'placement': 'top', 'container': 'body', 'html': true});
715 +
716 + $('[data-spy="scroll"]').each(function () {
717 + var $spy = $(this).scrollspy('refresh')
718 + })
719 +}
720 +
721 +var thumbsScrollPosition = null;
722 +function switchToMainGraph() {
723 + //mylog('switchToMainGraph()');
724 +
725 + if(!mainchart) return;
726 +
727 + if(!group_charts) thumbsScrollPosition = window.pageYOffset;
728 +
729 + document.getElementById('maingraph_container').style.display = 'block';
730 + document.getElementById('thumbgraphs_container').style.display = 'none';
731 + document.getElementById('groupgraphs_container').style.display = 'none';
732 +
733 + document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + mainchart.title + "</a></li></ul>";
734 +
735 + window.scrollTo(0, 0);
736 +
737 + mode = MODE_MAIN;
738 + playGraphs();
739 + updateUI();
740 +}
741 +
742 +function switchToThumbGraphs() {
743 + //mylog('switchToThumbGraphs()');
744 +
745 + document.getElementById('maingraph_container').style.display = 'none';
746 + document.getElementById('thumbgraphs_container').style.display = 'block';
747 + document.getElementById('groupgraphs_container').style.display = 'none';
748 +
749 + document.getElementById("main_menu_div").innerHTML = mainmenu;
750 +
751 + if(thumbsScrollPosition) window.scrollTo(0, thumbsScrollPosition);
752 +
753 + // switch mode
754 + mode = MODE_THUMBS;
755 + playGraphs();
756 + updateUI();
757 +}
758 +
759 +function switchToGroupGraphs() {
760 + //mylog('switchToGroupGraphs()');
761 +
762 + if(!group_charts) return;
763 +
764 + if(!mainchart) thumbsScrollPosition = window.pageYOffset;
765 +
766 + document.getElementById('maingraph_container').style.display = 'none';
767 + document.getElementById('thumbgraphs_container').style.display = 'none';
768 + document.getElementById('groupgraphs_container').style.display = 'block';
769 +
770 + document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + group_charts[0].group_tag + " charts</a></li></ul>";
771 +
772 + window.scrollTo(0, 0);
773 +
774 + mode = MODE_GROUP_THUMBS;
775 + playGraphs();
776 + updateUI();
777 +}
778 +
779 +
780 +// ------------------------------------------------------------------------
781 +// Group Charts
782 +
783 +var group_charts = null;
784 +function initGroupGraphs(group) {
785 + var count = 0;
786 +
787 + if(group_charts) clearGroupGraphs();
788 + group_charts = new Array();
789 +
790 + var groupbody = "";
791 + $.each(mycharts, function(i, c) {
792 + if(c.group_tag == group) {
793 + group_charts[count] = [];
794 + group_charts[count] = $.extend(true, {}, c);
795 + group_charts[count].div += "_group";
796 + group_charts[count].enabled = true;
797 + group_charts[count].chart = null;
798 + group_charts[count].last_updated = 0;
799 + count++;
800 + }
801 + });
802 + group_charts.sort(chartssort);
803 +
804 + var sizes = groupChartSizes();
805 +
806 + var groupbody = "";
807 + $.each(group_charts, function(i, c) {
808 + c.chartOptions.width = sizes.width;
809 + c.chartOptions.height = sizes.height;
810 +
811 + calculateChartPointsToShow(c, c.chartOptions.isStacked?GROUPS_STACKED_POINTS_DIVISOR:GROUPS_POINTS_DIVISOR, GROUPS_MAX_TIME_TO_SHOW, -1);
812 +
813 + groupbody += "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
814 + });
815 + groupbody += "";
816 +
817 + document.getElementById("groupgraphs").innerHTML = groupbody;
818 + switchToGroupGraphs();
819 +}
820 +
821 +function clearGroupGraphs() {
822 + if(group_charts && group_charts.length) {
823 + $.each(group_charts, function(i, c) {
824 + cleanThisChart(c, 'emptydivs');
825 + });
826 +
827 + group_charts = null;
828 + }
829 +
830 + document.getElementById("groupgraphs").innerHTML = "";
831 +}
832 +
833 +
834 +// ------------------------------------------------------------------------
835 +// Global entry point
836 +// initialize the thumb charts
837 +
838 +// load the charts from the server
839 +// generate html for the thumbgraphs to support them
840 +function initCharts() {
841 + var width = thumbWidth();
842 + var height = TARGET_THUMB_GRAPH_HEIGHT;
843 +
844 + loadCharts(null, function(c) {
845 + mycharts = c;
846 +
847 + if(mycharts == null || mycharts.length == 0) {
848 + alert("Cannot load data from server.");
849 + return;
850 + }
851 +
852 + var thumbsContainer = document.getElementById("thumbgraphs");
853 + if(!thumbsContainer) {
854 + alert("Cannot find the thumbsContainer");
855 + return;
856 + }
857 +
858 + mycharts.sort(chartssort);
859 +
860 + document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
861 + document.title = mycharts[0].hostname;
862 +
863 + // create an array for grouping all same-type graphs together
864 + var categories = new Array();
865 + $.each(mycharts, function(i, c) {
866 + c.chartOptions.width = width;
867 + c.chartOptions.height = height;
868 +
869 + // calculate how many point to show for each chart
870 + //c.points_to_show = Math.round(c.entries / c.group) - 1;
871 + // show max 10 mins of data
872 + //if(c.points_to_show * c.group > THUMBS_MAX_TIME_TO_SHOW) c.points_to_show = THUMBS_MAX_TIME_TO_SHOW / c.group;
873 + calculateChartPointsToShow(c, c.chartOptions.isStacked?THUMBS_STACKED_POINTS_DIVISOR:THUMBS_POINTS_DIVISOR, THUMBS_MAX_TIME_TO_SHOW, -1);
874 +
875 + if(c.enabled) {
876 + var j;
877 + var h = "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
878 + + thumbChartActions(i, c)
879 + + "</td></tr></table></div>";
880 +
881 + // find the categories object for this type
882 + for(j = 0; j < categories.length ;j++) {
883 + if(categories[j].name == c.type) {
884 + categories[j].html += h;
885 + categories[j].count++;
886 + break;
887 + }
888 + }
889 +
890 + if(j == categories.length) {
891 + categories.push({name: c.type, title: c.category, description: '', priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
892 + }
893 + }
894 + });
895 +
896 + $.each(categories, function(i, a) {
897 + if(a.name == "system") a.priority = 1;
898 + else if(a.name == "net") a.priority = 2;
899 + else if(a.name == "tc") a.priority = 3;
900 + else if(a.name == "conntrack") a.priority = 4;
901 + else if(a.name == "ipvs") a.priority = 5;
902 + else if(a.name == "ipv4") a.priority = 6;
903 + else if(a.name == "cpu") a.priority = 7;
904 + else if(a.name == "mem") a.priority = 8;
905 + else if(a.name == "disk") a.priority = 9;
906 + else a.priority = 99;
907 +
908 + a.html = "<tr><td id=\"" + a.name + "\"><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> &nbsp; <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
909 + });
910 +
911 + function categoriessort(a, b) {
912 + if(a.priority < b.priority) return -1;
913 + return 1;
914 + }
915 + categories.sort(categoriessort);
916 +
917 + // combine all the htmls into one
918 + var allcategories = "<table width=\"100%\">";
919 + mainmenu = "<ul class=\"nav navbar-nav\"><li><a href=\"#\">Home</a></li>";
920 + $.each(categories, function(i, a) {
921 + allcategories += a.html;
922 + mainmenu += "<li><a href=\"#" + a.name + "\">" + a.title + "</a></li>";
923 + });
924 + allcategories += "</table>";
925 + mainmenu += "</ul>";
926 +
927 + thumbsContainer.innerHTML = allcategories;
928 + switchToThumbGraphs();
929 + checkRefreshThread();
930 + });
931 +}
932 +
933 +// Set a callback to run when the Google Visualization API is loaded.
934 +google.setOnLoadCallback(initCharts);
935 +