]> arthur.barton.de Git - netdata.git/blob - web/dashboard.js
Merge pull request #35 from alonbl/cleanups
[netdata.git] / web / dashboard.js
1 // You can set the following variables before loading this script:
2 //
3 // var netdataStopDygraph = 1;                  // do not use dygraph
4 // var netdataStopSparkline = 1;                // do not use sparkline
5 // var netdataStopPeity = 1;                    // do not use peity
6 //
7 // You can also set the default netdata server, using the following.
8 // When this variable is not set, we assume the page is hosted on your
9 // netdata server already.
10 // var netdataServer = "http://yourhost:19999"; // set your NetData server
11
12 // --------------------------------------------------------------------------------------------------------------------
13 // For google charts you need this in your page:
14 //      <script type="text/javascript" src="https://www.google.com/jsapi"></script>
15 //      <script type='text/javascript'>google.load('visualization', '1.1', {'packages':['corechart', 'controls']});</script>
16
17 (function(window)
18 {
19         var NETDATA = window.NETDATA || {};
20
21         // ----------------------------------------------------------------------------------------------------------------
22         // Detect the netdata server
23
24         // http://stackoverflow.com/questions/984510/what-is-my-script-src-url
25         // http://stackoverflow.com/questions/6941533/get-protocol-domain-and-port-from-url
26         NETDATA._scriptSource = function(scripts) {
27                 var script = null, base = null;
28
29                 if(typeof document.currentScript != 'undefined') {
30                         script = document.currentScript;
31                 }
32                 else {
33                         var all_scripts = document.getElementsByTagName('script');
34                         script = all_scripts[all_scripts.length - 1];
35                 }
36
37                 if (script.getAttribute.length != 'undefined')
38                         script = script.src;
39                 else
40                         script = script.getAttribute('src', -1);
41
42                 var link = document.createElement('a');
43                 link.setAttribute('href', script);
44
45                 if(!link.protocol || !link.hostname) return null;
46
47                 base = link.protocol;
48                 if(base) base += "//";
49                 base += link.hostname;
50
51                 if(link.port) base += ":" + link.port;
52                 base += "/";
53
54                 return base;
55         };
56
57         if(typeof netdataServer != 'undefined')
58                 NETDATA.serverDefault = netdataServer + "/";
59         else
60                 NETDATA.serverDefault = NETDATA._scriptSource();
61
62         NETDATA.jQuery       = NETDATA.serverDefault + 'lib/jquery-1.11.3.min.js';
63         NETDATA.peity_js     = NETDATA.serverDefault + 'lib/jquery.peity.min.js';
64         NETDATA.sparkline_js = NETDATA.serverDefault + 'lib/jquery.sparkline.min.js';
65         NETDATA.dygraph_js   = NETDATA.serverDefault + 'lib/dygraph-combined.js';
66         NETDATA.raphael_js   = NETDATA.serverDefault + 'lib/raphael-min.js';
67         NETDATA.morris_js    = NETDATA.serverDefault + 'lib/morris.min.js';
68         NETDATA.morris_css   = NETDATA.serverDefault + 'css/morris.css';
69         NETDATA.google_js    = 'https://www.google.com/jsapi';
70         NETDATA.colors  = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6', '#DD4477',
71                 '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11', '#6633CC', '#E67300', '#8B0707',
72                 '#329262', '#5574A6', '#3B3EAC' ];
73
74         // ----------------------------------------------------------------------------------------------------------------
75         // the defaults for all charts
76
77         NETDATA.chartDefaults = {
78                 host: NETDATA.serverDefault,    // the server to get data from
79                 width: 100,                                             // the chart width
80                 height: 20,                                             // the chart height
81                 library: 'peity',                               // the graphing library to use
82                 method: 'average',                              // the grouping method
83                 before: 0,                                              // panning
84                 after: -600,                                    // panning
85                 point_width: 1,                                 // the detail of the chart
86         }
87
88         NETDATA.all_url = 'all2.js';
89         NETDATA.idle_between_charts = 50;
90         NETDATA.idle_between_loops = 100;
91         NETDATA.debug = 1;
92
93         if(NETDATA.debug) console.log('welcome to NETDATA');
94
95
96         // ----------------------------------------------------------------------------------------------------------------
97         // Error Handling
98
99         NETDATA.errorCodes = {
100                 100: { message: "Cannot load chart library", alert: true },
101                 101: { message: "Cannot load jQuery", alert: true },
102                 402: { message: "Chart library not found", alert: false },
103                 404: { message: "Chart not found", alert: false },
104         };
105         NETDATA.errorLast = {
106                 code: 0,
107                 message: "",
108                 datetime: 0,
109         };
110
111         NETDATA.error = function(code, msg) {
112                 NETDATA.errorLast.code = code;
113                 NETDATA.errorLast.message = msg;
114                 NETDATA.errorLast.datetime = new Date().getTime();
115
116                 console.log("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg);
117
118                 if(NETDATA.errorCodes[code].alert)
119                         alert("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg);
120         }
121
122         NETDATA.errorReset = function() {
123                 NETDATA.errorLast.code = 0;
124                 NETDATA.errorLast.message = "You are doing fine!";
125                 NETDATA.errorLast.datetime = 0;
126         }
127
128         NETDATA.messageInABox = function(div, width, height, message) {
129                 div.innerHTML = '<table border="0"><tr><td width="' + width + '" height="' + height
130                         + '" valign="middle" align="center">'
131                         + message
132                         + '</td></tr></table>';
133         }
134
135         // ----------------------------------------------------------------------------------------------------------------
136         // Load a script without jquery
137         // This is used to load jquery - after it is loaded, we use jquery
138
139         NETDATA._loadjQuery = function(callback) {
140                 if(typeof jQuery == 'undefined') {
141                         var script = document.createElement('script');
142                         script.type = 'text/javascript';
143                         script.async = true;
144                         script.src = NETDATA.jQuery;
145
146                         // script.onabort = onError;
147                         script.onerror = function(err, t) { NETDATA.error(101, NETDATA.jQuery); };
148                         if(typeof callback == "function")
149                                 script.onload = callback;
150
151                         var s = document.getElementsByTagName('script')[0];
152                         s.parentNode.insertBefore(script, s);
153                 }
154                 else if(typeof callback == "function")
155                         callback();
156         }
157
158         NETDATA.generateDataURL = function(args) {
159                 // build the data URL
160                 var url = args.host + args.url;
161                 url += "&points=";
162                 url += args.points.toString();
163                 url += "&group=";
164                 url += args.method;
165                 url += "&after=";
166                 url += args.after || "0";
167                 url += "&before=";
168                 url += args.before || "0";
169                 url += "&options=" + NETDATA.chartLibraries[args.library].options + '|';
170                 url += (args.non_zero)?"nonzero":"";
171                 url += "&format=" + NETDATA.chartLibraries[args.library].format;
172
173                 if(args.dimensions)
174                         url += "&dimensions=" + args.dimensions;
175
176                 if(NETDATA.debug) console.log('generateDataURL(' + args + ') = ' + url );
177                 return url;
178         }
179
180         NETDATA.loadCharts = function(targets, index, callback) {
181                 if(NETDATA.debug) console.log('loadCharts(<targets, ' + index + ')');
182
183                 var target = targets.get(index);
184
185                 if(target == null) {
186                         console.log('loaded all charts');
187                         callback();
188                 }
189                 else {
190                         var self = $(target);
191
192                         if(!self.data('loaded')) {
193                                 var id = self.data('netdata');
194
195                                 var host = self.data('host') || NETDATA.chartDefaults.host;
196                                 var width = self.data('width') || NETDATA.chartDefaults.width;
197                                 var height = self.data('height') || NETDATA.chartDefaults.height;
198                                 var method = self.data('method') || NETDATA.chartDefaults.method;
199                                 var after = self.data('after') || NETDATA.chartDefaults.after;
200                                 var before = self.data('before') || NETDATA.chartDefaults.before;
201                                 var host = self.data('host') || NETDATA.chartDefaults.host;
202                                 var library = self.data('chart-library') || NETDATA.chartDefaults.library;
203                                 var dimensions = self.data('dimensions') || null;
204
205                                 if(typeof NETDATA.chartLibraries[library] == 'undefined') {
206                                         NETDATA.error(402, library);
207                                         NETDATA.messageInABox(target, width, height, 'chart library "' + library + '" is not found');
208                                         self.data('enabled', false);
209                                         NETDATA.loadCharts(targets, ++index, callback);
210                                 }
211                                 else {
212                                         var url = host + "/api/v1/chart?chart=" + id;
213
214                                         $.ajax( {
215                                                 url:  url,
216                                                 crossDomain: true
217                                         })
218                                         .done(function(chart) {
219
220                                                 var point_width = self.data('point-width') || NETDATA.chartLibraries[library].pixels;
221                                                 var points = self.data('points') || Math.round(width / point_width);
222
223                                                 var url = NETDATA.generateDataURL({
224                                                         host: host,
225                                                         url: chart.data_url,
226                                                         dimensions: dimensions,
227                                                         library: library,
228                                                         method: method,
229                                                         before: before,
230                                                         points: points,
231                                                         after: after,
232                                                         non_zero: null
233                                                 });
234
235                                                 // done processing of this DIV
236                                                 // store the processing result, in
237                                                 // 'data' sections in the DIV
238                                                 self
239                                                         .data('chart', chart)
240                                                         .data('chart-url', url)
241                                                         .data('last-updated', 0)
242                                                         .data('update-every', chart.update_every * 1000)
243                                                         .data('enabled', true);
244                                         })
245                                         .fail(function() {
246                                                 NETDATA.error(404, url);
247                                                 NETDATA.messageInABox(target, width, height, 'chart "' + id + '" not found on url "' + url + '"');
248                                                 self.data('enabled', false);
249                                         })
250                                         .always(function() {
251                                                 NETDATA.loadCharts(targets, ++index, callback);
252                                         });
253                                 }
254                         }
255                 }
256         }
257
258         function netdataParsePageCharts() {
259                 if(NETDATA.debug) console.log('processing web page defined charts');
260
261                 // targets
262                 // a list of all DIVs containing netdata charts
263
264                 var targets = $('div[data-netdata]')
265                 .bind('create', function(event, data) {
266                         var self = $(this);
267                         var lib = self.data('chart-library') || 'dygraph';
268                         var method = lib + 'ChartCreate';
269
270                         console.log('Calling ' + method + '()');
271                         NETDATA[method].apply(this, arguments);
272                 })
273                 .bind('update', function() {
274                         var self = $(this);
275                         var lib = self.data('chart-library') || 'dygraph';
276                         var method = lib + 'ChartUpdate';
277
278                         console.log('Calling ' + method + '()');
279                         NETDATA[method].apply(this, arguments);
280                 });
281
282                 NETDATA.loadCharts(targets, 0, function() {
283                         // done processing all netdata DIVs in this page
284                         // call the refresh handler
285                         netdataRefreshTargets(targets, 0);
286                 });
287         }
288
289         // ----------------------------------------------------------------------------------------------------------------
290         // Charts Libraries Registration
291
292         NETDATA.chartLibraries = {};
293
294         NETDATA.registerChartLibrary = function(library, url, format, options, min_pixels_per_point) {
295                 console.log("registering chart library: " + library);
296
297                 NETDATA.chartLibraries[library] = {
298                         initialized: new Date().getTime(),
299                         url: url,
300                         format: format,
301                         options: options,
302                         pixels: min_pixels_per_point
303                 };
304
305                 console.log(NETDATA.chartLibraries);
306         }
307
308         // ----------------------------------------------------------------------------------------------------------------
309
310         //var chart = function() {
311         //}
312
313         //chart.prototype.color = function() {
314         //      return 'red';
315         //}
316
317         //var c = new chart();
318         //c.color();
319
320         function netdataDownloadChartData(callback) {
321                 var self = $(this);
322                 var last = self.data('last-updated') || 0;
323                 var every = self.data('update-every') || 1;
324
325                 // check if this chart has to be refreshed now
326                 var now = new Date().getTime();
327                 if(last + every > now) {
328                         if(typeof callback == 'function')
329                                 callback();
330                 }
331                 else {
332                         var url = self.data('chart-url');
333
334                         if(NETDATA.debug) console.log('netdataDownloadChartData(): downloading ' + url);
335
336                         $.ajax( {
337                                 url: url,
338                                 crossDomain: true
339                         })
340                         .then(function(data) {
341                                 //var result = $.map(data.rows, function(item) {
342                                         // get from the 3rd column the 'v' member
343                                         //return item.c[3].v;
344                                 //});
345
346                                 // since we downloaded the data
347                                 // update the last-updated time to prevent
348                                 // another download too soon
349                                 self.data('last-updated', new Date().getTime());
350
351                                 // render it
352                                 var created = self.data('created');
353                                 self.trigger((created ? 'update' : 'create'), [data]).data('created', true)
354                         })
355                         .fail(function() {
356                                 console.log('failed to download chart data');
357                         })
358                         .always(function() {
359                                 var last = self.data('last-updated');
360                                 var now = new Date().getTime();
361                                 var dt = now - last;
362                                 self.data('refresh-dt', dt);
363
364                                 var element_name = self.data('dt-element-name') || null;
365                                 if(element_name) {
366                                         var element = document.getElementById(element_name) || null;
367                                         if(element) {
368                                                 element.innerHTML = dt.toString();
369                                         }
370                                 }
371
372                                 if(typeof callback == 'function')
373                                         callback();
374                         });
375                 }
376         };
377
378         function netdataRefreshTargets(targets, index) {
379                 // if(NETDATA.debug) console.log('netdataRefreshTargets(<targets, ' + index + ')');
380
381                 var target = targets.get(index);
382
383                 if(target == null) {
384                         console.log('restart');
385
386                         // finished, restart
387                         setTimeout(function() {
388                                 netdataRefreshTargets(targets, 0);
389                         }, NETDATA.idle_between_loops);
390                 }
391                 else {
392                         var self = $(target);
393
394                         if(!self.data('enabled')) {
395                                 netdataRefreshTargets(targets, ++index);
396                         }
397                         else {
398                                 setTimeout(function() {
399                                         netdataDownloadChartData.call(target, function() {
400                                                 netdataRefreshTargets(targets, ++index);
401                                         });
402                                 }, NETDATA.idle_between_charts);
403                         }
404                 }
405         }
406
407         NETDATA.guid = function() {
408                 function s4() {
409                         return Math.floor((1 + Math.random()) * 0x10000)
410                                         .toString(16)
411                                         .substring(1);
412                         }
413
414                         return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
415         }
416
417         // ----------------------------------------------------------------------------------------------------------------
418         // piety
419
420         NETDATA.peityInitialize = function(callback) {
421                 if(typeof netdataStopPeity == 'undefined') {
422                         $.getScript(NETDATA.peity_js)
423                                 .done(function() {
424                                         NETDATA.registerChartLibrary('peity', NETDATA.peity_js, 'ssvcomma', 'null2zero|flip|min2max', 2);
425                                 })
426                                 .fail(function() {
427                                         NETDATA.error(100, NETDATA.peity_js);
428                                 })
429                                 .always(function() {
430                                         if(typeof callback == "function")
431                                                 callback();
432                                 })
433                 }
434                 else if(typeof callback == "function")
435                         callback();
436         };
437
438         NETDATA.peityChartUpdate = function(event, data) {
439                 var self = $(this);
440                 var instance = self.html(data).not('[data-created]');
441                 instance.change();
442         }
443
444         NETDATA.peityChartCreate = function(event, data) {
445                 var self = $(this);
446                 var width = self.data('width') || NETDATA.chartDefaults.width;
447                 var height = self.data('height') || NETDATA.chartDefaults.height;
448                 var instance = self.html(data).not('[data-created]');
449
450                 instance.peity('line', {
451                         width: width,
452                         height: height
453                 })
454                 .data('created', true);
455         }
456
457         // ----------------------------------------------------------------------------------------------------------------
458         // sparkline
459
460         NETDATA.sparklineInitialize = function(callback) {
461                 if(typeof netdataStopSparkline == 'undefined') {
462                         $.getScript(NETDATA.sparkline_js)
463                                 .done(function() {
464                                         NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js, 'array', 'flip|min2max', 2);
465                                 })
466                                 .fail(function() {
467                                         NETDATA.error(100, NETDATA.sparkline_js);
468                                 })
469                                 .always(function() {
470                                         if(typeof callback == "function")
471                                                 callback();
472                                 })
473                 }
474                 else if(typeof callback == "function")
475                         callback();
476         };
477
478         NETDATA.sparklineChartUpdate = function(event, data) {
479                 var self = $(this);
480                 var options = self.data('sparkline-options');
481                 self.sparkline(data, options);
482         }
483
484         NETDATA.sparklineChartCreate = function(event, data) {
485                 var self = $(this);
486                 var chart = self.data('chart');
487                 var width = self.data('width') || NETDATA.chartDefaults.width;
488                 var height = self.data('height') || NETDATA.chartDefaults.height;
489                 var type = self.data('sparkline-type') || 'line';
490                 var lineColor = self.data('sparkline-lineColor') || undefined;
491                 var fillColor = self.data('sparkline-fillColor') || (chart.chart_type == 'line')?'#FFF':undefined;
492                 var chartRangeMin = self.data('sparkline-chartRangeMin') || undefined;
493                 var chartRangeMax = self.data('sparkline-chartRangeMax') || undefined;
494                 var composite = self.data('sparkline-composite') || undefined;
495                 var enableTagOptions = self.data('sparkline-enableTagOptions') || undefined;
496                 var tagOptionPrefix = self.data('sparkline-tagOptionPrefix') || undefined;
497                 var tagValuesAttribute = self.data('sparkline-tagValuesAttribute') || undefined;
498                 var disableHiddenCheck = self.data('sparkline-disableHiddenCheck') || undefined;
499                 var defaultPixelsPerValue = self.data('sparkline-defaultPixelsPerValue') || undefined;
500                 var spotColor = self.data('sparkline-spotColor') || undefined;
501                 var minSpotColor = self.data('sparkline-minSpotColor') || undefined;
502                 var maxSpotColor = self.data('sparkline-maxSpotColor') || undefined;
503                 var spotRadius = self.data('sparkline-spotRadius') || undefined;
504                 var valueSpots = self.data('sparkline-valueSpots') || undefined;
505                 var highlightSpotColor = self.data('sparkline-highlightSpotColor') || undefined;
506                 var highlightLineColor = self.data('sparkline-highlightLineColor') || undefined;
507                 var lineWidth = self.data('sparkline-lineWidth') || undefined;
508                 var normalRangeMin = self.data('sparkline-normalRangeMin') || undefined;
509                 var normalRangeMax = self.data('sparkline-normalRangeMax') || undefined;
510                 var drawNormalOnTop = self.data('sparkline-drawNormalOnTop') || undefined;
511                 var xvalues = self.data('sparkline-xvalues') || undefined;
512                 var chartRangeClip = self.data('sparkline-chartRangeClip') || undefined;
513                 var xvalues = self.data('sparkline-xvalues') || undefined;
514                 var chartRangeMinX = self.data('sparkline-chartRangeMinX') || undefined;
515                 var chartRangeMaxX = self.data('sparkline-chartRangeMaxX') || undefined;
516                 var disableInteraction = self.data('sparkline-disableInteraction') || false;
517                 var disableTooltips = self.data('sparkline-disableTooltips') || false;
518                 var disableHighlight = self.data('sparkline-disableHighlight') || false;
519                 var highlightLighten = self.data('sparkline-highlightLighten') || 1.4;
520                 var highlightColor = self.data('sparkline-highlightColor') || undefined;
521                 var tooltipContainer = self.data('sparkline-tooltipContainer') || undefined;
522                 var tooltipClassname = self.data('sparkline-tooltipClassname') || undefined;
523                 var tooltipFormat = self.data('sparkline-tooltipFormat') || undefined;
524                 var tooltipPrefix = self.data('sparkline-tooltipPrefix') || undefined;
525                 var tooltipSuffix = self.data('sparkline-tooltipSuffix') || ' ' + chart.units;
526                 var tooltipSkipNull = self.data('sparkline-tooltipSkipNull') || true;
527                 var tooltipValueLookups = self.data('sparkline-tooltipValueLookups') || undefined;
528                 var tooltipFormatFieldlist = self.data('sparkline-tooltipFormatFieldlist') || undefined;
529                 var tooltipFormatFieldlistKey = self.data('sparkline-tooltipFormatFieldlistKey') || undefined;
530                 var numberFormatter = self.data('sparkline-numberFormatter') || function(n){ return n.toFixed(2); };
531                 var numberDigitGroupSep = self.data('sparkline-numberDigitGroupSep') || undefined;
532                 var numberDecimalMark = self.data('sparkline-numberDecimalMark') || undefined;
533                 var numberDigitGroupCount = self.data('sparkline-numberDigitGroupCount') || undefined;
534                 var animatedZooms = self.data('sparkline-animatedZooms') || false;
535
536                 var options = {
537                         type: type,
538                         lineColor: lineColor,
539                         fillColor: fillColor,
540                         chartRangeMin: chartRangeMin,
541                         chartRangeMax: chartRangeMax,
542                         composite: composite,
543                         enableTagOptions: enableTagOptions,
544                         tagOptionPrefix: tagOptionPrefix,
545                         tagValuesAttribute: tagValuesAttribute,
546                         disableHiddenCheck: disableHiddenCheck,
547                         defaultPixelsPerValue: defaultPixelsPerValue,
548                         spotColor: spotColor,
549                         minSpotColor: minSpotColor,
550                         maxSpotColor: maxSpotColor,
551                         spotRadius: spotRadius,
552                         valueSpots: valueSpots,
553                         highlightSpotColor: highlightSpotColor,
554                         highlightLineColor: highlightLineColor,
555                         lineWidth: lineWidth,
556                         normalRangeMin: normalRangeMin,
557                         normalRangeMax: normalRangeMax,
558                         drawNormalOnTop: drawNormalOnTop,
559                         xvalues: xvalues,
560                         chartRangeClip: chartRangeClip,
561                         chartRangeMinX: chartRangeMinX,
562                         chartRangeMaxX: chartRangeMaxX,
563                         disableInteraction: disableInteraction,
564                         disableTooltips: disableTooltips,
565                         disableHighlight: disableHighlight,
566                         highlightLighten: highlightLighten,
567                         highlightColor: highlightColor,
568                         tooltipContainer: tooltipContainer,
569                         tooltipClassname: tooltipClassname,
570                         tooltipChartTitle: chart.title,
571                         tooltipFormat: tooltipFormat,
572                         tooltipPrefix: tooltipPrefix,
573                         tooltipSuffix: tooltipSuffix,
574                         tooltipSkipNull: tooltipSkipNull,
575                         tooltipValueLookups: tooltipValueLookups,
576                         tooltipFormatFieldlist: tooltipFormatFieldlist,
577                         tooltipFormatFieldlistKey: tooltipFormatFieldlistKey,
578                         numberFormatter: numberFormatter,
579                         numberDigitGroupSep: numberDigitGroupSep,
580                         numberDecimalMark: numberDecimalMark,
581                         numberDigitGroupCount: numberDigitGroupCount,
582                         animatedZooms: animatedZooms,
583                         width: width,
584                         height: height
585                 };
586
587                 var uuid = NETDATA.guid();
588                 this.innerHTML = '<div style="display: inline-block; position: relative;" id="' + uuid + '"></div>';
589                 var div = document.getElementById(uuid);
590
591                 self.sparkline(data, options);
592                 self.data('sparkline-options', options)
593                 .data('uuid', uuid)
594                 .data('created', true);
595         };
596
597         // ----------------------------------------------------------------------------------------------------------------
598         // dygraph
599
600         NETDATA.dygraphAllCharts = [];
601         NETDATA.dygraphInitSync = function(callback) {
602                 //$.getScript(NETDATA.serverDefault + 'dygraph-synchronizer.js')
603                 //      .always(function() {
604                                 if(typeof callback == "function")
605                                         callback();
606                 //      })
607         }
608
609         NETDATA.dygraphSync = null;
610         NETDATA.dygraphSyncAll = function() {
611                 if(NETDATA.dygraphSync) {
612                         NETDATA.dygraphSync.detach();
613                         NETDATA.dygraphSync = null;
614                 }
615
616                 NETDATA.dygraphSync = Dygraph.synchronize(NETDATA.dygraphAllCharts, {
617                         selection: true,
618                         zoom: false
619                 });
620         }
621
622         NETDATA.dygraphInitialize = function(callback) {
623                 if(typeof netdataStopDygraph == 'undefined') {
624                         $.getScript(NETDATA.dygraph_js)
625                                 .done(function() {
626                                         NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js, 'json', 'ms|flip', 2);
627                                 })
628                                 .fail(function() {
629                                         NETDATA.error(100, NETDATA.dygraph_js);
630                                 })
631                                 .always(function() {
632                                         NETDATA.dygraphInitSync(callback);
633                                 })
634                 }
635                 else if(typeof callback == "function")
636                         callback();
637         };
638
639         NETDATA.dygraphChartUpdate = function(event, data) {
640                 var self = $(this);
641                 var dygraph = self.data('dygraph-instance');
642
643                 if(typeof data.update_every != 'undefined')
644                         self.data('update-every', data.update_every * 1000);
645
646                 if(dygraph != null) {
647                         console.log('updating dygraphs');
648                         dygraph.updateOptions( { 'file': data.data, 'labels': data.labels } );
649                 }
650                 else
651                         console.log('not updating dygraphs');
652         };
653
654         NETDATA.dygraphChartCreate = function(event, data) {
655                 var self = $(this);
656                 var width = self.data('width') || NETDATA.chartDefaults.width;
657                 var height = self.data('height') || NETDATA.chartDefaults.height;
658                 var chart = self.data('chart');
659                 var title = self.data('dygraph-title') || chart.title;
660                 var titleHeight = self.data('dygraph-titleHeight') || 20;
661                 var labelsDiv = self.data('dygraph-labelsDiv') || undefined;
662                 var connectSeparatedPoints = self.data('dygraph-connectSeparatedPoints') || false;
663                 var yLabelWidth = self.data('dygraph-yLabelWidth') || 12;
664                 var stackedGraph = self.data('dygraph-stackedGraph') || (chart.chart_type == 'stacked')?true:false;
665                 var stackedGraphNaNFill = self.data('dygraph-stackedGraphNaNFill') || 'none';
666                 var hideOverlayOnMouseOut = self.data('dygraph-hideOverlayOnMouseOut') || true;
667                 var fillGraph = self.data('dygraph-fillGraph') || (chart.chart_type == 'area')?true:false;
668                 var drawPoints = self.data('dygraph-drawPoints') || false;
669                 var labelsDivStyles = self.data('dygraph-labelsDivStyles') || { 'fontSize':'10' };
670                 var labelsDivWidth = self.data('dygraph-labelsDivWidth') || 250;
671                 var labelsSeparateLines = self.data('dygraph-labelsSeparateLines') || false;
672                 var labelsShowZeroValues = self.data('dygraph-labelsShowZeroValues') || true;
673                 var legend = self.data('dygraph-legend') || 'onmouseover';
674                 var showLabelsOnHighlight = self.data('dygraph-showLabelsOnHighlight') || true;
675                 var gridLineColor = self.data('dygraph-gridLineColor') || '#EEE';
676                 var axisLineColor = self.data('dygraph-axisLineColor') || '#EEE';
677                 var maxNumberWidth = self.data('dygraph-maxNumberWidth') || 8;
678                 var sigFigs = self.data('dygraph-sigFigs') || null;
679                 var digitsAfterDecimal = self.data('dygraph-digitsAfterDecimal') || 2;
680                 var axisLabelFontSize = self.data('dygraph-axisLabelFontSize') || 10;
681                 var axisLineWidth = self.data('dygraph-axisLineWidth') || 0.3;
682                 var drawAxis = self.data('dygraph-drawAxis') || true;
683                 var strokeWidth = self.data('dygraph-strokeWidth') || 1.0;
684                 var drawGapEdgePoints = self.data('dygraph-drawGapEdgePoints') || true;
685                 var colors = self.data('dygraph-colors') || NETDATA.colors;
686                 var pointSize = self.data('dygraph-pointSize') || 1;
687                 var stepPlot = self.data('dygraph-stepPlot') || false;
688                 var strokeBorderColor = self.data('dygraph-strokeBorderColor') || 'white';
689                 var strokeBorderWidth = self.data('dygraph-strokeBorderWidth') || (chart.chart_type == 'stacked')?1.0:0.0;
690                 var strokePattern = self.data('dygraph-strokePattern') || undefined;
691                 var highlightCircleSize = self.data('dygraph-highlightCircleSize') || 3;
692                 var highlightSeriesOpts = self.data('dygraph-highlightSeriesOpts') || { strokeWidth: 1.5 };
693                 var highlightSeriesBackgroundAlpha = self.data('dygraph-highlightSeriesBackgroundAlpha') || (chart.chart_type == 'stacked')?0.7:0.5;
694                 var pointClickCallback = self.data('dygraph-pointClickCallback') || undefined;
695                 var showRangeSelector = self.data('dygraph-showRangeSelector') || false;
696                 var showRoller = self.data('dygraph-showRoller') || false;
697                 var valueFormatter = self.data('dygraph-valueFormatter') || undefined; //function(x){ return x.toFixed(2); };
698                 var rightGap = self.data('dygraph-rightGap') || 5;
699                 var drawGrid = self.data('dygraph-drawGrid') || true;
700                 var drawXGrid = self.data('dygraph-drawXGrid') || undefined;
701                 var drawYGrid = self.data('dygraph-drawYGrid') || undefined;
702                 var gridLinePattern = self.data('dygraph-gridLinePattern') || null;
703                 var gridLineWidth = self.data('dygraph-gridLineWidth') || 0.3;
704
705                 var options = {
706                         title: title,
707                         titleHeight: titleHeight,
708                         ylabel: chart.units,
709                         yLabelWidth: yLabelWidth,
710                         connectSeparatedPoints: connectSeparatedPoints,
711                         drawPoints: drawPoints,
712                         fillGraph: fillGraph,
713                         stackedGraph: stackedGraph,
714                         stackedGraphNaNFill: stackedGraphNaNFill,
715                         drawGrid: drawGrid,
716                         drawXGrid: drawXGrid,
717                         drawYGrid: drawYGrid,
718                         gridLinePattern: gridLinePattern,
719                         gridLineWidth: gridLineWidth,
720                         gridLineColor: gridLineColor,
721                         axisLineColor: axisLineColor,
722                         axisLineWidth: axisLineWidth,
723                         drawAxis: drawAxis,
724                         hideOverlayOnMouseOut: hideOverlayOnMouseOut,
725                         labelsDiv: labelsDiv,
726                         labelsDivStyles: labelsDivStyles,
727                         labelsDivWidth: labelsDivWidth,
728                         labelsSeparateLines: labelsSeparateLines,
729                         labelsShowZeroValues: labelsShowZeroValues,
730                         labelsKMB: false,
731                         labelsKMG2: false,
732                         legend: legend,
733                         showLabelsOnHighlight: showLabelsOnHighlight,
734                         maxNumberWidth: maxNumberWidth,
735                         sigFigs: sigFigs,
736                         digitsAfterDecimal: digitsAfterDecimal,
737                         axisLabelFontSize: axisLabelFontSize,
738                         colors: colors,
739                         strokeWidth: strokeWidth,
740                         drawGapEdgePoints: drawGapEdgePoints,
741                         pointSize: pointSize,
742                         stepPlot: stepPlot,
743                         strokeBorderColor: strokeBorderColor,
744                         strokeBorderWidth: strokeBorderWidth,
745                         strokePattern: strokePattern,
746                         highlightCircleSize: highlightCircleSize,
747                         highlightSeriesOpts: highlightSeriesOpts,
748                         highlightSeriesBackgroundAlpha: highlightSeriesBackgroundAlpha,
749                         pointClickCallback: pointClickCallback,
750                         showRangeSelector: showRangeSelector,
751                         showRoller: showRoller,
752                         valueFormatter: valueFormatter,
753                         rightGap: rightGap,
754                         width: width,
755                         height: height,
756                         labels: data.labels,
757                         axes: {
758                                 x: {
759                                         pixelsPerLabel: 50,
760                                         ticker: Dygraph.dateTicker,
761                                         axisLabelFormatter: function (d, gran) {
762                                                 return Dygraph.zeropad(d.getHours()) + ":" + Dygraph.zeropad(d.getMinutes()) + ":" + Dygraph.zeropad(d.getSeconds());
763                                         },
764                                         valueFormatter :function (ms) {
765                                                 var d = new Date(ms);
766                                                 return Dygraph.zeropad(d.getHours()) + ":" + Dygraph.zeropad(d.getMinutes()) + ":" + Dygraph.zeropad(d.getSeconds());
767                                         }
768                                 },
769                                 y: {
770                                         pixelsPerLabel: 15,
771                                 }
772                         }
773                 };
774
775                 var uuid = NETDATA.guid();
776                 self.html('<div id="' + uuid + '"></div>');
777
778                 var dchart = new Dygraph(document.getElementById(uuid),
779                         data.data, options);
780
781                 self.data('dygraph-instance', dchart)
782                 .data('dygraph-options', options)
783                 .data('uuid', uuid)
784                 .data('created', true);
785
786                 //NETDATA.dygraphAllCharts.push(dchart);
787                 //if(NETDATA.dygraphAllCharts.length > 1)
788                 //      NETDATA.dygraphSyncAll();
789         };
790
791         // ----------------------------------------------------------------------------------------------------------------
792         // morris
793
794         NETDATA.morrisInitialize = function(callback) {
795                 if(typeof netdataStopMorris == 'undefined') {
796                         var fileref = document.createElement("link");
797                         fileref.setAttribute("rel", "stylesheet");
798                         fileref.setAttribute("type", "text/css");
799                         fileref.setAttribute("href", NETDATA.morris_css);
800
801                         if (typeof fileref != "undefined")
802                                 document.getElementsByTagName("head")[0].appendChild(fileref);
803
804                         $.getScript(NETDATA.morris_js)
805                                 .done(function() {
806                                         NETDATA.registerChartLibrary('morris', NETDATA.morris_js, 'json', 'objectrows|ms', 10);
807                                 })
808                                 .fail(function() {
809                                         NETDATA.error(100, NETDATA.morris_js);
810                                 })
811                                 .always(function() {
812                                         if(typeof callback == "function")
813                                                 callback();
814                                 })
815                 }
816                 else if(typeof callback == "function")
817                         callback();
818         };
819
820         NETDATA.morrisChartUpdate = function(event, data) {
821                 var self = $(this);
822                 var width = self.data('width') || NETDATA.chartDefaults.width;
823                 var height = self.data('height') || NETDATA.chartDefaults.height;
824                 var morris = self.data('morris-instance');
825
826                 if(typeof data.update_every != 'undefined')
827                         self.data('update-every', data.update_every * 1000);
828
829                 if(morris != null) {
830                         console.log('updating morris');
831                         morris.setData(data.data);
832                 }
833                 else
834                         console.log('not updating morris');
835         };
836
837         NETDATA.morrisChartCreate = function(event, data) {
838                 var self = $(this);
839                 var width = self.data('width') || NETDATA.chartDefaults.width;
840                 var height = self.data('height') || NETDATA.chartDefaults.height;
841                 var chart = self.data('chart');
842
843                 self.html('<div id="morris-' + chart.id + '" style="width: ' + width + 'px; height: ' + height + 'px;"></div>');
844
845                 // remove the 'time' element from the labels
846                 data.labels.splice(0, 1);
847
848                 var options = {
849                                 element: 'morris-' + chart.id,
850                                 data: data.data,
851                                 xkey: 'time',
852                                 ykeys: data.labels,
853                                 labels: data.labels,
854                                 lineWidth: 2,
855                                 pointSize: 2,
856                                 smooth: true,
857                                 hideHover: 'auto',
858                                 parseTime: true,
859                                 continuousLine: false,
860                                 behaveLikeLine: false,
861                                 width: width,
862                                 height: height
863                 };
864
865                 var morris;
866                 if(chart.chart_type == 'line')
867                         morris = new Morris.Line(options);
868
869                 else if(chart.chart_type == 'area') {
870                         options.behaveLikeLine = true;
871                         morris = new Morris.Area(options);
872                 }
873                 else // stacked
874                         morris = new Morris.Area(options);
875
876                 self.data('morris-instance', morris)
877                 .data('created', true);
878         };
879
880         // ----------------------------------------------------------------------------------------------------------------
881         // raphael
882
883         NETDATA.raphaelInitialize = function(callback) {
884                 if(typeof netdataStopRaphael == 'undefined') {
885                         $.getScript(NETDATA.raphael_js)
886                                 .done(function() {
887                                         NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js, 'json', 'flip|min2max', 1);
888                                 })
889                                 .fail(function() {
890                                         NETDATA.error(100, NETDATA.raphael_js);
891                                 })
892                                 .always(function() {
893                                         if(typeof callback == "function")
894                                                 callback();
895                                 })
896                 }
897                 else if(typeof callback == "function")
898                         callback();
899         };
900
901         NETDATA.raphaelChartUpdate = function(event, data) {
902                 var self = $(this);
903                 var width = self.data('width') || NETDATA.chartDefaults.width;
904                 var height = self.data('height') || NETDATA.chartDefaults.height;
905
906                 self.raphael(data, {
907                         width: width,
908                         height: height
909                 })
910         };
911
912         NETDATA.raphaelChartCreate = function(event, data) {
913                 var self = $(this);
914                 var width = self.data('width') || NETDATA.chartDefaults.width;
915                 var height = self.data('height') || NETDATA.chartDefaults.height;
916
917                 self.raphael(data, {
918                         width: width,
919                         height: height
920                 })
921                 .data('created', true);
922         };
923
924         // ----------------------------------------------------------------------------------------------------------------
925         // google charts
926
927         NETDATA.googleInitialize = function(callback) {
928                 if(typeof netdataStopGoogleCharts == 'undefined' && typeof google != 'undefined') {
929                         NETDATA.registerChartLibrary('google', NETDATA.google_js, 'datatable', '', 3);
930                         if(typeof callback == "function")
931                                 callback();
932                 }
933                 else if(typeof callback == "function")
934                         callback();
935         };
936
937         NETDATA.googleChartUpdate = function(event, data) {
938                 var self = $(this);
939                 var width = self.data('width') || NETDATA.chartDefaults.width;
940                 var height = self.data('height') || NETDATA.chartDefaults.height;
941                 var gchart = self.data('google-instance');
942                 var options = self.data('google-options');
943
944                 if(typeof data.update_every != 'undefined')
945                         self.data('update-every', data.update_every * 1000);
946
947                 var datatable = new google.visualization.DataTable(data);
948
949                 gchart.draw(datatable, options);
950         };
951
952         NETDATA.googleChartCreate = function(event, data) {
953                 var self = $(this);
954                 var width = self.data('width') || NETDATA.chartDefaults.width;
955                 var height = self.data('height') || NETDATA.chartDefaults.height;
956                 var chart = self.data('chart');
957
958                 var datatable = new google.visualization.DataTable(data);
959                 var gchart;
960
961                 var options = {
962                         width: width,
963                         height: height,
964                         lineWidth: 1,
965                         title: chart.title,
966                         fontSize: 11,
967                         hAxis: {
968                         //      title: "Time of Day",
969                         //      format:'HH:mm:ss',
970                                 viewWindowMode: 'maximized',
971                                 slantedText: false,
972                                 format:'HH:mm:ss',
973                                 textStyle: {
974                                         fontSize: 9
975                                 },
976                                 gridlines: {
977                                         color: '#EEE'
978                                 }
979                         },
980                         vAxis: {
981                                 title: chart.units,
982                                 viewWindowMode: 'pretty',
983                                 minValue: -0.1,
984                                 maxValue: 0.1,
985                                 direction: 1,
986                                 textStyle: {
987                                         fontSize: 9
988                                 },
989                                 gridlines: {
990                                         color: '#EEE'
991                                 }
992                         },
993                         chartArea: {
994                                 width: '65%',
995                                 height: '80%'
996                         },
997                         focusTarget: 'category',
998                         annotation: {
999                                 '1': {
1000                                         style: 'line'
1001                                 }
1002                         },
1003                         pointsVisible: 0,
1004                         titlePosition: 'out',
1005                         titleTextStyle: {
1006                                 fontSize: 11
1007                         },
1008                         tooltip: {
1009                                 isHtml: false,
1010                                 ignoreBounds: true,
1011                                 textStyle: {
1012                                         fontSize: 9
1013                                 }
1014                         },
1015                         curveType: 'function',
1016                         areaOpacity: 0.3,
1017                         isStacked: false
1018                 };
1019
1020                 switch(chart.chart_type) {
1021                         case "area":
1022                                 options.vAxis.viewWindowMode = 'maximized';
1023                                 gchart = new google.visualization.AreaChart(this);
1024                                 break;
1025
1026                         case "stacked":
1027                                 options.isStacked = true;
1028                                 options.areaOpacity = 0.85;
1029                                 options.vAxis.viewWindowMode = 'maximized';
1030                                 options.vAxis.minValue = null;
1031                                 options.vAxis.maxValue = null;
1032                                 gchart = new google.visualization.AreaChart(this);
1033                                 break;
1034
1035                         default:
1036                         case "line":
1037                                 options.lineWidth = 2;
1038                                 gchart = new google.visualization.LineChart(this);
1039                                 break;
1040                 }
1041
1042                 gchart.draw(datatable, options);
1043
1044                 self.data('google-instance', gchart)
1045                 .data('google-options', options)
1046                 .data('created', true);
1047         };
1048
1049         // ----------------------------------------------------------------------------------------------------------------
1050         // load all libraries and initialize
1051
1052         NETDATA.errorReset();
1053
1054         NETDATA._loadjQuery(function() {
1055                 NETDATA.raphaelInitialize(function() {
1056                         NETDATA.morrisInitialize(function() {
1057                                 NETDATA.peityInitialize(function() {
1058                                         NETDATA.sparklineInitialize(function() {
1059                                                 NETDATA.dygraphInitialize(function() {
1060                                                         NETDATA.googleInitialize(function() {
1061                                                                 netdataParsePageCharts();
1062                                                         }) // google
1063                                                 }) // dygraph.js
1064                                         }) // sparkline.js
1065                                 }) // piety.js
1066                         }) // morris.js
1067                 }) // raphael.js
1068         });
1069
1070 })(window);
1071