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