]> arthur.barton.de Git - netdata.git/blob - web/index.html
goto-host-from-alarm now searches all known URLs for a host
[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.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>';
713                             document.location = finalURL;
714                         }
715                     }
716                 }
717                 else {
718                     if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
719                         error = 'wrong machine';
720
721                     document.getElementById(guid + '-' + id + '-status').innerHTML = error;
722                     gotoServerValidateRemaining--;
723                     if(gotoServerValidateRemaining <= 0) {
724                         gotoServerMiddleClick = false;
725                         document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
726                     }
727                 }
728             });
729         }, (id * 50) + penaldy);
730     }
731
732     function gotoServerModalHandler(guid) {
733         // console.log('goto server: ' + guid);
734
735         gotoServerStop = false;
736         var checked = {};
737         var len = NETDATA.registry.machines[guid].alternate_urls.length;
738         var count = 0;
739
740         document.getElementById('gotoServerResponse').innerHTML = '';
741         document.getElementById('gotoServerList').innerHTML = '';
742         document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
743         $('#gotoServerModal').modal('show');
744
745         gotoServerValidateRemaining = len;
746         while(len--) {
747             var url = NETDATA.registry.machines[guid].alternate_urls[len];
748             checked[url] = true;
749             gotoServerValidateUrl(count++, guid, url);
750         }
751
752         setTimeout(function() {
753             if(gotoServerStop === false) {
754                 document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
755                 NETDATA.registry.search(guid, function(data) {
756                     // console.log(data);
757                     len = data.urls.length;
758                     while(len--) {
759                         var url = data.urls[len][1];
760                         // console.log(url);
761                         if(typeof checked[url] === 'undefined') {
762                             gotoServerValidateRemaining++;
763                             checked[url] = true;
764                             gotoServerValidateUrl(count++, guid, url);
765                         }
766                     }
767                 });
768             }
769         }, 2000);
770         return false;
771     }
772
773     function gotoServerInit() {
774         $(".registry_link").on('click', function(e) {
775             if(e.which === 2) {
776                 e.preventDefault();
777                 gotoServerMiddleClick = true;
778             }
779             else {
780                 gotoServerMiddleClick = false;
781             }
782
783             return true;
784         });
785     }
786
787     function switchRegistryModalHandler() {
788         document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
789         document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
790         document.getElementById('switchRegistryResponse').innerHTML = '';
791         $('#switchRegistryModal').modal('show');
792     }
793
794     function notifyForSwitchRegistry() {
795         var n = document.getElementById('switchRegistryPersonGUID').value;
796
797         if(n !== '' && n.length === 36) {
798             NETDATA.registry.switch(n, function(result) {
799                 if(result !== null) {
800                     $('#switchRegistryModal').modal('hide');
801                     NETDATA.registry.init();
802                 }
803                 else {
804                     document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
805                 }
806             });
807         }
808         else
809             document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
810     }
811
812     var deleteRegistryUrl = null;
813     function deleteRegistryModalHandler(guid, name, url) {
814         deleteRegistryUrl = url;
815         document.getElementById('deleteRegistryServerName').innerHTML = name;
816         document.getElementById('deleteRegistryServerName2').innerHTML = name;
817         document.getElementById('deleteRegistryServerURL').innerHTML = url;
818         document.getElementById('deleteRegistryResponse').innerHTML = '';
819         $('#deleteRegistryModal').modal('show');
820     }
821
822     function notifyForDeleteRegistry() {
823         if(deleteRegistryUrl) {
824             NETDATA.registry.delete(deleteRegistryUrl, function(result) {
825                 if(result !== null) {
826                     deleteRegistryUrl = null;
827                     $('#deleteRegistryModal').modal('hide');
828                     NETDATA.registry.init();
829                 }
830                 else {
831                     document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
832                 }
833             });
834         }
835     }
836
837     var options = {
838         sparklines_registry: {},
839         menus: {},
840         submenu_names: {},
841         data: null,
842         hostname: 'netdata_server', // will be overwritten by the netdata server
843         categories: new Array(),
844         categories_idx: {},
845         families: new Array(),
846         families_idx: {},
847
848         chartsPerRow: 0,
849         chartsMinWidth: 1450,
850         chartsHeight: 180,
851         sparklinesHeight: 60,
852     };
853
854     // generate a sparkline
855     // used in the documentation
856     function sparkline(chart, dimension, units) {
857         var key = chart + '.' + dimension;
858
859         if(typeof units === 'undefined')
860             units = '';
861
862         if(typeof options.sparklines_registry[key] === 'undefined')
863             options.sparklines_registry[key] = { count: 1 };
864         else
865             options.sparklines_registry[key].count++;
866
867         key = key + '.' + options.sparklines_registry[key].count;
868
869         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 + ')';
870
871         return h;
872     }
873
874     function chartsPerRow(total) {
875         if(options.chartsPerRow === 0) {
876             width = Math.floor(total / options.chartsMinWidth);
877             if(width === 0) width = 1;
878             return width;
879         }
880         else return options.chartsPerRow;
881     }
882
883     function prioritySort(a, b) {
884         if(a.priority < b.priority) return -1;
885         if(a.priority > b.priority) return 1;
886         if(a.name < b.name) return -1;
887         return 1;
888     }
889
890     function sortObjectByPriority(object) {
891         var idx = {};
892         var sorted = new Array();
893
894         for(var i in object) {
895             if(typeof idx[i] === 'undefined') {
896                 idx[i] = object[i];
897                 sorted.push(i);
898             }
899         }
900
901         sorted.sort(function(a, b) {
902             if(idx[a].priority < idx[b].priority) return -1;
903             if(idx[a].priority > idx[b].priority) return 1;
904             if(a < b) return -1;
905             return 1;
906         });
907
908         return sorted;
909     }
910
911
912     // ----------------------------------------------------------------------------
913     // scroll to a section, without changing the browser history
914
915     function scrollToId(hash) {
916         if(hash && hash != '') {
917             var offset = $('#' + hash).offset();
918             if(typeof offset !== 'undefined')
919                 $('html, body').animate({ scrollTop: offset.top }, 0);
920         }
921
922         // we must return false to prevent the default action
923         return false;
924     }
925
926     // ----------------------------------------------------------------------------
927
928     var netdataDashboard = {
929         menu: {},
930         submenu: {},
931         context: {},
932
933         gaugeChart: function(title, width, dimensions, colors) {
934             if(typeof colors === 'undefined')
935                 colors = '';
936
937             if(typeof dimensions === 'undefined')
938                 dimensions = '';
939
940             return '<div data-netdata="CHART_UNIQUE_ID"'
941                                     + ' data-dimensions="' + dimensions + '"'
942                                     + ' data-chart-library="gauge"'
943                                     + ' data-gauge-adjust="width"'
944                                     + ' data-title="' + title + '"'
945                                     + ' data-width="' + width + '"'
946                                     + ' data-before="0"'
947                                     + ' data-after="-CHART_DURATION"'
948                                     + ' data-points="CHART_DURATION"'
949                                     + ' data-colors="' + colors + '"'
950                                     + ' role="application"></div>';
951         },
952
953         anyAttribute: function(obj, attr, key, def) {
954             if(typeof obj[key] !== 'undefined') {
955                 if(typeof obj[key][attr] !== 'undefined')
956                     return obj[key][attr];
957             }
958             return def;
959         },
960
961         menuTitle: function(chart) {
962             if(typeof chart.menu_pattern !== 'undefined') {
963                 return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
964                         + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
965             }
966
967             return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
968         },
969
970         menuIcon: function(chart) {
971             if(typeof chart.menu_pattern !== 'undefined')
972                 return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
973
974             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
975         },
976
977         menuInfo: function(menu) {
978             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null);
979         },
980
981         menuHeight: function(menu, relative) {
982             return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative;
983         },
984
985         submenuTitle: function(menu, submenu) {
986             var key = menu + '.' + submenu;
987             var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');;
988             if(title.length > 28) {
989                 var a = title.substring(0, 13);
990                 var b = title.substring(title.length - 12, title.length);
991                 return a + '...' + b;
992             }
993             return title;
994         },
995
996         submenuInfo: function(menu, submenu) {
997             var key = menu + '.' + submenu;
998             return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null);
999         },
1000
1001         submenuHeight: function(menu, submenu, relative) {
1002             var key = menu + '.' + submenu;
1003             return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative;
1004         },
1005
1006         contextInfo: function(id) {
1007             if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined')
1008                 return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>';
1009             else
1010                 return '';
1011         },
1012
1013         contextHeight: function(id, def) {
1014             if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined')
1015                 return def * netdataDashboard.context[id].height;
1016             else
1017                 return def;
1018         }
1019     };
1020
1021     // ----------------------------------------------------------------------------
1022
1023     // enrich the data structure returned by netdata
1024     // to reflect our menu system and content
1025     function enrichChartData(chart) {
1026         var tmp = chart.type.split('_')[0];
1027
1028         switch(tmp) {
1029             case 'ap':
1030             case 'net':
1031             case 'disk':
1032                 chart.menu = tmp;
1033                 break;
1034
1035             case 'cgroup':
1036                 chart.menu = chart.type;
1037                 if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1038                     chart.menu_pattern = 'cgqemu';
1039                 else
1040                     chart.menu_pattern = 'cgroup';
1041                 break;
1042
1043             case 'apache':
1044             case 'exim':
1045             case 'memcached':
1046             case 'mysql':
1047             case 'named':
1048             case 'nginx':
1049             case 'nut':
1050             case 'phpfpm':
1051             case 'postfix':
1052             case 'redis':
1053             case 'retroshare':
1054             case 'ipfs':
1055             case 'smawebbox':
1056             case 'squid':
1057             case 'snmp':
1058             case 'tomcat':
1059                 chart.menu = chart.type;
1060                 chart.menu_pattern = tmp;
1061                 break;
1062
1063             case 'tc':
1064                 chart.menu = tmp;
1065
1066                 // find a name for this device from fireqos info
1067                 // we strip '_(in|out)' or '(in|out)_'
1068                 if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
1069                     var n = chart.name.split('.')[1];
1070                     if(n.endsWith('_in'))
1071                         options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1072                     else if(n.endsWith('_out'))
1073                         options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1074                     else if(n.startsWith('in_'))
1075                         options.submenu_names[chart.family] = n.slice(3, n.length);
1076                     else if(n.startsWith('out_'))
1077                         options.submenu_names[chart.family] = n.slice(4, n.length);
1078                 }
1079
1080                 // increase the priority of IFB devices
1081                 // to have inbound appear before outbound
1082                 if(chart.id.match(/.*-ifb$/))
1083                     chart.priority--;
1084
1085                 break;
1086
1087             default:
1088                 chart.menu = chart.type;
1089                 break;
1090         }
1091
1092         chart.submenu = chart.family;
1093     }
1094
1095     // ----------------------------------------------------------------------------
1096
1097     function headMain(charts, duration) {
1098         var head = '';
1099
1100         if(typeof charts['system.swap'] !== 'undefined')
1101             head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1102             + ' data-dimensions="free"'
1103             + ' data-append-options="percentage"'
1104             + ' data-chart-library="easypiechart"'
1105             + ' data-title="Free Swap"'
1106             + ' data-units="%"'
1107             + ' data-easypiechart-max-value="100"'
1108             + ' data-width="8%"'
1109             + ' data-before="0"'
1110             + ' data-after="-' + duration.toString() + '"'
1111             + ' data-points="' + duration.toString() + '"'
1112             + ' data-colors="#DD4400"'
1113             + ' role="application"></div>';
1114
1115         if(typeof charts['system.io'] !== 'undefined') {
1116             head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1117             + ' data-dimensions="in"'
1118             + ' data-chart-library="easypiechart"'
1119             + ' data-title="Disk Read"'
1120             + ' data-width="10%"'
1121             + ' data-before="0"'
1122             + ' data-after="-' + duration.toString() + '"'
1123             + ' data-points="' + duration.toString() + '"'
1124             + ' role="application"></div>';
1125
1126             head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1127             + ' data-dimensions="out"'
1128             + ' data-chart-library="easypiechart"'
1129             + ' data-title="Disk Write"'
1130             + ' data-width="10%"'
1131             + ' data-before="0"'
1132             + ' data-after="-' + duration.toString() + '"'
1133             + ' data-points="' + duration.toString() + '"'
1134             + ' role="application"></div>';
1135         }
1136
1137         if(typeof charts['system.cpu'] !== 'undefined')
1138             head += '<div data-netdata="system.cpu"'
1139             + ' data-chart-library="gauge"'
1140             + ' data-title="CPU"'
1141             + ' data-units="%"'
1142             + ' data-gauge-max-value="100"'
1143             + ' data-width="18%"'
1144             + ' data-after="-' + duration.toString() + '"'
1145             + ' data-points="' + duration.toString() + '"'
1146             + ' data-colors="' + NETDATA.colors[12] + '"'
1147             + ' role="application"></div>';
1148
1149         if(typeof charts['system.ipv4'] !== 'undefined') {
1150             head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1151             + ' data-dimensions="received"'
1152             + ' data-chart-library="easypiechart"'
1153             + ' data-title="IPv4 Inbound"'
1154             + ' data-width="10%"'
1155             + ' data-before="0"'
1156             + ' data-after="-' + duration.toString() + '"'
1157             + ' data-points="' + duration.toString() + '"'
1158             + ' role="application"></div>';
1159
1160             head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1161             + ' data-dimensions="sent"'
1162             + ' data-chart-library="easypiechart"'
1163             + ' data-title="IPv4 Outbound"'
1164             + ' data-width="10%"'
1165             + ' data-before="0"'
1166             + ' data-after="-' + duration.toString() + '"'
1167             + ' data-points="' + duration.toString() + '"'
1168             + ' role="application"></div>';
1169         }
1170         else if(typeof charts['system.ipv6'] !== 'undefined') {
1171             head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1172             + ' data-dimensions="received"'
1173             + ' data-chart-library="easypiechart"'
1174             + ' data-title="IPv6 Inbound"'
1175             + ' data-units="kbps"'
1176             + ' data-width="10%"'
1177             + ' data-before="0"'
1178             + ' data-after="-' + duration.toString() + '"'
1179             + ' data-points="' + duration.toString() + '"'
1180             + ' role="application"></div>';
1181
1182             head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1183             + ' data-dimensions="sent"'
1184             + ' data-chart-library="easypiechart"'
1185             + ' data-title="IPv6 Outbound"'
1186             + ' data-units="kbps"'
1187             + ' data-width="10%"'
1188             + ' data-before="0"'
1189             + ' data-after="-' + duration.toString() + '"'
1190             + ' data-points="' + duration.toString() + '"'
1191             + ' role="application"></div>';
1192         }
1193
1194         if(typeof charts['system.ram'] !== 'undefined')
1195             head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1196             + ' data-dimensions="cached|free"'
1197             + ' data-append-options="percentage"'
1198             + ' data-chart-library="easypiechart"'
1199             + ' data-title="Available RAM"'
1200             + ' data-units="%"'
1201             + ' data-easypiechart-max-value="100"'
1202             + ' data-width="8%"'
1203             + ' data-after="-' + duration.toString() + '"'
1204             + ' data-points="' + duration.toString() + '"'
1205             + ' data-colors="' + NETDATA.colors[7] + '"'
1206             + ' role="application"></div>';
1207
1208         return head;
1209     }
1210
1211     function generateHeadCharts(type, chart, duration) {
1212         var head = '';
1213         var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1214         if(hcharts.length > 0) {
1215             var hi = 0, hlen = hcharts.length;
1216             while(hi < hlen) {
1217                 if(typeof hcharts[hi] === 'function')
1218                     head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1219                 else
1220                     head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1221                 hi++;
1222             }
1223         }
1224         return head;
1225     }
1226
1227     function renderPage(menus, data) {
1228         var div = document.getElementById('charts_div');
1229         var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1230
1231         // find the proper duration for per-second updates
1232         var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1233         var html = '';
1234         var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1235         var mainhead = headMain(data.charts, duration);
1236
1237         // sort the menus
1238         var main = sortObjectByPriority(menus);
1239         var i = 0, len = main.length;
1240         while(i < len) {
1241             var menu = main[i++];
1242
1243             // generate an entry at the main menu
1244
1245             var menuid = NETDATA.name2id('menu_' + menu);
1246             sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1247             html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1248
1249             if(menus[menu].info !== null)
1250                 html += menus[menu].info;
1251
1252             // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1253
1254             var shtml = '';
1255             var mhead = '<div class="netdata-chart-row">' + mainhead;
1256             mainhead = '';
1257
1258             // sort the submenus of this menu
1259             var sub = sortObjectByPriority(menus[menu].submenus);
1260             var si = 0, slen = sub.length;
1261             while(si < slen) {
1262                 var submenu = sub[si++];
1263
1264                 // generate an entry at the submenu
1265                 var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1266                 sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1267                 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>';
1268
1269                 if(menus[menu].submenus[submenu].info !== null)
1270                     shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1271
1272                 var head = '<div class="netdata-chart-row">';
1273                 var chtml = '';
1274
1275                 // console.log('    \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1276
1277                 // sort the charts in this submenu of this menu
1278                 menus[menu].submenus[submenu].charts.sort(prioritySort);
1279                 var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1280                 while(ci < clen) {
1281                     var chart = menus[menu].submenus[submenu].charts[ci++];
1282
1283                     // generate the submenu heading charts
1284                     mhead += generateHeadCharts('mainheads', chart, duration);
1285                     head += generateHeadCharts('heads', chart, duration);
1286
1287                     // generate the chart
1288                     chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1289                         + ' data-width="' + pcent_width.toString() + '%"'
1290                         + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1291                         + ' data-before="0"'
1292                         + ' data-after="-' + duration.toString() + '"'
1293                         + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1294                         + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1295                         + ' role="application"></div>';
1296
1297                     // console.log('         \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context  + ' height: ' + menus[menu].submenus[submenu].height);
1298                 }
1299
1300                 head += '</div>';
1301                 shtml += head + chtml + '</div>';
1302             }
1303
1304             mhead += '</div>';
1305             sidebar += '</ul></li>';
1306             html += mhead + shtml + '</div></div><hr role="separator"/>';
1307         }
1308
1309         sidebar += '</ul>';
1310         div.innerHTML = html;
1311         document.getElementById('sidebar').innerHTML = sidebar;
1312         finalizePage();
1313     }
1314
1315     function renderChartsAndMenu(data) {
1316         var menus = options.menus;
1317         var charts = data.charts;
1318
1319         for(var c in charts) {
1320             enrichChartData(charts[c]);
1321
1322             // create the menu
1323             if(typeof menus[charts[c].menu] === 'undefined') {
1324                 menus[charts[c].menu] = {
1325                     priority: charts[c].priority,
1326                     submenus: {},
1327                     title: netdataDashboard.menuTitle(charts[c]),
1328                     icon: netdataDashboard.menuIcon(charts[c]),
1329                     info: netdataDashboard.menuInfo(charts[c].menu),
1330                     height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight)
1331                 };
1332             }
1333
1334             if(charts[c].priority < menus[charts[c].menu].priority)
1335                 menus[charts[c].menu].priority = charts[c].priority;
1336
1337             // create the submenu
1338             if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') {
1339                 menus[charts[c].menu].submenus[charts[c].submenu] = {
1340                     priority: charts[c].priority,
1341                     charts: new Array(),
1342                     title: null,
1343                     info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu),
1344                     height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height)
1345                 };
1346             }
1347
1348             if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority)
1349                 menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority;
1350
1351             // index the chart in the menu/submenu
1352             menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]);
1353         }
1354
1355         // propagate the descriptive subname given to QoS
1356         // to all the other submenus with the same name
1357         for(var m in menus) {
1358             for(var s in menus[m].submenus) {
1359                 // set the family using a name
1360                 if(typeof options.submenu_names[s] !== 'undefined') {
1361                     menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1362                 }
1363                 else {
1364                     menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s);
1365                 }
1366             }
1367         }
1368
1369         renderPage(menus, data);
1370     }
1371
1372     // ----------------------------------------------------------------------------
1373
1374     function loadJs(url, callback) {
1375         $.ajax({
1376             url: url,
1377             cache: true,
1378             dataType: "script",
1379             xhrFields: { withCredentials: true } // required for the cookie
1380         })
1381         .fail(function() {
1382             alert('Cannot load required JS library: ' + url);
1383         })
1384         .always(function() {
1385             if(typeof callback === 'function')
1386                 callback();
1387         })
1388     }
1389
1390     var bootstrapTableLoaded = false;
1391     function loadBootstrapTable(callback) {
1392         if(bootstrapTableLoaded === false) {
1393             bootstrapTableLoaded === true;
1394             loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1395                 loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1396                     loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1397                 })
1398             });
1399         }
1400         else callback();
1401     }
1402
1403     function alarmsUpdateModal() {
1404         var active = '<h3>Raised Alarms</h3><table class="table">';
1405         var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1406         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.';
1407
1408         NETDATA.alarms.get('all', function(data) {
1409             options.alarm_families = new Array();
1410
1411             alarmsCallback(data);
1412
1413             if(data === null) {
1414                 document.getElementById('alarms_active').innerHTML =
1415                         document.getElementById('alarms_all').innerHTML =
1416                                 document.getElementById('alarms_log').innerHTML =
1417                                         'failed to load alarm data!';
1418                 return;
1419             }
1420
1421             function timestamp4human(timestamp, space) {
1422                 if(typeof space === 'undefined')
1423                     space = '&nbsp;';
1424
1425                 var t = new Date(timestamp * 1000);
1426                 var now = new Date();
1427
1428                 if(t.toDateString() == now.toDateString())
1429                     return t.toLocaleTimeString();
1430
1431                 return t.toLocaleDateString() + space + t.toLocaleTimeString();
1432             }
1433
1434             function seconds4human(seconds, sfx, space) {
1435                 if(typeof space === 'undefined')
1436                     space = '&nbsp;';
1437
1438                 if(seconds === 0)
1439                     return 'now';
1440
1441                 var suffix = '';
1442                 if(seconds < 0) {
1443                     seconds = -seconds;
1444                     if(sfx) suffix = space + 'ago';
1445                 }
1446
1447                 var hours = Math.floor(seconds / 3600);
1448                 seconds -= (hours * 3600);
1449
1450                 var minutes = Math.floor(seconds / 60);
1451                 seconds -= (minutes * 60);
1452
1453                 var txt = '';
1454                 
1455                 if(hours > 1) txt += hours.toString() + space + 'hours';
1456                 else if(hours === 1) txt += hours.toString() + space + 'hour';
1457
1458                 if(hours > 0 && minutes > 0 && seconds == 0)
1459                     txt += space + 'and' + space;
1460                 else if(hours > 0 && minutes > 0 && seconds > 0)
1461                     txt += ',' + space;
1462
1463                 if(minutes > 1) txt += minutes.toString() + space + 'minutes';
1464                 else if(minutes === 1) txt += minutes.toString() + space + 'minute';
1465
1466                 if((minutes > 0 || minutes > 0) && seconds > 0)
1467                     txt += space + 'and' + space;
1468
1469                 if(seconds > 1) txt += seconds.toString() + space + 'seconds';
1470                 else if(seconds === 1) txt += seconds.toString() + space + 'second';
1471
1472                 return txt + suffix;
1473             }
1474
1475             function alarm_lookup_explain(alarm, chart) {
1476                 var dimensions = ' of all values ';
1477
1478                 if(chart.dimensions.length > 1)
1479                     dimensions = ' of the sum of all dimensions ';
1480
1481                 if(typeof alarm.lookup_dimensions !== 'undefined') {
1482                     var d = alarm.lookup_dimensions.replace('|', ',');
1483                     var x = d.split(',');
1484                     if(x.length > 1)
1485                         dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1486                     else
1487                         dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1488                 }
1489
1490                 return '<code>' + alarm.lookup_method + '</code> '
1491                     + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1492                     + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before, true) + '</code> and up to <code>' + seconds4human(alarm.lookup_before, true) + '</code>'
1493                     + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1494                     + '.';
1495             }
1496
1497             function alarm_to_html(alarm, full) {
1498                 var chart = options.data.charts[alarm.chart];
1499
1500                 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>'
1501                     + '<td><table class="table">'
1502                     + ((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>'):'')
1503                     + ((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>'):'');
1504
1505                 if(full === true) {
1506                         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>'):'')
1507                         + ((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>'):'')
1508                         + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
1509                         + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
1510                 }
1511
1512                 var delay = '';
1513                 if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1514                     if(alarm.delay_up_duration == alarm.delay_down_duration) {
1515                         delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration);
1516                     }
1517                     else {
1518                         delay = '<small><br/>hysteresis ';
1519                         if(alarm.delay_up_duration > 0) {
1520                             delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration) + '</code>, ';
1521                         }
1522                         if(alarm.delay_down_duration > 0) {
1523                             delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration) + '</code>, ';
1524                         }
1525                     }
1526                     if(alarm.delay_multiplier != 1.0) {
1527                         delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1528                         delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration) + '</code>';
1529                     }
1530                     delay += '</small>';
1531                 }
1532
1533                 html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every) + '</td></tr>'
1534                     + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'
1535                     + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1536                     + '</table></td></tr>';
1537
1538                 return html;
1539             }
1540
1541             function alarm_family_show(id) {
1542                 var html = '<table class="table">';
1543                 var family = options.alarm_families[id];
1544                 var len = family.arr.length;
1545                 while(len--) {
1546                     var alarm = family.arr[len];
1547                     html += alarm_to_html(alarm, true);
1548                 }
1549                 html += '</table>';
1550
1551                 $('#alarm_all_' + id.toString()).html(html);
1552             }
1553
1554             // find the proper family of each alarm
1555             var now = new Date().getTime();
1556             var x;
1557             var count_active = 0;
1558             var count_all = 0;
1559             var families = {};
1560             var families_sort = new Array();
1561             for(x in data.alarms) {
1562                 var alarm = data.alarms[x];
1563                 var family = alarm.family;
1564
1565                 // find the chart
1566                 var chart = options.data.charts[alarm.chart];
1567                 if(typeof chart === 'undefined')
1568                     chart = options.data.charts_by_name[alarm.chart];
1569
1570                 // not found - this should never happen!
1571                 if(typeof chart === 'undefined') {
1572                     console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1573                     chart = { priority: 9999999 };
1574                 }
1575                 else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1576                     // the family based on the chart
1577                     family = chart.menu + ' - ' + chart.submenu;
1578
1579                 if(typeof families[family] === 'undefined') {
1580                     families[family] = {
1581                         name: family,
1582                         arr: new Array(),
1583                         priority: chart.priority
1584                     };
1585
1586                     families_sort.push(families[family]);
1587                 }
1588
1589                 if(chart.priority < families[family].priority)
1590                     families[family].priority = chart.priority;
1591
1592                 families[family].arr.unshift(alarm);
1593             }
1594
1595             // sort the families, like the dashboard menu does
1596             var families_sorted = families_sort.sort(function (a, b) {
1597                 if (a.priority > b.priority) return -1;
1598                 if (a.priority < b.priority) return 1;
1599                 return 0;
1600             });
1601
1602             var fc = 0;
1603             var len = families_sorted.length;
1604             while(len--) {
1605                 var family = families_sorted[len].name;
1606                 var active_family_added = false;
1607                 var expanded = 'true';
1608                 var collapsed = '';
1609                 var cin = 'in';
1610
1611                 if(fc !== 0) {
1612                     all += "</table></div></div></div>";
1613                     expanded = 'false';
1614                     collapsed = 'class="collapsed"'
1615                     cin = '';
1616                 }
1617
1618                 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() + '">';
1619
1620                 options.alarm_families[fc] = families[family];
1621
1622                 fc++;
1623
1624                 var arr = families[family].arr;
1625                 var c = arr.length;
1626                 while(c--) {
1627                     var alarm = arr[c];
1628                     if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1629                         if(!active_family_added) {
1630                             active_family_added = true;
1631                             active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1632                         }
1633                         count_active++;
1634                         active += alarm_to_html(alarm, true);
1635                     }
1636
1637                     count_all++;
1638                 }
1639             }
1640             active += "</table>";
1641             if(families_sorted.length > 0) all += "</div></div></div>";
1642             all += "</div>";
1643
1644             if(!count_active)
1645                 active += "<h4>Everything is normal. No raised alarms.</h4>";
1646             else
1647                 active += footer;
1648
1649             if(!count_all)
1650                 all += "<h4>No alarms are running in this system.</h4>";
1651             else
1652                 all += footer;
1653
1654             document.getElementById('alarms_active').innerHTML = active;
1655             document.getElementById('alarms_all').innerHTML = all;
1656
1657             if(families_sorted.length > 0) alarm_family_show(0);
1658
1659             // register bootstrap events
1660             $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1661                 var target = $(d.target);
1662                 var id = $(target).data('alarm-id');
1663                 alarm_family_show(id);
1664             });
1665             $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1666                 var target = $(d.target);
1667                 var id = $(target).data('alarm-id');
1668                 $('#alarm_all_' + id.toString()).html('');
1669             });
1670
1671             document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1672
1673             loadBootstrapTable(function () {
1674                 $('#alarms_log_table').bootstrapTable({
1675                     url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1676                     cache: false,
1677                     pagination: true,
1678                     pageSize: 10,
1679                     showPaginationSwitch: false,
1680                     search: true,
1681                     searchTimeOut: 300,
1682                     searchAlign: 'left',
1683                     showColumns: true,
1684                     showExport: true,
1685                     exportDataType: 'basic',
1686                     exportOptions: {
1687                         fileName: 'netdata_alarm_log'
1688                     },
1689                     rowStyle: function(row, index) {
1690                         switch(row.status) {
1691                             case 'CRITICAL' : return { classes: 'danger'  }; break;
1692                             case 'WARNING'  : return { classes: 'warning' }; break;
1693                             case 'UNDEFINED': return { classes: 'info'    }; break;
1694                             case 'CLEAR'    : return { classes: 'success' }; break;
1695                         }
1696                         return {};
1697                     },
1698                     showFooter: false,
1699                     showHeader: true,
1700                     showRefresh: true,
1701                     showToggle: false,
1702                     sortable: true,
1703                     silentSort: false,
1704                     columns: [
1705                         {
1706                             field: 'when',
1707                             title: 'Event Date',
1708                             valign: 'middle',
1709                             switchable: false,
1710                             sortable: true,
1711                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1712                         },
1713                         {
1714                             field: 'hostname',
1715                             title: 'Host',
1716                             valign: 'middle',
1717                             visible: false,
1718                             sortable: true
1719                         },
1720                         {
1721                             field: 'unique_id',
1722                             title: 'Unique ID',
1723                             valign: 'middle',
1724                             visible: false,
1725                             sortable: true
1726                         },
1727                         {
1728                             field: 'alarm_id',
1729                             title: 'Alarm ID',
1730                             valign: 'middle',
1731                             visible: false,
1732                             sortable: true
1733                         },
1734                         {
1735                             field: 'alarm_event_id',
1736                             title: 'Alarm Event ID',
1737                             valign: 'middle',
1738                             visible: false,
1739                             sortable: true
1740                         },
1741                         {
1742                             field: 'chart',
1743                             title: 'Chart',
1744                             valign: 'middle',
1745                             switchable: false,
1746                             sortable: true
1747                         },
1748                         {
1749                             field: 'family',
1750                             title: 'Family',
1751                             valign: 'middle',
1752                             visible: false,
1753                             sortable: true
1754                         },
1755                         {
1756                             field: 'name',
1757                             title: 'Alarm',
1758                             formatter: function(value, row, index) {
1759                                 return value.toString().replace(/_/g, ' ');
1760                             },
1761                             valign: 'middle',
1762                             switchable: false,
1763                             sortable: true
1764                         },
1765                         {
1766                             field: 'old_value',
1767                             title: 'Old Value',
1768                             valign: 'middle',
1769                             visible: false,
1770                             sortable: true
1771                         },
1772                         {
1773                             field: 'value',
1774                             title: 'Value',
1775                             formatter: function(value, row, index) {
1776                                 return ((value !== null)?Math.floor(value):'NaN').toString();
1777                             },
1778                             align: 'right',
1779                             valign: 'middle',
1780                             sortable: true
1781                         },
1782                         {
1783                             field: 'units',
1784                             title: 'Units',
1785                             valign: 'middle',
1786                             sortable: true
1787                         },
1788                         {
1789                             field: 'old_status',
1790                             title: 'Old Status',
1791                             valign: 'middle',
1792                             visible: false,
1793                             sortable: true
1794                         },
1795                         {
1796                             field: 'status',
1797                             title: 'Status',
1798                             valign: 'middle',
1799                             switchable: false,
1800                             sortable: true
1801                         },
1802                         {
1803                             field: 'duration',
1804                             title: 'Duration',
1805                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1806                             valign: 'middle',
1807                             visible: false,
1808                             sortable: true
1809                         },
1810                         {
1811                             field: 'non_clear_duration',
1812                             title: 'Raised Duration',
1813                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1814                             valign: 'middle',
1815                             visible: false,
1816                             sortable: true
1817                         },
1818                         {
1819                             field: 'recipient',
1820                             title: 'Recipient',
1821                             valign: 'middle',
1822                             visible: false,
1823                             sortable: true
1824                         },
1825                         {
1826                             field: 'processed',
1827                             title: 'Processed Status',
1828                             valign: 'middle',
1829                             visible: false,
1830                             sortable: true
1831                         },
1832                         {
1833                             field: 'updated',
1834                             title: 'Updated Status',
1835                             valign: 'middle',
1836                             visible: false,
1837                             sortable: true
1838                         },
1839                         {
1840                             field: 'updated_by_id',
1841                             title: 'Updated By ID',
1842                             valign: 'middle',
1843                             visible: false,
1844                             sortable: true
1845                         },
1846                         {
1847                             field: 'updates_id',
1848                             title: 'Updates ID',
1849                             valign: 'middle',
1850                             visible: false,
1851                             sortable: true
1852                         },
1853                         {
1854                             field: 'exec',
1855                             title: 'Script',
1856                             valign: 'middle',
1857                             visible: false,
1858                             sortable: true
1859                         },
1860                         {
1861                             field: 'exec_run',
1862                             title: 'Script Run At',
1863                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1864                             valign: 'middle',
1865                             visible: false,
1866                             sortable: true
1867                         },
1868                         {
1869                             field: 'exec_code',
1870                             title: 'Script Return Value',
1871                             valign: 'middle',
1872                             visible: false,
1873                             sortable: true
1874                         },
1875                         {
1876                             field: 'delay',
1877                             title: 'Script Delay',
1878                             formatter: function(value, row, index) { return seconds4human(value, false, ' '); },
1879                             valign: 'middle',
1880                             visible: false,
1881                             sortable: true
1882                         },
1883                         {
1884                             field: 'delay_up_to_timestamp',
1885                             title: 'Script Delay Run At',
1886                             formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1887                             valign: 'middle',
1888                             visible: false,
1889                             sortable: true
1890                         },
1891                         {
1892                             field: 'info',
1893                             title: 'Description',
1894                             valign: 'middle',
1895                             visible: false,
1896                             sortable: true
1897                         },
1898                         {
1899                             field: 'source',
1900                             title: 'Alarm Source',
1901                             valign: 'middle',
1902                             visible: false,
1903                             sortable: true
1904                         }
1905                     ]
1906                 });
1907                 // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
1908             });
1909         });
1910     }
1911
1912     function alarmsCallback(data) {
1913         var count = 0;
1914         for(x in data.alarms) {
1915             var alarm = data.alarms[x];
1916             if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
1917                 count++;
1918         }
1919
1920         if(count > 0)
1921             document.getElementById('alarms_count_badge').innerHTML = count.toString();
1922         else
1923             document.getElementById('alarms_count_badge').innerHTML = '';
1924     }
1925
1926     function initializeDynamicDashboard(netdata_url) {
1927         if(typeof netdata_url === 'undefined' || netdata_url === null)
1928             netdata_url = NETDATA.serverDefault;
1929
1930         // initialize clickable alarms
1931         NETDATA.alarms.chart_div_offset = 100;
1932         NETDATA.alarms.chart_div_id_prefix = 'chart_';
1933         NETDATA.alarms.chart_div_animation_duration = 0;
1934
1935         NETDATA.pause(function() {
1936             NETDATA.alarms.callback = alarmsCallback;
1937
1938             // download all the charts the server knows
1939             NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
1940                 if(data !== null) {
1941                     options.hostname = data.hostname;
1942                     options.data = data;
1943
1944                     // update the dashboard hostname
1945                     document.getElementById('hostname').innerHTML = options.hostname;
1946                     document.getElementById('hostname').href = NETDATA.serverDefault;
1947
1948                     // update the dashboard title
1949                     document.title = options.hostname + ' netdata dashboard';
1950
1951                     // close the splash screen
1952                     $("#loadOverlay").css("display","none");
1953
1954                     // create a chart_by_name index
1955                     data.charts_by_name = {};
1956                     var charts = data.charts;
1957                     var x;
1958                     for(x in charts) {
1959                         var chart = charts[x];
1960                         data.charts_by_name[chart.name] = chart;
1961                     }
1962
1963                     // render all charts
1964                     renderChartsAndMenu(data);
1965                 }
1966             });
1967         });
1968     }
1969
1970     // ----------------------------------------------------------------------------
1971
1972     function versionLog(msg) {
1973         document.getElementById('versionCheckLog').innerHTML = msg;
1974     }
1975
1976     function getNetdataVersion(callback) {
1977         versionLog('Downloading installed version info from netdata...');
1978
1979         $.ajax({
1980             url: 'version.txt',
1981             async: true,
1982             cache: false,
1983             xhrFields: { withCredentials: true } // required for the cookie
1984         })
1985         .done(function(data) {
1986             data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
1987             if(data.length !== 40) {
1988                 versionLog('Received version string is invalid.');
1989                 callback(null);
1990             }
1991             else {
1992                 versionLog('Installed version of netdata is ' + data);
1993                 document.getElementById('netdataVersion').innerHTML = data;
1994                 callback(data);
1995             }
1996         })
1997         .fail(function() {
1998             versionLog('Failed to download installed version info from netdata!');
1999             callback(null);
2000         });
2001     }
2002
2003     function getGithubLatestCommit(callback) {
2004         versionLog('Downloading latest version info from github...');
2005
2006         $.ajax({
2007             url: 'https://api.github.com/repos/firehol/netdata/commits',
2008             async: true,
2009             cache: false
2010         })
2011         .done(function(data) {
2012             versionLog('Latest version info from github is ' + data[0].sha);
2013             callback(data[0].sha);
2014         })
2015         .fail(function() {
2016             versionLog('Failed to download installed version info from github!');
2017             callback(null);
2018         });
2019     }
2020
2021     function checkForUpdate(callback) {
2022         getNetdataVersion(function(sha1) {
2023             if(sha1 === null) callback(null, null);
2024
2025             getGithubLatestCommit(function(sha2) {
2026                 callback(sha1, sha2);
2027             });
2028         });
2029
2030         return null;
2031     }
2032
2033     function notifyForUpdate(force) {
2034         versionLog('<p>checking for updates...</p>');
2035
2036         var now = new Date().getTime();
2037
2038         if(typeof force === 'undefined' || force !== true) {
2039             var last = loadLocalStorage('last_update_check');
2040
2041             if(typeof last === 'string')
2042                 last = parseInt(last);
2043             else
2044                 last = 0;
2045
2046             if(now - last < 3600000 * 8) {
2047                 // no need to check it - too soon
2048                 return;
2049             }
2050         }
2051
2052         checkForUpdate(function(sha1, sha2) {
2053             var save = false;
2054
2055             if(sha1 === null) {
2056                 save = false;
2057                 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>');
2058             }
2059             else if(sha2 === null) {
2060                 save = false;
2061                 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>');
2062             }
2063             else if(sha1 === sha2) {
2064                 save = true;
2065                 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>');
2066             }
2067             else {
2068                 save = true;
2069                 var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2070
2071                 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>');
2072
2073                 document.getElementById('update_badge').innerHTML = '!';
2074             }
2075
2076             if(save)
2077                 saveLocalStorage('last_update_check', now.toString());
2078         });
2079     }
2080
2081     // ----------------------------------------------------------------------------
2082
2083     function finalizePage() {
2084         // resize all charts - without starting the background thread
2085         // this has to be done while NETDATA is paused
2086         // if we ommit this, the affix menu will be wrong, since all
2087         // the Dom elements are initially zero-sized
2088         NETDATA.parseDom();
2089
2090         if(urlOptions.pan_and_zoom === true)
2091             NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2092
2093         // ------------------------------------------------------------------------
2094         // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2095         $.fn.shorten = function(settings) {
2096             "use strict";
2097
2098             var config = {
2099                 showChars: 750,
2100                 minHideChars: 10,
2101                 ellipsesText: "...",
2102                 moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2103                 lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2104                 onLess: function() { NETDATA.onscroll(); },
2105                 onMore: function() { NETDATA.onscroll(); },
2106                 errMsg: null,
2107                 force: false
2108             };
2109
2110             if (settings) {
2111                 $.extend(config, settings);
2112             }
2113
2114             if ($(this).data('jquery.shorten') && !config.force) {
2115                 return false;
2116             }
2117             $(this).data('jquery.shorten', true);
2118
2119             $(document).off("click", '.morelink');
2120
2121             $(document).on({
2122                 click: function() {
2123
2124                     var $this = $(this);
2125                     if ($this.hasClass('less')) {
2126                         $this.removeClass('less');
2127                         $this.html(config.moreText);
2128                         $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2129                             config.onLess();
2130                         });
2131
2132                     } else {
2133                         $this.addClass('less');
2134                         $this.html(config.lessText);
2135                         $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2136                             config.onMore();
2137                         });
2138                     }
2139                     return false;
2140                 }
2141             }, '.morelink');
2142
2143             return this.each(function() {
2144                 var $this = $(this);
2145
2146                 var content = $this.html();
2147                 var contentlen = $this.text().length;
2148                 if (contentlen > config.showChars + config.minHideChars) {
2149                     var c = content.substr(0, config.showChars);
2150                     if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2151                     {
2152                         var inTag = false; // I'm in a tag?
2153                         var bag = ''; // Put the characters to be shown here
2154                         var countChars = 0; // Current bag size
2155                         var openTags = []; // Stack for opened tags, so I can close them later
2156                         var tagName = null;
2157
2158                         for (var i = 0, r = 0; r <= config.showChars; i++) {
2159                             if (content[i] == '<' && !inTag) {
2160                                 inTag = true;
2161
2162                                 // This could be "tag" or "/tag"
2163                                 tagName = content.substring(i + 1, content.indexOf('>', i));
2164
2165                                 // If its a closing tag
2166                                 if (tagName[0] == '/') {
2167
2168
2169                                     if (tagName != '/' + openTags[0]) {
2170                                         config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2171                                     } else {
2172                                         openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2173                                     }
2174
2175                                 } else {
2176                                     // There are some nasty tags that don't have a close tag like <br/>
2177                                     if (tagName.toLowerCase() != 'br') {
2178                                         openTags.unshift(tagName); // Add to start the name of the tag that opens
2179                                     }
2180                                 }
2181                             }
2182                             if (inTag && content[i] == '>') {
2183                                 inTag = false;
2184                             }
2185
2186                             if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2187                             else {
2188                                 r++;
2189                                 if (countChars <= config.showChars) {
2190                                     bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2191                                     countChars++;
2192                                 } else // Now I have the characters needed
2193                                 {
2194                                     if (openTags.length > 0) // I have unclosed tags
2195                                     {
2196                                         //console.log('They were open tags');
2197                                         //console.log(openTags);
2198                                         for (j = 0; j < openTags.length; j++) {
2199                                             //console.log('Cierro tag ' + openTags[j]);
2200                                             bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2201
2202                                             // 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
2203                                         }
2204                                         break;
2205                                     }
2206                                 }
2207                             }
2208                         }
2209                         c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2210                     }else{
2211                         c+=config.ellipsesText;
2212                     }
2213
2214                     var html = '<div class="shortcontent">' + c +
2215                             '</div><div class="allcontent">' + content +
2216                             '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2217
2218                     $this.html(html);
2219                     $this.find(".allcontent").hide(); // Hide all text
2220                     $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2221                 }
2222             });
2223
2224         };
2225         $(".chart-message").shorten();
2226         // ------------------------------------------------------------------------
2227
2228         // callback for us to track PanAndZoom operations
2229         NETDATA.globalPanAndZoom.callback = netdataPanAndZoomCallback;
2230
2231         // let it run (update the charts)
2232         NETDATA.unpause();
2233
2234         // check if we have to jump to a specific section
2235         scrollToId(urlOptions.hash.replace('#',''));
2236
2237         if(urlOptions.chart !== null) {
2238             NETDATA.alarms.scrollToChart(urlOptions.chart);
2239             //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2240             //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2241             //console.log('hash = ' + urlOptions.hash);
2242         }
2243
2244         /* activate bootstrap sidebar (affix) */
2245         $('#sidebar').affix({
2246             offset: {
2247                 top: (isdemo())?150:0,
2248                 bottom: 0
2249             }
2250         });
2251
2252         /* fix scrolling of very long affix lists
2253            http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2254          */
2255         $('#sidebar').on('affixed.bs.affix', function() {
2256             $(this).removeAttr('style');
2257         });
2258
2259         /* activate bootstrap scrollspy (needed for sidebar) */
2260         $(document.body).scrollspy({
2261             target: '#sidebar',
2262             offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2263         });
2264
2265         // change the URL based on the current position of the screen
2266         $('#sidebar').on('activate.bs.scrollspy', function (e) {
2267             // console.log(e);
2268             var el = $(e.target);
2269             //if(el.find('ul').size() == 0) {
2270             var hash = el.find('a').attr('href');
2271             if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2272                 urlOptions.hash = hash;
2273                 //console.log(urlOptions.hash);
2274                 netdataHashUpdate();
2275             }
2276             //else console.log('hash: not accepting ' + hash);
2277             //}
2278             //else console.log('el.find(): not found');
2279         });
2280
2281         document.getElementById('footer').style.display = 'block';
2282
2283         var update_options_modal = function() {
2284             // console.log('update_options_modal');
2285
2286             var sync_option = function(option) {
2287                 var self = $('#' + option);
2288
2289                 if(self.prop('checked') !== NETDATA.getOption(option)) {
2290                     // console.log('switching ' + option.toString());
2291                     self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2292                 }
2293             }
2294
2295             var theme_sync_option = function(option) {
2296                 var self = $('#' + option);
2297
2298                 self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2299             }
2300
2301             sync_option('eliminate_zero_dimensions');
2302             sync_option('destroy_on_hide');
2303             sync_option('async_on_scroll');
2304             sync_option('parallel_refresher');
2305             sync_option('concurrent_refreshes');
2306             sync_option('sync_selection');
2307             sync_option('sync_pan_and_zoom');
2308             sync_option('stop_updates_when_focus_is_lost');
2309             sync_option('smooth_plot');
2310             sync_option('pan_and_zoom_data_padding');
2311             sync_option('show_help');
2312             theme_sync_option('netdata_theme_control');
2313
2314             if(NETDATA.getOption('parallel_refresher') === false) {
2315                 $('#concurrent_refreshes_row').hide();
2316             }
2317             else {
2318                 $('#concurrent_refreshes_row').show();
2319             }
2320         };
2321         NETDATA.setOption('setOptionCallback', update_options_modal);
2322
2323         // handle options changes
2324         $('#eliminate_zero_dimensions').change(function()       { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2325         $('#destroy_on_hide').change(function()                 { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2326         $('#async_on_scroll').change(function()                 { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2327         $('#parallel_refresher').change(function()              { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2328         $('#concurrent_refreshes').change(function()            { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2329         $('#sync_selection').change(function()                  { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2330         $('#sync_pan_and_zoom').change(function()               { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2331         $('#stop_updates_when_focus_is_lost').change(function() { NETDATA.setOption('stop_updates_when_focus_is_lost', $(this).prop('checked')); });
2332         $('#smooth_plot').change(function()                     { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2333         $('#pan_and_zoom_data_padding').change(function()       { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2334         $('#show_help').change(function()                       {
2335             urlOptions.help = $(this).prop('checked');
2336             NETDATA.setOption('show_help', urlOptions.help);
2337             netdataReload();
2338         });
2339
2340         // this has to be the last
2341         // it reloads the page
2342         $('#netdata_theme_control').change(function() {
2343             urlOptions.theme = $(this).prop('checked')?'slate':'white';
2344             if(setTheme(urlOptions.theme))
2345                 netdataReload();
2346         });
2347
2348         $('#updateModal').on('shown.bs.modal', function() {
2349             notifyForUpdate(true);
2350         });
2351
2352         $('#alarmsModal').on('shown.bs.modal', function() {
2353             NETDATA.pause(alarmsUpdateModal);
2354         });
2355
2356         $('#alarmsModal').on('hidden.bs.modal', function() {
2357             NETDATA.unpause();
2358             document.getElementById('alarms_active').innerHTML =
2359                     document.getElementById('alarms_all').innerHTML =
2360                     document.getElementById('alarms_log').innerHTML =
2361                             'loading...';
2362         });
2363
2364         $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2365             deleteRegistryGuid = null;
2366         });
2367
2368         if(isdemo()) {
2369             if(urlOptions.nowelcome !== true) {
2370                 setTimeout(function() {
2371                     $('#welcomeModal').modal();
2372                 }, 1000);
2373             }
2374
2375             // google analytics when this is used for the home page of the demo sites
2376             // this does not run on user's installations
2377             setTimeout(function() {
2378                 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2379                 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2380                 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2381                 })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2382
2383                 ga('create', 'UA-64295674-3', 'auto');
2384                 ga('send', 'pageview');
2385             }, 2000);
2386         }
2387         else notifyForUpdate();
2388
2389         if(urlOptions.show_alarms === true)
2390             setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2391     }
2392
2393     function resetDashboardOptions() {
2394         var help = NETDATA.options.current.show_help;
2395
2396         NETDATA.resetOptions();
2397         if(setTheme('slate'))
2398             netdataReload();
2399
2400         if(help !== NETDATA.options.current.show_help)
2401             netdataReload();
2402     }
2403
2404     // callback to add the dashboard info to the
2405     // parallel javascript downloader in netdata
2406     var netdataPrepCallback = function() {
2407         NETDATA.requiredCSS.push({
2408             url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2409             isAlreadyLoaded: function() { return false; }
2410         });
2411
2412         NETDATA.requiredJs.push({
2413             url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2414             isAlreadyLoaded: function() { return false; }
2415         });
2416
2417         NETDATA.requiredJs.push({
2418             url: NETDATA.serverDefault + 'dashboard_info.js?v20161002-1',
2419             async: false,
2420             isAlreadyLoaded: function() { return false; }
2421         });
2422
2423         if(isdemo()) {
2424             document.getElementById('masthead').style.display = 'block';
2425         }
2426     }
2427
2428     // our entry point
2429     var netdataCallback = initializeDynamicDashboard;
2430
2431 </script>
2432
2433 <body data-spy="scroll" data-target="#sidebar">
2434     <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
2435         netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>
2436     </div>
2437     <script type="text/javascript">
2438         // change the loadOverlay colors ASAP to match the theme
2439         document.getElementById('loadOverlay').style = (urlOptions.theme === 'slate')?"background-color:#272b30; color: #373b40;":"background-color:#fff; color: #ddd;";
2440     </script>
2441     <nav class="navbar navbar-default navbar-fixed-top" role="banner">
2442         <div class="container">
2443             <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left hidden-sm hidden-xs" role="navigation" style="padding-right: 20px;">
2444                 <ul class="nav navbar-nav">
2445                     <li class="dropdown">
2446                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
2447                         <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu">
2448                             <div class="row">
2449                                 <div class="col-sm-6" style="width: 85%; padding-right: 0;">
2450                                     <ul id="mynetdata_servers" class="multi-column-dropdown">
2451                                         <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2452                                     </ul>
2453                                 </div>
2454                                 <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
2455                                     <ul id="mynetdata_actions1" class="multi-column-dropdown">
2456                                     <li style="color: #999;">&nbsp;</li>
2457                                     </ul>
2458                                 </div>
2459                             </div>
2460                         </ul>
2461                     </li>
2462                 </ul>
2463             </nav>
2464             <div class="navbar-header">
2465                 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse">
2466                     <span class="sr-only">Toggle navigation</span>
2467                     <span class="icon-bar"></span>
2468                     <span class="icon-bar"></span>
2469                     <span class="icon-bar"></span>
2470                 </button>
2471                 <a href="/" class="navbar-brand" id="hostname" title="reload the dashboard">netdata</a>
2472             </div>
2473             <nav class="collapse navbar-collapse navbar-right" role="navigation">
2474                 <ul class="nav navbar-nav">
2475                     <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>
2476                     <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>
2477                     <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>
2478                     <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>
2479                     <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>
2480                     <!--
2481                     <li class="dropdown hidden-md hidden-lg hidden-xs">
2482                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">Menu <strong class="caret"></strong></a>
2483                         <ul class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2484                             <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fa fa-bell"></i> alarms</a></li>
2485                             <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fa fa-sliders"></i> settings</a></li>
2486                             <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank"><i class="fa fa-github"></i> community</a></li>
2487                             <li><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fa fa-question-circle"></i> help</a></li>
2488                         </ul>
2489                     </li>
2490                     -->
2491                     <li class="dropdown hidden-sm hidden-md hidden-lg">
2492                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="current_view">my-netdata <strong class="caret"></strong></a>
2493                         <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu">
2494                             <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
2495                         </ul>
2496                     </li>
2497                 </ul>
2498             </nav>
2499     </nav>
2500         </div>
2501     </nav>
2502
2503     <div id="masthead" style="display: none;">
2504         <div class="container">
2505             <div class="row">
2506                 <div class="col-md-7">
2507                     <h1>Netdata
2508                         <p class="lead">Real-time performance monitoring, in the greatest possible detail</p>
2509                     </h1>
2510                 </div>
2511                 <div class="col-md-5">
2512                     <div class="well well-lg">
2513                         <div class="row">
2514                         <div class="col-md-6">
2515                             <b>Drag</b> charts to pan.
2516                             <b>Shift + wheel</b> on them, to zoom in and out.
2517                             <b>Double-click</b> on them, to reset.
2518                             <b>Hover</b> on them too!
2519                             </div>
2520                         <div class="col-md-6">
2521                             <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>
2522                             </div>
2523                         </div>
2524                     </div>
2525                 </div>
2526             </div>
2527         </div>
2528     </div>
2529
2530     <div class="container">
2531         <div class="row">
2532             <div class="charts-body" role="main">
2533                 <div id="charts_div"></div>
2534             </div>
2535             <div class="sidebar-body hidden-xs hidden-sm" role="complementary">
2536                 <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav>
2537             </div>
2538         </div>
2539     </div>
2540
2541     <div id="footer" class="container" style="display: none;">
2542         <div class="row">
2543             <div class="col-md-10" role="main">
2544                 <div class="p">
2545                     <big><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></big><br/>
2546                     <i class="fa fa-copyright"></i> Copyright 2016, Costa Tsaousis.<br/>
2547                     Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>.<br/>
2548                 </div>
2549                 <div class="p">
2550                     <small>
2551                         <a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a> re-distributes these software tools:
2552
2553                         <i class="fa fa-circle"></i> The excellent <a href="http://dygraphs.com/" target="_blank">Dygraphs.com</a> web chart library,
2554                         <i class="fa fa-copyright"></i> Copyright 2009, Dan Vanderkam, <a href="http://dygraphs.com/legal.html" target="_blank">MIT License</a>
2555
2556                         <i class="fa fa-circle"></i> <a href="https://rendro.github.io/easy-pie-chart/" target="_blank">Easy Pie Chart</a> web chart library,
2557                         <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>
2558
2559                         <i class="fa fa-circle"></i> <a href="http://bernii.github.io/gauge.js/" target="_blank">Gauge.js</a> web chart library,
2560                         <i class="fa fa-copyright"></i> Copyright, Bernard Kobos, <a href="http://bernii.github.io/gauge.js/" target="_blank">MIT License</a>
2561
2562                         <i class="fa fa-circle"></i> <a href="https://jquery.org/" target="_blank">jQuery</a>,
2563                         <i class="fa fa-copyright"></i> Copyright 2015, jQuery Foundation, <a href="https://jquery.org/license/" target="_blank">MIT License</a>
2564
2565                         <i class="fa fa-circle"></i> <a href="http://getbootstrap.com/getting-started/" target="_blank">Bootstrap</a>,
2566                         <i class="fa fa-copyright"></i> Copyright 2015, Twitter, <a href="http://getbootstrap.com/getting-started/#license-faqs" target="_blank">MIT License</a>
2567
2568                         <i class="fa fa-circle"></i> <a href="http://www.bootstraptoggle.com/" target="_blank">Bootstrap Toggle</a>,
2569                         <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>
2570
2571                         <i class="fa fa-circle"></i> <a href="https://jamesflorentino.github.io/nanoScrollerJS/" target="_blank">NanoScroller</a>,
2572                         <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>
2573
2574                         <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
2575                         <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>
2576
2577                         <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.
2578
2579                         <i class="fa fa-circle"></i> <a href="http://bootstrap-table.wenzhixin.net.cn/" target="_blank">bootstrap-table</a>,
2580                         <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>
2581
2582                         <i class="fa fa-circle"></i> <a href="https://github.com/hhurz/tableExport.jquery.plugin" target="_blank">tableExport.jquery.plugin</a>,
2583                         <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>
2584
2585                     </small>
2586                 </div>
2587             </div>
2588         </div>
2589     </div>
2590
2591     <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel">
2592         <div class="modal-dialog modal-lg" role="document">
2593             <div class="modal-content">
2594                 <div class="modal-header">
2595                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2596                     <h4 class="modal-title" id="welcomeModalLabel">Welcome!</h4>
2597                 </div>
2598                 <div class="modal-body">
2599                         <div class="p">
2600                         <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.
2601                         </div>
2602                         <div class="p">
2603                         <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.
2604                         </div>
2605                         <div class="p">
2606                         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.
2607                         </div>
2608                         <div class="p">
2609                         <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>%),
2610                         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).
2611                         </div>
2612                         <div class="p">
2613                         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>!).
2614                         </div>
2615                         <div class="p">
2616                         For more information please refer to the <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata wiki</a></b>.
2617                         </div>
2618                 </div>
2619                 <div class="modal-footer">
2620                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2621                 </div>
2622             </div>
2623         </div>
2624     </div>
2625
2626     <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel">
2627         <div class="modal-dialog modal-lg" role="document">
2628             <div class="modal-content">
2629                 <div class="modal-header">
2630                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2631                     <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4>
2632                 </div>
2633                 <div class="modal-body">
2634
2635                     <h4>Dygraphs (line, area and stacked area charts)</h4>
2636
2637                     <!-- Nav tabs -->
2638                     <ul class="nav nav-tabs" role="tablist">
2639                         <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li>
2640                         <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li>
2641                     </ul>
2642
2643                     <!-- Tab panes -->
2644                     <div class="tab-content">
2645                         <div role="tabpanel" class="tab-pane active" id="help_mouse">
2646                             <div class="p">
2647                                 <h4>Mouse Over / Hover</h4>
2648                                 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).
2649                                 <br/>
2650                                 All the other visible charts will also show and highlight their values for the same timestamp.
2651                             </div>
2652                             <hr/>
2653                             <div class="p">
2654                                 <h4>Drag Chart Contents</h4>
2655                                 Drag the contents of a chart to pan it horizontally.
2656                                 <br/>
2657                                 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).
2658                                 <br/>
2659                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart.
2660                             </div>
2661                             <hr/>
2662                             <div class="p">
2663                                 <h4>Double Click</h4>
2664                                 Double Click a chart to reset all the charts to their default auto-refreshing state.
2665                             </div>
2666                             <hr/>
2667                             <div class="p">
2668                                 <h4>SHIFT + Drag</h4>
2669                                 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:
2670                                 <ul>
2671                                     <li>The already loaded chart contents are zoomed (low resolution)</li>
2672                                     <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li>
2673                                 </ul>
2674                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2675                             </div>
2676                             <hr/>
2677                             <div class="p">
2678                                 <h4>SHIFT + Mouse Wheel <small>(does not work on firefox and IE/Edge)</small></h4>
2679                                 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.
2680                                 <br/>
2681                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2682                             </div>
2683                             <hr/>
2684                             <div class="p">
2685                                 <h4>Legend Operations</h4>
2686                                 Click on the label or value of a dimension, will select / un-select this dimension.
2687                                 <br/>
2688                                 You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions.
2689                             </div>
2690                         </div>
2691                         <div role="tabpanel" class="tab-pane" id="help_touch">
2692                             <div class="p">
2693                                 <h4>Single Tap</h4>
2694                                 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).
2695                                 <br/>
2696                                 All the other visible charts will also show and highlight their values for the same timestamp.
2697                             </div>
2698                             <hr/>
2699                             <div class="p">
2700                                 <h4>Drag Chart Contents</h4>
2701                                 Touch and Drag the contents of a chart to pan it horizontally.
2702                                 <br/>
2703                                 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).
2704                                 <br/>
2705                                 Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart.
2706                             </div>
2707                             <hr/>
2708                             <div class="p">
2709                                 <h4>Double Tap</h4>
2710                                 Double tap a chart to reset all the charts to their default auto-refreshing state.
2711                             </div>
2712                             <hr/>
2713                             <div class="p">
2714                                 <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4>
2715                                 With two fingers, zoom in or out.
2716                                 <br/>
2717                                 Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart.
2718                             </div>
2719                             <hr/>
2720                             <div class="p">
2721                                 <h4>Legend Operations</h4>
2722                                 Tap on the label or value of a dimension, will select / un-select this dimension.
2723                             </div>
2724                         </div>
2725                     </div>
2726                 </div>
2727                 <div class="modal-footer">
2728                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2729                 </div>
2730             </div>
2731         </div>
2732     </div>
2733
2734     <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel">
2735         <div class="modal-dialog modal-lg" role="document"  style="display: table;"> <!-- allow the modal to expand horizontally -->
2736             <div class="modal-content">
2737                 <div class="modal-header">
2738                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2739                     <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4>
2740                 </div>
2741                 <div class="modal-body">
2742                     <!-- Nav tabs -->
2743                     <ul class="nav nav-tabs" role="tablist">
2744                         <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li>
2745                         <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li>
2746                         <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li>
2747                     </ul>
2748
2749                     <!-- Tab panes -->
2750                     <div class="tab-content">
2751                         <div role="tabpanel" class="tab-pane active" id="alarms_active">
2752                             loading...
2753                         </div>
2754                         <div role="tabpanel" class="tab-pane" id="alarms_all">
2755                             loading...
2756                         </div>
2757                         <div role="tabpanel" class="tab-pane" id="alarms_log">
2758                             loading...
2759                         </div>
2760                     </div>
2761                 </div>
2762                 <div class="modal-footer">
2763                     <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> -->
2764                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2765                 </div>
2766             </div>
2767         </div>
2768     </div>
2769
2770     <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel">
2771         <div class="modal-dialog modal-lg" role="document">
2772             <div class="modal-content">
2773                 <div class="modal-header">
2774                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2775                     <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4>
2776                 </div>
2777                 <div class="modal-body">
2778                     <center>
2779                         <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server.
2780                         <br/>
2781                         Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option).
2782                         <br/>
2783                         To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small>
2784                     </center>
2785                     <div style="padding: 10px;"></div>
2786
2787                     <!-- Nav tabs -->
2788                     <ul class="nav nav-tabs" role="tablist">
2789                         <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li>
2790                         <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li>
2791                         <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li>
2792                     </ul>
2793
2794                     <!-- Tab panes -->
2795                     <div class="tab-content">
2796                         <div role="tabpanel" class="tab-pane active" id="settings_performance">
2797                             <form id="optionsForm1" method="get" class="form-horizontal">
2798                                 <div class="form-group">
2799                                     <table>
2800                                     <tr class="option-row">
2801                                         <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>
2802                                         <td class="option-info"><strong>When to refresh the charts?</strong><br/>
2803                                             <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>
2804                                         </td>
2805                                         </tr>
2806                                     <tr class="option-row">
2807                                         <td class="option-control">
2808                                         <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px">
2809                                         </td>
2810                                         <td class="option-info"><strong>Which dimensions to show?</strong><br/>
2811                                             <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>
2812                                         </td>
2813                                         </tr>
2814                                     <tr class="option-row">
2815                                         <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td>
2816                                         <td class="option-info"><strong>How to handle hidden charts?</strong><br/>
2817                                             <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>
2818                                         </td>
2819                                         </tr>
2820                                     <tr class="option-row">
2821                                         <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td>
2822                                         <td class="option-info"><strong>Page scroll handling?</strong><br/>
2823                                             <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>
2824                                         </td>
2825                                         </tr>
2826                                     </table>
2827                                 </div>
2828                             </form>
2829                         </div>
2830                         <div role="tabpanel" class="tab-pane" id="settings_sync">
2831                             <form id="optionsForm2" method="get" class="form-horizontal">
2832                                 <div class="form-group">
2833                                     <table>
2834                                     <tr class="option-row">
2835                                         <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td>
2836                                         <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/>
2837                                             <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>
2838                                         </td>
2839                                         </tr>
2840                                     <tr class="option-row" id="concurrent_refreshes_row">
2841                                         <td class="option-control"></td>
2842                                         <td class="option-info">
2843                                             <table>
2844                                             <tr class="option-row">
2845                                             <td class="option-control">
2846                                             <input id="concurrent_refreshes" type="checkbox" checked data-toggle="toggle" data-on="Resync" data-off="Best Effort" data-width="110px">
2847                                             </td>
2848                                             <td class="option-info">
2849                                             <strong>Shall we re-sync chart refreshes?</strong><br/>
2850                                             <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>
2851                                             </td>
2852                                             </tr>
2853                                             </table>
2854                                         </td>
2855                                         </tr>
2856                                     <tr class="option-row">
2857                                         <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>
2858                                         <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/>
2859                                             <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>
2860                                         </td>
2861                                         </tr>
2862                                     <tr class="option-row">
2863                                         <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>
2864                                         <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/>
2865                                             <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>
2866                                         </td>
2867                                         </tr>
2868                                     </table>
2869                                 </div>
2870                             </form>
2871                         </div>
2872                         <div role="tabpanel" class="tab-pane" id="settings_visual">
2873                             <form id="optionsForm3" method="get" class="form-horizontal">
2874                                 <div class="form-group">
2875                                     <table>
2876                                     <tr class="option-row">
2877                                         <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>
2878                                         <td class="option-info"><strong>Which theme to use?</strong><br/>
2879                                             <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>.
2880                                             <br/>
2881                                             <b>Switching this will reload the dashboard</b>.
2882                                             </small>
2883                                         </td>
2884                                         </tr>
2885                                     <tr class="option-row">
2886                                         <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>
2887                                         <td class="option-info"><strong>Do you need help?</strong><br/>
2888                                             <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.
2889                                             <br/>
2890                                             <b>Switching this will reload the dashboard</b>.
2891                                             </small>
2892                                         </td>
2893                                         </tr>
2894                                     <tr class="option-row">
2895                                         <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>
2896                                         <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/>
2897                                             <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>
2898                                         </td>
2899                                         </tr>
2900                                     <tr class="option-row">
2901                                         <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle"  data-on="Smooth" data-off="Rough" data-width="110px"></td>
2902                                         <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/>
2903                                             <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.
2904                                             <br/>
2905                                             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>
2906                                         </td>
2907                                         </tr>
2908                                     </table>
2909                                 </div>
2910                             </form>
2911                         </div>
2912                     </div>
2913                 </div>
2914                 <div class="modal-footer">
2915                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2916                 </div>
2917             </div>
2918         </div>
2919     </div>
2920
2921
2922     <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel">
2923         <div class="modal-dialog" role="document">
2924             <div class="modal-content">
2925                 <div class="modal-header">
2926                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2927                     <h4 class="modal-title" id="updateModalLabel">Update Check</h4>
2928                 </div>
2929                 <div class="modal-body">
2930                     Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b>
2931                     <br/>
2932                     <div style="padding: 10px;"></div>
2933                     <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div>
2934                 </div>
2935                 <div class="modal-footer">
2936                     <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a>
2937                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
2938                 </div>
2939             </div>
2940         </div>
2941     </div>
2942
2943     <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel">
2944         <div class="modal-dialog" role="document">
2945             <div class="modal-content">
2946                 <div class="modal-header">
2947                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2948                     <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4>
2949                 </div>
2950                 <div class="modal-body">
2951                     You are about to delete, from your personal list of netdata servers, the following server:
2952                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
2953                     <b><span id="deleteRegistryServerName2"></span></b>
2954                     <br/>
2955                     <b><span id="deleteRegistryServerURL"></span></b>
2956                     </p>
2957                     Are you sure you want to do this?
2958                     <br/>
2959                     <div style="padding: 10px;"></div>
2960                     <small>Keep in mind, this server will be added back if and when you visit it again.</small>
2961                     <br/>
2962                     <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
2963                 </div>
2964                 <div class="modal-footer">
2965                     <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button>
2966                     <a href="#" onclick="notifyForDeleteRegistry(true); return false;" type="button" class="btn btn-danger">delete it</a>
2967                 </div>
2968             </div>
2969         </div>
2970     </div>
2971
2972     <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel">
2973         <div class="modal-dialog" role="document">
2974             <div class="modal-content">
2975                 <div class="modal-header">
2976                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
2977                     <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4>
2978                 </div>
2979                 <div class="modal-body">
2980                     You can copy and paste the following ID to all your browsers (e.g. work and home).
2981                     <br/>
2982                     All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
2983                     <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
2984                     <form action="#">
2985                     <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
2986                     </form>
2987                     </p>
2988                     Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
2989                     <p style="padding-top: 10px;"><small>
2990                         Keep in mind that:
2991                         <ul>
2992                             <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li>
2993                             <li>both IDs (your old and the new) must list this netdata at their personal lists.</li>
2994                             <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li>
2995                             <li>to get a new ID, just clear your browser cookies.</li>
2996                         </ul>
2997                     </small></p>
2998                     <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
2999                 </div>
3000                 <div class="modal-footer">
3001                     <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button>
3002                     <a href="#" onclick="notifyForSwitchRegistry(true); return false;" type="button" class="btn btn-danger">impersonate</a>
3003                 </div>
3004             </div>
3005         </div>
3006     </div>
3007
3008     <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel">
3009         <div class="modal-dialog" role="document">
3010             <div class="modal-content">
3011                 <div class="modal-header">
3012                     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3013                     <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4>
3014                 </div>
3015                 <div class="modal-body">
3016                     Checking known URLs for this server...
3017                     <div  style="padding-top: 20px;">
3018                         <table id="gotoServerList">
3019                         </table>
3020                     </div>
3021                     <p style="padding-top: 10px;"><small>
3022                         Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only.
3023                     </small></p>
3024                     <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div>
3025                 </div>
3026                 <div class="modal-footer">
3027                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
3028                 </div>
3029             </div>
3030         </div>
3031     </div>
3032 </body>
3033 </html>
3034 <script type="text/javascript" src="dashboard.js?v20161002-1"></script>