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