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