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> " + 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> <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> " + 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> <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
+