new dashboard; now charts support pan and zoom; dygraphs are also synchronized
Costa Tsaousis (ktsaou) committed
Dec 5, 2015 at 22:11 UTC
201b4595dedc61c55ad7008c3e12581e84b36dbd
2 files changed
+942
-594
src/rrd2json.c
+9
-6
@@ -442,11 +442,17 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
442
buffer_sprintf(wb, "{\n"
443
" %sid%s: %s%s%s,\n"
444
" %sname%s: %s%s%s,\n"
445
+ " %sview_update_every%s: %d,\n"
446
" %supdate_every%s: %d,\n"
447
+ " %sfirst_entry_t%s: %u, \n"
448
+ " %slast_entry_t%s: %u, \n"
449
" %smin%s: "
450
, kq, kq, sq, r->st->id, sq
451
, kq, kq, sq, r->st->name, sq
452
, kq, kq, r->update_every
453
+ , kq, kq, r->st->update_every
454
+ , kq, kq, rrdset_first_entry_t(r->st)
455
+ , kq, kq, rrdset_last_entry_t(r->st)
456
, kq, kq);
457
458
buffer_rrd_value(wb, r->min);
@@ -1171,6 +1177,8 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1177
1178
r->group = group;
1179
r->update_every = group * st->update_every;
1180
+ r->before = now;
1181
+ r->after = now;
1182
1183
long slot = start_at_slot, counter = 0, stop_now = 0, added = 0, group_count = 0, add_this = 0;
1184
for(; !stop_now ; now -= dt, slot--, counter++) {
@@ -1194,10 +1202,6 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1202
1203
if(unlikely(group_count == 0)) {
1204
group_start_t = now;
1197
- if(unlikely(!r->before)) {
1198
- r->before = group_start_t;
1199
- r->after = group_start_t;
1200
- }
1205
}
1206
group_count++;
1207
@@ -1240,7 +1244,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1244
if(unlikely(add_this)) {
1245
if(unlikely(!rrdr_line_init(r, group_start_t))) break;
1246
1243
- r->after = group_start_t;
1247
+ r->after = now;
1248
1249
calculated_number *cn = rrdr_line_values(r);
1250
uint8_t *co = rrdr_line_options(r);
@@ -1280,7 +1284,6 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g
1284
add_this = 0;
1285
}
1286
}
1283
- r->after += group * st->update_every;
1287
1288
rrdr_done(r);
1289
//error("SHIFT: %s: wanted %ld points, got %ld", st->id, points, rrdr_rows(r));
web/dashboard.js
+933
-588
@@ -79,7 +79,7 @@
79
width: '100%', // the chart width
80
height: '100%', // the chart height
81
library: 'dygraph', // the graphing library to use
82
- method: 'average', // the grouping method
82
+ method: 'max', // the grouping method
83
before: 0, // panning
84
after: -600, // panning
85
pixels_per_point: 1 // the detail of the chart
@@ -88,16 +88,17 @@
88
NETDATA.options = {
89
targets: null,
90
updated_dom: 1,
91
- last_paused: 0,
91
+ auto_refresher_fast_weight: 0,
92
page_is_visible: 1,
93
double_click_ms: 100,
94
- refreshed_stop_until: 0,
94
+ auto_refresher_stop_until: 0,
95
96
current: {
97
pixels_per_point: 1,
98
- idle_between_charts: 100,
99
- idle_between_loops: 500,
98
+ idle_between_charts: 50,
99
+ idle_between_loops: 200,
100
idle_lost_focus: 500,
101
+ global_pan_sync_time: 500,
102
fast_render_timeframe: 200 // render continously for these many ms
103
},
104
@@ -148,20 +149,671 @@
149
NETDATA.errorLast.code = 0;
150
NETDATA.errorLast.message = "You are doing fine!";
151
NETDATA.errorLast.datetime = 0;
152
+ };
153
+
154
+ // ----------------------------------------------------------------------------------------------------------------
155
+
156
+ NETDATA.chartRegistry = {
157
+ charts: {},
158
+
159
+ add: function(host, id, data) {
160
+ host = host.replace(/:/g, "_").replace(/\//g, "_");
161
+ id = id.replace(/:/g, "_").replace(/\//g, "_");
162
+
163
+ if(typeof this.charts[host] == 'undefined')
164
+ this.charts[host] = {};
165
+
166
+ this.charts[host][id] = data;
167
+ },
168
+
169
+ get: function(host, id) {
170
+ host = host.replace(/:/g, "_").replace(/\//g, "_");
171
+ id = id.replace(/:/g, "_").replace(/\//g, "_");
172
+
173
+ if(typeof this.charts[host] == 'undefined')
174
+ return null;
175
+
176
+ if(typeof this.charts[host][id] == 'undefined')
177
+ return null;
178
+
179
+ return this.charts[host][id];
180
+ }
181
+ };
182
+
183
+ // ----------------------------------------------------------------------------------------------------------------
184
+
185
+ NETDATA.globalPanAndZoom = {
186
+ seq: 0,
187
+ state: null,
188
+ before_ms: null,
189
+ after_ms: null,
190
+ force_before_ms: null,
191
+ force_after_ms: null,
192
+
193
+ setMaster: function(state, after, before) {
194
+ if(this.state && this.state != state) this.state.resetChart();
195
+
196
+ this.state = state;
197
+ this.seq = new Date().getTime();
198
+ this.force_after_ms = after;
199
+ this.force_before_ms = before;
200
+ },
201
+ clearMaster: function() {
202
+ if(this.state) {
203
+ var state = this.state;
204
+ this.state = null; // prevent infinite recursion
205
+ this.seq = 0;
206
+ state.resetChart();
207
+ NETDATA.options.auto_refresher_stop_until = 0;
208
+ }
209
+ else {
210
+ this.state = null;
211
+ this.seq = 0;
212
+ }
213
+ },
214
+ shouldBeAutoRefreshed: function(state) {
215
+ if(!this.state || !this.seq)
216
+ return false;
217
+
218
+ if(state.follows_global == this.seq)
219
+ return false;
220
+
221
+ return true;
222
+ }
223
}
224
153
- NETDATA.messageInABox = function(element, message) {
225
+ // ----------------------------------------------------------------------------------------------------------------
226
+ // Our state object, where all per-chart values are stored
227
+
228
+ NETDATA.chartInitialState = function(element) {
229
self = $(element);
230
156
- bgcolor = ""
157
- if(NETDATA.options.debug.show_boxes)
158
- bgcolor = " background-color: lightgrey;";
231
+ var state = {
232
+ uuid: NETDATA.guid(), // GUID - a unique identifier for the chart
233
+ id: self.data('netdata'), // string - the name of chart
234
+
235
+ // the user given dimensions of the element
236
+ width: self.data('width') || NETDATA.chartDefaults.width,
237
+ height: self.data('height') || NETDATA.chartDefaults.height,
238
+
239
+ // these are calculated every time the chart is refreshed
240
+ calculated_width: 0,
241
+ calculated_height: 0,
242
+
243
+ // string - the netdata server URL, without any path
244
+ host: self.data('host') || NETDATA.chartDefaults.host,
245
+
246
+ // string - the grouping method requested by the user
247
+ method: self.data('method') || NETDATA.chartDefaults.method,
248
+
249
+ // the time-range requested by the user
250
+ after: self.data('after') || NETDATA.chartDefaults.after,
251
+ before: self.data('before') || NETDATA.chartDefaults.before,
252
+
253
+ // the pixels per point requested by the user
254
+ pixels_per_point: 1,
255
+ points: self.data('points') || null,
256
+
257
+ // the dimensions requested by the user
258
+ dimensions: self.data('dimensions') || null,
259
+
260
+ // the chart library requested by the user
261
+ library_name: self.data('chart-library') || NETDATA.chartDefaults.library,
262
+ library: null, // object - the chart library used
263
+
264
+ element: element, // the element it is linked to
265
+
266
+ chart_url: null, // string - the url to download chart info
267
+ chart: null, // object - the chart as downloaded from the server
268
+
269
+ downloaded_ms: 0, // milliseconds - the timestamp we downloaded the chart
270
+ created_ms: 0, // boolean - the timestamp the chart was created
271
+ validated: false, // boolean - has the chart been validated?
272
+ enabled: true, // boolean - is the chart enabled for refresh?
273
+ paused: false, // boolean - is the chart paused for any reason?
274
+ debug: false,
275
+ updates_counter: 0, // numeric - the number of refreshes made so far
276
+
277
+ follows_global: 0,
278
+
279
+ mode: null, // auto, pan, zoom
280
+ auto: {
281
+ name: 'auto',
282
+ autorefresh: true,
283
+ url: 'invalid://', // string - the last url used to update the chart
284
+ last_updated_ms: 0, // milliseconds - the timestamp of last refresh
285
+ view_update_every: 0, // milliseconds - the minimum acceptable refresh duration
286
+ after_ms: 0, // milliseconds - the first timestamp of the data
287
+ before_ms: 0, // milliseconds - the last timestamp of the data
288
+ points: 0, // number - the number of points in the data
289
+ data: null, // the last downloaded data
290
+ force_before_ms: null,
291
+ force_after_ms: null,
292
+ requested_before_ms: null,
293
+ requested_after_ms: null,
294
+ first_entry_ms: null,
295
+ last_entry_ms: null,
296
+ },
297
+ pan: {
298
+ name: 'pan',
299
+ autorefresh: false,
300
+ url: 'invalid://', // string - the last url used to update the chart
301
+ last_updated_ms: 0, // milliseconds - the timestamp of last refresh
302
+ view_update_every: 0, // milliseconds - the minimum acceptable refresh duration
303
+ after_ms: 0, // milliseconds - the first timestamp of the data
304
+ before_ms: 0, // milliseconds - the last timestamp of the data
305
+ points: 0, // number - the number of points in the data
306
+ data: null, // the last downloaded data
307
+ force_before_ms: null,
308
+ force_after_ms: null,
309
+ requested_before_ms: null,
310
+ requested_after_ms: null,
311
+ first_entry_ms: null,
312
+ last_entry_ms: null,
313
+ },
314
+ zoom: {
315
+ name: 'zoom',
316
+ autorefresh: false,
317
+ url: 'invalid://', // string - the last url used to update the chart
318
+ last_updated_ms: 0, // milliseconds - the timestamp of last refresh
319
+ view_update_every: 0, // milliseconds - the minimum acceptable refresh duration
320
+ after_ms: 0, // milliseconds - the first timestamp of the data
321
+ before_ms: 0, // milliseconds - the last timestamp of the data
322
+ points: 0, // number - the number of points in the data
323
+ data: null, // the last downloaded data
324
+ force_before_ms: null,
325
+ force_after_ms: null,
326
+ requested_before_ms: null,
327
+ requested_after_ms: null,
328
+ first_entry_ms: null,
329
+ last_entry_ms: null,
330
+ },
331
+ refresh_dt_ms: 0, // milliseconds - the time the last refresh took
332
+ refresh_dt_element_name: self.data('dt-element-name') || null, // string - the element to print refresh_dt_ms
333
+ refresh_dt_element: null,
334
+
335
+ log(msg) {
336
+ console.log(this.id + ' (' + this.library_name + ' ' + this.uuid + '): ' + msg);
337
+ },
338
+
339
+ setSelection: function(t) {
340
+ if(typeof this.library.setSelection == 'function')
341
+ return this.library.setSelection(this, t);
342
+ else
343
+ return false;
344
+ },
345
+
346
+ clearSelection: function() {
347
+ if(typeof this.library.clearSelection == 'function')
348
+ return this.library.clearSelection(this);
349
+ else
350
+ return false;
351
+ },
352
+
353
+ timeIsVisible: function(t) {
354
+ if(t >= this.mode.after_ms && t <= this.mode.before_ms)
355
+ return true;
356
+ return false;
357
+ },
358
+
359
+ calculateRowForTime: function(t) {
360
+ if(!this.timeIsVisible(t)) return -1;
361
+
362
+ var r = Math.floor((t - this.mode.after_ms) / this.mode.view_update_every);
363
+ // console.log(this.mode.data);
364
+
365
+ return r;
366
+ },
367
+
368
+ pauseChart: function() {
369
+ this.paused = true;
370
+ },
371
+
372
+ unpauseChart: function() {
373
+ this.paused = false;
374
+ },
375
+
376
+ resetChart: function() {
377
+ if(NETDATA.globalPanAndZoom.state == this)
378
+ NETDATA.globalPanAndZoom.clearMaster();
379
160
- element.innerHTML = '<div style="font-size: xx-small; overflow: hidden;' + bgcolor + ' width: 100%; height: 100%;"><small>'
161
- + message
162
- + '</small></div>';
380
+ if(state.mode.name != 'auto')
381
+ this.setMode('auto');
382
+
383
+ this.mode.force_before_ms = null;
384
+ this.mode.force_after_ms = null;
385
+ this.mode.last_updated_ms = 0;
386
+ this.follows_global = 0;
387
+ this.paused = false;
388
+ this.enabled = true;
389
+ this.debug = false;
390
+
391
+ state.updateChart();
392
+ },
393
+
394
+ setMode: function(m) {
395
+ if(this.mode) {
396
+ if(this.mode.name == m) return;
397
+
398
+ this[m].url = this.mode.url;
399
+ this[m].last_updated_ms = this.mode.last_updated_ms;
400
+ this[m].view_update_every = this.mode.view_update_every;
401
+ this[m].after_ms = this.mode.after_ms;
402
+ this[m].before_ms = this.mode.before_ms;
403
+ this[m].points = this.mode.points;
404
+ this[m].data = this.mode.data;
405
+ this[m].requested_before_ms = this.mode.requested_before_ms;
406
+ this[m].requested_after_ms = this.mode.requested_after_ms;
407
+ this[m].first_entry_ms = this.mode.first_entry_ms;
408
+ this[m].last_entry_ms = this.mode.last_entry_ms;
409
+ }
410
+
411
+ if(m == 'auto')
412
+ this.mode = this.auto;
413
+ else if(m == 'pan')
414
+ this.mode = this.pan;
415
+ else if(m == 'zoom')
416
+ this.mode = this.zoom;
417
+ else
418
+ this.mode = this.auto;
419
+
420
+ this.mode.force_before_ms = null;
421
+ this.mode.force_after_ms = null;
422
+
423
+ if(this.debug) this.log('mode set to ' + this.mode.name);
424
+ },
425
+
426
+ _minPanOrZoomStep: function() {
427
+ return (((this.mode.before_ms - this.mode.after_ms) / this.mode.points) * ((this.mode.points * 5 / 100) + 1) );
428
+ // return this.mode.view_update_every * 10;
429
+ },
430
+
431
+ _shouldBeMoved: function(old_after, old_before, new_after, new_before) {
432
+ var dt_after = Math.abs(old_after - new_after);
433
+ var dt_before = Math.abs(old_before - new_before);
434
+ var old_range = old_before - old_after;
435
+
436
+ var new_range = new_before - new_after;
437
+ var dt = Math.abs(old_range - new_range);
438
+ var step = Math.max(dt_after, dt_before, dt);
439
+
440
+ var min_step = this._minPanOrZoomStep();
441
+ if(new_range < old_range && new_range / this.calculated_width < 100) {
442
+ if(this.debug) this.log('_shouldBeMoved(' + (new_after / 1000).toString() + ' - ' + (new_before / 1000).toString() + '): minimum point size: 0.10, wanted point size: ' + (new_range / this.calculated_width / 1000).toString() + ': TOO SMALL RANGE');
443
+ return false;
444
+ }
445
+
446
+ if(step >= min_step) {
447
+ if(this.debug) this.log('_shouldBeMoved(' + (new_after / 1000).toString() + ' - ' + (new_before / 1000).toString() + '): minimum step: ' + (min_step / 1000).toString() + ', this step: ' + (step / 1000).toString() + ': YES');
448
+ return true;
449
+ }
450
+ else {
451
+ if(this.debug) this.log('_shouldBeMoved(' + (new_after / 1000).toString() + ' - ' + (new_before / 1000).toString() + '): minimum step: ' + (min_step / 1000).toString() + ', this step: ' + (step / 1000).toString() + ': NO');
452
+ return false;
453
+ }
454
+ },
455
+
456
+ updateChartPanOrZoom: function(after, before, callback) {
457
+ var move = false;
458
+
459
+ if(this.mode.name == 'auto') {
460
+ if(this.debug) this.log('updateChartPanOrZoom(): caller did not set proper mode');
461
+ this.setMode('pan');
462
+ }
463
+
464
+ if(!this.mode.force_after_ms || !this.mode.force_before_ms) {
465
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): INIT');
466
+ move = true;
467
+ }
468
+ else if(this._shouldBeMoved(this.mode.force_after_ms, this.mode.force_before_ms, after, before) && this._shouldBeMoved(this.mode.after_ms, this.mode.before_ms, after, before)) {
469
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): FORCE CHANGE from ' + (this.mode.force_after_ms / 1000).toString() + ' - ' + (this.mode.force_before_ms / 1000).toString());
470
+ move = true;
471
+ }
472
+ else if(this._shouldBeMoved(this.mode.requested_after_ms, this.mode.requested_before_ms, after, before) && this._shouldBeMoved(this.mode.after_ms, this.mode.before_ms, after, before)) {
473
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): REQUESTED CHANGE from ' + (this.mode.requested_after_ms / 1000).toString() + ' - ' + (this.mode.requested_before_ms / 1000).toString());
474
+ move = true;
475
+ }
476
+
477
+ if(move) {
478
+ var now = new Date().getTime();
479
+ NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.global_pan_sync_time;
480
+ NETDATA.globalPanAndZoom.setMaster(this, after, before);
481
+
482
+ this.mode.force_after_ms = after;
483
+ this.mode.force_before_ms = before;
484
+ this.updateChart(callback);
485
+ return true;
486
+ }
487
+
488
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): IGNORE');
489
+ if(typeof callback != 'undefined') callback();
490
+ return false;
491
+ },
492
+
493
+ updateChart: function(callback) {
494
+ if(!this.library || !this.library.enabled) {
495
+ this.error('chart library "' + this.library_name + '" is not enabled');
496
+ if(typeof callback != 'undefined') callback();
497
+ return;
498
+ }
499
+
500
+ if(!this.enabled) {
501
+ if(this.debug) this.error('chart "' + this.id + '" is not enabled');
502
+ if(typeof callback != 'undefined') callback();
503
+ return;
504
+ }
505
+
506
+ if(!self.visible(true)) {
507
+ if(NETDATA.options.debug.visibility || this.debug) this.log('is not visible');
508
+ if(typeof callback != 'undefined') callback();
509
+ return;
510
+ }
511
+ if(!this.chart) {
512
+ var this_state_object = this;
513
+ this.getChart(function() { this_state_object.updateChart(callback); });
514
+ return;
515
+ }
516
+
517
+ if(!this.library.initialized) {
518
+ var this_state_object = this;
519
+ this.library.initialize(function() { this_state_object.updateChart(callback); });
520
+ return;
521
+ }
522
+
523
+ this.clearSelection();
524
+ this.chartURL();
525
+ if(this.debug) this.log('updating from ' + this.mode.url);
526
+
527
+ var this_state_object = this;
528
+ $.ajax( {
529
+ url: this_state_object.mode.url,
530
+ crossDomain: true
531
+ })
532
+ .then(function(data) {
533
+ if(this_state_object.debug) this_state_object.log('got data from netdata server');
534
+ this_state_object.mode.data = data;
535
+
536
+ var started = new Date().getTime();
537
+
538
+ // if the result is JSON, find the latest update-every
539
+ if(typeof data == 'object' && this_state_object.library.jsonWrapper) {
540
+ if(!this_state_object.follows_global && typeof data.view_update_every != 'undefined')
541
+ this_state_object.mode.view_update_every = data.view_update_every * 1000;
542
+
543
+ if(typeof data.after != 'undefined')
544
+ this_state_object.mode.after_ms = data.after * 1000;
545
+
546
+ if(typeof data.before != 'undefined')
547
+ this_state_object.mode.before_ms = data.before * 1000;
548
+
549
+ if(typeof data.first_entry_t != 'undefined')
550
+ this_state_object.mode.first_entry_ms = data.first_entry_t * 1000;
551
+
552
+ if(typeof data.last_entry_t != 'undefined')
553
+ this_state_object.mode.last_entry_ms = data.last_entry_t * 1000;
554
+
555
+ if(typeof data.points != 'undefined')
556
+ this_state_object.mode.points = data.points;
557
+
558
+ data.state = this_state_object;
559
+ }
560
+
561
+ this_state_object.updates_counter++;
562
+
563
+ if(this_state_object.debug) {
564
+ this_state_object.log('UPDATE No ' + this_state_object.updates_counter + ' COMPLETED');
565
+
566
+ if(this_state_object.mode.force_after_ms)
567
+ this_state_object.log('STATUS: forced : ' + (this_state_object.mode.force_after_ms / 1000).toString() + ' - ' + (this_state_object.mode.force_before_ms / 1000).toString());
568
+ else
569
+ this_state_object.log('STATUS: forced: unset');
570
+
571
+ this_state_object.log('STATUS: requested: ' + (this_state_object.mode.requested_after_ms / 1000).toString() + ' - ' + (this_state_object.mode.requested_before_ms / 1000).toString());
572
+ this_state_object.log('STATUS: rendered : ' + (this_state_object.mode.after_ms / 1000).toString() + ' - ' + (this_state_object.mode.before_ms / 1000).toString());
573
+ this_state_object.log('STATUS: points : ' + (this_state_object.mode.points).toString() + ', min step: ' + (this_state_object._minPanOrZoomStep() / 1000).toString());
574
+ }
575
164
- self.data('chart-created', false);
576
+ if(this_state_object.created_ms) {
577
+ if(this_state_object.debug) this_state_object.log('updating chart...');
578
+
579
+ if(NETDATA.options.debug.chart_errors) {
580
+ this_state_object.library.update(this_state_object.element, data);
581
+ }
582
+ else {
583
+ try {
584
+ this_state_object.library.update(this_state_object.element, data);
585
+ }
586
+ catch(err) {
587
+ this_state_object.error('chart "' + state.id + '" failed to be updated as ' + state.library_name);
588
+ }
589
+ }
590
+ }
591
+ else {
592
+ if(this_state_object.debug) this_state_object.log('creating chart...');
593
+
594
+ if(NETDATA.options.debug.chart_errors) {
595
+ this_state_object.library.create(this_state_object.element, data);
596
+ this_state_object.created_ms = new Date().getTime();
597
+ }
598
+ else {
599
+ try {
600
+ this_state_object.library.create(this_state_object.element, data);
601
+ this_state_object.created_ms = new Date().getTime();
602
+ }
603
+ catch(err) {
604
+ this_state_object.error('chart "' + state.id + '" failed to be created as ' + state.library_name);
605
+ }
606
+ }
607
+ }
608
+
609
+ // update the performance counters
610
+ this_state_object.mode.last_updated_ms = new Date().getTime();
611
+ this_state_object.refresh_dt_ms = this_state_object.mode.last_updated_ms - started;
612
+ NETDATA.options.auto_refresher_fast_weight += this_state_object.refresh_dt_ms;
613
+
614
+ if(this_state_object.refresh_dt_element)
615
+ this_state_object.refresh_dt_element.innerHTML = this_state_object.refresh_dt_ms.toString();
616
+ })
617
+ .fail(function() {
618
+ this_state_object.error('cannot download chart from ' + this_state_object.mode.url);
619
+ })
620
+ .always(function() {
621
+ if(typeof callback == 'function') callback();
622
+ });
623
+ },
624
+
625
+ chartURL: function() {
626
+ this.calculated_width = self.width();
627
+ this.calculated_height = self.height();
628
+
629
+ var before;
630
+ var after;
631
+ if(NETDATA.globalPanAndZoom.state) {
632
+ after = Math.round(NETDATA.globalPanAndZoom.force_after_ms / 1000);
633
+ before = Math.round(NETDATA.globalPanAndZoom.force_before_ms / 1000);
634
+ this.follows_global = NETDATA.globalPanAndZoom.seq;
635
+ }
636
+ else {
637
+ before = this.mode.force_before_ms != null ? Math.round(this.mode.force_before_ms / 1000) : this.before;
638
+ after = this.mode.force_after_ms != null ? Math.round(this.mode.force_after_ms / 1000) : this.after;
639
+ this.follows_global = 0;
640
+ }
641
+
642
+ this.mode.requested_after_ms = after * 1000;
643
+ this.mode.requested_before_ms = before * 1000;
644
+
645
+ // force an options provided detail
646
+ var pixels_per_point = this.pixels_per_point;
647
+ if(pixels_per_point < NETDATA.options.current.pixels_per_point)
648
+ pixels_per_point = NETDATA.options.current.pixels_per_point
649
+
650
+ this.mode.points = this.points || Math.round(this.calculated_width / pixels_per_point);
651
+
652
+ // build the data URL
653
+ this.mode.url = this.chart.data_url;
654
+ this.mode.url += "&format=" + this.library.format;
655
+ this.mode.url += "&points=" + this.mode.points.toString();
656
+ this.mode.url += "&group=" + this.method;
657
+ this.mode.url += "&options=" + this.library.options;
658
+ if(this.library.jsonWrapper) this.mode.url += '|jsonwrap';
659
+
660
+ if(after)
661
+ this.mode.url += "&after=" + after.toString();
662
+
663
+ if(before)
664
+ this.mode.url += "&before=" + before.toString();
665
+
666
+ if(this.dimensions)
667
+ this.mode.url += "&dimensions=" + this.dimensions;
668
+
669
+ if(NETDATA.options.debug.chart_data_url) this.log('chartURL(): ' + this.mode.url + ' WxH:' + this.calculated_width + 'x' + this.calculated_height + ' points: ' + this.mode.points + ' library: ' + this.library_name);
670
+ },
671
+
672
+ canBeAutoRefreshed: function(auto_refresher) {
673
+ if(this.mode.autorefresh) {
674
+ var now = new Date().getTime();
675
+
676
+ if(this.updates_counter && !NETDATA.options.page_is_visible) {
677
+ if(NETDATA.options.debug.focus || this.debug) this.log('page does not have focus');
678
+ return false;
679
+ }
680
+
681
+ if(!auto_refresher) return true;
682
+
683
+ if(!self.visible(true)) return false;
684
+
685
+ // options valid only for autoRefresh()
686
+ if(NETDATA.options.auto_refresher_stop_until == 0 || NETDATA.options.auto_refresher_stop_until < now) {
687
+ if(NETDATA.globalPanAndZoom.state) {
688
+ if(NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this))
689
+ return true;
690
+ else
691
+ return false;
692
+ }
693
+
694
+ if(this.paused) return false;
695
+
696
+ if(now - this.mode.last_updated_ms > this.mode.view_update_every)
697
+ return true;
698
+ }
699
+ }
700
+
701
+ return false;
702
+ },
703
+
704
+ autoRefresh: function(callback) {
705
+ if(this.canBeAutoRefreshed(true))
706
+ this.updateChart(callback);
707
+ else if(typeof callback != 'undefined')
708
+ callback();
709
+ },
710
+
711
+ // fetch the chart description from the netdata server
712
+ getChart: function(callback) {
713
+ this.chart = NETDATA.chartRegistry.get(this.host, this.id);
714
+ if(this.chart) {
715
+ if(typeof callback == 'function') callback();
716
+ }
717
+ else {
718
+ this.chart_url = this.host + "/api/v1/chart?chart=" + this.id;
719
+ if(this.debug) this.log('downloading ' + this.chart_url);
720
+ this_state_object = this;
721
+
722
+ $.ajax( {
723
+ url: this.chart_url,
724
+ crossDomain: true
725
+ })
726
+ .done(function(chart) {
727
+ chart.data_url = (this_state_object.host + chart.data_url);
728
+ this_state_object.chart = chart;
729
+ this_state_object.mode.view_update_every = chart.update_every * 1000;
730
+ this_state_object.mode.points = Math.round(self.width() / (chart.update_every / 1000));
731
+
732
+ chart.url = this_state_object.chart_url;
733
+ NETDATA.chartRegistry.add(this_state_object.host, this_state_object.id, chart);
734
+ })
735
+ .fail(function() {
736
+ NETDATA.error(404, this_state_object.chart_url);
737
+ this_state_object.error('chart "' + this_state_object.id + '" not found on url "' + this_state_object.chart_url + '"');
738
+ })
739
+ .always(function() {
740
+ if(typeof callback == 'function') callback();
741
+ });
742
+ }
743
+ },
744
+
745
+ // resize the chart to its real dimensions
746
+ // as given by the caller
747
+ sizeChart: function() {
748
+ if(this.debug) this.log('sizing element');
749
+ self.css('width', this.width)
750
+ .css('height', this.height)
751
+ .css('display', 'inline-block')
752
+ .css('overflow', 'hidden');
753
+ },
754
+
755
+ // show a message in the chart
756
+ message: function(msg) {
757
+ var bgcolor = ""
758
+ if(NETDATA.options.debug.show_boxes)
759
+ bgcolor = " background-color: lightgrey;";
760
+
761
+ this.element.innerHTML = '<div style="font-size: x-small; overflow: hidden;' + bgcolor + ' width: 100%; height: 100%;"><small>'
762
+ + msg
763
+ + '</small></div>';
764
+
765
+ // reset the creation datetime
766
+ // since we overwrote the whole element
767
+ this.created_ms = 0
768
+ if(this.debug) this.log(msg);
769
+ },
770
+
771
+ // show an error on the chart and stop it forever
772
+ error: function(msg) {
773
+ this.message(msg);
774
+ this.enabled = false;
775
+ },
776
+
777
+ // show a message indicating the chart is loading
778
+ loading: function() {
779
+ this.message('chart ' + this.id + ' is loading...');
780
+ }
781
+ };
782
+
783
+ if(state.debug) state.log('created');
784
+ state.sizeChart();
785
+ state.loading();
786
+
787
+ if(typeof NETDATA.chartLibraries[state.library_name] == 'undefined') {
788
+ NETDATA.error(402, state.library_name);
789
+ state.error('chart library "' + state.library_name + '" is not found');
790
+ }
791
+ else if(!NETDATA.chartLibraries[state.library_name].enabled) {
792
+ NETDATA.error(403, state.library_name);
793
+ state.error('chart library "' + state.library_name + '" is not enabled');
794
+ }
795
+ else {
796
+ state.library = NETDATA.chartLibraries[state.library_name];
797
+ state.pixels_per_point = self.data('pixels-per-point') || state.library.pixels_per_point;
798
+ }
799
+
800
+ if(state.refresh_dt_element_name)
801
+ state.refresh_dt_element = document.getElementById(state.refresh_dt_element_name) || null;
802
+
803
+ state.setMode('auto');
804
+
805
+ return state;
806
+ }
807
+
808
+ // get or create a chart state, given a DOM element
809
+ NETDATA.chartState = function(element) {
810
+ self = $(element);
811
+ var state = self.data('state') || null;
812
+ if(!state) {
813
+ state = NETDATA.chartInitialState(element);
814
+ self.data('state', state);
815
+ }
816
+ return state;
817
}
818
819
// ----------------------------------------------------------------------------------------------------------------
@@ -217,25 +869,6 @@
869
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
870
}
871
220
- // this is the main function - where everything starts
221
- NETDATA.init = function() {
222
- // this should be called only once
223
-
224
- $(window).blur(function() {
225
- NETDATA.options.page_is_visible = 0;
226
- if(NETDATA.options.debug.focus) console.log('Lost Focus!');
227
- });
228
-
229
- $(window).focus(function() {
230
- NETDATA.options.page_is_visible = 1;
231
- if(NETDATA.options.debug.focus) console.log('Focus restored!');
232
- });
233
-
234
- NETDATA.getDomCharts(function() {
235
- NETDATA.chartRefresher(0);
236
- });
237
- }
238
-
872
// user function to signal us the DOM has been
873
// updated.
874
NETDATA.updatedDom = function() {
@@ -244,201 +877,93 @@
877
878
// ----------------------------------------------------------------------------------------------------------------
879
247
- NETDATA.generateChartDataURL = function() {
248
- self = $(this);
249
-
250
- var chart = self.data('chart');
251
- var host = self.data('host') || NETDATA.chartDefaults.host;
252
- var width = self.width();
253
- var height = self.height();
254
- var method = self.data('method') || NETDATA.chartDefaults.method;
255
- var after = self.data('after') || NETDATA.chartDefaults.after;
256
- var before = self.data('before') || NETDATA.chartDefaults.before;
257
- var library = self.data('chart-library') || NETDATA.chartDefaults.library;
258
- var dimensions = self.data('dimensions') || null;
259
- var pixels_per_point = self.data('pixels-per-point') || NETDATA.chartLibraries[library].pixels_per_point;
260
-
261
- if(self.data('chart-panning') || self.data('chart-zooming')) {
262
- before = self.data('panning-before') || 0;
263
- after = self.data('panning-after') || 0;
264
- }
265
-
266
- // force an options provided detail
267
- if(pixels_per_point < NETDATA.options.current.pixels_per_point)
268
- pixels_per_point = NETDATA.options.current.pixels_per_point
269
-
270
- var points = self.data('points') || Math.round(width / pixels_per_point);
271
- var format = self.data('format') || NETDATA.chartLibraries[library].format;
272
- var options = self.data('options') || NETDATA.chartLibraries[library].options;
273
-
274
- // build the data URL
275
- var url = host + chart.data_url;
276
- url += "&format=" + format;
277
- url += "&points=" + points.toString();
278
- url += "&group=" + method;
279
- url += "&options=" + options;
280
- if(NETDATA.chartLibraries[library].jsonWrapper) url += '|jsonwrap';
281
-
282
- if(after)
283
- url += "&after=" + after.toString();
284
-
285
- if(before)
286
- url += "&before=" + before.toString();
287
-
288
- if(dimensions)
289
- url += "&dimensions=" + dimensions;
290
-
291
- self.data('calculated-width', width)
292
- .data('calculated-height', height)
293
- .data('calculated-points', points)
294
- .data('calculated-options', options)
295
- .data('calculated-url', url);
880
+ NETDATA.chartRefresher = function(index) {
881
+ // if(NETDATA.options.debug.mail_loop) console.log('NETDATA.chartRefresher(<targets, ' + index + ')');
882
297
- if(NETDATA.options.debug.chart_data_url) console.log('generateChartDataURL(): ' + url + ' WxH:' + width + 'x' + height + ' points: ' + points + ' library: ' + library);
298
- return url;
299
- }
883
+ if(NETDATA.options.updated_dom) {
884
+ // the dom has been updated
885
+ // get the dom parts again
886
+ NETDATA.getDomCharts(function() {
887
+ NETDATA.chartRefresher(0);
888
+ });
889
301
- NETDATA.validateDomCharts = function(targets, index, callback) {
302
- if(NETDATA.options.debug.main_loop) console.log('validateDomCharts() working on ' + index);
890
+ return;
891
+ }
892
304
- var target = targets.get(index);
893
+ var target = NETDATA.options.targets.get(index);
894
if(target == null) {
306
- if(NETDATA.options.debug.main_loop) console.log('validateDomCharts(): all ' + (index - 1) + ' charts parsed.');
307
- if(typeof callback == 'function') callback();
308
- }
895
+ if(NETDATA.options.debug.main_loop) console.log('waiting to restart main loop...');
896
+ NETDATA.options.auto_refresher_fast_weight = 0;
897
+
898
+ setTimeout(function() {
899
+ NETDATA.chartRefresher(0);
900
+ }, NETDATA.options.current.idle_between_loops);
901
+ }
902
else {
310
- var self = $(target);
311
- if(!self.data('prepared')) {
312
- self.data('prepared', true)
313
- .data('updated', 0)
314
- .data('chart-created', false)
315
- .data('refresher-enabled', false)
316
- .data('chart-panning', false)
317
- .data('chart-zooming', false)
318
- .data('chart-paused', false)
319
- .data('panning-before', 0)
320
- .data('panning-after', 0);
321
-
322
- var id = self.data('netdata');
323
- var host = self.data('host') || NETDATA.chartDefaults.host;
324
- var library = self.data('chart-library') || NETDATA.chartDefaults.library;
325
-
326
- if(NETDATA.options.debug.main_loop) console.log('validateDomCharts() parsing ' + id + ' of type ' + library);
327
-
328
- if(typeof NETDATA.chartLibraries[library] == 'undefined') {
329
- NETDATA.error(402, library);
330
- NETDATA.messageInABox(target, 'chart library "' + library + '" is not found');
331
- NETDATA.validateDomCharts(targets, ++index, callback);
332
- }
333
- else if(!NETDATA.chartLibraries[library].enabled) {
334
- NETDATA.error(403, library);
335
- NETDATA.messageInABox(target, 'chart library "' + library + '" is not enabled');
336
- NETDATA.validateDomCharts(targets, ++index, callback);
337
- }
338
- else if(!NETDATA.chartLibraries[library].initialized) {
339
- self.data('prepared', false);
340
- NETDATA.chartLibraries[library].initialize(function() {
341
- NETDATA.validateDomCharts(targets, index, callback);
342
- });
343
- }
344
- else {
345
- var url = host + "/api/v1/chart?chart=" + id;
903
+ var state = NETDATA.chartState(target);
904
347
- $.ajax( {
348
- url: url,
349
- crossDomain: true
350
- })
351
- .done(function(chart) {
352
- self.data('chart', chart)
353
- .data('update-every', chart.update_every * 1000)
354
- .data('refresher-enabled', true)
355
- .data('host', host)
356
- .data('chart-library', library);
357
- })
358
- .fail(function() {
359
- NETDATA.error(404, url);
360
- NETDATA.messageInABox(target, 'chart "' + id + '" not found on url "' + url + '"');
361
- })
362
- .always(function() {
363
- NETDATA.validateDomCharts(targets, ++index, callback);
364
- });
365
- }
905
+ if(NETDATA.options.auto_refresher_fast_weight < NETDATA.options.current.fast_render_timeframe) {
906
+ if(NETDATA.options.debug.main_loop) console.log('fast rendering...');
907
+
908
+ state.autoRefresh(function() {
909
+ NETDATA.chartRefresher(++index);
910
+ }, false);
911
}
912
else {
368
- NETDATA.validateDomCharts(targets, ++index, callback);
913
+ if(NETDATA.options.debug.main_loop) console.log('waiting for next refresh...');
914
+ NETDATA.options.auto_refresher_fast_weight = 0;
915
+
916
+ setTimeout(function() {
917
+ state.autoRefresh(function() {
918
+ NETDATA.chartRefresher(++index);
919
+ }, false);
920
+ }, NETDATA.options.current.idle_between_charts);
921
}
922
}
923
}
924
373
- NETDATA.sizeDomCharts = function(targets, index, callback) {
374
- // this is used to quickly size all charts to their size
375
-
376
- if(NETDATA.options.debug.main_loop) console.log('sizeDomCharts() working on ' + index);
925
+ NETDATA.getDomCharts = function(callback) {
926
+ NETDATA.options.updated_dom = 0;
927
378
- var target = targets.get(index);
379
- if(target == null) {
380
- if(NETDATA.options.debug.main_loop) console.log('sizeDomCharts(): all ' + (index - 1) + ' charts sized.');
381
- if(typeof callback == 'function') callback();
382
- }
383
- else {
384
- var self = $(target);
928
+ NETDATA.options.targets = $('div[data-netdata]').filter(':visible');
929
386
- var id = self.data('netdata');
387
- var width = self.data('width') || NETDATA.chartDefaults.width;
388
- var height = self.data('height') || NETDATA.chartDefaults.height;
930
+ if(NETDATA.options.debug.main_loop)
931
+ console.log('DOM updated - there are ' + NETDATA.options.targets.length + ' charts on page.');
932
390
- self.css('width', width)
391
- .css('height', height)
392
- .css('display', 'inline-block')
393
- .css('overflow', 'hidden');
933
+ // we need to re-size all the charts quickly
934
+ // before making any external calls
935
+ $.each(NETDATA.options.targets, function(i, target) {
936
+ // the initialization will take care of sizing
937
+ // and the "loading..." message
938
+ var state = NETDATA.chartState(target);
939
+ });
940
395
- NETDATA.messageInABox(target, 'chart "' + id + '" is loading...');
396
- NETDATA.sizeDomCharts(targets, ++index, callback);
397
- }
941
+ if(typeof callback == 'function') callback();
942
}
943
400
- NETDATA.getDomCharts = function(callback) {
401
- NETDATA.options.updated_dom = 0;
944
+ // this is the main function - where everything starts
945
+ NETDATA.init = function() {
946
+ // this should be called only once
947
403
- NETDATA.options.targets = $('div[data-netdata]').filter(':visible')
404
- .bind('create', function(event, data) {
405
- var self = $(this);
948
+ NETDATA.options.page_is_visible = 1;
949
407
- if(NETDATA.options.debug.chart_errors) {
408
- NETDATA.chartLibraries[self.data('chart-library')].create(this, data);
409
- self.data('chart-created', true);
410
- }
411
- else {
412
- try {
413
- NETDATA.chartLibraries[self.data('chart-library')].create(this, data);
414
- self.data('chart-created', true);
415
- }
416
- catch(err) {
417
- NETDATA.messageInABox(this, 'chart "' + self.data('netdata') + '" failed to be created as ' + self.data('chart-library'));
418
- self.data('chart-created', false);
419
- }
420
- }
421
- })
422
- .bind('update', function(event, data) {
423
- var self = $(this);
424
- if(NETDATA.options.debug.chart_errors)
425
- NETDATA.chartLibraries[self.data('chart-library')].update(this, data);
426
- else {
427
- try {
428
- NETDATA.chartLibraries[self.data('chart-library')].update(this, data);
429
- }
430
- catch(err) {
431
- NETDATA.messageInABox(this, 'chart "' + self.data('netdata') + '" failed to be updated as ' + self.data('chart-library'));
432
- self.data('chart-created', false);
433
- }
434
- }
435
- });
950
+ $(window).blur(function() {
951
+ NETDATA.options.page_is_visible = 0;
952
+ if(NETDATA.options.debug.focus) console.log('Lost Focus!');
953
+ });
954
437
- if(NETDATA.options.debug.main_loop)
438
- console.log('DOM updated - there are ' + NETDATA.options.targets.length + ' charts on page.');
955
+ $(window).focus(function() {
956
+ NETDATA.options.page_is_visible = 1;
957
+ if(NETDATA.options.debug.focus) console.log('Focus restored!');
958
+ });
959
440
- NETDATA.sizeDomCharts(NETDATA.options.targets, 0, function() {
441
- NETDATA.validateDomCharts(NETDATA.options.targets, 0, callback);
960
+ if(typeof document.hasFocus == 'function' && !document.hasFocus()) {
961
+ NETDATA.options.page_is_visible = 0;
962
+ if(NETDATA.options.debug.focus) console.log('Document has no focus!');
963
+ }
964
+
965
+ NETDATA.getDomCharts(function() {
966
+ NETDATA.chartRefresher(0);
967
});
968
}
969
@@ -454,153 +979,6 @@
979
//var c = new chart();
980
//c.color();
981
457
- NETDATA.chartValuesDownloader = function(element, callback, panning) {
458
- var self = $(element);
459
- var last = self.data('updated') || 0;
460
- var every = self.data('update-every') || 1;
461
-
462
- // check if this chart has to be refreshed now
463
- var now = new Date().getTime();
464
- if(!panning && last + every > now) {
465
- if(NETDATA.options.debug.chart_timing) console.log(self.data('netdata') + ' too soon - skipping.');
466
- if(typeof callback == 'function') callback();
467
- }
468
- else if(!panning && !self.visible(true)) {
469
- if(NETDATA.options.debug.visibility) console.log(self.data('netdata') + ' is NOT visible.');
470
- if(typeof callback == 'function') callback();
471
- }
472
- else {
473
- if(NETDATA.options.debug.visibility) console.log(self.data('netdata') + ' is visible, downloading data...');
474
- $.ajax( {
475
- url: NETDATA.generateChartDataURL.call(element), // self.data('chart-url'),
476
- crossDomain: true
477
- })
478
- .then(function(data) {
479
- var started = new Date().getTime();
480
-
481
- // if the result is JSON, find the latest update-every
482
- if(NETDATA.chartLibraries[self.data('chart-library')].jsonWrapper) {
483
- if(!panning && typeof data.update_every != 'undefined')
484
- self.data('update-every', data.update_every * 1000);
485
-
486
- if(typeof data.after != 'undefined')
487
- self.data('panning-after', data.after);
488
-
489
- if(typeof data.before != 'undefined')
490
- self.data('panning-before', data.before);
491
- }
492
-
493
- if(self.data('chart-created')) {
494
- if(NETDATA.options.debug.chart_calls) console.log('updating ' + self.data('chart-library') + ' chart ' + self.data('netdata'));
495
- self.trigger('update', [data]);
496
- // NETDATA.chartLibraries[self.data('chart-library')].update(element, data);
497
- }
498
- else {
499
- if(NETDATA.options.debug.chart_calls) console.log('creating ' + self.data('chart-library') + ' chart ' + self.data('netdata'));
500
- self.trigger('create', [data]);
501
- //NETDATA.chartLibraries[self.data('chart-library')].create(element, data);
502
- }
503
-
504
- var ended = new Date().getTime();
505
- self.data('updated', ended);
506
-
507
- var dt = ended - started;
508
-
509
- self.data('refresh-dt', dt);
510
- var element_name = self.data('dt-element-name') || null;
511
- if(element_name) {
512
- var element = document.getElementById(element_name) || null;
513
- if(element) {
514
- element.innerHTML = dt.toString();
515
- }
516
- }
517
- })
518
- .fail(function() {
519
- NETDATA.messageInABox(element, 'cannot download chart "' + self.data('netdata') + '" values from url "' + self.data('chart-url') + '"');
520
- })
521
- .always(function() {
522
- if(typeof callback == 'function') callback();
523
- });
524
- }
525
- };
526
-
527
- NETDATA.chartRefresher = function(index) {
528
- // if(NETDATA.options.debug.mail_loop) console.log('NETDATA.chartRefresher(<targets, ' + index + ')');
529
-
530
- if(!NETDATA.options.page_is_visible) {
531
- if(NETDATA.options.debug.main_loop) console.log('waiting focus...');
532
- setTimeout(function() {
533
- NETDATA.chartRefresher(index);
534
- }, NETDATA.options.current.idle_lost_focus);
535
- }
536
- else {
537
- now = new Date().getTime();
538
-
539
- if(now < NETDATA.options.refreshed_stop_until) {
540
- if(NETDATA.options.debug.main_loop) console.log('refreshed stopped until...');
541
- setTimeout(function() {
542
- NETDATA.chartRefresher(index);
543
- }, NETDATA.options.current.idle_between_loops);
544
- }
545
- else if(NETDATA.options.updated_dom) {
546
- // the dom has been updated
547
- // get the dom parts again
548
- NETDATA.getDomCharts(function() {
549
- NETDATA.chartRefresher(0);
550
- });
551
- }
552
- else {
553
- var target = NETDATA.options.targets.get(index);
554
- if(target == null) {
555
- if(NETDATA.options.debug.main_loop) console.log('waiting to restart main loop...');
556
- NETDATA.options.last_paused = now;
557
-
558
- setTimeout(function() {
559
- NETDATA.chartRefresher(0);
560
- }, NETDATA.options.current.idle_between_loops);
561
- }
562
- else {
563
- var self = $(target);
564
- if(!self.data('refresher-enabled')) {
565
- if(NETDATA.options.debug.main_loop) console.log('chart has refresher disabled...');
566
- NETDATA.chartRefresher(++index);
567
- }
568
- else if(self.data('chart-panning')) {
569
- if(NETDATA.options.debug.main_loop) console.log('chart is panning...');
570
- NETDATA.chartRefresher(++index);
571
- }
572
- else if(self.data('chart-zooming')) {
573
- if(NETDATA.options.debug.main_loop) console.log('chart is zooming...');
574
- NETDATA.chartRefresher(++index);
575
- }
576
- else if(self.data('chart-paused')) {
577
- if(NETDATA.options.debug.main_loop) console.log('chart is paused...');
578
- NETDATA.chartRefresher(++index);
579
- }
580
- else {
581
- if(now - NETDATA.options.last_paused < NETDATA.options.current.fast_render_timeframe) {
582
- if(NETDATA.options.debug.main_loop) console.log('fast rendering...');
583
-
584
- NETDATA.chartValuesDownloader(target, function() {
585
- NETDATA.chartRefresher(++index);
586
- }, false);
587
- }
588
- else {
589
- if(NETDATA.options.debug.main_loop) console.log('waiting for next refresh...');
590
- NETDATA.options.last_paused = now;
591
-
592
- setTimeout(function() {
593
- NETDATA.chartValuesDownloader(target, function() {
594
- NETDATA.chartRefresher(++index);
595
- }, false);
596
- }, NETDATA.options.current.idle_between_charts);
597
- }
598
- }
599
- }
600
- }
601
- }
602
- }
603
-
982
// ----------------------------------------------------------------------------------------------------------------
983
// peity
984
@@ -626,30 +1004,20 @@
1004
};
1005
1006
NETDATA.peityChartUpdate = function(element, data) {
629
- var self = $(element);
630
- var instance = self.data('peity-instance');
631
- var ins = $(instance);
632
- ins.html(data.result);
633
-
1007
+ var peity = $(data.state.peity_element);
1008
+ peity.html(data.result);
1009
// peity.change() does not accept options
1010
// to pass width and height
636
- //ins.change();
637
- ins.peity('line', { width: self.data('calculated-width'), height: self.data('calculated-height') })
1011
+ //peity.change();
1012
+ peity.peity('line', { width: data.state.calculated_width, height: data.state.calculated_height });
1013
}
1014
1015
NETDATA.peityChartCreate = function(element, data) {
641
- var self = $(element);
642
-
643
- var uuid = NETDATA.guid();
644
- element.innerHTML = '<div id="' + uuid + '">' + data.result + '</div>';
645
- var instance = document.getElementById(uuid);
646
- var ins = $(instance);
647
-
648
- ins.peity('line', { width: self.data('calculated-width'), height: self.data('calculated-height') })
1016
+ element.innerHTML = '<div id="peity-' + data.state.uuid + '">' + data.result + '</div>';
1017
+ data.state.peity_element = document.getElementById('peity-' + data.state.uuid);
1018
+ var peity = $(data.state.peity_element);
1019
650
- self.data('peity-uuid', uuid)
651
- .data('peity-instance', instance)
652
- .data('chart-created', true);
1020
+ peity.peity('line', { width: data.state.calculated_width, height: data.state.calculated_height });
1021
}
1022
1023
// ----------------------------------------------------------------------------------------------------------------
@@ -677,19 +1045,18 @@
1045
};
1046
1047
NETDATA.sparklineChartUpdate = function(element, data) {
680
- var self = $(element);
681
- var options = self.data('sparkline-options');
682
- options.width = self.data('calculated-width');
683
- options.height = self.data('calculated-height');
684
- self.sparkline(data.result, options);
1048
+ data.state.sparkline_options.width = data.state.calculated_width;
1049
+ data.state.sparkline_options.height = data.state.calculated_height;
1050
+
1051
+ spark = $(data.state.sparkline_element);
1052
+ spark.sparkline(data.result, data.state.sparkline_options);
1053
}
1054
1055
NETDATA.sparklineChartCreate = function(element, data) {
1056
var self = $(element);
689
- var chart = self.data('chart');
1057
var type = self.data('sparkline-type') || 'line';
1058
var lineColor = self.data('sparkline-linecolor') || NETDATA.colors[0];
692
- var fillColor = self.data('sparkline-fillcolor') || (chart.chart_type == 'line')?'#FFF':NETDATA.ColorLuminance(lineColor, 0.8);
1059
+ var fillColor = self.data('sparkline-fillcolor') || (data.state.chart.chart_type == 'line')?'#FFF':NETDATA.ColorLuminance(lineColor, 0.8);
1060
var chartRangeMin = self.data('sparkline-chartrangemin') || undefined;
1061
var chartRangeMax = self.data('sparkline-chartrangemax') || undefined;
1062
var composite = self.data('sparkline-composite') || undefined;
@@ -723,7 +1090,7 @@
1090
var tooltipClassname = self.data('sparkline-tooltipclassname') || undefined;
1091
var tooltipFormat = self.data('sparkline-tooltipformat') || undefined;
1092
var tooltipPrefix = self.data('sparkline-tooltipprefix') || undefined;
726
- var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + chart.units;
1093
+ var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + data.state.chart.units;
1094
var tooltipSkipNull = self.data('sparkline-tooltipskipnull') || true;
1095
var tooltipValueLookups = self.data('sparkline-tooltipvaluelookups') || undefined;
1096
var tooltipFormatFieldlist = self.data('sparkline-tooltipformatfieldlist') || undefined;
@@ -734,7 +1101,7 @@
1101
var numberDigitGroupCount = self.data('sparkline-numberdigitgroupcount') || undefined;
1102
var animatedZooms = self.data('sparkline-animatedzooms') || false;
1103
737
- var options = {
1104
+ data.state.sparkline_options = {
1105
type: type,
1106
lineColor: lineColor,
1107
fillColor: fillColor,
@@ -768,7 +1135,7 @@
1135
highlightColor: highlightColor,
1136
tooltipContainer: tooltipContainer,
1137
tooltipClassname: tooltipClassname,
771
- tooltipChartTitle: chart.title,
1138
+ tooltipChartTitle: data.state.chart.title,
1139
tooltipFormat: tooltipFormat,
1140
tooltipPrefix: tooltipPrefix,
1141
tooltipSuffix: tooltipSuffix,
@@ -781,43 +1148,92 @@
1148
numberDecimalMark: numberDecimalMark,
1149
numberDigitGroupCount: numberDigitGroupCount,
1150
animatedZooms: animatedZooms,
784
- width: self.data('calculated-width'),
785
- height: self.data('calculated-height')
1151
+ width: data.state.calculated_width,
1152
+ height: data.state.calculated_height
1153
};
1154
788
- var uuid = NETDATA.guid();
789
- element.innerHTML = '<div style="display: inline-block; position: relative;" id="' + uuid + '"></div>';
790
- var div = document.getElementById(uuid);
1155
+ element.innerHTML = '<div id="sparkline-' + data.state.uuid + '" style="display: inline-block; position: relative;"></div>';
1156
+ data.state.sparkline_element = document.getElementById('sparkline-' + data.state.uuid);
1157
792
- self.sparkline(data.result, options);
793
- self.data('sparkline-options', options)
794
- .data('uuid', uuid)
795
- .data('chart-created', true);
1158
+ spark = $(data.state.sparkline_element);
1159
+ spark.sparkline(data.result, data.state.sparkline_options);
1160
};
1161
1162
// ----------------------------------------------------------------------------------------------------------------
1163
// dygraph
1164
801
- NETDATA.dygraphAllCharts = [];
802
- NETDATA.dygraphInitSync = function(callback) {
803
- //$.getScript(NETDATA.serverDefault + 'dygraph-synchronizer.js')
804
- // .always(function() {
805
- if(typeof callback == "function")
806
- callback();
807
- // })
1165
+ NETDATA.dygraph = {
1166
+ sync: false,
1167
+ paused: []
1168
+ };
1169
+
1170
+ NETDATA.dygraph.syncStart = function(state, event, x, points, row, seriesName) {
1171
+ if(NETDATA.options.debug.dygraph || state.debug) console.log('dygraph.syncStart()');
1172
+ state.pauseChart();
1173
+
1174
+ var dygraph = state.dygraph_instance;
1175
+
1176
+ if(!NETDATA.dygraph.sync) {
1177
+ $.each(NETDATA.options.targets, function(i, target) {
1178
+ var st = NETDATA.chartState(target);
1179
+ if(typeof st.dygraph_instance == 'object' && st.library_name == state.library_name && st.canBeAutoRefreshed(false)) {
1180
+ NETDATA.dygraph.paused.push(st);
1181
+ }
1182
+ });
1183
+ }
1184
+
1185
+ $.each(NETDATA.dygraph.paused, function(i, st) {
1186
+ st.setSelection(x);
1187
+ });
1188
+
1189
}
1190
810
- NETDATA.dygraphSync = null;
811
- NETDATA.dygraphSyncAll = function() {
812
- if(NETDATA.dygraphSync) {
813
- NETDATA.dygraphSync.detach();
814
- NETDATA.dygraphSync = null;
1191
+ NETDATA.dygraph.syncStop = function(state) {
1192
+ if(NETDATA.options.debug.dygraph || state.debug) console.log('dygraph.syncStop()');
1193
+
1194
+ if(!NETDATA.dygraph.sync) {
1195
+ $.each(NETDATA.dygraph.paused, function(i, st) {
1196
+ st.clearSelection();
1197
+ });
1198
+
1199
+ NETDATA.dygraph.sync = false;
1200
+ NETDATA.dygraph.paused = [];
1201
}
1202
817
- NETDATA.dygraphSync = Dygraph.synchronize(NETDATA.dygraphAllCharts, {
818
- selection: true,
819
- zoom: false
820
- });
1203
+ state.unpauseChart();
1204
+ }
1205
+
1206
+ NETDATA.dygraph.resetChart = function(element, dygraph) {
1207
+ if(NETDATA.options.debug.dygraph) console.log('dygraph.resetChart()');
1208
+
1209
+ state = NETDATA.chartState(element);
1210
+ state.resetChart();
1211
+ if(NETDATA.globalPanAndZoom.clearMaster());
1212
+ }
1213
+
1214
+ NETDATA.dygraph.zoomOrPan = function(element, dygraph, after, before) {
1215
+ if(NETDATA.options.debug.dygraph) console.log('>>>> dygraph.zoomOrPan(element, dygraph, after:' + after + ', before: ' + before + ')');
1216
+
1217
+ state = NETDATA.chartState(element);
1218
+ state.updateChartPanOrZoom(after, before);
1219
+ return;
1220
+ }
1221
+
1222
+ NETDATA.dygraphSetSelection = function(state, t) {
1223
+ var r = state.calculateRowForTime(t);
1224
+ if(r != -1) {
1225
+ state.dygraph_instance.setSelection(r);
1226
+ state.pauseChart();
1227
+ }
1228
+ else {
1229
+ state.dygraph_instance.clearSelection();
1230
+ state.unpauseChart();
1231
+ }
1232
+ }
1233
+
1234
+ NETDATA.dygraphclearSelection = function(state, t) {
1235
+ state.dygraph_instance.clearSelection();
1236
+ state.unpauseChart();
1237
}
1238
1239
NETDATA.dygraphInitialize = function(callback) {
@@ -830,7 +1246,8 @@
1246
NETDATA.error(100, NETDATA.dygraph_js);
1247
})
1248
.always(function() {
833
- NETDATA.dygraphInitSync(callback);
1249
+ if(typeof callback == "function")
1250
+ callback();
1251
})
1252
}
1253
else {
@@ -840,90 +1257,25 @@
1257
}
1258
};
1259
843
- NETDATA.dygraphReset = function(element, dygraph) {
844
- if(NETDATA.options.debug.dygraph) console.log('dygraphReset()');
845
-
846
- self = $(element);
847
-
848
- if(self.data('chart-panning') || self.data('chart-paused')) {
849
- self.data('chart-panning', false)
850
- .data('chart-zooming', false)
851
- .data('chart-paused', false)
852
- .data('panning-before', 0)
853
- .data('panning-after', 0)
854
- .data('updated', 0)
855
- .data('panning-before-max', 0);
856
-
857
- NETDATA.options.refreshed_stop_until = 0;
858
- NETDATA.chartValuesDownloader(element, null, false);
859
- }
860
- }
861
-
862
- NETDATA.dygraphZoomOrPan = function(element, dygraph, after, before, zoom) {
863
- if(NETDATA.options.debug.dygraph) console.log('dygraphZoomOrPan()');
864
-
865
- self = $(element);
866
-
867
- var before_old = self.data('panning-before');
868
- var after_old = self.data('panning-after');
869
- var range_old = before_old - after_old;
870
-
871
- var shift = Math.abs(before_old - before);
872
-
873
- var range = before - after;
874
-
875
- if((shift > range_old / 20 || zoom) && range > 10) {
876
- // the user is panning
877
- if(NETDATA.options.debug.dygraph) console.log('dygraphZoomOrPan() ' + after_old + ' - ' + before_old + ', NEW: ' + after + ' - ' + before + ', shift by: ' + shift + ' old range: ' + (before_old - after_old).toString() + ' new range: ' + (before - after).toString());
878
-
879
- if(!self.data('chart-panning') && !self.data('chart-zooming')) {
880
- self.data('chart-panning', true)
881
- .data('panning-before-max', before);
882
- }
883
-
884
- var before_max = self.data('panning-before-max');
885
- if(zoom || before <= before_max) {
886
- NETDATA.options.refreshed_stop_until = now + 2000;
887
-
888
- if(NETDATA.options.debug.dygraph) console.log('dygraphZoomOrPan() rendering.');
889
-
890
- if(zoom) {
891
- self.data('chart-panning', false)
892
- .data('chart-zooming', true);
893
- }
894
- else {
895
- self.data('chart-panning', true)
896
- .data('chart-zooming', false);
897
- }
898
-
899
- self.data('chart-paused', true)
900
- .data('panning-before', before)
901
- .data('panning-after', after)
902
- .data('updated', 0);
903
-
904
- NETDATA.chartValuesDownloader(element, null, true);
905
- }
906
- }
907
- }
908
-
1260
NETDATA.dygraphChartUpdate = function(element, data) {
910
- if(NETDATA.options.debug.dygraph) console.log('dygraphChartUpdate()');
1261
+ if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate()');
1262
912
- var self = $(element);
913
- var dygraph = self.data('dygraph-instance');
1263
+ var dygraph = data.state.dygraph_instance;
1264
915
- if(self.data('chart-panning')) {
1265
+ if(data.state.mode.name == 'pan') {
1266
+ if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate() loose update');
1267
dygraph.updateOptions({
1268
file: data.result.data,
1269
labels: data.result.labels,
919
- labelsDivWidth: self.width() - 70
1270
+ labelsDivWidth: data.state.calculated_width - 70
1271
});
1272
}
1273
else {
1274
+ if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate() strict update');
1275
dygraph.updateOptions({
1276
file: data.result.data,
1277
labels: data.result.labels,
926
- labelsDivWidth: self.width() - 70,
1278
+ labelsDivWidth: data.state.calculated_width - 70,
1279
dateWindow: null,
1280
valueRange: null
1281
});
@@ -931,19 +1283,18 @@
1283
};
1284
1285
NETDATA.dygraphChartCreate = function(element, data) {
934
- if(NETDATA.options.debug.dygraph) console.log('dygraphChartCreate()');
1286
+ if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartCreate()');
1287
1288
var self = $(element);
937
- var chart = self.data('chart');
938
- var title = self.data('dygraph-title') || chart.title;
1289
+ var title = self.data('dygraph-title') || data.state.chart.title;
1290
var titleHeight = self.data('dygraph-titleheight') || 20;
1291
var labelsDiv = self.data('dygraph-labelsdiv') || undefined;
1292
var connectSeparatedPoints = self.data('dygraph-connectseparatedpoints') || false;
1293
var yLabelWidth = self.data('dygraph-ylabelwidth') || 12;
943
- var stackedGraph = self.data('dygraph-stackedgraph') || (chart.chart_type == 'stacked')?true:false;
1294
+ var stackedGraph = self.data('dygraph-stackedgraph') || (data.state.chart.chart_type == 'stacked')?true:false;
1295
var stackedGraphNaNFill = self.data('dygraph-stackedgraphnanfill') || 'none';
1296
var hideOverlayOnMouseOut = self.data('dygraph-hideoverlayonmouseout') || true;
946
- var fillGraph = self.data('dygraph-fillgraph') || (chart.chart_type == 'area')?true:false;
1297
+ var fillGraph = self.data('dygraph-fillgraph') || (data.state.chart.chart_type == 'area')?true:false;
1298
var drawPoints = self.data('dygraph-drawpoints') || false;
1299
var labelsDivStyles = self.data('dygraph-labelsdivstyles') || { 'fontSize':'10px' };
1300
var labelsDivWidth = self.data('dygraph-labelsdivwidth') || self.width() - 70;
@@ -965,11 +1316,11 @@
1316
var pointSize = self.data('dygraph-pointsize') || 1;
1317
var stepPlot = self.data('dygraph-stepplot') || false;
1318
var strokeBorderColor = self.data('dygraph-strokebordercolor') || 'white';
968
- var strokeBorderWidth = self.data('dygraph-strokeborderwidth') || (chart.chart_type == 'stacked')?1.0:0.0;
1319
+ var strokeBorderWidth = self.data('dygraph-strokeborderwidth') || (data.state.chart.chart_type == 'stacked')?1.0:0.0;
1320
var strokePattern = self.data('dygraph-strokepattern') || undefined;
1321
var highlightCircleSize = self.data('dygraph-highlightcirclesize') || 3;
1322
var highlightSeriesOpts = self.data('dygraph-highlightseriesopts') || { strokeWidth: 1.5 };
972
- var highlightSeriesBackgroundAlpha = self.data('dygraph-highlightseriesbackgroundalpha') || (chart.chart_type == 'stacked')?0.7:0.5;
1323
+ var highlightSeriesBackgroundAlpha = self.data('dygraph-highlightseriesbackgroundalpha') || (data.state.chart.chart_type == 'stacked')?0.7:0.5;
1324
var pointClickCallback = self.data('dygraph-pointclickcallback') || undefined;
1325
var showRangeSelector = self.data('dygraph-showrangeselector') || false;
1326
var showRoller = self.data('dygraph-showroller') || false;
@@ -981,10 +1332,10 @@
1332
var gridLinePattern = self.data('dygraph-gridlinepattern') || null;
1333
var gridLineWidth = self.data('dygraph-gridlinewidth') || 0.3;
1334
984
- var options = {
1335
+ data.state.dygraph_options = {
1336
title: title,
1337
titleHeight: titleHeight,
987
- ylabel: chart.units,
1338
+ ylabel: data.state.chart.units,
1339
yLabelWidth: yLabelWidth,
1340
connectSeparatedPoints: connectSeparatedPoints,
1341
drawPoints: drawPoints,
@@ -1048,47 +1399,57 @@
1399
}
1400
},
1401
drawCallback: function(dygraph, is_initial) {
1051
- if(NETDATA.options.debug.dygraph) console.log('dygraphDrawCallback()');
1402
+ if(data.state.mode.name != 'auto') {
1403
+ if(NETDATA.options.debug.dygraph) console.log('dygraphDrawCallback()');
1404
1053
- var x_range = dygraph.xAxisRange();
1054
- var after = Math.round(x_range[0] / 1000);
1055
- var before = Math.round(x_range[1] / 1000);
1405
+ var x_range = dygraph.xAxisRange();
1406
+ var after = Math.round(x_range[0]);
1407
+ var before = Math.round(x_range[1]);
1408
1057
- NETDATA.dygraphZoomOrPan(element, this, after, before, false, true);
1409
+ NETDATA.dygraph.zoomOrPan(element, this, after, before);
1410
+ }
1411
},
1412
zoomCallback: function(minDate, maxDate, yRanges) {
1413
if(NETDATA.options.debug.dygraph) console.log('dygraphZoomCallback()');
1061
- NETDATA.dygraphZoomOrPan(element, this, Math.round(minDate / 1000), Math.round(maxDate / 1000), false, true);
1414
+ NETDATA.dygraph.zoomOrPan(element, this, minDate, maxDate);
1415
},
1416
highlightCallback: function(event, x, points, row, seriesName) {
1417
if(NETDATA.options.debug.dygraph) console.log('dygraphHighlightCallback()');
1065
- self.data('chart-paused', true);
1418
+ NETDATA.dygraph.syncStart(data.state, event, x, points, row, seriesName);
1419
},
1420
unhighlightCallback: function(event) {
1421
if(NETDATA.options.debug.dygraph) console.log('dygraphUnhighlightCallback()');
1069
- self.data('chart-paused', false);
1422
+ NETDATA.dygraph.syncStop(data.state);
1423
},
1424
interactionModel : {
1425
mousedown: function(event, dygraph, context) {
1426
if(NETDATA.options.debug.dygraph) console.log('dygraphMouseDown()');
1427
1075
- // Right-click should not initiate a zoom.
1428
+ // Right-click should not initiate a zoom.
1429
if (event.button && event.button == 2) return;
1430
1431
context.initializeMouseDown(event, dygraph, context);
1432
1080
- if (event.altKey || event.shiftKey)
1433
+ if (event.altKey || event.shiftKey) {
1434
+ data.state.setMode('zoom');
1435
Dygraph.startZoom(event, dygraph, context);
1082
- else
1436
+ }
1437
+ else {
1438
+ data.state.setMode('pan');
1439
Dygraph.startPan(event, dygraph, context);
1440
+ }
1441
},
1442
mousemove: function(event, dygraph, context) {
1443
if(NETDATA.options.debug.dygraph) console.log('dygraphMouseMove()');
1444
1088
- if (context.isPanning)
1445
+ if (context.isPanning) {
1446
+ data.state.setMode('pan');
1447
Dygraph.movePan(event, dygraph, context);
1090
- else if (context.isZooming)
1448
+ }
1449
+ else if (context.isZooming) {
1450
+ data.state.setMode('zoom');
1451
Dygraph.moveZoom(event, dygraph, context);
1452
+ }
1453
},
1454
mouseup: function(event, dygraph, context) {
1455
if(NETDATA.options.debug.dygraph) console.log('dygraphMouseUp()');
@@ -1104,7 +1465,7 @@
1465
},
1466
dblclick: function(event, dygraph, context) {
1467
if(NETDATA.options.debug.dygraph) console.log('dygraphMouseDoubleClick()');
1107
- NETDATA.dygraphReset(element, dygraph);
1468
+ NETDATA.dygraph.resetChart(element, dygraph);
1469
},
1470
mousewheel: function(event, dygraph, context) {
1471
if(NETDATA.options.debug.dygraph) console.log('dygraphMouseWheel()');
@@ -1112,27 +1473,31 @@
1473
if(event.altKey || event.shiftKey) {
1474
// http://dygraphs.com/gallery/interaction-api.js
1475
var normal = (event.detail) ? event.detail * -1 : event.wheelDelta / 40;
1115
- var percentage = normal / 10;
1476
+ var percentage = normal / 25;
1477
1117
- var before_old = self.data('panning-before');
1118
- var after_old = self.data('panning-after');
1478
+ var before_old = data.state.mode.before_ms;
1479
+ var after_old = data.state.mode.after_ms;
1480
var range_old = before_old - after_old;
1481
1482
var range = range_old * ( 1 - percentage );
1483
var dt = Math.round((range_old - range) / 2);
1123
- before = before_old - dt;
1124
- after = after_old + dt;
1484
+
1485
+ var before = before_old - dt;
1486
+ var after = after_old + dt;
1487
1488
if(NETDATA.options.debug.dygraph) console.log('percent: ' + percentage + ' from ' + after_old + ' - ' + before_old + ' to ' + after + ' - ' + before + ', range from ' + (before_old - after_old).toString() + ' to ' + (before - after).toString());
1489
1128
- NETDATA.dygraphZoomOrPan(element, dygraph, after, before, true);
1490
+ data.state.setMode('zoom');
1491
+ NETDATA.dygraph.zoomOrPan(element, dygraph, after, before);
1492
}
1493
},
1494
touchstart: function(event, dygraph, context) {
1495
Dygraph.Interaction.startTouch(event, dygraph, context);
1133
- //context.touchDirections.y = 0;
1496
+ context.touchDirections = { x: true, y: false };
1497
+ data.state.setMode('zoom');
1498
},
1499
touchmove: function(event, dygraph, context) {
1500
+ //Dygraph.cancelEvent(event);
1501
Dygraph.Interaction.moveTouch(event, dygraph, context);
1502
},
1503
touchend: function(event, dygraph, context) {
@@ -1141,20 +1506,10 @@
1506
}
1507
};
1508
1144
- var uuid = NETDATA.guid();
1145
- self.html('<div id="' + uuid + '" style="width: 100%; height: 100%;"></div>');
1146
-
1147
- var dchart = new Dygraph(document.getElementById(uuid),
1148
- data.result.data, options);
1509
+ self.html('<div id="dygraph-' + data.state.uuid + '" style="width: 100%; height: 100%;"></div>');
1510
1150
- self.data('dygraph-instance', dchart)
1151
- .data('dygraph-options', options)
1152
- .data('uuid', uuid)
1153
- .data('chart-created', true);
1154
-
1155
- //NETDATA.dygraphAllCharts.push(dchart);
1156
- //if(NETDATA.dygraphAllCharts.length > 1)
1157
- // NETDATA.dygraphSyncAll();
1511
+ data.state.dygraph_instance = new Dygraph(document.getElementById('dygraph-' + data.state.uuid),
1512
+ data.result.data, data.state.dygraph_options);
1513
};
1514
1515
// ----------------------------------------------------------------------------------------------------------------
@@ -1176,26 +1531,27 @@
1531
callback();
1532
}
1533
}
1534
+ else {
1535
+ var fileref = document.createElement("link");
1536
+ fileref.setAttribute("rel", "stylesheet");
1537
+ fileref.setAttribute("type", "text/css");
1538
+ fileref.setAttribute("href", NETDATA.morris_css);
1539
1180
- var fileref = document.createElement("link");
1181
- fileref.setAttribute("rel", "stylesheet");
1182
- fileref.setAttribute("type", "text/css");
1183
- fileref.setAttribute("href", NETDATA.morris_css);
1184
-
1185
- if (typeof fileref != "undefined")
1186
- document.getElementsByTagName("head")[0].appendChild(fileref);
1540
+ if (typeof fileref != "undefined")
1541
+ document.getElementsByTagName("head")[0].appendChild(fileref);
1542
1188
- $.getScript(NETDATA.morris_js)
1189
- .done(function() {
1190
- NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
1191
- })
1192
- .fail(function() {
1193
- NETDATA.error(100, NETDATA.morris_js);
1194
- })
1195
- .always(function() {
1196
- if(typeof callback == "function")
1197
- callback();
1198
- })
1543
+ $.getScript(NETDATA.morris_js)
1544
+ .done(function() {
1545
+ NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
1546
+ })
1547
+ .fail(function() {
1548
+ NETDATA.error(100, NETDATA.morris_js);
1549
+ })
1550
+ .always(function() {
1551
+ if(typeof callback == "function")
1552
+ callback();
1553
+ })
1554
+ }
1555
}
1556
else {
1557
NETDATA.chartLibraries.morris.enabled = false;
@@ -1205,26 +1561,15 @@
1561
};
1562
1563
NETDATA.morrisChartUpdate = function(element, data) {
1208
- var self = $(element);
1209
- var morris = self.data('morris-instance');
1210
-
1211
- if(morris != null) {
1212
- console.log('updating morris');
1213
- morris.setData(data.result.data);
1214
- }
1215
- else
1216
- console.log('not updating morris');
1564
+ data.state.morris_instance.setData(data.result.data);
1565
};
1566
1567
NETDATA.morrisChartCreate = function(element, data) {
1220
- var self = $(element);
1221
- var chart = self.data('chart');
1568
1223
- var uuid = NETDATA.guid();
1224
- self.html('<div id="' + uuid + '" style="width: ' + self.data('calculated-width') + 'px; height: ' + self.data('calculated-height') + 'px;"></div>');
1569
+ element.innerHTML = '<div id="morris-' + data.state.uuid + '" style="width: ' + data.state.calculated_width + 'px; height: ' + data.state.calculated_height + 'px;"></div>';
1570
1571
var options = {
1227
- element: uuid,
1572
+ element: 'morris-' + data.state.uuid,
1573
data: data.result.data,
1574
xkey: 'time',
1575
ykeys: data.dimension_names,
@@ -1239,18 +1584,18 @@
1584
};
1585
1586
var morris;
1242
- if(chart.chart_type == 'line')
1587
+ if(data.state.chart.chart_type == 'line')
1588
morris = new Morris.Line(options);
1589
1245
- else if(chart.chart_type == 'area') {
1590
+ else if(data.state.chart.chart_type == 'area') {
1591
options.behaveLikeLine = true;
1592
morris = new Morris.Area(options);
1593
}
1594
else // stacked
1595
morris = new Morris.Area(options);
1596
1252
- self.data('morris-instance', morris)
1253
- .data('chart-created', true);
1597
+ data.state.morris_instance = morris;
1598
+ data.state.morris_options = options;
1599
};
1600
1601
// ----------------------------------------------------------------------------------------------------------------
@@ -1281,8 +1626,8 @@
1626
var self = $(element);
1627
1628
self.raphael(data, {
1284
- width: self.data('calculated-width'),
1285
- height: self.data('calculated-height')
1629
+ width: data.state.calculated_width,
1630
+ height: data.state.calculated_height
1631
})
1632
};
1633
@@ -1290,10 +1635,9 @@
1635
var self = $(element);
1636
1637
self.raphael(data, {
1293
- width: self.data('calculated-width'),
1294
- height: self.data('calculated-height')
1638
+ width: data.state.calculated_width,
1639
+ height: data.state.calculated_height
1640
})
1296
- .data('chart-created', true);
1641
};
1642
1643
// ----------------------------------------------------------------------------------------------------------------
@@ -1324,28 +1668,19 @@
1668
};
1669
1670
NETDATA.googleChartUpdate = function(element, data) {
1327
- var self = $(element);
1328
- var gchart = self.data('google-instance');
1329
- var options = self.data('google-options');
1330
-
1671
var datatable = new google.visualization.DataTable(data.result);
1332
-
1333
- gchart.draw(datatable, options);
1672
+ data.state.google_instance.draw(datatable, data.state.google_options);
1673
};
1674
1675
NETDATA.googleChartCreate = function(element, data) {
1337
- var self = $(element);
1338
- var chart = self.data('chart');
1339
-
1676
var datatable = new google.visualization.DataTable(data.result);
1341
- var gchart;
1677
1678
var options = {
1679
// do not set width, height - the chart resizes itself
1345
- //width: self.data('calculated-width'),
1346
- //height: self.data('calculated-height'),
1680
+ //width: data.state.calculated_width,
1681
+ //height: data.state.calculated_height,
1682
lineWidth: 1,
1348
- title: chart.title,
1683
+ title: data.state.chart.title,
1684
fontSize: 11,
1685
hAxis: {
1686
// title: "Time of Day",
@@ -1361,7 +1696,7 @@
1696
}
1697
},
1698
vAxis: {
1364
- title: chart.units,
1699
+ title: data.state.chart.units,
1700
viewWindowMode: 'pretty',
1701
minValue: -0.1,
1702
maxValue: 0.1,
@@ -1400,13 +1735,13 @@
1735
isStacked: false
1736
};
1737
1403
- var uuid = NETDATA.guid();
1404
- self.html('<div id="' + uuid + '" style="width: 100%; height: 100%;"></div>');
1738
+ element.innerHTML = '<div id="google-' + data.state.uuid + '" style="width: 100%; height: 100%;"></div>';
1739
1406
- switch(chart.chart_type) {
1740
+ var gchart;
1741
+ switch(data.state.chart.chart_type) {
1742
case "area":
1743
options.vAxis.viewWindowMode = 'maximized';
1409
- gchart = new google.visualization.AreaChart(document.getElementById(uuid));
1744
+ gchart = new google.visualization.AreaChart(document.getElementById('google-' + data.state.uuid));
1745
break;
1746
1747
case "stacked":
@@ -1415,22 +1750,20 @@
1750
options.vAxis.viewWindowMode = 'maximized';
1751
options.vAxis.minValue = null;
1752
options.vAxis.maxValue = null;
1418
- gchart = new google.visualization.AreaChart(document.getElementById(uuid));
1753
+ gchart = new google.visualization.AreaChart(document.getElementById('google-' + data.state.uuid));
1754
break;
1755
1756
default:
1757
case "line":
1758
options.lineWidth = 2;
1424
- gchart = new google.visualization.LineChart(document.getElementById(uuid));
1759
+ gchart = new google.visualization.LineChart(document.getElementById('google-' + data.state.uuid));
1760
break;
1761
}
1762
1763
gchart.draw(datatable, options);
1764
1430
- self.data('google-instance', gchart)
1431
- .data('google-options', options)
1432
- .data('uuid', uuid)
1433
- .data('chart-created', true);
1765
+ data.state.google_instance = gchart;
1766
+ data.state.google_options = options;
1767
};
1768
1769
// ----------------------------------------------------------------------------------------------------------------
@@ -1441,6 +1774,8 @@
1774
initialize: NETDATA.dygraphInitialize,
1775
create: NETDATA.dygraphChartCreate,
1776
update: NETDATA.dygraphChartUpdate,
1777
+ setSelection: NETDATA.dygraphSetSelection,
1778
+ clearSelection: NETDATA.dygraphClearSelection,
1779
initialized: false,
1780
enabled: true,
1781
format: 'json',
@@ -1453,6 +1788,8 @@
1788
initialize: NETDATA.sparklineInitialize,
1789
create: NETDATA.sparklineChartCreate,
1790
update: NETDATA.sparklineChartUpdate,
1791
+ setSelection: null,
1792
+ clearSelection: null,
1793
initialized: false,
1794
enabled: true,
1795
format: 'array',
@@ -1465,6 +1802,8 @@
1802
initialize: NETDATA.peityInitialize,
1803
create: NETDATA.peityChartCreate,
1804
update: NETDATA.peityChartUpdate,
1805
+ setSelection: null,
1806
+ clearSelection: null,
1807
initialized: false,
1808
enabled: true,
1809
format: 'ssvcomma',
@@ -1477,6 +1816,8 @@
1816
initialize: NETDATA.morrisInitialize,
1817
create: NETDATA.morrisChartCreate,
1818
update: NETDATA.morrisChartUpdate,
1819
+ setSelection: null,
1820
+ clearSelection: null,
1821
initialized: false,
1822
enabled: true,
1823
format: 'json',
@@ -1489,6 +1830,8 @@
1830
initialize: NETDATA.googleInitialize,
1831
create: NETDATA.googleChartCreate,
1832
update: NETDATA.googleChartUpdate,
1833
+ setSelection: null,
1834
+ clearSelection: null,
1835
initialized: false,
1836
enabled: true,
1837
format: 'datatable',
@@ -1501,11 +1844,13 @@
1844
initialize: NETDATA.raphaelInitialize,
1845
create: NETDATA.raphaelChartCreate,
1846
update: NETDATA.raphaelChartUpdate,
1847
+ setSelection: null,
1848
+ clearSelection: null,
1849
initialized: false,
1850
enabled: true,
1851
format: 'json',
1852
options: '',
1508
- jsonWrapper: false,
1853
+ jsonWrapper: true,
1854
pixels_per_point: 1,
1855
detects_dimensions_on_update: false
1856
}
@@ -1518,7 +1863,7 @@
1863
NETDATA.chartLibraries[library].initialized = true;
1864
NETDATA.chartLibraries[library].enabled = true;
1865
1521
- console.log(NETDATA.chartLibraries);
1866
+ // console.log(NETDATA.chartLibraries);
1867
}
1868
1869
// ----------------------------------------------------------------------------------------------------------------