]> arthur.barton.de Git - netdata.git/blob - web/index.html
9e32bfe63a159d501d9d1063ab5c98b026a3309d
[netdata.git] / web / index.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4     <title>netdata dashboard</title>
5     <meta name="application-name" content="netdata">
6
7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8     <meta charset="utf-8">
9     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10     <meta name="viewport" content="width=device-width, initial-scale=1">
11     <meta name="apple-mobile-web-app-capable" content="yes">
12     <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
13     <meta name="author" content="costa@tsaousis.gr">
14
15     <link rel="shortcut icon" href="images/seo-performance-multi-size.ico">
16
17     <link rel="apple-touch-icon" href="images/seo-performance-72.png">
18     <link rel="apple-touch-icon" sizes="72x72" href="images/seo-performance-72.png">
19     <link rel="apple-touch-icon" sizes="114x114" href="images/seo-performance-114.png">
20
21     <link rel="icon" type="image/png" sizes="512x512" href="images/seo-performance-512.png">
22     <link rel="icon" type="image/png" sizes="256x256" href="images/seo-performance-256.png">
23     <link rel="icon" type="image/png" sizes="128x128" href="images/seo-performance-128.png">
24     <link rel="icon" type="image/png" sizes="64x64" href="images/seo-performance-64.png">
25     <link rel="icon" type="image/png" sizes="48x48" href="images/seo-performance-48.png">
26     <link rel="icon" type="image/png" sizes="32x32" href="images/seo-performance-32.png">
27     <link rel="icon" type="image/png" sizes="24x24" href="images/seo-performance-24.png">
28     <link rel="icon" type="image/png" sizes="16x16" href="images/seo-performance-16.png">
29
30     <meta property="og:locale" content="en_US" />
31     <meta property="og:image" content="http://my-netdata.io/images/post.png"/>
32     <meta property="og:url" content="http://my-netdata.io/"/>
33     <meta property="og:type" content="website"/>
34     <meta property="og:site_name" content="netdata"/>
35     <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/>
36     <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." />
37
38     <style>
39     /* prevent body from hiding under the navbar */
40     body {
41         padding-top: 50px;
42     }
43
44     .loadOverlay {
45         position: absolute;
46         top: 0px;
47         left: 0px;
48         width: 100%;
49         height:100%;
50         z-index: 2000;
51         font-size: 10vh;
52         font-family: sans-serif;
53         padding: 40vh 0 40vh 0;
54         font-weight: bold;
55         text-align: center;
56     }
57
58     .modal-wide .modal-dialog {
59         width: 80%;
60     }
61
62     /* fix # anchors scrolling under the navbar
63        https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033
64      */
65     h1 {
66         position: relative;
67         z-index: -1;
68     }
69     h2 {
70         position: relative;
71         z-index: -2;
72     }
73     h1:before, h2:before {
74         display: block;
75         content: " ";
76         margin-top: -70px;
77         height: 70px;
78         visibility: hidden;
79     }
80
81     .p {
82         display: block;
83         margin-top: 15px;
84     }
85
86     .option-row,
87     .option-control {
88         vertical-align: top;
89         padding: 10px;
90         padding-top: 30px;
91         padding-left: 30px;
92     }
93
94     .option-info {
95         padding: 10px;
96     }
97
98     .chart-message {
99         display: block;
100         margin-top: 10px;
101     }
102
103     #masthead h1 {
104         /*font-size: 30px;*/
105         line-height: 1;
106         padding-top: 30px;
107     }
108
109     #masthead .well {
110         margin-top:4%;
111     }
112
113     /* fix the navbar shifting when a modal is open */
114     /* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */
115     body.modal-open{
116         width: 100% !important;
117         padding-right: 0 !important;
118 /*      overflow-y: scroll !important; */
119 /*      position: fixed !important;*/
120         overflow: visible;
121     }
122
123     /* make accordion use the whole header bar for expand/collapse */
124     .panel-title a {
125         display: block;
126         padding: 10px 15px;
127         margin: -10px -15px;
128     }
129
130     /*
131      * Side navigation
132      *
133      * Scrollspy and affixed enhanced navigation to highlight sections and secondary
134      * sections of docs content.
135      */
136
137     .affix {
138         position: static;
139         top: 70px !important;
140         /*width: 220px;*/
141     }
142
143     .affix-top {
144         /*width: 220px;*/
145     }
146
147     .dashboard-sidebar {
148         max-height: calc(100% - 70px) !important;
149         overflow-y: auto;
150         /*width: 220px !important;*/
151     }
152
153     /* By default it's not affixed in mobile views, so undo that */
154     .dashboard-sidebar.affix {
155         position: static;
156     }
157
158     @media (min-width: 768px) {
159         .dashboard-sidebar {
160             padding-left: 20px;
161         }
162     }
163
164     /* First level of nav */
165     .dashboard-sidenav {
166         margin-top: 20px;
167         margin-bottom: 20px;
168     }
169
170     /* All levels of nav */
171     .dashboard-sidebar .nav > li > a {
172         display: block;
173         padding: 4px 20px;
174         font-size: 13px;
175         font-weight: 500;
176         color: #767676;
177     }
178     .dashboard-sidebar .nav > li > a:hover,
179     .dashboard-sidebar .nav > li > a:focus {
180         padding-left: 19px;
181         color: #563d7c;
182         text-decoration: none;
183         background-color: transparent;
184         border-left: 1px solid #563d7c;
185     }
186     .dashboard-sidebar .nav > .active > a,
187     .dashboard-sidebar .nav > .active:hover > a,
188     .dashboard-sidebar .nav > .active:focus > a {
189         padding-left: 18px;
190         font-weight: bold;
191         color: #563d7c;
192         background-color: transparent;
193         border-left: 2px solid #563d7c;
194     }
195
196     /* Nav: second level (shown on .active) */
197     .dashboard-sidebar .nav .nav {
198         display: none; /* Hide by default, but at >768px, show it */
199         padding-bottom: 10px;
200     }
201     .dashboard-sidebar .nav .nav > li > a {
202         padding-top: 1px;
203         padding-bottom: 1px;
204         padding-left: 30px;
205         font-size: 12px;
206         font-weight: normal;
207     }
208     .dashboard-sidebar .nav .nav > li > a:hover,
209     .dashboard-sidebar .nav .nav > li > a:focus {
210         padding-left: 29px;
211     }
212     .dashboard-sidebar .nav .nav > .active > a,
213     .dashboard-sidebar .nav .nav > .active:hover > a,
214     .dashboard-sidebar .nav .nav > .active:focus > a {
215         padding-left: 28px;
216         font-weight: 500;
217     }
218
219     .dropdown-menu {
220         min-width: 200px;
221     }
222     .dropdown-menu.columns-2 {
223         margin: 0;
224         padding: 0;
225         width: 400px;
226     }
227     .dropdown-menu li a {
228         padding: 5px 15px;
229         font-weight: 300;
230     }
231     .dropdown-menu.multi-column {
232         overflow-x: hidden;
233     }
234     .multi-column-dropdown {
235         list-style: none;
236         padding: 0;
237     }
238     .multi-column-dropdown li a {
239         display: block;
240         clear: both;
241         line-height: 1.428571429;
242         white-space: normal;
243     }
244     .multi-column-dropdown li a:hover {
245         text-decoration: none;
246         color: #f5f5f5;
247         background-color: #262626;
248     }
249     .scrollable-menu {
250         height: auto;
251         max-height: 80vh;
252         overflow-x: hidden;
253     }
254
255     /* Back to top (hidden on mobile) */
256     .back-to-top,
257     .dashboard-theme-toggle {
258         display: none;
259         padding: 4px 10px;
260         margin-top: 10px;
261         margin-left: 10px;
262         font-size: 12px;
263         font-weight: 500;
264         color: #999;
265     }
266     .back-to-top:hover,
267     .dashboard-theme-toggle:hover {
268         color: #563d7c;
269         text-decoration: none;
270     }
271     .dashboard-theme-toggle {
272         margin-top: 0;
273     }
274
275     .container {
276         width: calc(100% - 20px) !important;
277     }
278
279     .charts-body {
280         display: inline-block;
281         width: 100%;
282     }
283
284     .sidebar-body {
285         position: absolute;
286         display: none;
287     }
288
289     @media (min-width: 768px) {
290         .charts-body {
291             padding-left: 0%;
292             padding-right: 0%;
293         }
294
295         .back-to-top,
296         .dashboard-theme-toggle {
297             display: block;
298         }
299     }
300
301     /* Show and affix the side nav when space allows it */
302     @media (min-width: 992px) {
303         .container {
304             padding-left: 0% !important;
305         }
306
307         .charts-body {
308             width: calc(100% - 213px) !important;
309             padding-left: 1% !important;
310             padding-right: 0% !important;
311         }
312
313         .sidebar-body {
314             display: inline-block !important;
315             width: 213px !important;
316         }
317
318         .dashboard-sidebar .nav > .active > ul {
319             display: block;
320         }
321
322         /* Widen the fixed sidebar */
323         .dashboard-sidebar.affix,
324         .dashboard-sidebar.affix-top,
325         .dashboard-sidebar.affix-bottom {
326             width: 213px !important;
327         }
328         .dashboard-sidebar.affix {
329             position: fixed; /* Undo the static from mobile first approach */
330             top: 20px;
331         }
332         .dashboard-sidebar.affix-bottom {
333             position: absolute; /* Undo the static from mobile first approach */
334         }
335         .dashboard-sidebar.affix-bottom .dashboard-sidenav,
336         .dashboard-sidebar.affix .dashboard-sidenav {
337             margin-top: 0;
338             margin-bottom: 0;
339         }
340     }
341
342     @media (min-width: 1200px) {
343         .container {
344             padding-left: 2% !important;
345         }
346
347         .charts-body {
348             width: calc(100% - 233px) !important;
349             padding-left: 1% !important;
350             padding-right: 1% !important;
351         }
352
353         .sidebar-body {
354             display: inline-block !important;
355             width: 233px !important;
356         }
357
358         /* Widen the fixed sidebar again */
359         .dashboard-sidebar.affix,
360         .dashboard-sidebar.affix-top,
361         .dashboard-sidebar.affix-bottom {
362             width: 233px !important;
363         }
364     }
365     
366     @media (min-width: 1360px) {
367         .container {
368             padding-left: 3% !important;
369         }
370
371         .charts-body {
372             width: calc(100% - 263px) !important;
373             padding-left: 1% !important;
374             padding-right: 2% !important;
375         }
376
377         .sidebar-body {
378             display: inline-block !important;
379             width: 263px !important;
380         }
381
382         /* Widen the fixed sidebar again */
383         .dashboard-sidebar.affix,
384         .dashboard-sidebar.affix-top,
385         .dashboard-sidebar.affix-bottom {
386             width: 263px !important;
387         }
388     }
389
390     </style>
391 </head>
392
393 <!-- check which theme to use -->
394 <script type="text/javascript">
395     // enable alarms checking and notifications
396     var netdataShowAlarms = true;
397
398     // enable registry updates
399     var netdataRegistry = true;
400     
401     // --------------------------------------------------------------------
402     // urlOptions
403
404     var urlOptions = {
405         hash: '#',
406         theme: null,
407         help: null,
408         pan_and_zoom: false,
409         after: 0,
410         before: 0,
411         nowelcome: false,
412         show_alarms: false,
413         chart: null,
414         family: null,
415         alarm: null,
416         alarm_unique_id: 0,
417         alarm_id: 0,
418         alarm_event_id: 0,
419         hasProperty: function(property) {
420             // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
421             return typeof this[property] !== 'undefined';
422         }
423     };
424
425     function netdataPanAndZoomCallback(status, after, before) {
426         urlOptions.pan_and_zoom = status;
427         urlOptions.after = after;
428         urlOptions.before = before;
429         netdataHashUpdate();
430     }
431
432     function netdataHashUpdate() {
433         history.replaceState(null, '', netdataHash());
434     }
435
436     function netdataHash() {
437         var hash = urlOptions.hash;
438
439         if(urlOptions.pan_and_zoom === true) {
440             hash += ';after='  + urlOptions.after.toString() +
441                     ';before=' + urlOptions.before.toString();
442         }
443
444         if(urlOptions.theme !== null)
445             hash += ';theme=' + urlOptions.theme.toString();
446
447         if(urlOptions.help !== null)
448             hash += ';help=' + urlOptions.help.toString();
449
450         return hash;
451     }
452
453     function netdataHashParse() {
454         var variables = document.location.hash.split(';');
455         var len = variables.length;
456         while(len--) {
457             if(len !== 0) {
458                 var p = variables[len].split('=');
459                 if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined')
460                     urlOptions[p[0]] = decodeURIComponent(p[1]);
461             }
462             else {
463                 if(variables[len].length > 0)
464                     urlOptions.hash = variables[len];
465             }
466         }
467
468         var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom' ];
469         len = booleans.length;
470         while(len--) {
471             if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1)
472                 urlOptions[booleans[len]] = true;
473             else
474                 urlOptions[booleans[len]] = false;
475         }
476
477         if(urlOptions.before > 0 && urlOptions.after > 0) {
478             urlOptions.pan_and_zoom = true;
479             urlOptions.nowelcome = true;
480         }
481         else
482             urlOptions.pan_and_zoom = false;
483
484         // console.log(urlOptions);
485     }
486
487     netdataHashParse();
488
489     // --------------------------------------------------------------------
490     // check options that should be processed before loading netdata.js
491     
492     function loadLocalStorage(name) {
493         var ret = null;
494
495         try {
496             if(typeof Storage !== "undefined" && typeof localStorage === 'object')
497                 ret = localStorage.getItem(name);
498         }
499         catch(error) {
500             ;
501         }
502
503         if(typeof ret === 'undefined' || ret === null)
504             return null;
505
506         // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
507
508         return ret;
509     }
510
511     function saveLocalStorage(name, value) {
512         // console.log('saving: ' + name.toString() + ' = ' + value.toString());
513         try {
514             if(typeof Storage !== "undefined" && typeof localStorage === 'object') {
515                 localStorage.setItem(name, value.toString());
516                 return true;
517             }
518         }
519         catch(error) {
520             ;
521         }
522
523         return false;
524     }
525
526     function getTheme(def) {
527         var ret = loadLocalStorage('netdataTheme');
528         if(typeof ret === 'undefined' || ret === null || ret === 'undefined')
529             return def;
530         else
531             return ret;
532     }
533
534     function setTheme(theme) {
535         if(theme === netdataTheme) return false;
536         return saveLocalStorage('netdataTheme', theme);
537     }
538
539     var netdataTheme = getTheme('slate');
540     var netdataShowHelp = true;
541
542     if(urlOptions.theme !== null) {
543         setTheme(urlOptions.theme);
544         netdataTheme = urlOptions.theme;
545     }
546     else
547         urlOptions.theme = netdataTheme;
548
549     if(urlOptions.help !== null) {
550         saveLocalStorage('options.show_help', urlOptions.help);
551         netdataShowHelp = urlOptions.help;
552     }
553     else {
554         urlOptions.help = loadLocalStorage('options.show_help');
555     }
556
557     // --------------------------------------------------------------------
558     // registry call back to render my-netdata menu
559
560     var netdataRegistryCallback = function(machines_array) {
561         var el = '';
562         var a1 = '';
563         var found = 0;
564
565         if(machines_array === null) {
566             var ret = loadLocalStorage("registryCallback");
567             if(typeof ret !== 'undefined' && ret !== null) {
568                 machines_array = JSON.parse(ret);
569                 console.log("failed to contact the registry - loaded registry data from browser local storage");
570             }
571         }
572
573         if(machines_array) {
574             saveLocalStorage("registryCallback", JSON.stringify(machines_array));
575
576             var machines = machines_array.sort(function (a, b) {
577                 if (a.name > b.name) return -1;
578                 if (a.name < b.name) return 1;
579                 return 0;
580             });
581
582             var len = machines.length;
583             while(len--) {
584                 var u = machines[len];
585                 found++;
586                 el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
587                 a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fa fa-trash-o" aria-hidden="true" style="color: #999;"></i></a></li>';
588             }
589         }
590
591         if(!found) {
592             if(machines)
593                 el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
594             else
595                 el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
596
597             a1 += '<li><a href="#" onClick="return false;">&nbsp;</a></li>';
598
599             el += '<li role="separator" class="divider"></li>' +
600                     '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
601                     '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
602                     '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
603                     '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
604                     '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
605                     '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
606                     '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
607                     '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
608             a1 += '<li role="separator" class="divider"></li>' +
609                     '<li><a href="#">&nbsp;</a></li>' +
610                     '<li><a href="#">&nbsp;</a></li>'+
611                     '<li><a href="#">&nbsp;</a></li>'+
612                     '<li><a href="#">&nbsp;</a></li>'+
613                     '<li><a href="#">&nbsp;</a></li>'+
614                     '<li><a href="#">&nbsp;</a></li>'+
615                     '<li><a href="#">&nbsp;</a></li>'+
616                     '<li><a href="#">&nbsp;</a></li>';
617         }
618
619         el += '<li role="separator" class="divider"></li>';
620         a1 += '<li role="separator" class="divider"></li>';
621
622         el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
623         a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
624
625         document.getElementById('mynetdata_servers').innerHTML = el;
626         document.getElementById('mynetdata_servers2').innerHTML = el;
627         document.getElementById('mynetdata_actions1').innerHTML = a1;
628
629         gotoServerInit();
630     };
631
632     var this_is_demo = null;
633     function isdemo() {
634         if(this_is_demo !== null) return this_is_demo;
635         this_is_demo = false;
636
637         try {
638             if(typeof document.location.hostname === 'string') {
639                 if(document.location.hostname.endsWith('.my-netdata.io') ||
640                         document.location.hostname.endsWith('.mynetdata.io') ||
641                         document.location.hostname.endsWith('.netdata.rocks') ||
642                         document.location.hostname.endsWith('.firehol.org') ||
643                         document.location.hostname.endsWith('.netdata.online'))
644                         this_is_demo = true;
645             }
646         }
647         catch(error) {
648             ;
649         }
650
651         return this_is_demo;
652     }
653
654     function netdataURL(url) {
655         if(typeof url === 'undefined')
656             url = document.location.toString();
657
658         if(url.indexOf('#') !== -1)
659             url = url.substring(0, url.indexOf('#'));
660
661         var hash = netdataHash();
662
663         // console.log('netdataURL: ' + url + hash);
664
665         return url + hash;
666     }
667
668     function netdataReload(url) {
669         var t = netdataURL(url);
670         // console.log('netdataReload: ' + t);
671         document.location = t;
672
673         // since we play with hash
674         // this is needed to reload the page
675         location.reload();
676     }
677
678     var gotoServerValidateRemaining = 0;
679     var gotoServerMiddleClick = false;
680     var gotoServerStop = false;
681     function gotoServerValidateUrl(id, guid, url) {
682         var penaldy = 0;
683         var error = 'failed';
684
685         if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
686                 // we penalize https only if the current url is http
687                 // to allow the user walk through all its servers.
688                 penaldy = 500;
689
690         else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://'))
691             error = 'can\'t check';
692         
693         var finalURL = netdataURL(url);
694
695         setTimeout(function() {
696             document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + finalURL + '" target="_blank">' + url + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
697
698             NETDATA.registry.hello(url, function(data) {
699                 if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
700                     // console.log('OK ' + id + ' URL: ' + url);
701                     document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
702
703                     if(!gotoServerStop) {
704                         gotoServerStop = true;
705
706                         if(gotoServerMiddleClick) {
707                             window.open(finalURL, '_blank');
708                             gotoServerMiddleClick = false;
709                             document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + finalURL + '">' + url + '</a></b><br/>(check your pop-up blocker if it fails)';
710                         }
711                         else
712                             document.location = finalURL;
713                     }
714                 }
715                 else {
716                     if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
717                         error = 'wrong machine';
718
719                     document.getElementById(guid + '-' + id + '-status').innerHTML = error;
720                     gotoServerValidateRemaining--;
721                     if(gotoServerValidateRemaining <= 0) {
722                         gotoServerMiddleClick = false;
723                         document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
724                     }
725                 }
726             });
727         }, (id * 50) + penaldy);
728     }
729
730     function gotoServerModalHandler(guid) {
731         // console.log('goto server: ' + guid);
732
733         gotoServerStop = false;
734         var checked = {};
735         var len = NETDATA.registry.machines[guid].alternate_urls.length;
736         var count = 0;
737
738         document.getElementById('gotoServerResponse').innerHTML = '';
739         document.getElementById('gotoServerList').innerHTML = '';
740         document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
741         $('#gotoServerModal').modal('show');
742
743         gotoServerValidateRemaining = len;
744         while(len--) {
745             var url = NETDATA.registry.machines[guid].alternate_urls[len];
746             checked[url] = true;
747             gotoServerValidateUrl(count++, guid, url);
748         }
749
750         setTimeout(function() {
751             if(gotoServerStop === false) {
752                 document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
753                 NETDATA.registry.search(guid, function(data) {
754                     console.log(data);
755                     len = data.urls.length;
756                     while(len--) {
757                         var url = data.urls[len][1];
758                         console.log(url);
759                         if(typeof checked[url] === 'undefined') {
760                             gotoServerValidateRemaining++;
761                             checked[url] = true;
762                             gotoServerValidateUrl(count++, guid, url);
763                         }
764                     }
765                 });
766             }
767         }, 2000);
768         return false;
769     }
770
771     function gotoServerInit() {
772         $(".registry_link").on('click', function(e) {
773             if(e.which === 2) {
774                 e.preventDefault();
775                 gotoServerMiddleClick = true;
776             }
777             else {
778                 gotoServerMiddleClick = false;
779             }
780
781             return true;
782         });
783     }
784
785     function switchRegistryModalHandler() {
786         document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
787         document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
788         document.getElementById('switchRegistryResponse').innerHTML = '';
789         $('#switchRegistryModal').modal('show');
790     }
791
792     function notifyForSwitchRegistry() {
793         var n = document.getElementById('switchRegistryPersonGUID').value;
794
795         if(n !== '' && n.length === 36) {
796             NETDATA.registry.switch(n, function(result) {
797                 if(result !== null) {
798                     $('#switchRegistryModal').modal('hide');
799                     NETDATA.registry.init();
800                 }
801                 else {
802                     document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
803                 }
804             });
805         }
806         else
807             document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
808     }
809
810     var deleteRegistryUrl = null;
811     function deleteRegistryModalHandler(guid, name, url) {
812         deleteRegistryUrl = url;
813         document.getElementById('deleteRegistryServerName').innerHTML = name;
814         document.getElementById('deleteRegistryServerName2').innerHTML = name;
815         document.getElementById('deleteRegistryServerURL').innerHTML = url;
816         document.getElementById('deleteRegistryResponse').innerHTML = '';
817         $('#deleteRegistryModal').modal('show');
818     }
819
820     function notifyForDeleteRegistry() {
821         if(deleteRegistryUrl) {
822             NETDATA.registry.delete(deleteRegistryUrl, function(result) {
823                 if(result !== null) {
824                     deleteRegistryUrl = null;
825                     $('#deleteRegistryModal').modal('hide');
826                     NETDATA.registry.init();
827                 }
828                 else {
829                     document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
830                 }
831             });
832         }
833     }
834
835     var options = {
836         sparklines_registry: {},
837         menus: {},
838         submenu_names: {},
839         data: null,
840         hostname: 'netdata_server', // will be overwritten by the netdata server
841         categories: new Array(),
842         categories_idx: {},
843         families: new Array(),
844         families_idx: {},
845
846         chartsPerRow: 0,
847         chartsMinWidth: 1450,
848         chartsHeight: 180,
849         sparklinesHeight: 60,
850     };
851
852     // generate a sparkline
853     // used in the documentation
854     function sparkline(chart, dimension, units) {
855         var key = chart + '.' + dimension;
856
857         if(typeof units === 'undefined')
858             units = '';
859
860         if(typeof options.sparklines_registry[key] === 'undefined')
861             options.sparklines_registry[key] = { count: 1 };
862         else
863             options.sparklines_registry[key].count++;
864
865         key = key + '.' + options.sparklines_registry[key].count;
866
867         var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')';
868
869         return h;
870     }
871
872     function chartsPerRow(total) {
873         if(options.chartsPerRow === 0) {
874             width = Math.floor(total / options.chartsMinWidth);
875             if(width === 0) width = 1;
876             return width;
877         }
878         else return options.chartsPerRow;
879     }
880
881     function prioritySort(a, b) {
882         if(a.priority < b.priority) return -1;
883         if(a.priority > b.priority) return 1;
884         if(a.name < b.name) return -1;
885         return 1;
886     }
887
888     function sortObjectByPriority(object) {
889         var idx = {};
890         var sorted = new Array();
891
892         for(var i in object) {
893             if(typeof idx[i] === 'undefined') {
894                 idx[i] = object[i];
895                 sorted.push(i);
896             }
897         }
898
899         sorted.sort(function(a, b) {
900             if(idx[a].priority < idx[b].priority) return -1;
901             if(idx[a].priority > idx[b].priority) return 1;
902             if(a < b) return -1;
903             return 1;
904         });
905
906         return sorted;
907     }
908
909
910     // ----------------------------------------------------------------------------
911     // scroll to a section, without changing the browser history
912
913     function scrollToId(hash) {
914         if(hash && hash != '') {
915             var offset = $('#' + hash).offset();
916             if(typeof offset !== 'undefined')
917                 $('html, body').animate({ scrollTop: offset.top }, 0);
918         }
919
920         // we must return false to prevent the default action
921         return false;
922     }
923
924     // ----------------------------------------------------------------------------
925
926     var netdataDashboard = {
927         menu: {},
928         submenu: {},
929         context: {},
930
931         gaugeChart: function(title, width, dimensions, colors) {
932             if(typeof colors === 'undefined')
933                 colors = '';
934
935             if(typeof dimensions === 'undefined')
936                 dimensions = '';
937
938             return '<div data-netdata="CHART_UNIQUE_ID"'
939                                     + ' data-dimensions="' + dimensions + '"'
940                                     + ' data-chart-library="gauge"'
941                                     + ' data-gauge-adjust="width"'
942                                     + ' data-title="' + title + '"'
943                                     + ' data-width="' + width + '"'
944                                     + ' data-before="0"'
945                                     + ' data-after="-CHART_DURATION"'
946                                     + ' data-points="CHART_DURATION"'
947                                     + ' data-colors="' + colors + '"'
948                                     + ' role="application"></div>';
949         },
950
951         anyAttribute: function(obj, attr, key, def) {
952             if(typeof obj[key] !== 'undefined') {
953                 if(typeof obj[key][attr] !== 'undefined')
954                     return obj[key][attr];
955             }
956             return def;
957         },
958
959         menuTitle: function(chart) {
960             if(typeof chart.menu_pattern !== 'undefined') {
961                 return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
962                         + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
963             }
964
965             return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
966         },
967
968         menuIcon: function(chart) {
969             if(typeof chart.menu_pattern !== 'undefined')
970                 return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
971
972             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
973         },
974
975         menuInfo: function(menu) {
976             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null);
977         },
978
979         menuHeight: function(menu, relative) {
980             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative;
981         },
982
983         submenuTitle: function(menu, submenu) {
984             var key = menu + '.' + submenu;
985             var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');;
986             if(title.length > 28) {
987                 var a = title.substring(0, 13);
988                 var b = title.substring(title.length - 12, title.length);
989                 return a + '...' + b;
990             }
991             return title;
992         },
993
994         submenuInfo: function(menu, submenu) {
995             var key = menu + '.' + submenu;
996             return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null);
997         },
998
999         submenuHeight: function(menu, submenu, relative) {
1000             var key = menu + '.' + submenu;
1001             return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative;
1002         },
1003
1004         contextInfo: function(id) {
1005             if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined')
1006                 return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>';
1007             else
1008                 return '';
1009         },
1010
1011         contextHeight: function(id, def) {
1012             if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined')
1013                 return def * netdataDashboard.context[id].height;
1014             else
1015                 return def;
1016         }
1017     };
1018
1019     // ----------------------------------------------------------------------------
1020
1021     // enrich the data structure returned by netdata
1022     // to reflect our menu system and content
1023     function enrichChartData(chart) {
1024         var tmp = chart.type.split('_')[0];
1025
1026         switch(tmp) {
1027             case 'ap':
1028             case 'net':
1029             case 'disk':
1030                 chart.menu = tmp;
1031                 break;
1032
1033             case 'cgroup':
1034                 chart.menu = chart.type;
1035                 if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1036                     chart.menu_pattern = 'cgqemu';
1037                 else
1038                     chart.menu_pattern = 'cgroup';
1039                 break;
1040
1041             case 'apache':
1042             case 'exim':
1043             case 'memcached':
1044             case 'mysql':
1045             case 'named':
1046             case 'nginx':
1047             case 'nut':
1048             case 'phpfpm':
1049             case 'postfix':
1050             case 'redis':
1051             case 'retroshare':
1052             case 'ipfs':
1053             case 'smawebbox':
1054             case 'squid':
1055             case 'snmp':
1056             case 'tomcat':
1057                 chart.menu = chart.type;
1058                 chart.menu_pattern = tmp;
1059                 break;
1060
1061             case 'tc':
1062                 chart.menu = tmp;
1063
1064                 // find a name for this device from fireqos info
1065                 // we strip '_(in|out)' or '(in|out)_'
1066                 if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
1067                     var n = chart.name.split('.')[1];
1068                     if(n.endsWith('_in'))
1069                         options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1070                     else if(n.endsWith('_out'))
1071                         options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1072                     else if(n.startsWith('in_'))
1073                         options.submenu_names[chart.family] = n.slice(3, n.length);
1074                     else if(n.startsWith('out_'))
1075                         options.submenu_names[chart.family] = n.slice(4, n.length);
1076                 }
1077
1078                 // increase the priority of IFB devices
1079                 // to have inbound appear before outbound
1080                 if(chart.id.match(/.*-ifb$/))
1081                     chart.priority--;
1082
1083                 break;
1084
1085             default:
1086                 chart.menu = chart.type;
1087                 break;
1088         }
1089
1090         chart.submenu = chart.family;
1091     }
1092
1093     // ----------------------------------------------------------------------------
1094
1095     function headMain(charts, duration) {
1096         var head = '';
1097
1098         if(typeof charts['system.swap'] !== 'undefined')
1099             head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1100             + ' data-dimensions="free"'
1101             + ' data-append-options="percentage"'
1102             + ' data-chart-library="easypiechart"'
1103             + ' data-title="Free Swap"'
1104             + ' data-units="%"'
1105             + ' data-easypiechart-max-value="100"'
1106             + ' data-width="8%"'
1107             + ' data-before="0"'
1108             + ' data-after="-' + duration.toString() + '"'
1109             + ' data-points="' + duration.toString() + '"'
1110             + ' data-colors="#DD4400"'
1111             + ' role="application"></div>';
1112
1113         if(typeof charts['system.io'] !== 'undefined') {
1114             head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1115             + ' data-dimensions="in"'
1116             + ' data-chart-library="easypiechart"'
1117             + ' data-title="Disk Read"'
1118             + ' data-width="10%"'
1119             + ' data-before="0"'
1120             + ' data-after="-' + duration.toString() + '"'
1121             + ' data-points="' + duration.toString() + '"'
1122             + ' role="application"></div>';
1123
1124             head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1125             + ' data-dimensions="out"'
1126             + ' data-chart-library="easypiechart"'
1127             + ' data-title="Disk Write"'
1128             + ' data-width="10%"'
1129             + ' data-before="0"'
1130             + ' data-after="-' + duration.toString() + '"'
1131             + ' data-points="' + duration.toString() + '"'
1132             + ' role="application"></div>';
1133         }
1134
1135         if(typeof charts['system.cpu'] !== 'undefined')
1136             head += '<div data-netdata="system.cpu"'
1137             + ' data-chart-library="gauge"'
1138             + ' data-title="CPU"'
1139             + ' data-units="%"'
1140             + ' data-gauge-max-value="100"'
1141             + ' data-width="18%"'
1142             + ' data-after="-' + duration.toString() + '"'
1143             + ' data-points="' + duration.toString() + '"'
1144             + ' data-colors="' + NETDATA.colors[12] + '"'
1145             + ' role="application"></div>';
1146
1147         if(typeof charts['system.ipv4'] !== 'undefined') {
1148             head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1149             + ' data-dimensions="received"'
1150             + ' data-chart-library="easypiechart"'
1151             + ' data-title="IPv4 Inbound"'
1152             + ' data-width="10%"'
1153             + ' data-before="0"'
1154             + ' data-after="-' + duration.toString() + '"'
1155             + ' data-points="' + duration.toString() + '"'
1156             + ' role="application"></div>';
1157
1158             head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1159             + ' data-dimensions="sent"'
1160             + ' data-chart-library="easypiechart"'
1161             + ' data-title="IPv4 Outbound"'
1162             + ' data-width="10%"'
1163             + ' data-before="0"'
1164             + ' data-after="-' + duration.toString() + '"'
1165             + ' data-points="' + duration.toString() + '"'
1166             + ' role="application"></div>';
1167         }
1168         else if(typeof charts['system.ipv6'] !== 'undefined') {
1169             head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1170             + ' data-dimensions="received"'
1171             + ' data-chart-library="easypiechart"'
1172             + ' data-title="IPv6 Inbound"'
1173             + ' data-units="kbps"'
1174             + ' data-width="10%"'
1175             + ' data-before="0"'
1176             + ' data-after="-' + duration.toString() + '"'
1177             + ' data-points="' + duration.toString() + '"'
1178             + ' role="application"></div>';
1179
1180             head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1181             + ' data-dimensions="sent"'
1182             + ' data-chart-library="easypiechart"'
1183             + ' data-title="IPv6 Outbound"'
1184             + ' data-units="kbps"'
1185             + ' data-width="10%"'
1186             + ' data-before="0"'
1187             + ' data-after="-' + duration.toString() + '"'
1188             + ' data-points="' + duration.toString() + '"'
1189             + ' role="application"></div>';
1190         }
1191
1192         if(typeof charts['system.ram'] !== 'undefined')
1193             head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1194             + ' data-dimensions="cached|free"'
1195             + ' data-append-options="percentage"'
1196             + ' data-chart-library="easypiechart"'
1197             + ' data-title="Available RAM"'
1198             + ' data-units="%"'
1199             + ' data-easypiechart-max-value="100"'
1200             + ' data-width="8%"'
1201             + ' data-after="-' + duration.toString() + '"'
1202             + ' data-points="' + duration.toString() + '"'
1203             + ' data-colors="' + NETDATA.colors[7] + '"'
1204             + ' role="application"></div>';
1205
1206         return head;
1207     }
1208
1209     function generateHeadCharts(type, chart, duration) {
1210         var head = '';
1211         var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1212         if(hcharts.length > 0) {
1213             var hi = 0, hlen = hcharts.length;
1214             while(hi < hlen) {
1215                 if(typeof hcharts[hi] === 'function')
1216                     head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1217                 else
1218                     head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1219                 hi++;
1220             }
1221         }
1222         return head;
1223     }
1224
1225     function renderPage(menus, data) {
1226         var div = document.getElementById('charts_div');
1227         var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1228
1229         // find the proper duration for per-second updates
1230         var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1231         var html = '';
1232         var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1233         var mainhead = headMain(data.charts, duration);
1234
1235         // sort the menus
1236         var main = sortObjectByPriority(menus);
1237         var i = 0, len = main.length;
1238         while(i < len) {
1239             var menu = main[i++];
1240
1241             // generate an entry at the main menu
1242
1243             var menuid = NETDATA.name2id('menu_' + menu);
1244             sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1245             html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1246
1247             if(menus[menu].info !== null)
1248                 html += menus[menu].info;
1249
1250             // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1251
1252             var shtml = '';
1253             var mhead = '<div class="netdata-chart-row">' + mainhead;
1254             mainhead = '';
1255
1256             // sort the submenus of this menu
1257             var sub = sortObjectByPriority(menus[menu].submenus);
1258             var si = 0, slen = sub.length;
1259             while(si < slen) {
1260                 var submenu = sub[si++];
1261
1262                 // generate an entry at the submenu
1263                 var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1264                 sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1265                 shtml += '<div class="netdata-group-container" id="' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
1266
1267                 if(menus[menu].submenus[submenu].info !== null)
1268                     shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1269
1270                 var head = '<div class="netdata-chart-row">';
1271                 var chtml = '';
1272
1273                 // console.log('    \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1274
1275                 // sort the charts in this submenu of this menu
1276                 menus[menu].submenus[submenu].charts.sort(prioritySort);
1277                 var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1278                 while(ci < clen) {
1279                     var chart = menus[menu].submenus[submenu].charts[ci++];
1280
1281                     // generate the submenu heading charts
1282                     mhead += generateHeadCharts('mainheads', chart, duration);
1283                     head += generateHeadCharts('heads', chart, duration);
1284
1285                     // generate the chart
1286                     chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1287                         + ' data-width="' + pcent_width.toString() + '%"'
1288                         + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1289                         + ' data-before="0"'
1290                         + ' data-after="-' + duration.toString() + '"'
1291                         + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1292                         + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1293                         + ' role="application"></div>';
1294
1295                     // console.log('         \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context  + ' height: ' + menus[menu].submenus[submenu].height);
1296                 }
1297
1298                 head += '</div>';
1299                 shtml += head + chtml + '</div>';
1300             }
1301
1302             mhead += '</div>';
1303             sidebar += '</ul></li>';
1304             html += mhead + shtml + '</div></div><hr role="separator"/>';
1305         }
1306
1307         sidebar += '</ul>';
1308         div.innerHTML = html;
1309         document.getElementById('sidebar').innerHTML = sidebar;
1310         finalizePage();
1311     }
1312
1313     function renderChartsAndMenu(data) {
1314         var menus = options.menus;
1315         var charts = data.charts;
1316
1317         for(var c in charts) {
1318             enrichChartData(charts[c]);
1319
1320             // create the menu
1321             if(typeof menus[charts[c].menu] === 'undefined') {
1322                 menus[charts[c].menu] = {
1323                     priority: charts[c].priority,
1324                     submenus: {},
1325                     title: netdataDashboard.menuTitle(charts[c]),
1326                     icon: netdataDashboard.menuIcon(charts[c]),
1327                     info: netdataDashboard.menuInfo(charts[c].menu),
1328                     height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight)
1329                 };
1330             }
1331
1332             if(charts[c].priority < menus[charts[c].menu].priority)
1333                 menus[charts[c].menu].priority = charts[c].priority;
1334
1335             // create the submenu
1336             if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') {
1337                 menus[charts[c].menu].submenus[charts[c].submenu] = {
1338                     priority: charts[c].priority,
1339                     charts: new Array(),
1340                     title: null,
1341                     info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu),
1342                     height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height)
1343                 };
1344             }
1345
1346             if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority)
1347                 menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority;
1348
1349             // index the chart in the menu/submenu
1350             menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]);
1351         }
1352
1353         // propagate the descriptive subname given to QoS
1354         // to all the other submenus with the same name
1355         for(var m in menus) {
1356             for(var s in menus[m].submenus) {
1357                 // set the family using a name
1358                 if(typeof options.submenu_names[s] !== 'undefined') {
1359                     menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1360                 }
1361                 else {
1362                     menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s);
1363                 }
1364             }
1365         }
1366
1367         renderPage(menus, data);
1368     }
1369
1370     // ----------------------------------------------------------------------------
1371
1372     function loadJs(url, callback) {
1373         $.ajax({
1374             url: url,
1375             cache: true,
1376             dataType: "script",
1377             xhrFields: { withCredentials: true } // required for the cookie
1378         })
1379         .fail(function() {
1380             alert('Cannot load required JS library: ' + url);
1381         })
1382         .always(function() {
1383             if(typeof callback === 'function')
1384                 callback();
1385         })
1386     }
1387
1388     var bootstrapTableLoaded = false;
1389     function loadBootstrapTable(callback) {
1390         if(bootstrapTableLoaded === false) {
1391             bootstrapTableLoaded === true;
1392             loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1393                 loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1394                     loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1395                 })
1396             });
1397         }
1398         else callback();
1399     }
1400
1401     function alarmsUpdateModal() {
1402         var active = '<h3>Raised Alarms</h3><table class="table">';
1403         var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1404         var footer = '<hr/><a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b>&nbsp;red&nbsp;</b></span> is critical, <span style="color:#fe7d37"><b>&nbsp;orange&nbsp;</b></span> is warning, <span style="color: #4c1"><b>&nbsp;bright green&nbsp;</b></span> is ok, <span style="color: #9f9f9f"><b>&nbsp;light grey&nbsp;</b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b>&nbsp;black&nbsp;</b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/firehol/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.';
1405
1406         NETDATA.alarms.get('all', function(data) {
1407             options.alarm_families = new Array();
1408
1409             alarmsCallback(data);
1410
1411             if(data === null) {
1412                 document.getElementById('alarms_active').innerHTML =
1413                         document.getElementById('alarms_all').innerHTML =
1414                                 document.getElementById('alarms_log').innerHTML =
1415                                         'failed to load alarm data!';
1416                 return;
1417             }
1418
1419             function timestamp4human(timestamp, space) {
1420                 if(typeof space === 'undefined')
1421                     space = '&nbsp;';
1422
1423                 var t = new Date(timestamp * 1000);
1424                 var now = new Date();
1425
1426                 if(t.toDateString() == now.toDateString())
1427                     return t.toLocaleTimeString();
1428
1429                 return t.toLocaleDateString() + space + t.toLocaleTimeString();
1430             }
1431
1432             function seconds4human(seconds, sfx, space) {
1433                 if(typeof space === 'undefined')
1434                     space = '&nbsp;';
1435
1436                 if(seconds === 0)
1437                     return 'now';
1438
1439                 var suffix = '';
1440                 if(seconds < 0) {
1441                     seconds = -seconds;
1442                     if(sfx) suffix = space + 'ago';
1443                 }
1444
1445                 var hours = Math.floor(seconds / 3600);
1446                 seconds -= (hours * 3600);
1447
1448                 var minutes = Math.floor(seconds / 60);
1449                 seconds -= (minutes * 60);
1450
1451                 var txt = '';
1452                 
1453                 if(hours > 1) txt += hours.toString() + space + 'hours';
1454                 else if(hours === 1) txt += hours.toString() + space + 'hour';
1455
1456                 if(hours > 0 && minutes > 0 && seconds == 0)
1457                     txt += space + 'and' + space;
1458                 else if(hours > 0 && minutes > 0 && seconds > 0)
1459                     txt += ',' + space;
1460
1461                 if(minutes > 1) txt += minutes.toString() + space + 'minutes';
1462                 else if(minutes === 1) txt += minutes.toString() + space + 'minute';
1463
1464                 if((minutes > 0 || minutes > 0) && seconds > 0)
1465                     txt += space + 'and' + space;
1466
1467                 if(seconds > 1) txt += seconds.toString() + space + 'seconds';
1468                 else if(seconds === 1) txt += seconds.toString() + space + 'second';
1469
1470                 return txt + suffix;
1471             }
1472
1473             function alarm_lookup_explain(alarm, chart) {
1474                 var dimensions = ' of all values ';
1475
1476                 if(chart.dimensions.length > 1)
1477                     dimensions = ' of the sum of all dimensions ';
1478
1479                 if(typeof alarm.lookup_dimensions !== 'undefined') {
1480                     var d = alarm.lookup_dimensions.replace('|', ',');
1481                     var x = d.split(',');
1482                     if(x.length > 1)
1483                         dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1484                     else
1485                         dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1486                 }
1487
1488                 return '<code>' + alarm.lookup_method + '</code> '
1489                     + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1490                     + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before, true) + '</code> and up to <code>' + seconds4human(alarm.lookup_before, true) + '</code>'
1491                     + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1492                     + '.';
1493             }
1494
1495             function alarm_to_html(alarm, full) {
1496                 var chart = options.data.charts[alarm.chart];
1497
1498                 var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/>&nbsp;<br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20"/><br/>&nbsp;<br/><span style="font-size: 18px">' + alarm.info + '</span><br/>&nbsp;<br/>role: <b>' + alarm.recipient + '</b><br/>&nbsp;<br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small>&nbsp;&nbsp;<a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small></td>'
1499                     + '<td><table class="table">'
1500                     + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning&nbsp;when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
1501                     + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical&nbsp;when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
1502
1503                 if(full === true) {
1504                         html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db&nbsp;lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
1505                         + ((typeof alarm.calc !== 'undefined')?('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>'):'')
1506                         + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
1507                         + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
1508                 }
1509
1510                 var delay = '';
1511                 if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1512                     if(alarm.delay_up_duration == alarm.delay_down_duration) {
1513                         delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration);
1514                     }
1515                     else {
1516                         delay = '<small><br/>hysteresis ';
1517                         if(alarm.delay_up_duration > 0) {
1518                             delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration) + '</code>, ';
1519                         }
1520                         if(alarm.delay_down_duration > 0) {
1521                             delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration) + '</code>, ';
1522                         }
1523                     }
1524                     if(alarm.delay_multiplier != 1.0) {
1525                         delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1526                         delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration) + '</code>';
1527                     }
1528                     delay += '</small>';
1529                 }
1530
1531                 html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every) + '</td></tr>'
1532                     + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'
1533                     + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1534                     + '</table></td></tr>';
1535
1536                 return html;
1537             }
1538
1539             function alarm_family_show(id) {
1540                 var html = '<table class="table">';
1541                 var family = options.alarm_families[id];
1542                 var len = family.arr.length;
1543                 while(len--) {
1544                     var alarm = family.arr[len];
1545                     html += alarm_to_html(alarm, true);
1546                 }
1547                 html += '</table>';
1548
1549                 $('#alarm_all_' + id.toString()).html(html);
1550             }
1551
1552             // find the proper family of each alarm
1553             var now = new Date().getTime();
1554             var x;
1555             var count_active = 0;
1556             var count_all = 0;
1557             var families = {};
1558             var families_sort = new Array();
1559             for(x in data.alarms) {
1560                 var alarm = data.alarms[x];
1561                 var family = alarm.family;
1562
1563                 // find the chart
1564                 var chart = options.data.charts[alarm.chart];
1565                 if(typeof chart === 'undefined')
1566                     chart = options.data.charts_by_name[alarm.chart];
1567
1568                 // not found - this should never happen!
1569                 if(typeof chart === 'undefined') {
1570                     console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1571                     chart = { priority: 9999999 };
1572                 }
1573                 else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1574                     // the family based on the chart
1575                     family = chart.menu + ' - ' + chart.submenu;
1576
1577                 if(typeof families[family] === 'undefined') {
1578                     families[family] = {
1579                         name: family,
1580                         arr: new Array(),
1581                         priority: chart.priority
1582                     };
1583
1584                     families_sort.push(families[family]);
1585                 }
1586
1587                 if(chart.priority < families[family].priority)
1588                     families[family].priority = chart.priority;
1589
1590                 families[family].arr.unshift(alarm);
1591             }
1592
1593             // sort the families, like the dashboard menu does
1594             var families_sorted = families_sort.sort(function (a, b) {
1595                 if (a.priority > b.priority) return -1;
1596                 if (a.priority < b.priority) return 1;
1597                 return 0;
1598             });
1599
1600             var fc = 0;
1601             var len = families_sorted.length;
1602             while(len--) {
1603                 var family = families_sorted[len].name;
1604                 var active_family_added = false;
1605                 var expanded = 'true';
1606                 var collapsed = '';
1607                 var cin = 'in';
1608
1609                 if(fc !== 0) {
1610                     all += "</table></div></div></div>";
1611                     expanded = 'false';
1612                     collapsed = 'class="collapsed"'
1613                     cin = '';
1614                 }
1615
1616                 all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
1617
1618                 options.alarm_families[fc] = families[family];
1619
1620                 fc++;
1621
1622                 var arr = families[family].arr;
1623                 var c = arr.length;
1624                 while(c--) {
1625                     var alarm = arr[c];
1626                     if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1627                         if(!active_family_added) {
1628                             active_family_added = true;
1629                             active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1630                         }
1631                         count_active++;
1632                         active += alarm_to_html(alarm, true);
1633                     }
1634
1635                     count_all++;
1636                 }
1637             }
1638             active += "</table>";
1639             if(families_sorted.length > 0) all += "</div></div></div>";
1640             all += "</div>";
1641
1642             if(!count_active)
1643                 active += "<h4>Everything is normal. No raised alarms.</h4>";
1644             else
1645                 active += footer;
1646
1647             if(!count_all)
1648                 all += "<h4>No alarms are running in this system.</h4>";
1649             else
1650                 all += footer;
1651
1652             document.getElementById('alarms_active').innerHTML = active;
1653             document.getElementById('alarms_all').innerHTML = all;
1654
1655             if(families_sorted.length > 0) alarm_family_show(0);
1656
1657             // register bootstrap events
1658             $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1659                 var target = $(d.target);
1660                 var id = $(target).data('alarm-id');
1661                 alarm_family_show(id);
1662             });
1663             $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1664                 var target = $(d.target);
1665                 var id = $(target).data('alarm-id');
1666                 $('#alarm_all_' + id.toString()).html('');
1667             });
1668
1669             document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1670
1671             loadBootstrapTable(function () {
1672                 $('#alarms_log_table').bootstrapTable({
1673                     url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1674                     cache: false,
1675                     pagination: true,
1676                     pageSize: 10,
1677                     showPaginationSwitch: false,
1678                     search: true,
1679                     searchTimeOut: 300,
1680                     searchAlign: 'left',
1681                     showColumns: true,
1682                     showExport: true,
1683                     exportDataType: 'basic',
1684                     exportOptions: {
1685                         fileName: 'netdata_alarm_log'
1686                     },
1687                     rowStyle: function(row, index) {
1688                         switch(row.status) {
1689                             case 'CRITICAL' : return { classes: 'danger'  }; break;
1690                             case 'WARNING'  : return { classes: 'warning' }; break;
1691                             case 'UNDEFINED': return { classes: 'info'    }; break;
1692                             case 'CLEAR'    : return { classes: 'success' }; break;
1693                         }
1694                         return {};
1695                     },
1696                     showFooter: false,
1697                     showHeader: true,
1698                     showRefresh: true,
1699                     showToggle: false,
1700                     sortable: true,
1701                     silentSort: false,
1702                     columns: [
1703                         {
1704                             field: 'when',
1705                             title: 'Event Date',
1706                             valign: 'middle',
1707                             switchable: false,
1708                             sortable: true,
1709                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1710                         },
1711                         {
1712                             field: 'hostname',
1713                             title: 'Host',
1714                             valign: 'middle',
1715                             visible: false,
1716                             sortable: true
1717                         },
1718                         {
1719                             field: 'unique_id',
1720                             title: 'Unique ID',
1721                             valign: 'middle',
1722                             visible: false,
1723                             sortable: true
1724                         },
1725                         {
1726                             field: 'alarm_id',
1727                             title: 'Alarm ID',
1728                             valign: 'middle',
1729                             visible: false,
1730                             sortable: true
1731                         },
1732                         {
1733                             field: 'alarm_event_id',
1734                             title: 'Alarm Event ID',
1735                             valign: 'middle',
1736                             visible: false,
1737                             sortable: true
1738                         },
1739                         {
1740                             field: 'chart',
1741                             title: 'Chart',
1742                             valign: 'middle',
1743                             switchable: false,
1744                             sortable: true
1745                         },
1746                         {
1747                             field: 'family',
1748                             title: 'Family',
1749                             valign: 'middle',
1750                             visible: false,
1751                             sortable: true
1752                         },
1753                         {
1754                             field: 'name',
1755                             title: 'Alarm',
1756                             formatter: function(value, row, index) {
1757                                 return value.toString().replace(/_/g, ' ');
1758                             },
1759                             valign: 'middle',
1760                             switchable: false,
1761                             sortable: true
1762                         },
1763                         {
1764                             field: 'old_value',
1765                             title: 'Old Value',
1766                             valign: 'middle',
1767                             visible: false,
1768                             sortable: true
1769                         },
1770                         {
1771                             field: 'value',
1772                             title: 'Value',
1773                             formatter: function(value, row, index) {
1774                                 return ((value !== null)?Math.floor(value):'NaN').toString();
1775                             },
1776                             align: 'right',
1777                             valign: 'middle',
1778                             sortable: true
1779                         },
1780                         {
1781                             field: 'units',
1782                             title: 'Units',
1783                             valign: 'middle',
1784                             sortable: true
1785                         },
1786                         {
1787                             field: 'old_status',
1788                             title: 'Old Status',
1789                             valign: 'middle',
1790                             visible: false,
1791                             sortable: true
1792                         },
1793                         {
1794                             field: 'status',
1795                             title: 'Status',
1796                             valign: 'middle',
1797                             switchable: false,
1798                             sortable: true
1799                         },
1800                         {
1801                             field: 'duration',
1802                             title: 'Duration',
1803                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1804                             valign: 'middle',
1805                             visible: false,
1806                             sortable: true
1807                         },
1808                         {
1809                             field: 'non_clear_duration',
1810                             title: 'Raised Duration',
1811                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1812                             valign: 'middle',
1813                             visible: false,
1814                             sortable: true
1815                         },
1816                         {
1817                             field: 'recipient',
1818                             title: 'Recipient',
1819                             valign: 'middle',
1820                             visible: false,
1821                             sortable: true
1822                         },
1823                         {
1824                             field: 'processed',
1825                             title: 'Processed Status',
1826                             valign: 'middle',
1827                             visible: false,
1828                             sortable: true
1829                         },
1830                         {
1831                             field: 'updated',
1832                             title: 'Updated Status',
1833                             valign: 'middle',
1834                             visible: false,
1835                             sortable: true
1836                         },
1837                         {
1838                             field: 'updated_by_id',
1839                             title: 'Updated By ID',
1840                             valign: 'middle',
1841                             visible: false,
1842                             sortable: true
1843                         },
1844                         {
1845                             field: 'updates_id',
1846                             title: 'Updates ID',
1847                             valign: 'middle',
1848                             visible: false,
1849                             sortable: true
1850                         },
1851                         {
1852                             field: 'exec',
1853                             title: 'Script',
1854                             valign: 'middle',
1855                             visible: false,
1856                             sortable: true
1857                         },
1858                         {
1859                             field: 'exec_run',
1860                             title: 'Script Run At',
1861                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1862                             valign: 'middle',
1863                             visible: false,
1864                             sortable: true
1865                         },
1866                         {
1867                             field: 'exec_code',
1868                             title: 'Script Return Value',
1869                             valign: 'middle',
1870                             visible: false,
1871                             sortable: true
1872                         },
1873                         {
1874                             field: 'delay',
1875                             title: 'Script Delay',
1876                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1877                             valign: 'middle',
1878                             visible: false,
1879                             sortable: true
1880                         },
1881                         {
1882                             field: 'delay_up_to_timestamp',
1883                             title: 'Script Delay Run At',
1884                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1885                             valign: 'middle',
1886                             visible: false,
1887                             sortable: true
1888                         },
1889                         {
1890                             field: 'info',
1891                             title: 'Description',
1892                             valign: 'middle',
1893                             visible: false,
1894                             sortable: true
1895                         },
1896                         {
1897                             field: 'source',
1898                             title: 'Alarm Source',
1899                             valign: 'middle',
1900                             visible: false,
1901                             sortable: true
1902                         }
1903                     ]
1904                 });
1905                 // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
1906             });
1907         });
1908     }
1909
1910     function alarmsCallback(data) {
1911         var count = 0;
1912         for(x in data.alarms) {
1913             var alarm = data.alarms[x];
1914             if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
1915                 count++;
1916         }
1917
1918         if(count > 0)
1919             document.getElementById('alarms_count_badge').innerHTML = count.toString();
1920         else
1921             document.getElementById('alarms_count_badge').innerHTML = '';
1922     }
1923
1924     function initializeDynamicDashboard(netdata_url) {
1925         if(typeof netdata_url === 'undefined' || netdata_url === null)
1926             netdata_url = NETDATA.serverDefault;
1927
1928         // initialize clickable alarms
1929         NETDATA.alarms.chart_div_offset = 100;
1930         NETDATA.alarms.chart_div_id_prefix = 'chart_';
1931         NETDATA.alarms.chart_div_animation_duration = 0;
1932
1933         NETDATA.pause(function() {
1934             NETDATA.alarms.callback = alarmsCallback;
1935
1936             // download all the charts the server knows
1937             NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
1938                 if(data !== null) {
1939                     options.hostname = data.hostname;
1940                     options.data = data;
1941
1942                     // update the dashboard hostname
1943                     document.getElementById('hostname').innerHTML = options.hostname;
1944                     document.getElementById('hostname').href = NETDATA.serverDefault;
1945
1946                     // update the dashboard title
1947                     document.title = options.hostname + ' netdata dashboard';
1948
1949                     // close the splash screen
1950                     $("#loadOverlay").css("display","none");
1951
1952                     // create a chart_by_name index
1953                     data.charts_by_name = {};
1954                     var charts = data.charts;
1955                     var x;
1956                     for(x in charts) {
1957                         var chart = charts[x];
1958                         data.charts_by_name[chart.name] = chart;
1959                     }
1960
1961                     // render all charts
1962                     renderChartsAndMenu(data);
1963                 }
1964             });
1965         });
1966     }
1967
1968     // ----------------------------------------------------------------------------
1969
1970     function versionLog(msg) {
1971         document.getElementById('versionCheckLog').innerHTML = msg;
1972     }
1973
1974     function getNetdataVersion(callback) {
1975         versionLog('Downloading installed version info from netdata...');
1976
1977         $.ajax({
1978             url: 'version.txt',
1979             async: true,
1980             cache: false,
1981             xhrFields: { withCredentials: true } // required for the cookie
1982         })
1983         .done(function(data) {
1984             data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
1985             if(data.length !== 40) {
1986                 versionLog('Received version string is invalid.');
1987                 callback(null);
1988             }
1989             else {
1990                 versionLog('Installed version of netdata is ' + data);
1991                 document.getElementById('netdataVersion').innerHTML = data;
1992                 callback(data);
1993             }
1994         })
1995         .fail(function() {
1996             versionLog('Failed to download installed version info from netdata!');
1997             callback(null);
1998         });
1999     }
2000
2001     function getGithubLatestCommit(callback) {
2002         versionLog('Downloading latest version info from github...');
2003
2004         $.ajax({
2005             url: 'https://api.github.com/repos/firehol/netdata/commits',
2006             async: true,
2007             cache: false
2008         })
2009         .done(function(data) {
2010             versionLog('Latest version info from github is ' + data[0].sha);
2011             callback(data[0].sha);
2012         })
2013         .fail(function() {
2014             versionLog('Failed to download installed version info from github!');
2015             callback(null);
2016         });
2017     }
2018
2019     function checkForUpdate(callback) {
2020         getNetdataVersion(function(sha1) {
2021             if(sha1 === null) callback(null, null);
2022
2023             getGithubLatestCommit(function(sha2) {
2024                 callback(sha1, sha2);
2025             });
2026         });
2027
2028         return null;
2029     }
2030
2031     function notifyForUpdate(force) {
2032         versionLog('<p>checking for updates...</p>');
2033
2034         var now = new Date().getTime();
2035
2036         if(typeof force === 'undefined' || force !== true) {
2037             var last = loadLocalStorage('last_update_check');
2038
2039             if(typeof last === 'string')
2040                 last = parseInt(last);
2041             else
2042                 last = 0;
2043
2044             if(now - last < 3600000 * 8) {
2045                 // no need to check it - too soon
2046                 return;
2047             }
2048         }
2049
2050         checkForUpdate(function(sha1, sha2) {
2051             var save = false;
2052
2053             if(sha1 === null) {
2054                 save = false;
2055                 versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2056             }
2057             else if(sha2 === null) {
2058                 save = false;
2059                 versionLog('<p><big>Failed to get the latest version from github.</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2060             }
2061             else if(sha1 === sha2) {
2062                 save = true;
2063                 versionLog('<p><big>You already have the latest version of netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>');
2064             }
2065             else {
2066                 save = true;
2067                 var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2068
2069                 versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
2070
2071                 document.getElementById('update_badge').innerHTML = '!';
2072             }
2073
2074             if(save)
2075                 saveLocalStorage('last_update_check', now.toString());
2076         });
2077     }
2078
2079     // ----------------------------------------------------------------------------
2080
2081     function finalizePage() {
2082         // resize all charts - without starting the background thread
2083         // this has to be done while NETDATA is paused
2084         // if we ommit this, the affix menu will be wrong, since all
2085         // the Dom elements are initially zero-sized
2086         NETDATA.parseDom();
2087
2088         if(urlOptions.pan_and_zoom === true)
2089             NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2090
2091         // ------------------------------------------------------------------------
2092         // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2093         $.fn.shorten = function(settings) {
2094             "use strict";
2095
2096             var config = {
2097                 showChars: 750,
2098                 minHideChars: 10,
2099                 ellipsesText: "...",
2100                 moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2101                 lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2102                 onLess: function() { NETDATA.onscroll(); },
2103                 onMore: function() { NETDATA.onscroll(); },
2104                 errMsg: null,
2105                 force: false
2106             };
2107
2108             if (settings) {
2109                 $.extend(config, settings);
2110             }
2111
2112             if ($(this).data('jquery.shorten') && !config.force) {
2113                 return false;
2114             }
2115             $(this).data('jquery.shorten', true);
2116
2117             $(document).off("click", '.morelink');
2118
2119             $(document).on({
2120                 click: function() {
2121
2122                     var $this = $(this);
2123                     if ($this.hasClass('less')) {
2124                         $this.removeClass('less');
2125                         $this.html(config.moreText);
2126                         $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2127                             config.onLess();
2128                         });
2129
2130                     } else {
2131                         $this.addClass('less');
2132                         $this.html(config.lessText);
2133                         $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2134                             config.onMore();
2135                         });
2136                     }
2137                     return false;
2138                 }
2139             }, '.morelink');
2140
2141             return this.each(function() {
2142                 var $this = $(this);
2143
2144                 var content = $this.html();
2145                 var contentlen = $this.text().length;
2146                 if (contentlen > config.showChars + config.minHideChars) {
2147                     var c = content.substr(0, config.showChars);
2148                     if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2149                     {
2150                         var inTag = false; // I'm in a tag?
2151                         var bag = ''; // Put the characters to be shown here
2152                         var countChars = 0; // Current bag size
2153                         var openTags = []; // Stack for opened tags, so I can close them later
2154                         var tagName = null;
2155
2156                         for (var i = 0, r = 0; r <= config.showChars; i++) {
2157                             if (content[i] == '<' && !inTag) {
2158                                 inTag = true;
2159
2160                                 // This could be "tag" or "/tag"
2161                                 tagName = content.substring(i + 1, content.indexOf('>', i));
2162
2163                                 // If its a closing tag
2164                                 if (tagName[0] == '/') {
2165
2166
2167                                     if (tagName != '/' + openTags[0]) {
2168                                         config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2169                                     } else {
2170                                         openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2171                                     }
2172
2173                                 } else {
2174                                     // There are some nasty tags that don't have a close tag like <br/>
2175                                     if (tagName.toLowerCase() != 'br') {
2176                                         openTags.unshift(tagName); // Add to start the name of the tag that opens
2177                                     }
2178                                 }
2179                             }
2180                             if (inTag && content[i] == '>') {
2181                                 inTag = false;
2182                             }
2183
2184                             if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2185                             else {
2186                                 r++;
2187                                 if (countChars <= config.showChars) {
2188                                     bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2189                                     countChars++;
2190                                 } else // Now I have the characters needed
2191                                 {
2192                                     if (openTags.length > 0) // I have unclosed tags
2193                                     {
2194                                         //console.log('They were open tags');
2195                                         //console.log(openTags);
2196                                         for (j = 0; j < openTags.length; j++) {
2197                                             //console.log('Cierro tag ' + openTags[j]);
2198                                             bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2199
2200                                             // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags
2201                                         }
2202                                         break;
2203                                     }
2204                                 }
2205                             }
2206                         }
2207                         c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2208                     }else{
2209                         c+=config.ellipsesText;
2210                     }
2211
2212                     var html = '<div class="shortcontent">' + c +
2213                             '</div><div class="allcontent">' + content +
2214                             '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2215
2216                     $this.html(html);
2217                     $this.find(".allcontent").hide(); // Hide all text
2218                     $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2219                 }
2220             });
2221
2222         };
2223         $(".chart-message").shorten();
2224         // ------------------------------------------------------------------------
2225
2226         // callback for us to track PanAndZoom operations
2227         NETDATA.globalPanAndZoom.callback = netdataPanAndZoomCallback;
2228
2229         // let it run (update the charts)
2230         NETDATA.unpause();
2231
2232         // check if we have to jump to a specific section
2233         scrollToId(urlOptions.hash.replace('#',''));
2234
2235         if(urlOptions.chart !== null) {
2236             NETDATA.alarms.scrollToChart(urlOptions.chart);
2237             //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2238             //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2239             //console.log('hash = ' + urlOptions.hash);
2240         }
2241
2242         /* activate bootstrap sidebar (affix) */
2243         $('#sidebar').affix({
2244             offset: {
2245                 top: (isdemo())?150:0,
2246                 bottom: 0
2247             }
2248         });
2249
2250         /* fix scrolling of very long affix lists
2251            http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2252          */
2253         $('#sidebar').on('affixed.bs.affix', function() {
2254             $(this).removeAttr('style');
2255         });
2256
2257         /* activate bootstrap scrollspy (needed for sidebar) */
2258         $(document.body).scrollspy({
2259             target: '#sidebar',
2260             offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2261         });
2262
2263         // change the URL based on the current position of the screen
2264         $('#sidebar').on('activate.bs.scrollspy', function (e) {
2265             // console.log(e);
2266             var el = $(e.target);
2267             //if(el.find('ul').size() == 0) {
2268             var hash = el.find('a').attr('href');
2269             if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2270                 urlOptions.hash = hash;
2271                 //console.log(urlOptions.hash);
2272                 netdataHashUpdate();
2273             }
2274             //else console.log('hash: not accepting ' + hash);
2275             //}
2276             //else console.log('el.find(): not found');
2277         });
2278
2279         document.getElementById('footer').style.display = 'block';
2280
2281         var update_options_modal = function() {
2282             // console.log('update_options_modal');
2283
2284             var sync_option = function(option) {
2285                 var self = $('#' + option);
2286
2287                 if(self.prop('checked') !== NETDATA.getOption(option)) {
2288                     // console.log('switching ' + option.toString());
2289                     self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2290                 }
2291             }
2292
2293             var theme_sync_option = function(option) {
2294                 var self = $('#' + option);
2295
2296                 self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2297             }
2298
2299             sync_option('eliminate_zero_dimensions');
2300             sync_option('destroy_on_hide');
2301             sync_option('async_on_scroll');
2302             sync_option('parallel_refresher');
2303             sync_option('concurrent_refreshes');
2304             sync_option('sync_selection');
2305             sync_option('sync_pan_and_zoom');
2306             sync_option('stop_updates_when_focus_is_lost');
2307             sync_option('smooth_plot');
2308             sync_option('pan_and_zoom_data_padding');
2309             sync_option('show_help');
2310             theme_sync_option('netdata_theme_control');
2311
2312             if(NETDATA.getOption('parallel_refresher') === false) {
2313                 $('#concurrent_refreshes_row').hide();
2314             }
2315             else {
2316                 $('#concurrent_refreshes_row').show();
2317             }
2318         };
2319         NETDATA.setOption('setOptionCallback', update_options_modal);
2320
2321         // handle options changes
2322         $('#eliminate_zero_dimensions').change(function()       { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2323         $('#destroy_on_hide').change(function()                 { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2324         $('#async_on_scroll').change(function()                 { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2325         $('#parallel_refresher').change(function()              { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2326         $('#concurrent_refreshes').change(function()            { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2327         $('#sync_selection').change(function()                  { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2328         $('#sync_pan_and_zoom').change(function()               { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2329         $('#stop_updates_when_focus_is_lost').change(function() { NETDATA.setOption('stop_updates_when_focus_is_lost', $(this).prop('checked')); });
2330         $('#smooth_plot').change(function()                     { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2331         $('#pan_and_zoom_data_padding').change(function()       { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2332         $('#show_help').change(function()                       {
2333             urlOptions.help = $(this).prop('checked');
2334             NETDATA.setOption('show_help', urlOptions.help);
2335             netdataReload();
2336         });
2337
2338         // this has to be the last
2339         // it reloads the page
2340         $('#netdata_theme_control').change(function() {
2341             urlOptions.theme = $(this).prop('checked')?'slate':'white';
2342             if(setTheme(urlOptions.theme))
2343                 netdataReload();
2344         });
2345
2346         $('#updateModal').on('shown.bs.modal', function() {
2347             notifyForUpdate(true);
2348         });
2349
2350         $('#alarmsModal').on('shown.bs.modal', function() {
2351             NETDATA.pause(alarmsUpdateModal);
2352         });
2353
2354         $('#alarmsModal').on('hidden.bs.modal', function() {
2355             NETDATA.unpause();
2356             document.getElementById('alarms_active').innerHTML =
2357                     document.getElementById('alarms_all').innerHTML =
2358                     document.getElementById('alarms_log').innerHTML =
2359                             'loading...';
2360         });
2361
2362         $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2363             deleteRegistryGuid = null;
2364         });
2365
2366         if(isdemo()) {
2367             if(urlOptions.nowelcome !== true) {
2368                 setTimeout(function() {
2369                     $('#welcomeModal').modal();
2370                 }, 1000);
2371             }
2372
2373             // google analytics when this is used for the home page of the demo sites
2374             // this does not run on user's installations
2375             setTimeout(function() {
2376                 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2377                 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2378                 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2379                 })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2380
2381                 ga('create', 'UA-64295674-3', 'auto');
2382                 ga('send', 'pageview');
2383             }, 2000);
2384         }
2385         else notifyForUpdate();
2386
2387         if(urlOptions.show_alarms === true)
2388             setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2389     }
2390
2391     function resetDashboardOptions() {
2392         var help = NETDATA.options.current.show_help;
2393
2394         NETDATA.resetOptions();
2395         if(setTheme('slate'))
2396             netdataReload();
2397
2398         if(help !== NETDATA.options.current.show_help)
2399             netdataReload();
2400     }
2401
2402     // callback to add the dashboard info to the
2403     // parallel javascript downloader in netdata
2404     var netdataPrepCallback = function() {
2405         NETDATA.requiredCSS.push({
2406             url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2407             isAlreadyLoaded: function() { return false; }
2408         });
2409
2410         NETDATA.requiredJs.push({
2411             url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2412             isAlreadyLoaded: function() { return false; }
2413         });
2414
2415         NETDATA.requiredJs.push({
2416             url: NETDATA.serverDefault + 'dashboard_info.js?v20161002-1',
2417             async: false,
2418             isAlreadyLoaded: function() { return false; }
2419         });
2420
2421         if(isdemo()) {
2422             document.getElementById('masthead').style.display = 'block';
2423         }
2424     }
2425
2426     // our entry point
2427     var netdataCallback = initializeDynamicDashboard;
2428
2429 </script>
2430
2431 <body data-spy="scroll" data-target="#sidebar">
2432     <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
2433         netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>
2434     </div>
2435     <script type="text/javascript">
2436         // change the loadOverlay colors ASAP to match the theme
2437         document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;";
2438     </script>
2439     <nav class="navbar navbar-default navbar-fixed-top" role="banner">
2440         <div class="container">
2441             <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
2442                 <ul class="nav navbar-nav">
2443                     <li class="dropdown">
2444                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
2445                         <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu">
2446                             <div class="row">
2447                                 <div class="col-sm-6" style="width: 85%; padding-right: 0;">
2448                                     <ul id="mynetdata_servers" class="multi-column-dropdown">
2449                                         <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2450                                     </ul>
2451                                 </div>
2452                                 <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
2453                                     <ul id="mynetdata_actions1" class="multi-column-dropdown">
2454                                     <li style="color: #999;">&nbsp;</li>
2455                                     </ul>
2456                                 </div>
2457                             </div>
2458                         </ul>
2459                     </li>
2460                 </ul>
2461             </nav>
2462             <div class="navbar-header">
2463                 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
2464                     <span class="sr-only">Toggle navigation</span>
2465                     <span class="icon-bar"></span>
2466                     <span class="icon-bar"></span>
2467                     <span class="icon-bar"></span>
2468                 </button>
2469                 <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
2470             </div>
2471             <nav class="collapse navbar-collapse navbar-right" role="navigation">
2472                 <ul class="nav navbar-nav">
2473                     <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i></span>&nbsp;<span class="hidden-sm">Alarms&nbsp;</span><span id="alarms_count_badge" class="badge"></a></li>
2474                     <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i>&nbsp;<span class="hidden-sm">Settings</span></a></li>
2475                     <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata community"><i class="fa fa-github"></i>&nbsp;<span class="hidden-sm hidden-md">Community</span></a></li>
2476                     <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i><span id="update_badge" class="badge"></span>&nbsp;<span class="hidden-sm hidden-md">Update</span></a></li>
2477                     <li class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal" title="dashboard help"><i class="fa fa-question-circle"></i>&nbsp;<span class="hidden-sm hidden-md">Help</span></a></li>
2478                     <!--
2479                     <li class="dropdown hidden-md hidden-lg hidden-xs">
2480                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">Menu <strong class="caret"></strong></a>
2481                         <ul class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2482                             <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fa fa-bell"></i> alarms</a></li>
2483                             <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-sliders"></i> settings</a></li>
2484                             <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank"><i class="fa fa-github"></i> community</a></li>
2485                             <li><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question-circle"></i> help</a></li>
2486                         </ul>
2487                     </li>
2488                     -->
2489                     <li class="dropdown hidden-sm hidden-md hidden-lg">
2490                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
2491                         <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2492                             <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2493                         </ul>
2494                     </li>
2495                 </ul>
2496             </nav>
2497     </nav>
2498         </div>
2499     </nav>
2500
2501     <div id="masthead" style="display: none;">
2502         <div class="container">
2503             <div class="row">
2504                 <div class="col-md-7">
2505                     <h1>Netdata
2506                         <p class="lead">Real-time performance monitoring, in the greatest possible detail</p>
2507                     </h1>
2508                 </div>
2509                 <div class="col-md-5">
2510                     <div class="well well-lg">
2511                         <div class="row">
2512                         <div class="col-md-6">
2513                             <b>Drag</b> charts to pan.
2514                             <b>Shift + wheel</b> on them, to zoom in and out.
2515                             <b>Double-click</b> on them, to reset.
2516                             <b>Hover</b> on them too!
2517                             </div>
2518                         <div class="col-md-6">
2519                             <div data-netdata="system.intr" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dygraph-type="line" data-dygraph-strokewidth="3" data-dygraph-smooth="true" data-dygraph-highlightcirclesize="6" data-after="-90" data-height="60px" data-colors="#C66"></div>
2520                             </div>
2521                         </div>
2522                     </div>
2523                 </div>
2524             </div>
2525         </div>
2526     </div>
2527
2528     <div class="container">
2529         <div class="row">
2530             <div class="charts-body" role="main">
2531                 <div id="charts_div"></div>
2532             </div>
2533             <div class="sidebar-body hidden-xs hidden-sm" role="complementary">
2534                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
2535             </div>
2536         </div>
2537     </div>
2538
2539     <div id="footer" class="container" style="display: none;">
2540         <div class="row">
2541             <div class="col-md-10" role="main">
2542                 <div class="p">
2543                     <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/>
2544                     <i class="fa fa-copyright"></i> Copyright 2016, Costa Tsaousis.<br/>
2545                     Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/>
2546                 </div>
2547                 <div class="p">
2548                     <small>
2549                         <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools:
2550
2551                         <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library,
2552                         <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a>
2553
2554                         <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library,
2555                         <i class="fa fa-copyright"></i> Copyright 2013, Robert Fleischmann, <a href="https://github.com/rendro/easy-pie-chart/blob/master/LICENSE" target="_blank">MIT License</a>
2556
2557                         <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library,
2558                         <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a>
2559
2560                         <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>,
2561                         <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a>
2562
2563                         <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>,
2564                         <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a>
2565
2566                         <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>,
2567                         <i class="fa fa-copyright"></i> Copyright (c) 2011-2014 Min Hur, The New York Times Company, <a href="https://github.com/minhur/bootstrap-toggle/blob/master/LICENSE" target="_blank">MIT License</a>
2568
2569                         <i class="fa fa-circle"></i> <a href="https://jamesflorentino.github.io/nanoScrollerJS/" target="_blank">NanoScroller</a>,
2570                         <i class="fa fa-copyright"></i> Copyright 2012, James Florentino, <a href="https://github.com/jamesflorentino/nanoScrollerJS/blob/master/LICENSE" target="_blank">MIT License</a>
2571
2572                         <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
2573                         <i class="fa fa-copyright"></i> Created by Dave Gandy, Font: <a href="http://scripts.sil.org/OFL" target="_blank">SIL OFL 1.1 License</a>, CSS: <a href="http://opensource.org/licenses/mit-license.html" target="_blank">MIT License</a>
2574
2575                         <i class="fa fa-circle"></i> <a href="http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html" target="_blank">IconsDB.com Icons</a>, Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.
2576
2577                         <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>,
2578                         <i class="fa fa-copyright"></i> Copyright (c) 2012-2016 Zhixin Wen, <a href="https://github.com/wenzhixin/bootstrap-table/blob/master/LICENSE" target="_blank">MIT License</a>
2579
2580                         <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>,
2581                         <i class="fa fa-copyright"></i> Copyright (c) 2015,2016 hhurz, <a href="http://rawgit.com/hhurz/tableExport.jquery.plugin/master/tableExport.js" target="_blank">MIT License</a>
2582
2583                     </small>
2584                 </div>
2585             </div>
2586         </div>
2587     </div>
2588
2589     <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
2590         <div class="modal-dialog modal-lg" role="document">
2591             <div class="modal-content">
2592                 <div class="modal-header">
2593                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2594                     <h4 class="modal-title" id="welcomeModalLabel">Welcome!</h4>
2595                 </div>
2596                 <div class="modal-body">
2597                         <div class="p">
2598                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is the fastest way to visualize metrics. It is a resource efficient, highly optimized system for collecting and visualizing any type of real-time time series data, from CPU usage, disk activity, SQL queries, API calls, web site visitors, etc.
2599                         </div>
2600                         <div class="p">
2601                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> tries to visualize the truth of <b>now</b>, in its <b>greatest detail</b>, so that you can get insights of what is happening now and what just happened, on your systems and applications.
2602                         </div>
2603                         <div class="p">
2604                         To make a chart in <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>, you just need a <b>number</b>. Just a number you can read somehow. <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> will turn this number to a real time, interactive, web chart. For collecting these numbers, it supports <a href="https://github.com/firehol/netdata/wiki/External-Plugins" target="_blank">external plugins</a>, even <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">shell</a> or <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">node.js</a> plugins. Any computer program, in any language, that can print a few lines of text on its standard output, can be a netdata data collector.
2605                         </div>
2606                         <div class="p">
2607                         <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> can embed charts everywhere, like this one <div data-netdata="system.cpu" data-dimensions="system" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-system-at="system.cpu.system.modal.1"></div> (my CPU system usage which is <span id="system.cpu.system.modal.1" style="display: inline-block; width: 40px; text-align: right;"></span>%),
2608                         or this one <div data-netdata="ipv4.tcppackets" data-dimensions="received" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-received-at="ipv4.tcppackets.received.modal.1"></div> (my IPv4 received TCP packets, which are <span id="ipv4.tcppackets.received.modal.1" style="display: inline-block; width: 60px; text-align: right;"></span>/second).
2609                         </div>
2610                         <div class="p">
2611                         You can have <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> charts on your site too. Just give it a <code>div</code> and a real time chart, zoomable and draggable will appear (try it even on these tiny ones - <b>drag</b> them to pan horizontally, <b>shift + drag</b> to zoom in, on <b>chrome shift + mouse wheel</b> to zoom in/out, <b>double click</b> on them to reset them - don't be afraid of <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> performance - <a href="https://github.com/firehol/netdata/wiki/Performance" target="_blank">a raspberry pi 2 can sustain 300 charts updates per second</a>!).
2612                         </div>
2613                         <div class="p">
2614                         For more information please refer to the <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata wiki</a></b>.
2615                         </div>
2616                 </div>
2617                 <div class="modal-footer">
2618                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2619                 </div>
2620             </div>
2621         </div>
2622     </div>
2623
2624     <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
2625         <div class="modal-dialog modal-lg" role="document">
2626             <div class="modal-content">
2627                 <div class="modal-header">
2628                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2629                     <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4>
2630                 </div>
2631                 <div class="modal-body">
2632
2633                     <h4>Dygraphs (line, area and stacked area charts)</h4>
2634
2635                     <!-- Nav tabs -->
2636                     <ul class="nav nav-tabs" role="tablist">
2637                         <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li>
2638                         <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li>
2639                     </ul>
2640
2641                     <!-- Tab panes -->
2642                     <div class="tab-content">
2643                         <div role="tabpanel" class="tab-pane active" id="help_mouse">
2644                             <div class="p">
2645                                 <h4>Mouse Over / Hover</h4>
2646                                 Mouse over on a chart to show, at its legend, the values for the timestamp under the mouse (the chart will also highlight the point at the chart).
2647                                 <br/>
2648                                 All the other visible charts will also show and highlight their values for the same timestamp.
2649                             </div>
2650                             <hr/>
2651                             <div class="p">
2652                                 <h4>Drag Chart Contents</h4>
2653                                 Drag the contents of a chart to pan it horizontally.
2654                                 <br/>
2655                                 All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring).
2656                                 <br/>
2657                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart.
2658                             </div>
2659                             <hr/>
2660                             <div class="p">
2661                                 <h4>Double Click</h4>
2662                                 Double Click a chart to reset all the charts to their default auto-refreshing state.
2663                             </div>
2664                             <hr/>
2665                             <div class="p">
2666                                 <h4>SHIFT + Drag</h4>
2667                                 While pressing the shift key, click on the contents of a chart and move the mouse to select an area, to zoom in. The other charts will follow too. Zooming is performed in two phases:
2668                                 <ul>
2669                                     <li>The already loaded chart contents are zoomed (low resolution)</li>
2670                                     <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li>
2671                                 </ul>
2672                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2673                             </div>
2674                             <hr/>
2675                             <div class="p">
2676                                 <h4>SHIFT + Mouse Wheel <small>(does not work on firefox and IE/Edge)</small></h4>
2677                                 While pressing the shift key and the mouse pointer is over the contents of a chart, scroll the mouse wheel to zoom in or out. This kind of zooming is aligned to center below the mouse pointer. The other charts will follow too.
2678                                 <br/>
2679                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2680                             </div>
2681                             <hr/>
2682                             <div class="p">
2683                                 <h4>Legend Operations</h4>
2684                                 Click on the label or value of a dimension, will select / un-select this dimension.
2685                                 <br/>
2686                                 You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions.
2687                             </div>
2688                         </div>
2689                         <div role="tabpanel" class="tab-pane" id="help_touch">
2690                             <div class="p">
2691                                 <h4>Single Tap</h4>
2692                                 Single Tap on the contents of a chart to show, at its legend, the values for the timestamp tapped (the chart will also highlight the point at the chart).
2693                                 <br/>
2694                                 All the other visible charts will also show and highlight their values for the same timestamp.
2695                             </div>
2696                             <hr/>
2697                             <div class="p">
2698                                 <h4>Drag Chart Contents</h4>
2699                                 Touch and Drag the contents of a chart to pan it horizontally.
2700                                 <br/>
2701                                 All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring).
2702                                 <br/>
2703                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart.
2704                             </div>
2705                             <hr/>
2706                             <div class="p">
2707                                 <h4>Double Tap</h4>
2708                                 Double tap a chart to reset all the charts to their default auto-refreshing state.
2709                             </div>
2710                             <hr/>
2711                             <div class="p">
2712                                 <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4>
2713                                 With two fingers, zoom in or out.
2714                                 <br/>
2715                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2716                             </div>
2717                             <hr/>
2718                             <div class="p">
2719                                 <h4>Legend Operations</h4>
2720                                 Tap on the label or value of a dimension, will select / un-select this dimension.
2721                             </div>
2722                         </div>
2723                     </div>
2724                 </div>
2725                 <div class="modal-footer">
2726                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2727                 </div>
2728             </div>
2729         </div>
2730     </div>
2731
2732     <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
2733         <div class="modal-dialog modal-lg" role="document"  style="display: table;"> <!-- allow the modal to expand horizontally -->
2734             <div class="modal-content">
2735                 <div class="modal-header">
2736                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2737                     <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
2738                 </div>
2739                 <div class="modal-body">
2740                     <!-- Nav tabs -->
2741                     <ul class="nav nav-tabs" role="tablist">
2742                         <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
2743                         <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
2744                         <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
2745                     </ul>
2746
2747                     <!-- Tab panes -->
2748                     <div class="tab-content">
2749                         <div role="tabpanel" class="tab-pane active" id="alarms_active">
2750                             loading...
2751                         </div>
2752                         <div role="tabpanel" class="tab-pane" id="alarms_all">
2753                             loading...
2754                         </div>
2755                         <div role="tabpanel" class="tab-pane" id="alarms_log">
2756                             loading...
2757                         </div>
2758                     </div>
2759                 </div>
2760                 <div class="modal-footer">
2761                     <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
2762                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2763                 </div>
2764             </div>
2765         </div>
2766     </div>
2767
2768     <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
2769         <div class="modal-dialog modal-lg" role="document">
2770             <div class="modal-content">
2771                 <div class="modal-header">
2772                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2773                     <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4>
2774                 </div>
2775                 <div class="modal-body">
2776                     <center>
2777                         <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server.
2778                         <br/>
2779                         Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option).
2780                         <br/>
2781                         To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small>
2782                     </center>
2783                     <div style="padding: 10px;"></div>
2784
2785                     <!-- Nav tabs -->
2786                     <ul class="nav nav-tabs" role="tablist">
2787                         <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li>
2788                         <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li>
2789                         <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li>
2790                     </ul>
2791
2792                     <!-- Tab panes -->
2793                     <div class="tab-content">
2794                         <div role="tabpanel" class="tab-pane active" id="settings_performance">
2795                             <form id="optionsForm1" method="get" class="form-horizontal">
2796                                 <div class="form-group">
2797                                     <table>
2798                                     <tr class="option-row">
2799                                         <td class="option-control"><input id="stop_updates_when_focus_is_lost" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="On Focus" data-off="Always" data-width="110px"></td>
2800                                         <td class="option-info"><strong>When to refresh the charts?</strong><br/>
2801                                             <small>When set to <b>On Focus</b>, the charts will stop being updated if the page / tab does not have the focus of the user. When set to <b>Always</b>, the charts will always be refreshed. Set it to <b>On Focus</b> it to lower the CPU requirements of the browser (and extend the battery of laptops and tablets) when this page does not have your focus. Set to <b>Always</b> to work on another window (i.e. change the settings of something) and have the charts auto-refresh in this window.</small>
2802                                         </td>
2803                                         </tr>
2804                                     <tr class="option-row">
2805                                         <td class="option-control">
2806                                         <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px">
2807                                         </td>
2808                                         <td class="option-info"><strong>Which dimensions to show?</strong><br/>
2809                                             <small>When set to <b>Non Zero</b>, dimensions that have all their values (within the current view) set to zero will not be transferred from the netdata server (except if all dimensions of the chart are zero, in which case this setting does nothing - all dimensions are transferred and shown). When set to <b>All</b>, all dimensions will always be shown. Set it to <b>Non Zero</b> to lower the data transferred between netdata and your browser, lower the CPU requirements of your browser (fewer lines to draw) and increase the focus on the legends (fewer entries at the legends).</small>
2810                                         </td>
2811                                         </tr>
2812                                     <tr class="option-row">
2813                                         <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td>
2814                                         <td class="option-info"><strong>How to handle hidden charts?</strong><br/>
2815                                             <small>When set to <b>Destroy</b>, charts that are not in the current viewport of the browser (are above, or below the visible area of the page), will be destroyed and re-created if and when they become visible again. When set to <b>Hide</b>, the not-visible charts will be just hidden, to simplify the DOM and speed up your browser. Set it to <b>Destroy</b>, to lower the memory requirements of your browser. Set it to <b>Hide</b> for faster restoration of charts on page scrolling.</small>
2816                                         </td>
2817                                         </tr>
2818                                     <tr class="option-row">
2819                                         <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td>
2820                                         <td class="option-info"><strong>Page scroll handling?</strong><br/>
2821                                             <small>When set to <b>Sync</b>, charts will be examined for their visibility synchronously. On slow computers this may impact the smoothness of page scrolling. To work asynchronously set it to <b>Async</b>. When set to <b>Sync</b>, the performance of page scrolling is monitored and this setting switches automatically to <b>Async</b> if the browser is found slow. Set it to <b>Sync</b> for best visual experience. Set it to <b>Async</b> for smoother page scrolling.</small>
2822                                         </td>
2823                                         </tr>
2824                                     </table>
2825                                 </div>
2826                             </form>
2827                         </div>
2828                         <div role="tabpanel" class="tab-pane" id="settings_sync">
2829                             <form id="optionsForm2" method="get" class="form-horizontal">
2830                                 <div class="form-group">
2831                                     <table>
2832                                     <tr class="option-row">
2833                                         <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td>
2834                                         <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/>
2835                                             <small>When set to <b>parallel</b>, visible charts are refreshed in parallel (all queries are sent to netdata server in parallel) and are rendered asynchronously. When set to <b>sequential</b> charts are refreshed one after another. Set it to parallel if your browser can cope with it (most modern browsers do), set it to sequential if you work on an older/slower computer.</small>
2836                                         </td>
2837                                         </tr>
2838                                     <tr class="option-row" id="concurrent_refreshes_row">
2839                                         <td class="option-control"></td>
2840                                         <td class="option-info">
2841                                             <table>
2842                                             <tr class="option-row">
2843                                             <td class="option-control">
2844                                             <input id="concurrent_refreshes" type="checkbox" checked data-toggle="toggle" data-on="Resync" data-off="Best Effort" data-width="110px">
2845                                             </td>
2846                                             <td class="option-info">
2847                                             <strong>Shall we re-sync chart refreshes?</strong><br/>
2848                                             <small>When set to <b>Resync</b>, the dashboard will attempt to re-synchronize all the charts so that they are refreshed concurrently. When set to <b>Best Effort</b>, each chart may be refreshed with a little time difference to the others. Normally, the dashboard starts refreshing them in parallel, but depending on the speed of your computer and the network latencies, charts start having a slight time difference. Setting this to <b>Resync</b> will attempt to re-synchronize the charts on every update. Setting it to <b>Best Effort</b> may lower the pressure on your browser and the network.</small>
2849                                             </td>
2850                                             </tr>
2851                                             </table>
2852                                         </td>
2853                                         </tr>
2854                                     <tr class="option-row">
2855                                         <td class="option-control"><input id="sync_selection" type="checkbox" checked data-toggle="toggle" data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td>
2856                                         <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/>
2857                                             <small>When enabled, a selection on one chart will automatically select the same time on all other visible charts and the legends of all visible charts will be updated to show the selected values. When disabled, only the chart getting the user's attention will be selected. Enable it to get better insights of the data. Disable it if you are on a very slow computer that cannot actually do it.</small>
2858                                         </td>
2859                                         </tr>
2860                                     <tr class="option-row">
2861                                         <td class="option-control"><input id="sync_pan_and_zoom" type="checkbox" checked data-toggle="toggle"  data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td>
2862                                         <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/>
2863                                             <small>When enabled, pan and zoom operations on a chart will be replicated to all charts (even the ones that are not currently visible - of course only when they will become visible). When disabled, pan and zoom operations will not be propagated to other charts.</small>
2864                                         </td>
2865                                         </tr>
2866                                     </table>
2867                                 </div>
2868                             </form>
2869                         </div>
2870                         <div role="tabpanel" class="tab-pane" id="settings_visual">
2871                             <form id="optionsForm3" method="get" class="form-horizontal">
2872                                 <div class="form-group">
2873                                     <table>
2874                                     <tr class="option-row">
2875                                         <td class="option-control"><input id="netdata_theme_control" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="Dark" data-off="White" data-width="110px"></td>
2876                                         <td class="option-info"><strong>Which theme to use?</strong><br/>
2877                                             <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>.
2878                                             <br/>
2879                                             <b>Switching this will reload the dashboard</b>.
2880                                             </small>
2881                                         </td>
2882                                         </tr>
2883                                     <tr class="option-row">
2884                                         <td class="option-control"><input id="show_help" type="checkbox" checked data-toggle="toggle" data-on="Help Me" data-off="No Help" data-width="110px"></td>
2885                                         <td class="option-info"><strong>Do you need help?</strong><br/>
2886                                             <small>Netdata can show some help in some areas to help you use the dashboard. If all these balloons bother you, disable them using this switch.
2887                                             <br/>
2888                                             <b>Switching this will reload the dashboard</b>.
2889                                             </small>
2890                                         </td>
2891                                         </tr>
2892                                     <tr class="option-row">
2893                                         <td class="option-control"><input id="pan_and_zoom_data_padding" type="checkbox" checked data-toggle="toggle"  data-on="Pad" data-off="Don't Pad" data-width="110px"></td>
2894                                         <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
2895                                             <small>When set to <b>Pad</b> the charts will be padded with more data, both before and after the visible area, thus giving the impression the whole database is loaded. This padding will happen only after the first pan or zoom operation on the chart (initially all charts have only the visible data). When set to <b>Don't Pad</b> only the visible data will be transfered from the netdata server, even after the first pan and zoom operation.</small>
2896                                         </td>
2897                                         </tr>
2898                                     <tr class="option-row">
2899                                         <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle"  data-on="Smooth" data-off="Rough" data-width="110px"></td>
2900                                         <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
2901                                             <small>When set to <b>Smooth</b> the charts libraries that support it, will plot smooth curves instead of simple straight lines to connect the points.
2902                                             <br/>
2903                                             Keep in mind <a href="http://dygraphs.com" target="_blank">dygraphs</a>, the main charting library in netdata dashboards, can only smooth line charts. It cannot smooth area or stacked charts. When set to <b>Rough</b>, this setting can lower the CPU resources consumed by your browser.</small>
2904                                         </td>
2905                                         </tr>
2906                                     </table>
2907                                 </div>
2908                             </form>
2909                         </div>
2910                     </div>
2911                 </div>
2912                 <div class="modal-footer">
2913                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2914                 </div>
2915             </div>
2916         </div>
2917     </div>
2918
2919
2920     <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel">
2921         <div class="modal-dialog" role="document">
2922             <div class="modal-content">
2923                 <div class="modal-header">
2924                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2925                     <h4 class="modal-title" id="updateModalLabel">Update Check</h4>
2926                 </div>
2927                 <div class="modal-body">
2928                     Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b>
2929                     <br/>
2930                     <div style="padding: 10px;"></div>
2931                     <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div>
2932                 </div>
2933                 <div class="modal-footer">
2934                     <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a>
2935                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2936                 </div>
2937             </div>
2938         </div>
2939     </div>
2940
2941     <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel">
2942         <div class="modal-dialog" role="document">
2943             <div class="modal-content">
2944                 <div class="modal-header">
2945                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2946                     <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4>
2947                 </div>
2948                 <div class="modal-body">
2949                     You are about to delete, from your personal list of netdata servers, the following server:
2950                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
2951                     <b><span id="deleteRegistryServerName2"></span></b>
2952                     <br/>
2953                     <b><span id="deleteRegistryServerURL"></span></b>
2954                     </p>
2955                     Are you sure you want to do this?
2956                     <br/>
2957                     <div style="padding: 10px;"></div>
2958                     <small>Keep in mind, this server will be added back if and when you visit it again.</small>
2959                     <br/>
2960                     <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
2961                 </div>
2962                 <div class="modal-footer">
2963                     <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button>
2964                     <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a>
2965                 </div>
2966             </div>
2967         </div>
2968     </div>
2969
2970     <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel">
2971         <div class="modal-dialog" role="document">
2972             <div class="modal-content">
2973                 <div class="modal-header">
2974                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2975                     <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4>
2976                 </div>
2977                 <div class="modal-body">
2978                     You can copy and paste the following ID to all your browsers (e.g. work and home).
2979                     <br/>
2980                     All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
2981                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
2982                     <form action="#">
2983                     <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
2984                     </form>
2985                     </p>
2986                     Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
2987                     <p style="padding-top: 10px;"><small>
2988                         Keep in mind that:
2989                         <ul>
2990                             <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li>
2991                             <li>both IDs (your old and the new) must list this netdata at their personal lists.</li>
2992                             <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li>
2993                             <li>to get a new ID, just clear your browser cookies.</li>
2994                         </ul>
2995                     </small></p>
2996                     <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
2997                 </div>
2998                 <div class="modal-footer">
2999                     <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button>
3000                     <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a>
3001                 </div>
3002             </div>
3003         </div>
3004     </div>
3005
3006     <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel">
3007         <div class="modal-dialog" role="document">
3008             <div class="modal-content">
3009                 <div class="modal-header">
3010                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3011                     <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4>
3012                 </div>
3013                 <div class="modal-body">
3014                     Checking known URLs for this server...
3015                     <div  style="padding-top: 20px;">
3016                         <table id="gotoServerList">
3017                         </table>
3018                     </div>
3019                     <p style="padding-top: 10px;"><small>
3020                         Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only.
3021                     </small></p>
3022                     <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3023                 </div>
3024                 <div class="modal-footer">
3025                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3026                 </div>
3027             </div>
3028         </div>
3029     </div>
3030 </body>
3031 </html>
3032 <script type="text/javascript" src="dashboard.js?v20161002-1"></script>