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