]> arthur.barton.de Git - netdata.git/blob - web/index.html
cleanup and rewrote the refreshing mechanism to always use one javascript thread
[netdata.git] / web / index.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5     <meta charset="utf-8">
6     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7     <meta name="viewport" content="width=device-width, initial-scale=1">
8     <meta name="apple-mobile-web-app-capable" content="yes">
9     <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10     <meta name="description" content="">
11     <meta name="author" content="costa@tsaousis.gr">
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 -->
20         <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>
23         <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; // chart width will range from 0.5 to 1.5 of that
34         var MINIMUM_THUMB_GRAPH_WIDTH = 400; // chart will generally try to be wider than that
35         var TARGET_THUMB_GRAPH_HEIGHT = 220;
36         var MAINCHART_MAX_TIME_TO_SHOW = 1200;
37         var THUMBS_MAX_TIME_TO_SHOW = 600;
38
39         var MODE_THUMBS = 1;
40         var MODE_MAIN = 2;
41         var MODE_GROUP_THUMBS = 3;
42         var mode; // one of the MODE_* values
43
44         var mycharts = new Array();
45         var mainchart;
46
47         // html for the main menu
48         var mainmenu = "";
49
50
51         // ------------------------------------------------------------------------
52         // common HTML generation
53
54         function chartIsLoadingHTML(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 chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
55
56         function showChartIsLoading(id, width, height) { document.getElementById(id).innerHTML = chartIsLoadingHTML(width, height); }
57
58         function thumbChartActions(i, c, nogroup) {
59                 var refinfo = "the chart " + c.name + " is drawing ";
60                 if(c.group == 1) refinfo += "every single point collected.";
61                 else refinfo += ((c.group_method == "average")?"the average":"the max") + " value for every " + (c.group * c.update_every) + " seconds of data";
62
63                 var html = "<div class=\"btn-group btn-group\">"
64                 +               "<button type=\"button\" class=\"btn btn-default\" data-toggle=\"tooltip\" title=\"" + refinfo + "\" onclick=\"alert('" + refinfo + "');\"><span class=\"glyphicon glyphicon-info-sign\"></span></button>";
65
66                 if(!nogroup) {
67                         var ingroup = 0;
68                         var ingroup_detail = 0;
69
70                         $.each(mycharts, function(i, d) {
71                                 if(d.group_tag == c.group_tag) {
72                                         ingroup++;
73                                         if(d.isdetail) ingroup_detail++;
74                                 }
75                         });
76
77                         var hidden = "";
78                         if(ingroup_detail) hidden = ", including " + ingroup_detail + " charts not shown now";
79
80                         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>";
81                 }
82
83                 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>"
84                 +               "<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>"
85                 +               "<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>"
86                 +       "</div>";
87
88                 return html;
89         }
90
91         function disableChart(i) {
92                 var chart = null;
93
94                 if(group_charts) 
95                         chart = group_charts[i];
96                 else
97                         chart = mycharts[i];
98
99                 if(chart) {
100                         chart.enabled = false;
101                         if(chart.chart) chart.chart.clearChart();
102                         chart.chart = null;
103                 }
104                 var div = document.getElementById(chart.div);
105                 if(div) div.innerHTML = "";
106
107                 div = document.getElementById(chart.div + "_parent");
108                 if(div) div.innerHTML = "";
109         }
110
111         function chartssort(a, b) {
112                 if(a.userpriority < b.userpriority) return -1;
113                 return 1;
114         }
115
116
117         // ------------------------------------------------------------------------
118         // MAINGRAPH = fullscreen view of 1 graph
119
120         // copy the chart c to mainchart
121         // switch to main graphs screen
122         function initMainChart(c) {
123                 if(mainchart && mainchart.chart) {
124                         mainchart.chart.clearChart();
125                         mainchart.chart = null;
126                 }
127
128                 mainchart = $.extend(true, {}, c);
129
130                 mainchart.chart = null;
131                 mainchart.chartOptions.width = screenWidth();
132                 mainchart.chartOptions.height = $(window).height() - 150;
133                 if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
134                 
135                 mainchart.group = 2;
136                 mainchart.div = 'maingraph';
137                 mainchart.last_updated = 0;
138
139                 if(mainchart.chartOptions.isStacked) mainchart.group = 5;
140                 //mainchart.chartOptions.titlePosition = 'none';
141                 mainchart.chartOptions.explorer = null;
142
143                 // initialize the div
144                 showChartIsLoading(mainchart.div, mainchart.chartOptions.width, mainchart.chartOptions.height);
145
146                 // set the radio buttons
147                 setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
148                 setMainChartMax('normal');
149
150                 $('#group' + mainchart.group).trigger('click');
151
152                 switchToMainGraph();
153         }
154
155         function initMainChartIndex(i) {
156                 if(mode == MODE_GROUP_THUMBS) 
157                         initMainChart(group_charts[i]);
158                 else if(mode == MODE_THUMBS)
159                         initMainChart(mycharts[i]);
160         }
161
162         var last_main_chart_max='normal';
163         function setMainChartMax(m) {
164                 if(!mainchart || mode != MODE_MAIN) return;
165
166                 if(m == 'toggle') {
167                         if(last_main_chart_max == 'maximized') m = 'normal';
168                         else m = 'maximized';
169                 }
170
171                 if(m == "maximized") {
172                         mainchart.chartOptions.theme = 'maximized';
173                         //mainchart.chartOptions.axisTitlesPosition = 'in';
174                         //mainchart.chartOptions.legend = {position: 'none'};
175                         //mainchart.chartOptions.hAxis.title = null;
176                         mainchart.chartOptions.hAxis.viewWindowMode = 'maximized';
177                         mainchart.chartOptions.vAxis.viewWindowMode = 'maximized';
178                 }
179                 else {
180                         mainchart.chartOptions.theme = null;
181                         mainchart.chartOptions.hAxis.viewWindowMode = null;
182                         mainchart.chartOptions.vAxis.viewWindowMode = null;
183                 }
184                 $('.mainchart_max_button').button(m);
185                 last_main_chart_max = m;
186                 mainchart.last_updated = 0;
187         }
188
189         function setMainChartGroup(g) {
190                 if(!mainchart || mode != MODE_MAIN) return;
191
192                 mainchart.group = g;
193                 mainchart.last_updated = 0;
194                 playGraphs();
195         }
196
197         var last_main_chart_avg = null;
198         function setMainChartGroupMethod(g, norefresh) {
199                 if(!mainchart || mode != MODE_MAIN) return;
200
201                 if(g == 'toggle') {
202                         if(last_main_chart_avg == 'max') g = 'average';
203                         else g = 'max';
204                 }
205
206                 mainchart.group_method = g;
207
208                 $('.mainchart_avg_button').button(g);
209
210                 if(!norefresh) {
211                         mainchart.last_updated = 0;
212                         playGraphs();
213                 }
214
215                 last_main_chart_avg = g;
216         }
217
218         function setMainChartPlay(p) {
219                 if(!mainchart) return;
220
221                 if(p == 'toggle') {
222                         if(stop_refreshing) p = 'play';
223                         else p = 'pause';
224                 }
225
226                 if(p == 'play') {
227                         mainchart.chartOptions.explorer = null;
228                         playGraphs();
229                 }
230                 else {
231                         mainchart.chartOptions.explorer = {
232                                 'axis': 'horizontal',
233                                 'maxZoomOut': 1,
234                         };
235                         mainchart.last_updated = 0;
236                         
237                         if(!refreshChart(mainchart, pauseGraphs))
238                                 pauseGraphs();
239                 }
240                 last_main_chart_play = p;
241         }
242
243
244         // ------------------------------------------------------------------------
245         // Chart resizing
246
247         function screenWidth() {
248                 return (($(window).width() * 0.95) - 40);
249         }
250
251         // calculate the proper width for the thumb charts
252         function thumbWidth() {
253                 var cwidth = screenWidth();
254                 var items = Math.round(cwidth / TARGET_THUMB_GRAPH_WIDTH);
255                 if(items < 1) items = 1;
256
257                 if(items > 1 && (cwidth / items) < MINIMUM_THUMB_GRAPH_WIDTH) items--;
258
259                 return Math.round(cwidth / items) - 1;
260         }
261
262         function groupWidth() {
263                 var width = screenWidth() / 2;
264                 if(width < 500) width = screenWidth();
265                 return width;
266         }
267
268         // resize all charts
269         // if the thumb charts need resize in their width, reset them
270         function resizeCharts() {
271                 var width = screenWidth();
272
273                 if(mainchart) {
274                         mainchart.chartOptions.width = width;
275                         mainchart.chartOptions.height = $(window).height() - 200;
276                         mainchart.last_updated = 0;
277                 }
278
279                 width = thumbWidth();
280                 $.each(mycharts, function(i, c) {
281                         if(c.enabled && c.chartOptions.width != width) {
282                                 if(c.chart) c.chart.clearChart();
283                                 c.chart = null;
284                                 c.chartOptions.width = width;
285                                 showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
286                                 c.last_updated = 0;
287                         }
288                 });
289
290                 width = groupWidth();
291                 if(group_charts) $.each(group_charts, function(i, c) {
292                         if(c.enabled && c.chartOptions.width != width) {
293                                 if(c.chart) c.chart.clearChart();
294                                 c.chart = null;
295                                 c.chartOptions.width = width;
296                                 showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
297                                 c.last_updated = 0;
298                         }
299                 });
300
301                 playGraphs();
302         }
303
304         window.onresize = function(event) {
305                 resizeCharts();
306         };
307
308
309         // ------------------------------------------------------------------------
310         // Core of the thread refreshing the charts
311
312         var stop_refreshing = 1;
313         var last_refresh = 0;
314         function playGraphs() {
315                 if(!stop_refreshing) {
316                         // check if the thread died due to a javascript error
317                         var now = new Date().getTime();
318                         if((now - last_refresh) > 5000) {
319                                 // it died!
320                                 console.log('It seems the refresh thread died. Restarting it.');
321                                 chartsRefresh();
322                         }
323                         return;
324                 }
325
326                 stop_refreshing = 0;
327                 $('.mainchart_play_button').button('play');
328                 chartsRefresh();
329         }
330
331         function pauseGraphs() {
332                 if(stop_refreshing) return;
333
334                 stop_refreshing = 1;
335                 $('.mainchart_play_button').button('pause');
336         }
337
338         // refresh the proper chart
339         // this is an internal function.
340         // never call it directly, or new javascript threads will be spawn
341         var timeout;
342         function chartsRefresh() {
343                 if(stop_refreshing) return;
344
345                 last_refresh = new Date().getTime();
346
347                      if(mode == MODE_THUMBS)            thumbChartsRefresh();
348                 else if(mode == MODE_GROUP_THUMBS)  groupChartsRefresh();
349                 else if(mode == MODE_MAIN)              mainChartRefresh();
350                 else                                    timeout = setTimeout(triggerRefresh, 500);
351         }
352
353         // callback for refreshing the charts later
354         // this is an internal function.
355         // never call it directly, or new javascript threads will be spawn
356         function triggerRefresh() {
357                 // cleanup has to take place when the charts are not refreshed
358                 // since the refreshing thread is in this function, it means
359                 // nothing is being refreshed.
360                 cleanupCharts();
361
362                      if(mode == MODE_THUMBS)            timeout = setTimeout(chartsRefresh, 200);
363                 else if(mode == MODE_GROUP_THUMBS)      timeout = setTimeout(chartsRefresh, 200);
364                 else if(mode == MODE_MAIN)              timeout = setTimeout(chartsRefresh, 200);
365                 else                                    timeout = setTimeout(triggerRefresh, 500);
366         }
367
368         // refresh the main chart
369         // make sure we don't loose the refreshing thread
370         function mainChartRefresh() {
371                 if(mode != MODE_MAIN || !mainchart) {
372                         triggerRefresh();
373                         return;
374                 }
375
376                 mainchart.points_to_show = Math.round(mainchart.entries / mainchart.group) - 1;
377
378                 if(mainchart.points_to_show * mainchart.group > MAINCHART_MAX_TIME_TO_SHOW)
379                         mainchart.points_to_show = MAINCHART_MAX_TIME_TO_SHOW / mainchart.group;
380
381                 if(!refreshChart(mainchart, triggerRefresh))
382                         triggerRefresh();
383         }
384
385         // refresh the thumb charts
386         // make sure we don't loose the refreshing thread
387         var last_thumb_updated = 0;
388         function thumbChartsRefresh() {
389                 if(mycharts.length == 0 || mode != MODE_THUMBS) {
390                         triggerRefresh();
391                         return;
392                 }
393
394                 if(last_thumb_updated >= mycharts.length) last_thumb_updated = 0;
395
396                 // find a chart to refresh
397                 var orig = last_thumb_updated;
398                 var refreshed = false;
399
400                 last_thumb_updated++;
401                 if(last_thumb_updated >= mycharts.length) last_thumb_updated = 0;
402
403                 while(1) {
404                         refreshed = refreshChart(mycharts[last_thumb_updated], chartsRefresh);
405                         if(refreshed) break;
406
407                         last_thumb_updated++;
408                         if(last_thumb_updated >= mycharts.length) last_thumb_updated = 0;
409                         if(last_thumb_updated == orig) break;
410                 }
411
412                 // no chart refreshed
413                 if(!refreshed) triggerRefresh();
414         }
415
416         // refresh the group charts
417         // make sure we don't loose the refreshing thread
418         var last_group_updated = 0;
419         function groupChartsRefresh() {
420                 if(!group_charts || group_charts.length == 0 || mode != MODE_GROUP_THUMBS) {
421                         triggerRefresh();
422                         return;
423                 }
424
425                 if(last_group_updated >= group_charts.length) last_group_updated = 0;
426
427                 // find a chart to refresh
428                 var orig = last_group_updated;
429                 var refreshed = false;
430
431                 last_group_updated++;
432                 if(last_group_updated >= group_charts.length) last_group_updated = 0;
433
434                 while(1) {
435                         refreshed = refreshChart(group_charts[last_group_updated], chartsRefresh);
436                         if(refreshed) break;
437
438                         last_group_updated++;
439                         if(last_group_updated >= group_charts.length) last_group_updated = 0;
440                         if(last_group_updated == orig) break;
441                 }
442
443                 // no chart refreshed
444                 if(!refreshed) triggerRefresh();
445         }
446
447
448         // ------------------------------------------------------------------------
449         // switch the screen between views
450         // these should be called only from initXXXX()
451
452         // cleanup the previously shown charts
453         function cleanupCharts() {
454                 if(mode != MODE_MAIN && mainchart) {
455                         if(mainchart.chart) {
456                                 mainchart.chart.clearChart();
457                                 mainchart.chart = null;
458                         }
459                         mainchart = null;
460                 }
461
462                 if(mode != MODE_GROUP_THUMBS && group_charts) {
463                         clearGroupGraphs();
464                 }
465
466                 // we never cleanup the thumb charts
467         }
468
469         var thumbsScrollPosition = null;
470         function switchToMainGraph() {
471                 if(!mainchart) return;
472
473                 if(!group_charts) thumbsScrollPosition = window.pageYOffset;
474
475                 document.getElementById('maingraph_container').style.display = 'block';
476                 document.getElementById('thumbgraphs_container').style.display = 'none';
477                 document.getElementById('groupgraphs_container').style.display = 'none';
478
479                 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>";
480
481                 mode = MODE_MAIN;
482                 playGraphs();
483         }
484
485         function switchToThumbGraphs() {
486                 document.getElementById('maingraph_container').style.display = 'none';
487                 document.getElementById('thumbgraphs_container').style.display = 'block';
488                 document.getElementById('groupgraphs_container').style.display = 'none';
489
490                 document.getElementById("main_menu_div").innerHTML = mainmenu;
491
492                 if(thumbsScrollPosition) window.scrollTo(0, thumbsScrollPosition);
493
494                 // switch mode
495                 mode = MODE_THUMBS;
496                 playGraphs();
497         }
498
499         function switchToGroupGraphs() {
500                 if(!group_charts) return;
501
502                 if(!mainchart) thumbsScrollPosition = window.pageYOffset;
503
504                 document.getElementById('maingraph_container').style.display = 'none';
505                 document.getElementById('thumbgraphs_container').style.display = 'none';
506                 document.getElementById('groupgraphs_container').style.display = 'block';
507
508                 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>";
509
510                 window.scrollTo(0, 0);
511
512                 mode = MODE_GROUP_THUMBS;
513                 playGraphs();
514         }
515
516
517         // ------------------------------------------------------------------------
518         // Group Charts
519
520         var group_charts = null;
521         function initGroupGraphs(group) {
522                 var width = groupWidth();
523                 var height = (($(window).height() - 130) / 3) - 10;
524                 if(height < TARGET_THUMB_GRAPH_HEIGHT) height = TARGET_THUMB_GRAPH_HEIGHT;
525
526                 var count = 0;
527                 
528                 if(group_charts) clearGroupGraphs();
529                 group_charts = new Array();
530
531                 var groupbody = "";
532                 $.each(mycharts, function(i, c) {
533                         if(c.group_tag == group) {
534                                 group_charts[count] = [];
535                                 group_charts[count] = $.extend(true, {}, c);
536                                 group_charts[count].div += "_group";
537                                 group_charts[count].enabled = true;
538                                 group_charts[count].chart = null;
539                                 group_charts[count].last_updated = 0;
540
541                                 group_charts[count].chartOptions.width = width;
542                                 group_charts[count].chartOptions.height = height;
543                                 count++;
544                         }
545                 });
546                 group_charts.sort(chartssort);
547
548                 var groupbody = "";
549                 $.each(group_charts, function(i, c) {
550                         groupbody += "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
551                 });
552                 groupbody += "";
553
554                 document.getElementById("groupgraphs").innerHTML = groupbody;
555                 switchToGroupGraphs();
556         }
557
558         function clearGroupGraphs() {
559                 if(group_charts && group_charts.length) {
560                         $.each(group_charts, function(i, c) {
561                                 if(c.chart) c.chart.clearChart();
562                                 c.chart = null;
563                         });
564
565                         group_charts = null;
566                 }
567
568                 document.getElementById("groupgraphs").innerHTML = "";
569         }
570
571
572         // ------------------------------------------------------------------------
573         // Global entry point
574         // initialize the thumb charts
575
576         // load the charts from the server
577         // generate html for the thumbgraphs to support them
578         function initCharts() {
579                 var width = thumbWidth();
580                 var height = TARGET_THUMB_GRAPH_HEIGHT;
581
582                 loadCharts(null, function(c) {
583                         mycharts = c;
584
585                         if(mycharts == null || mycharts.length == 0) {
586                                 alert("Cannot load data from server.");
587                                 return;
588                         }
589
590                         var thumbsContainer = document.getElementById("thumbgraphs");
591                         if(!thumbsContainer) {
592                                 alert("Cannot find the thumbsContainer");
593                                 return;
594                         }
595
596                         mycharts.sort(chartssort);
597
598                         document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
599                         document.title = mycharts[0].hostname;
600
601                         // create an array for grouping all same-type graphs together
602                         var categories = new Array();
603                         $.each(mycharts, function(i, c) {
604                                 c.chartOptions.width = width;
605                                 c.chartOptions.height = height;
606
607                                 // calculate how many point to show for each chart
608                                 c.points_to_show = Math.round(c.entries / c.group) - 1;
609
610                                 // show max 10 mins of data
611                                 if(c.points_to_show * c.group > THUMBS_MAX_TIME_TO_SHOW) c.points_to_show = THUMBS_MAX_TIME_TO_SHOW / c.group;
612
613                                 if(c.enabled) {
614                                         var j;
615                                         var h = "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
616                                         + thumbChartActions(i, c)
617                                         +       "</td></tr></table></div>";
618
619                                         // find the categories object for this type
620                                         for(j = 0; j < categories.length ;j++) {
621                                                 if(categories[j].name == c.type) {
622                                                         categories[j].html += h;
623                                                         categories[j].count++;
624                                                         break;
625                                                 }
626                                         }
627
628                                         if(j == categories.length) {
629                                                 categories.push({name: c.type, title: c.category, description: '', priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
630                                         }
631                                 }
632                         });
633
634                         $.each(categories, function(i, a) {
635                                      if(a.name == "system") a.priority = 1;
636                                 else if(a.name == "net") a.priority = 2;
637                                 else if(a.name == "tc") a.priority = 3;
638                                 else if(a.name == "conntrack") a.priority = 4;
639                                 else if(a.name == "ipvs") a.priority = 5;
640                                 else if(a.name == "ipv4") a.priority = 6;
641                                 else if(a.name == "cpu") a.priority = 7;
642                                 else if(a.name == "mem") a.priority = 8;
643                                 else if(a.name == "disk") a.priority = 9;
644                                 else a.priority = 99;
645
646                                 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>";
647                         });
648
649                         function categoriessort(a, b) {
650                                 if(a.priority < b.priority) return -1;
651                                 return 1;
652                         }
653                         categories.sort(categoriessort);
654                         
655                         // combine all the htmls into one
656                         var allcategories = "<table width=\"100%\">";
657                         mainmenu = "<ul class=\"nav navbar-nav\"><li class=\"active\"><a href=\"#\">Home</a></li>";
658                         $.each(categories, function(i, a) {
659                                 allcategories += a.html;
660                                 mainmenu += "<li><a href=\"#" + a.name + "\">" + a.title + "</a></li>";
661                         });
662                         allcategories += "</table>";
663                         mainmenu += "</ul>";
664
665                         thumbsContainer.innerHTML = allcategories;
666                         switchToThumbGraphs();
667                 });
668         }
669
670         </script>
671 </head>
672
673 <body role="document">
674     <nav id="mynav" class="navbar navbar-inverse navbar-fixed-top" role="navigation">
675       <div class="container">
676         <div class="navbar-header">
677           <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
678             <span class="sr-only">Toggle navigation</span>
679             <span class="icon-bar"></span>
680             <span class="icon-bar"></span>
681             <span class="icon-bar"></span>
682           </button>
683           <a class="navbar-brand" href="javascript:switchToThumbGraphs();" id="hostname_id">NetData</a>
684         </div>
685         <div class="collapse navbar-collapse" id="main_menu_div">
686           <ul class="nav navbar-nav">
687             <li class="active"><a href="#">Home</a></li>
688             <li><a href="#system">System</a></li>
689             <li><a href="#net">Network</a></li>
690             <li><a href="#tc">QoS</a></li>
691             <li><a href="#conntrack">Netfilter</a></li>
692             <li><a href="#ipv4">IPv4</a></li>
693             <li><a href="#ipvs">IPVS</a></li>
694             <li><a href="#cpu">CPU</a></li>
695             <li><a href="#disk">Disk</a></li>
696           </ul>
697         </div><!--/.nav-collapse -->
698       </div>
699     </nav>
700
701     <div class="container graphs" id="maingraph_container" style="display: none">
702                 <table>
703                         <tr><td>
704                         <div class="maingraph">
705                                         <table>
706                                                 <tr><td>
707                                                 <div class="maingraph" id="maingraph"></div>
708                                                 </td></tr>
709                                                 <tr><td align="center">
710                                                         <div class="btn-group">
711                                                                 <form id="mainchartform">
712                                                                         <div class="btn-group btn-group" data-toggle="tooltip" title=" click <span class='glyphicon glyphicon-play'></span> to have the graph auto-refresh, or click <span class='glyphicon glyphicon-pause'></span> to pause the graph. When paused the graph can be zoomed and panned horizontally." >
713                                                                                 <button type="button" class="btn btn-primary mainchart_play_button" data-play-text="<span class='glyphicon glyphicon-pause'></span>" data-pause-text="<span class='glyphicon glyphicon-play'></span>" onClick="setMainChartPlay('toggle');">
714                                                                                         <span class="glyphicon glyphicon-pause"></span>
715                                                                                 </button>
716                                                                         </div>
717                                                                         <div class="btn-group btn-group" data-toggle="tooltip" title="use the maximum ( <span class='glyphicon glyphicon-signal'></span> ) or the average ( <span class='glyphicon glyphicon-align-justify'></span> ) value of grouped points" >
718                                                                                 <button type="button" class="btn btn-primary mainchart_avg_button" data-max-text="<span class='glyphicon glyphicon-signal'></span>" data-average-text="<span class='glyphicon glyphicon-align-justify'></span>" onClick="setMainChartGroupMethod('toggle');">
719                                                                                         <span class="glyphicon glyphicon-signal"></span>
720                                                                                 </button>
721                                                                         </div>
722 <!--                                                                    <div class="btn-group btn-group" data-toggle="buttons">
723                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="show the MAX point among all points grouped">
724                                                                                         <input type="radio" name="groupmethod" id="groupmax" onChange="setMainChartGroupMethod('max');">
725                                                                                         <span class="glyphicon glyphicon-signal"></span>
726                                                                                 </label>
727                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="show the AVERAGE of all points grouped">
728                                                                                         <input type="radio" name="groupmethod" id="groupaverage" onChange="setMainChartGroupMethod('average');">
729                                                                                         <span class="glyphicon glyphicon-align-justify"></span>
730                                                                                 </label>
731                                                                         </div>
732 -->                                                                     <div class="btn-group btn-group" data-toggle="buttons" >
733                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="do not group points, show the raw data">
734                                                                                         <input type="radio" name="group" id="group1" onChange="setMainChartGroup(1);">1
735                                                                                 </label>
736                                                                                 
737                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group in half, show 1 every 2 points of data">
738                                                                                         <input type="radio" name="group" id="group2" onChange="setMainChartGroup(2);">2
739                                                                                 </label>
740
741                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 5 points of data">
742                                                                                         <input type="radio" name="group" id="group5" onChange="setMainChartGroup(5);">5
743                                                                                 </label>
744                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 10 points of data">
745                                                                                         <input type="radio" name="group" id="group10" onChange="setMainChartGroup(10);">10
746                                                                                 </label>
747                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 15 points of data">
748                                                                                         <input type="radio" name="group" id="group15" onChange="setMainChartGroup(15);">15
749                                                                                 </label>
750                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 20 points of data">
751                                                                                         <input type="radio" name="group" id="group20" onChange="setMainChartGroup(20);">20
752                                                                                 </label>
753                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 30 points of data">
754                                                                                         <input type="radio" name="group" id="group30" onChange="setMainChartGroup(30);">30
755                                                                                 </label>
756                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 45 points of data">
757                                                                                         <input type="radio" name="group" id="group45" onChange="setMainChartGroup(45);">45
758                                                                                 </label>
759                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="group every 60 points of data">
760                                                                                         <input type="radio" name="group" id="group60" onChange="setMainChartGroup(60);">60
761                                                                                 </label>
762                                                                         </div>
763                                                                         <div class="btn-group btn-group" data-toggle="tooltip" title="maximized ( <span class='glyphicon glyphicon-fullscreen'></span> ) or normal ( <span class='glyphicon glyphicon-resize-small'></span> ) view of the graph" >
764                                                                                 <button type="button" class="btn btn-primary mainchart_max_button" data-maximized-text="<span class='glyphicon glyphicon-resize-small'></span>" data-normal-text="<span class='glyphicon glyphicon-fullscreen'></span>" onClick="setMainChartMax('toggle');">
765                                                                                         <span class="glyphicon glyphicon-fullscreen"></span>
766                                                                                 </button>
767                                                                         </div>
768 <!--                                                                    <div class="btn-group btn-group" data-toggle="buttons" >
769                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="NORMAL chart size">
770                                                                                         <input type="radio" name="chartmax" id="chartnormal" onChange="setMainChartMax('normal');">
771                                                                                         <span class="glyphicon glyphicon-resize-small"></span>
772                                                                                 </label>
773                                                                                 <label class="btn btn-primary" data-toggle="tooltip" title="MAXIMIZED chart size">
774                                                                                         <input type="radio" name="chartmax" id="chartmax" onChange="setMainChartMax('maximized');">
775                                                                                         <span class="glyphicon glyphicon-fullscreen"></span>
776                                                                                 </label>
777                                                                         </div>
778 -->                                                             </form>
779                                                         </div>
780                                                         </td></tr>
781                                         </table>
782                            </div><!-- /.maingraph -->
783                         </td></tr>
784                 </table>
785         </div>
786
787     <div class="container graphs" id="thumbgraphs_container">
788         <div class="allgraphs" id="thumbgraphs">
789                 <table width="100%">
790                         <tr><td id="splash" align="center" style="vertical-align:middle">
791                                 <h1>
792                                 Welcome to <b>NetData</b>!
793                                 <br/><br/>
794                                 <span class="glyphicon glyphicon-off"></span>
795                                 <br/><br/>
796                                 loading charts
797                                 <br/><br/>
798                                 <span class="label label-default">Please wait...</span>
799                                 </h1>
800                         </td></tr>
801                 </table>
802         </div>
803         </div>
804
805     <div class="container graphs" id="groupgraphs_container">
806         <div class="allgraphs" id="groupgraphs">
807                 <table width="100%">
808                         <tr><td id="splash" align="center" style="vertical-align:middle">
809                                 <span class="glyphicon glyphicon-off"></span>
810                                 <br/><br/>
811                                 loading charts
812                                 <br/><br/>
813                                 <span class="label label-default">Please wait...</span>
814                                 </h1>
815                         </td></tr>
816                 </table>
817         </div>
818         </div>
819
820         <script type='text/javascript'>
821                 $(document).ready(function(){
822                         document.getElementById('splash').height = $(window).height();
823
824                         $('[data-toggle="tooltip"]').tooltip({'placement': 'top', 'container': 'body', 'html': true});
825                 });
826
827         </script>
828 </html>