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