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