added support for resizable and not resizable charts; added support for re-creating charts based on libraries that cause memory leaks on the browsers; more code cleanups;
Costa Tsaousis (ktsaou) committed
Dec 7, 2015 at 03:00 UTC
d5aef354ab36561f67d2279e2f584f202610b5a6
2 files changed
+486
-387
web/dashboard.css
+10
-12
@@ -25,37 +25,35 @@ html {
25
26
}
27
28
-/*
29
-.netdata-legend {
30
- width: 50px;
31
- height: 100%;
28
+.netdata-chart-legend {
29
background-color:Gray;
30
overflow: auto;
31
overflow-y: scroll;
32
+ display: inline-block;
33
}
36
-*/
37
-
38
-.netdata-chart-container {
34
35
+.netdata-chart {
36
+ display: inline-block;
37
+ overflow: hidden;
38
}
39
42
-.netdata-peity-container {
40
+.netdata-peity-chart {
41
42
}
43
46
-.netdata-sparkline-container {
44
+.netdata-sparkline-chart {
45
46
}
47
50
-.netdata-dygraph-container {
48
+.netdata-dygraph-chart {
49
50
}
51
54
-.netdata-morris-container {
52
+.netdata-morris-chart {
53
54
}
55
58
-.netdata-google-container {
56
+.netdata-google-chart {
57
58
}
59
web/dashboard.js
+476
-375
@@ -130,6 +130,8 @@
130
// rendering the chart that is panned or zoomed).
131
// Used with .current.global_pan_sync_time
132
133
+ last_resized: 0, // the timestamp of the last resize request
134
+
135
// the current profile
136
// we may have many...
137
current: {
@@ -159,9 +161,15 @@
161
// autorefreshing of charts is paused for this amount
162
// of time
163
162
- sync_delay: 1500 // ms - when you pan or zoom a chart, wait this amount
164
+ sync_selection_delay: 1500, // ms - when you pan or zoom a chart, wait this amount
165
// of time before setting up synchronized selections
166
// on hover.
167
+
168
+ sync_selection: true, // enable or disable selection sync
169
+
170
+ sync_pan_and_zoom: true, // enable or disable pan and zoom sync
171
+
172
+ update_only_visible: true // enable or disable visibility management
173
},
174
175
debug: {
@@ -170,7 +178,7 @@
178
focus: 0,
179
visibility: 0,
180
chart_data_url: 0,
173
- chart_errors: 0,
181
+ chart_errors: 1,
182
chart_timing: 0,
183
chart_calls: 0,
184
libraries: 0,
@@ -180,6 +188,9 @@
188
189
if(NETDATA.options.debug.main_loop) console.log('welcome to NETDATA');
190
191
+ window.onresize = function(event) {
192
+ NETDATA.options.last_resized = new Date().getTime();
193
+ };
194
195
// ----------------------------------------------------------------------------------------------------------------
196
// Error Handling
@@ -274,6 +285,8 @@
285
286
// set a new master
287
setMaster: function(state, after, before) {
288
+ if(!NETDATA.options.current.sync_pan_and_zoom) return;
289
+
290
if(this.master && this.master != state)
291
this.master.resetChart();
292
@@ -320,6 +333,9 @@
333
if(!this.master || !this.seq)
334
return false;
335
336
+ if(state.needsResize())
337
+ return true;
338
+
339
if(state.follows_global == this.seq)
340
return false;
341
@@ -341,10 +357,6 @@
357
width: self.data('width') || NETDATA.chartDefaults.width,
358
height: self.data('height') || NETDATA.chartDefaults.height,
359
344
- // these are calculated every time the chart is refreshed
345
- calculated_width: 0,
346
- calculated_height: 0,
347
-
360
// string - the netdata server URL, without any path
361
host: self.data('host') || NETDATA.chartDefaults.host,
362
@@ -356,7 +368,7 @@
368
before: self.data('before') || NETDATA.chartDefaults.before,
369
370
// the pixels per point requested by the user
359
- pixels_per_point: 1,
371
+ pixels_per_point: self.data('pixels-per-point') || 1,
372
points: self.data('points') || null,
373
374
// the dimensions requested by the user
@@ -366,7 +378,11 @@
378
library_name: self.data('chart-library') || NETDATA.chartDefaults.library,
379
library: null, // object - the chart library used
380
369
- element: element, // the element this chart appears in
381
+ element: element, // the element already created by the user
382
+ element_chart: null, // the element with the chart
383
+ element_chart_id: null,
384
+ element_legend: null, // the element with the legend of the chart (if created by us)
385
+ element_legend_id: null,
386
387
chart_url: null, // string - the url to download chart info
388
chart: null, // object - the chart as downloaded from the server
@@ -378,12 +394,16 @@
394
paused: false, // boolean - is the chart paused for any reason?
395
selected: false, // boolean - is the chart shown a selection?
396
debug: false, // boolena - console.log() debug info about this chart
397
+
398
updates_counter: 0, // numeric - the number of refreshes made so far
399
+ updates_since_last_creation: 0,
400
401
follows_global: 0, // the sequence number of the global synchronization
402
// between chart.
403
// Used with NETDATA.globalPanAndZoom.seq
404
405
+ last_resized: 0, // the last time the chart was resized
406
+
407
mode: null, // auto, pan, zoom
408
// this is a pointer to one of the sub-classes below
409
@@ -477,8 +497,9 @@
497
return this.selected;
498
},
499
500
+ // find if a timestamp (ms) is shown in the current chart
501
timeIsVisible: function(t) {
481
- if(t >= this.mode.after_ms && t <= this.mode.before_ms)
502
+ if(t >= this.current.after_ms && t <= this.current.before_ms)
503
return true;
504
return false;
505
},
@@ -486,8 +507,8 @@
507
calculateRowForTime: function(t) {
508
if(!this.timeIsVisible(t)) return -1;
509
489
- var r = Math.floor((t - this.mode.after_ms) / this.mode.view_update_every);
490
- // console.log(this.mode.data);
510
+ var r = Math.floor((t - this.current.after_ms) / this.current.view_update_every);
511
+ // console.log(this.current.data);
512
513
return r;
514
},
@@ -510,12 +531,12 @@
531
if(NETDATA.globalPanAndZoom.isMaster(this))
532
NETDATA.globalPanAndZoom.clearMaster();
533
513
- if(state.mode.name != 'auto')
534
+ if(state.current.name != 'auto')
535
this.setMode('auto');
536
516
- this.mode.force_before_ms = null;
517
- this.mode.force_after_ms = null;
518
- this.mode.last_updated_ms = 0;
537
+ this.current.force_before_ms = null;
538
+ this.current.force_after_ms = null;
539
+ this.current.last_updated_ms = 0;
540
this.follows_global = 0;
541
this.paused = false;
542
this.selected = false;
@@ -526,44 +547,45 @@
547
// or the chart will flip-flop when it is the master
548
// of a selection sync and another chart becomes
549
// the new master
529
- // state.updateChart();
550
+ if(!NETDATA.options.current.sync_pan_and_zoom)
551
+ state.updateChart();
552
},
553
554
setMode: function(m) {
533
- if(this.mode) {
534
- if(this.mode.name == m) return;
535
-
536
- this[m].url = this.mode.url;
537
- this[m].last_updated_ms = this.mode.last_updated_ms;
538
- this[m].view_update_every = this.mode.view_update_every;
539
- this[m].after_ms = this.mode.after_ms;
540
- this[m].before_ms = this.mode.before_ms;
541
- this[m].points = this.mode.points;
542
- this[m].data = this.mode.data;
543
- this[m].requested_before_ms = this.mode.requested_before_ms;
544
- this[m].requested_after_ms = this.mode.requested_after_ms;
545
- this[m].first_entry_ms = this.mode.first_entry_ms;
546
- this[m].last_entry_ms = this.mode.last_entry_ms;
555
+ if(this.current) {
556
+ if(this.current.name == m) return;
557
+
558
+ this[m].url = this.current.url;
559
+ this[m].last_updated_ms = this.current.last_updated_ms;
560
+ this[m].view_update_every = this.current.view_update_every;
561
+ this[m].after_ms = this.current.after_ms;
562
+ this[m].before_ms = this.current.before_ms;
563
+ this[m].points = this.current.points;
564
+ this[m].data = this.current.data;
565
+ this[m].requested_before_ms = this.current.requested_before_ms;
566
+ this[m].requested_after_ms = this.current.requested_after_ms;
567
+ this[m].first_entry_ms = this.current.first_entry_ms;
568
+ this[m].last_entry_ms = this.current.last_entry_ms;
569
}
570
571
if(m == 'auto')
550
- this.mode = this.auto;
572
+ this.current = this.auto;
573
else if(m == 'pan')
552
- this.mode = this.pan;
574
+ this.current = this.pan;
575
else if(m == 'zoom')
554
- this.mode = this.zoom;
576
+ this.current = this.zoom;
577
else
556
- this.mode = this.auto;
578
+ this.current = this.auto;
579
558
- this.mode.force_before_ms = null;
559
- this.mode.force_after_ms = null;
580
+ this.current.force_before_ms = null;
581
+ this.current.force_after_ms = null;
582
561
- if(this.debug) this.log('mode set to ' + this.mode.name);
583
+ if(this.debug) this.log('mode set to ' + this.current.name);
584
},
585
586
_minPanOrZoomStep: function() {
565
- return (((this.mode.before_ms - this.mode.after_ms) / this.mode.points) * ((this.mode.points * 5 / 100) + 1) );
566
- // return this.mode.view_update_every * 10;
587
+ return (((this.current.before_ms - this.current.after_ms) / this.current.points) * ((this.current.points * 5 / 100) + 1) );
588
+ // return this.current.view_update_every * 10;
589
},
590
591
_shouldBeMoved: function(old_after, old_before, new_after, new_before) {
@@ -576,8 +598,8 @@
598
var step = Math.max(dt_after, dt_before, dt);
599
600
var min_step = this._minPanOrZoomStep();
579
- if(new_range < old_range && new_range / this.calculated_width < 100) {
580
- 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');
601
+ if(new_range < old_range && new_range / this.chartWidth() < 100) {
602
+ 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.chartWidth() / 1000).toString() + ': TOO SMALL RANGE');
603
return false;
604
}
605
@@ -594,21 +616,21 @@
616
updateChartPanOrZoom: function(after, before, callback) {
617
var move = false;
618
597
- if(this.mode.name == 'auto') {
619
+ if(this.current.name == 'auto') {
620
if(this.debug) this.log('updateChartPanOrZoom(): caller did not set proper mode');
621
this.setMode('pan');
622
}
623
602
- if(!this.mode.force_after_ms || !this.mode.force_before_ms) {
624
+ if(!this.current.force_after_ms || !this.current.force_before_ms) {
625
if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): INIT');
626
move = true;
627
}
606
- 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)) {
607
- 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());
628
+ else if(this._shouldBeMoved(this.current.force_after_ms, this.current.force_before_ms, after, before) && this._shouldBeMoved(this.current.after_ms, this.current.before_ms, after, before)) {
629
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): FORCE CHANGE from ' + (this.current.force_after_ms / 1000).toString() + ' - ' + (this.current.force_before_ms / 1000).toString());
630
move = true;
631
}
610
- 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)) {
611
- 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());
632
+ else if(this._shouldBeMoved(this.current.requested_after_ms, this.current.requested_before_ms, after, before) && this._shouldBeMoved(this.current.after_ms, this.current.before_ms, after, before)) {
633
+ if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): REQUESTED CHANGE from ' + (this.current.requested_after_ms / 1000).toString() + ' - ' + (this.current.requested_before_ms / 1000).toString());
634
move = true;
635
}
636
@@ -617,8 +639,8 @@
639
NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.global_pan_sync_time;
640
NETDATA.globalPanAndZoom.setMaster(this, after, before);
641
620
- this.mode.force_after_ms = after;
621
- this.mode.force_before_ms = before;
642
+ this.current.force_after_ms = after;
643
+ this.current.force_before_ms = before;
644
this.updateChart(callback);
645
return true;
646
}
@@ -628,6 +650,216 @@
650
return false;
651
},
652
653
+ createChartDOM: function() {
654
+ this.element_chart_id = this.library_name + '-' + this.uuid + '-chart';
655
+ var html = '<div class="netdata-chart netdata-'
656
+ + this.library_name + '-chart" id="'
657
+ + this.element_chart_id
658
+ + '"style="width: 100%; height: 100%;"></div>';
659
+// + '"style="width: ' + this.chartWidth().toString() + 'px; height: ' + this.chartHeight().toString() + 'px;"></div>';
660
+
661
+ if(this.hasLegend()) {
662
+ this.element_legend_id = this.library_name + '-' + this.uuid + '-legend';
663
+ html += '<div class="netdata-chart-legend netdata-'
664
+ + this.library_name + '-legend" id="'
665
+ + this.element_legend_id
666
+ + '" style="width: ' + this.legendWidth().toString() + 'px; height: ' + this.legendHeight() + 'px;"></div>';
667
+ }
668
+
669
+ element.innerHTML = html;
670
+ this.element_chart = document.getElementById(this.element_chart_id);
671
+ $(this.element_chart).data('netdata-state-object', this);
672
+
673
+ if(this.hasLegend()) {
674
+ this.element_legend = document.getElementById(this.element_legend_id);
675
+ $(this.element_legend).data('netdata-state-object', this);
676
+ }
677
+ },
678
+
679
+ hasLegend: function() {
680
+ // return (this.library && this.library.legend == 'right-side');
681
+ return false;
682
+ },
683
+
684
+ legendWidth: function() {
685
+ return (this.hasLegend())?55:0;
686
+ },
687
+
688
+ legendHeight: function() {
689
+ return $(this.element).height();
690
+ },
691
+
692
+ chartWidth: function() {
693
+ return $(this.element).width() - this.legendWidth();
694
+ },
695
+
696
+ chartHeight: function() {
697
+ return $(this.element).height();
698
+ },
699
+
700
+ chartPixelsPerPoint: function() {
701
+ // force an options provided detail
702
+ var px = this.pixels_per_point;
703
+
704
+ if(this.library && px < this.library.pixels_per_point)
705
+ px = this.library.pixels_per_point;
706
+
707
+ if(px < NETDATA.options.current.pixels_per_point)
708
+ px = NETDATA.options.current.pixels_per_point;
709
+
710
+ return px;
711
+ },
712
+
713
+ needsResize: function() {
714
+ return (this.last_resized < NETDATA.options.last_resized);
715
+ },
716
+
717
+ resizeChart: function() {
718
+ if(this.needsResize()) {
719
+ if(this.library && !this.library.autoresize) {
720
+ if(this.debug) this.log('forcing re-generation due to window resize.');
721
+ this.created_ms = 0;
722
+ this.last_resized = new Date().getTime();
723
+ }
724
+ }
725
+ },
726
+
727
+ chartURL: function() {
728
+ var before;
729
+ var after;
730
+ if(NETDATA.globalPanAndZoom.isActive()) {
731
+ after = Math.round(NETDATA.globalPanAndZoom.force_after_ms / 1000);
732
+ before = Math.round(NETDATA.globalPanAndZoom.force_before_ms / 1000);
733
+ this.follows_global = NETDATA.globalPanAndZoom.seq;
734
+ }
735
+ else {
736
+ before = this.current.force_before_ms != null ? Math.round(this.current.force_before_ms / 1000) : this.before;
737
+ after = this.current.force_after_ms != null ? Math.round(this.current.force_after_ms / 1000) : this.after;
738
+ this.follows_global = 0;
739
+ }
740
+
741
+ this.current.requested_after_ms = after * 1000;
742
+ this.current.requested_before_ms = before * 1000;
743
+
744
+ this.current.points = this.points || Math.round(this.chartWidth() / this.chartPixelsPerPoint());
745
+
746
+ // build the data URL
747
+ this.current.url = this.chart.data_url;
748
+ this.current.url += "&format=" + this.library.format;
749
+ this.current.url += "&points=" + this.current.points.toString();
750
+ this.current.url += "&group=" + this.method;
751
+ this.current.url += "&options=" + this.library.options;
752
+ if(this.library.jsonWrapper) this.current.url += '|jsonwrap';
753
+
754
+ if(after)
755
+ this.current.url += "&after=" + after.toString();
756
+
757
+ if(before)
758
+ this.current.url += "&before=" + before.toString();
759
+
760
+ if(this.dimensions)
761
+ this.current.url += "&dimensions=" + this.dimensions;
762
+
763
+ if(NETDATA.options.debug.chart_data_url || this.debug) this.log('chartURL(): ' + this.current.url + ' WxH:' + this.chartWidth() + 'x' + this.chartHeight() + ' points: ' + this.current.points + ' library: ' + this.library_name);
764
+ },
765
+
766
+ updateChartWithData: function(data) {
767
+ if(this.debug) this.log('got data from netdata server');
768
+ this.current.data = data;
769
+
770
+ var started = new Date().getTime();
771
+
772
+ // if the result is JSON, find the latest update-every
773
+ if(typeof data == 'object' && this.library.jsonWrapper) {
774
+ if(!this.follows_global && typeof data.view_update_every != 'undefined')
775
+ this.current.view_update_every = data.view_update_every * 1000;
776
+
777
+ if(typeof data.after != 'undefined')
778
+ this.current.after_ms = data.after * 1000;
779
+
780
+ if(typeof data.before != 'undefined')
781
+ this.current.before_ms = data.before * 1000;
782
+
783
+ if(typeof data.first_entry_t != 'undefined')
784
+ this.current.first_entry_ms = data.first_entry_t * 1000;
785
+
786
+ if(typeof data.last_entry_t != 'undefined')
787
+ this.current.last_entry_ms = data.last_entry_t * 1000;
788
+
789
+ if(typeof data.points != 'undefined')
790
+ this.current.points = data.points;
791
+
792
+ data.state = this;
793
+ }
794
+
795
+ this.updates_counter++;
796
+
797
+ if(this.debug) {
798
+ this.log('UPDATE No ' + this.updates_counter + ' COMPLETED');
799
+
800
+ if(this.current.force_after_ms)
801
+ this.log('STATUS: forced : ' + (this.current.force_after_ms / 1000).toString() + ' - ' + (this.current.force_before_ms / 1000).toString());
802
+ else
803
+ this.log('STATUS: forced: unset');
804
+
805
+ this.log('STATUS: requested: ' + (this.current.requested_after_ms / 1000).toString() + ' - ' + (this.current.requested_before_ms / 1000).toString());
806
+ this.log('STATUS: rendered : ' + (this.current.after_ms / 1000).toString() + ' - ' + (this.current.before_ms / 1000).toString());
807
+ this.log('STATUS: points : ' + (this.current.points).toString() + ', min step: ' + (this._minPanOrZoomStep() / 1000).toString());
808
+ }
809
+
810
+ // this may force the chart to be re-created
811
+ this.resizeChart();
812
+ if(this.updates_since_last_creation >= this.library.max_updates_to_recreate) {
813
+ if(this.debug) this.log('max updates of ' + this.updates_since_last_creation.toString() + ' reached. Forcing re-generation.');
814
+ this.created_ms = 0;
815
+ }
816
+
817
+ if(this.created_ms && typeof this.library.update == 'function') {
818
+ if(this.debug) this.log('updating chart...');
819
+
820
+ this.updates_since_last_creation++;
821
+ if(NETDATA.options.debug.chart_errors) {
822
+ this.library.update(this, data);
823
+ }
824
+ else {
825
+ try {
826
+ this.library.update(this, data);
827
+ }
828
+ catch(err) {
829
+ this.error('chart "' + this.id + '" failed to be updated as ' + this.library_name);
830
+ }
831
+ }
832
+ }
833
+ else {
834
+ if(this.debug) this.log('creating chart...');
835
+
836
+ this.createChartDOM();
837
+ this.updates_since_last_creation = 0;
838
+
839
+ if(NETDATA.options.debug.chart_errors) {
840
+ this.library.create(this, data);
841
+ this.created_ms = new Date().getTime();
842
+ }
843
+ else {
844
+ try {
845
+ this.library.create(this, data);
846
+ this.created_ms = new Date().getTime();
847
+ }
848
+ catch(err) {
849
+ this.error('chart "' + this.id + '" failed to be created as ' + this.library_name);
850
+ }
851
+ }
852
+ }
853
+
854
+ // update the performance counters
855
+ this.current.last_updated_ms = new Date().getTime();
856
+ this.refresh_dt_ms = this.current.last_updated_ms - started;
857
+ NETDATA.options.auto_refresher_fast_weight += this.refresh_dt_ms;
858
+
859
+ if(this.refresh_dt_element)
860
+ this.refresh_dt_element.innerHTML = this.refresh_dt_ms.toString();
861
+ },
862
+
863
updateChart: function(callback) {
864
if(!this.library || !this.library.enabled) {
865
this.error('charting library "' + this.library_name + '" is not available');
@@ -641,7 +873,7 @@
873
return;
874
}
875
644
- if(!self.visible(true)) {
876
+ if(!this.isVisible()) {
877
if(NETDATA.options.debug.visibility || this.debug) this.log('is not visible');
878
if(typeof callback != 'undefined') callback();
879
return;
@@ -660,159 +892,33 @@
892
893
this.clearSelection();
894
this.chartURL();
663
- if(this.debug) this.log('updating from ' + this.mode.url);
895
+ if(this.debug) this.log('updating from ' + this.current.url);
896
897
var this_state_object = this;
898
$.ajax( {
667
- url: this_state_object.mode.url,
899
+ url: this.current.url,
900
crossDomain: true
901
})
902
.then(function(data) {
671
- if(this_state_object.debug) this_state_object.log('got data from netdata server');
672
- this_state_object.mode.data = data;
673
-
674
- var started = new Date().getTime();
675
-
676
- // if the result is JSON, find the latest update-every
677
- if(typeof data == 'object' && this_state_object.library.jsonWrapper) {
678
- if(!this_state_object.follows_global && typeof data.view_update_every != 'undefined')
679
- this_state_object.mode.view_update_every = data.view_update_every * 1000;
680
-
681
- if(typeof data.after != 'undefined')
682
- this_state_object.mode.after_ms = data.after * 1000;
683
-
684
- if(typeof data.before != 'undefined')
685
- this_state_object.mode.before_ms = data.before * 1000;
686
-
687
- if(typeof data.first_entry_t != 'undefined')
688
- this_state_object.mode.first_entry_ms = data.first_entry_t * 1000;
689
-
690
- if(typeof data.last_entry_t != 'undefined')
691
- this_state_object.mode.last_entry_ms = data.last_entry_t * 1000;
692
-
693
- if(typeof data.points != 'undefined')
694
- this_state_object.mode.points = data.points;
695
-
696
- data.state = this_state_object;
697
- }
698
-
699
- this_state_object.updates_counter++;
700
-
701
- if(this_state_object.debug) {
702
- this_state_object.log('UPDATE No ' + this_state_object.updates_counter + ' COMPLETED');
703
-
704
- if(this_state_object.mode.force_after_ms)
705
- this_state_object.log('STATUS: forced : ' + (this_state_object.mode.force_after_ms / 1000).toString() + ' - ' + (this_state_object.mode.force_before_ms / 1000).toString());
706
- else
707
- this_state_object.log('STATUS: forced: unset');
708
-
709
- this_state_object.log('STATUS: requested: ' + (this_state_object.mode.requested_after_ms / 1000).toString() + ' - ' + (this_state_object.mode.requested_before_ms / 1000).toString());
710
- this_state_object.log('STATUS: rendered : ' + (this_state_object.mode.after_ms / 1000).toString() + ' - ' + (this_state_object.mode.before_ms / 1000).toString());
711
- this_state_object.log('STATUS: points : ' + (this_state_object.mode.points).toString() + ', min step: ' + (this_state_object._minPanOrZoomStep() / 1000).toString());
712
- }
713
-
714
- if(this_state_object.created_ms) {
715
- if(this_state_object.debug) this_state_object.log('updating chart...');
716
-
717
- if(NETDATA.options.debug.chart_errors) {
718
- this_state_object.library.update(this_state_object.element, data);
719
- }
720
- else {
721
- try {
722
- this_state_object.library.update(this_state_object.element, data);
723
- }
724
- catch(err) {
725
- this_state_object.error('chart "' + state.id + '" failed to be updated as ' + state.library_name);
726
- }
727
- }
728
- }
729
- else {
730
- if(this_state_object.debug) this_state_object.log('creating chart...');
731
-
732
- if(NETDATA.options.debug.chart_errors) {
733
- this_state_object.library.create(this_state_object.element, data);
734
- this_state_object.created_ms = new Date().getTime();
735
- }
736
- else {
737
- try {
738
- this_state_object.library.create(this_state_object.element, data);
739
- this_state_object.created_ms = new Date().getTime();
740
- }
741
- catch(err) {
742
- this_state_object.error('chart "' + state.id + '" failed to be created as ' + state.library_name);
743
- }
744
- }
745
- }
746
-
747
- // update the performance counters
748
- this_state_object.mode.last_updated_ms = new Date().getTime();
749
- this_state_object.refresh_dt_ms = this_state_object.mode.last_updated_ms - started;
750
- NETDATA.options.auto_refresher_fast_weight += this_state_object.refresh_dt_ms;
751
-
752
- if(this_state_object.refresh_dt_element)
753
- this_state_object.refresh_dt_element.innerHTML = this_state_object.refresh_dt_ms.toString();
903
+ this_state_object.updateChartWithData(data);
904
})
905
.fail(function() {
756
- this_state_object.error('cannot download chart from ' + this_state_object.mode.url);
906
+ this_state_object.error('cannot download chart from ' + this_state_object.current.url);
907
})
908
.always(function() {
909
if(typeof callback == 'function') callback();
910
});
911
},
912
763
- chartURL: function() {
764
- this.calculated_width = self.width();
765
- this.calculated_height = self.height();
766
-
767
- var before;
768
- var after;
769
- if(NETDATA.globalPanAndZoom.isActive()) {
770
- after = Math.round(NETDATA.globalPanAndZoom.force_after_ms / 1000);
771
- before = Math.round(NETDATA.globalPanAndZoom.force_before_ms / 1000);
772
- this.follows_global = NETDATA.globalPanAndZoom.seq;
773
- }
774
- else {
775
- before = this.mode.force_before_ms != null ? Math.round(this.mode.force_before_ms / 1000) : this.before;
776
- after = this.mode.force_after_ms != null ? Math.round(this.mode.force_after_ms / 1000) : this.after;
777
- this.follows_global = 0;
778
- }
779
-
780
- this.mode.requested_after_ms = after * 1000;
781
- this.mode.requested_before_ms = before * 1000;
782
-
783
- // force an options provided detail
784
- var pixels_per_point = this.pixels_per_point;
785
- if(pixels_per_point < NETDATA.options.current.pixels_per_point)
786
- pixels_per_point = NETDATA.options.current.pixels_per_point
787
-
788
- this.mode.points = this.points || Math.round(this.calculated_width / pixels_per_point);
789
-
790
- // build the data URL
791
- this.mode.url = this.chart.data_url;
792
- this.mode.url += "&format=" + this.library.format;
793
- this.mode.url += "&points=" + this.mode.points.toString();
794
- this.mode.url += "&group=" + this.method;
795
- this.mode.url += "&options=" + this.library.options;
796
- if(this.library.jsonWrapper) this.mode.url += '|jsonwrap';
797
-
798
- if(after)
799
- this.mode.url += "&after=" + after.toString();
800
-
801
- if(before)
802
- this.mode.url += "&before=" + before.toString();
803
-
804
- if(this.dimensions)
805
- this.mode.url += "&dimensions=" + this.dimensions;
806
-
807
- 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);
808
- },
809
-
913
isVisible: function() {
811
- return self.visible(true);
914
+ if(NETDATA.options.current.update_only_visible)
915
+ return $(this.element).visible(true);
916
+ else
917
+ return true;
918
},
919
920
isAutoRefreshed: function() {
815
- return this.mode.autorefresh;
921
+ return this.current.autorefresh;
922
},
923
924
canBeAutoRefreshed: function() {
@@ -852,7 +958,7 @@
958
return false;
959
}
960
855
- if(now - this.mode.last_updated_ms > this.mode.view_update_every) {
961
+ if(now - this.current.last_updated_ms > this.current.view_update_every) {
962
if(this.debug) this.log('canBeAutoRefreshed(): It is time to update me.');
963
return true;
964
}
@@ -863,34 +969,42 @@
969
},
970
971
autoRefresh: function(callback) {
866
- if(this.canBeAutoRefreshed())
972
+ if(this.canBeAutoRefreshed()) {
973
this.updateChart(callback);
868
- else if(typeof callback != 'undefined')
869
- callback();
974
+ }
975
+ else {
976
+ if(typeof callback != 'undefined')
977
+ callback();
978
+ }
979
+ },
980
+
981
+ _defaultsFromDownloadedChart: function(chart) {
982
+ this.chart = chart;
983
+ this.chart_url = chart.url;
984
+ this.current.view_update_every = chart.update_every * 1000;
985
+ this.current.points = Math.round(this.chartWidth() / this.chartPixelsPerPoint());
986
},
987
988
// fetch the chart description from the netdata server
989
getChart: function(callback) {
990
this.chart = NETDATA.chartRegistry.get(this.host, this.id);
991
if(this.chart) {
992
+ this._defaultsFromDownloadedChart(this.chart);
993
if(typeof callback == 'function') callback();
994
}
995
else {
996
this.chart_url = this.host + "/api/v1/chart?chart=" + this.id;
997
if(this.debug) this.log('downloading ' + this.chart_url);
881
- this_state_object = this;
998
+ var this_state_object = this;
999
1000
$.ajax( {
1001
url: this.chart_url,
1002
crossDomain: true
1003
})
1004
.done(function(chart) {
888
- chart.data_url = (this_state_object.host + chart.data_url);
889
- this_state_object.chart = chart;
890
- this_state_object.mode.view_update_every = chart.update_every * 1000;
891
- this_state_object.mode.points = Math.round(self.width() / (chart.update_every / 1000));
892
-
1005
chart.url = this_state_object.chart_url;
1006
+ chart.data_url = (this_state_object.host + chart.data_url);
1007
+ this_state_object._defaultsFromDownloadedChart(chart);
1008
NETDATA.chartRegistry.add(this_state_object.host, this_state_object.id, chart);
1009
})
1010
.fail(function() {
@@ -911,17 +1025,17 @@
1025
if(this.debug) this.log('sizing element');
1026
1027
if(this.width)
914
- self.css('width', this.width);
1028
+ $(this.element).css('width', this.width);
1029
1030
if(this.height)
917
- self.css('height', this.height);
1031
+ $(this.element).css('height', this.height);
1032
1033
// these should be left to css
920
- //self.css('display', 'inline-block')
921
- //self.css('overflow', 'hidden');
1034
+ //$(this.element).css('display', 'inline-block')
1035
+ //$(this.element).css('overflow', 'hidden');
1036
1037
if(NETDATA.chartDefaults.min_width)
924
- self.css('min-width', NETDATA.chartDefaults.min_width);
1038
+ $(this.element).css('min-width', NETDATA.chartDefaults.min_width);
1039
},
1040
1041
// show a message in the chart
@@ -968,10 +1082,8 @@
1082
NETDATA.error(403, this.library_name);
1083
this.error('chart library "' + this.library_name + '" is not enabled');
1084
}
971
- else {
1085
+ else
1086
this.library = NETDATA.chartLibraries[this.library_name];
973
- this.pixels_per_point = self.data('pixels-per-point') || this.library.pixels_per_point;
974
- }
1087
1088
// if we need to report the rendering speed
1089
// find the element that needs to be updated
@@ -989,11 +1101,10 @@
1101
1102
// get or create a chart state, given a DOM element
1103
NETDATA.chartState = function(element) {
992
- self = $(element);
993
- var state = self.data('state') || null;
1104
+ var state = $(element).data('netdata-state-object') || null;
1105
if(!state) {
1106
state = NETDATA.chartInitialState(element);
996
- self.data('state', state);
1107
+ $(element).data('netdata-state-object', state);
1108
}
1109
return state;
1110
}
@@ -1081,7 +1192,6 @@
1192
1193
return;
1194
}
1084
-
1195
var target = NETDATA.options.targets.get(index);
1196
if(target == null) {
1197
if(NETDATA.options.debug.main_loop) console.log('waiting to restart main loop...');
@@ -1183,21 +1293,17 @@
1293
}
1294
};
1295
1186
- NETDATA.peityChartUpdate = function(element, data) {
1187
- var peity = $(data.state.peity_element);
1188
- peity.html(data.result);
1189
- // peity.change() does not accept options
1296
+ NETDATA.peityChartUpdate = function(state, data) {
1297
+ $(state.element_chart).html(data.result);
1298
+ // $(state.element_chart).change() does not accept options
1299
// to pass width and height
1191
- //peity.change();
1192
- peity.peity('line', { width: data.state.calculated_width, height: data.state.calculated_height });
1300
+ //$(state.element_chart).change();
1301
+ $(state.element_chart).peity('line', { width: state.chartWidth(), height: state.chartHeight() });
1302
}
1303
1195
- NETDATA.peityChartCreate = function(element, data) {
1196
- element.innerHTML = '<div class="netdata-chart-container netdata-peity-container" id="peity-' + data.state.uuid + '">' + data.result + '</div>';
1197
- data.state.peity_element = document.getElementById('peity-' + data.state.uuid);
1198
- var peity = $(data.state.peity_element);
1199
-
1200
- peity.peity('line', { width: data.state.calculated_width, height: data.state.calculated_height });
1304
+ NETDATA.peityChartCreate = function(state, data) {
1305
+ $(state.element_chart).html(data.result);
1306
+ $(state.element_chart).peity('line', { width: state.chartWidth(), height: state.chartHeight() });
1307
}
1308
1309
// ----------------------------------------------------------------------------------------------------------------
@@ -1224,19 +1330,18 @@
1330
}
1331
};
1332
1227
- NETDATA.sparklineChartUpdate = function(element, data) {
1228
- data.state.sparkline_options.width = data.state.calculated_width;
1229
- data.state.sparkline_options.height = data.state.calculated_height;
1333
+ NETDATA.sparklineChartUpdate = function(state, data) {
1334
+ state.sparkline_options.width = state.chartWidth();
1335
+ state.sparkline_options.height = state.chartHeight();
1336
1231
- spark = $(data.state.sparkline_element);
1232
- spark.sparkline(data.result, data.state.sparkline_options);
1337
+ $(state.element_chart).sparkline(data.result, state.sparkline_options);
1338
}
1339
1235
- NETDATA.sparklineChartCreate = function(element, data) {
1236
- var self = $(element);
1340
+ NETDATA.sparklineChartCreate = function(state, data) {
1341
+ var self = $(state.element);
1342
var type = self.data('sparkline-type') || 'line';
1343
var lineColor = self.data('sparkline-linecolor') || NETDATA.colors[0];
1239
- var fillColor = self.data('sparkline-fillcolor') || (data.state.chart.chart_type == 'line')?'#FFF':NETDATA.ColorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1344
+ var fillColor = self.data('sparkline-fillcolor') || (state.chart.chart_type == 'line')?'#FFF':NETDATA.ColorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1345
var chartRangeMin = self.data('sparkline-chartrangemin') || undefined;
1346
var chartRangeMax = self.data('sparkline-chartrangemax') || undefined;
1347
var composite = self.data('sparkline-composite') || undefined;
@@ -1270,7 +1375,7 @@
1375
var tooltipClassname = self.data('sparkline-tooltipclassname') || undefined;
1376
var tooltipFormat = self.data('sparkline-tooltipformat') || undefined;
1377
var tooltipPrefix = self.data('sparkline-tooltipprefix') || undefined;
1273
- var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + data.state.chart.units;
1378
+ var tooltipSuffix = self.data('sparkline-tooltipsuffix') || ' ' + state.chart.units;
1379
var tooltipSkipNull = self.data('sparkline-tooltipskipnull') || true;
1380
var tooltipValueLookups = self.data('sparkline-tooltipvaluelookups') || undefined;
1381
var tooltipFormatFieldlist = self.data('sparkline-tooltipformatfieldlist') || undefined;
@@ -1281,7 +1386,7 @@
1386
var numberDigitGroupCount = self.data('sparkline-numberdigitgroupcount') || undefined;
1387
var animatedZooms = self.data('sparkline-animatedzooms') || false;
1388
1284
- data.state.sparkline_options = {
1389
+ state.sparkline_options = {
1390
type: type,
1391
lineColor: lineColor,
1392
fillColor: fillColor,
@@ -1315,7 +1420,7 @@
1420
highlightColor: highlightColor,
1421
tooltipContainer: tooltipContainer,
1422
tooltipClassname: tooltipClassname,
1318
- tooltipChartTitle: data.state.chart.title,
1423
+ tooltipChartTitle: state.chart.title,
1424
tooltipFormat: tooltipFormat,
1425
tooltipPrefix: tooltipPrefix,
1426
tooltipSuffix: tooltipSuffix,
@@ -1328,15 +1433,11 @@
1433
numberDecimalMark: numberDecimalMark,
1434
numberDigitGroupCount: numberDigitGroupCount,
1435
animatedZooms: animatedZooms,
1331
- width: data.state.calculated_width,
1332
- height: data.state.calculated_height
1436
+ width: state.chartWidth(),
1437
+ height: state.chartHeight()
1438
};
1439
1335
- element.innerHTML = '<div class="netdata-chart-container netdata-sparkline-container" id="sparkline-' + data.state.uuid + '" style="display: inline-block; position: relative;"></div>';
1336
- data.state.sparkline_element = document.getElementById('sparkline-' + data.state.uuid);
1337
-
1338
- spark = $(data.state.sparkline_element);
1339
- spark.sparkline(data.result, data.state.sparkline_options);
1440
+ $(state.element_chart).sparkline(data.result, state.sparkline_options);
1441
};
1442
1443
// ----------------------------------------------------------------------------------------------------------------
@@ -1350,6 +1451,7 @@
1451
};
1452
1453
NETDATA.dygraph.syncStart = function(state, event, x, points, row, seriesName) {
1454
+ if(!NETDATA.options.current.sync_selection) return;
1455
if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraph.syncStart()');
1456
1457
//if(NETDATA.dygraph.state && NETDATA.dygraph.state != state) {
@@ -1358,12 +1460,12 @@
1460
//}
1461
// state.debug = true;
1462
1361
- var t = state.mode.after_ms + row * state.mode.view_update_every;
1463
+ var t = state.current.after_ms + row * state.current.view_update_every;
1464
// console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t == x)?'SAME':'DIFFERENT'));
1465
1466
now = new Date().getTime();
1467
if(now < NETDATA.dygraph.dont_sync_before) {
1366
- if(state.debug) st.log('sync: cannot sync yet.');
1468
+ if(state.debug) state.log('sync: cannot sync yet.');
1469
return;
1470
}
1471
@@ -1374,7 +1476,7 @@
1476
var dygraph = state.dygraph_instance;
1477
1478
if(!NETDATA.dygraph.sync) {
1377
- if(state.debug) st.log('sync: setting up...');
1479
+ if(state.debug) state.log('sync: setting up...');
1480
$.each(NETDATA.options.targets, function(i, target) {
1481
var st = NETDATA.chartState(target);
1482
if(st == state) {
@@ -1402,6 +1504,8 @@
1504
}
1505
1506
NETDATA.dygraph.syncStop = function(state) {
1507
+ if(!NETDATA.options.current.sync_selection) return;
1508
+
1509
if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraph.syncStop()');
1510
1511
//if(NETDATA.dygraph.state && NETDATA.dygraph.state != state) {
@@ -1437,10 +1541,9 @@
1541
if(NETDATA.globalPanAndZoom.clearMaster());
1542
}
1543
1440
- NETDATA.dygraph.zoomOrPan = function(element, dygraph, after, before) {
1441
- if(NETDATA.options.debug.dygraph) console.log('>>>> dygraph.zoomOrPan(element, dygraph, after:' + after + ', before: ' + before + ')');
1544
+ NETDATA.dygraph.chartPanOrZoom = function(state, dygraph, after, before) {
1545
+ if(NETDATA.options.debug.dygraph) console.log('>>>> dygraph.zoomOrPan(state, dygraph, after:' + after + ', before: ' + before + ')');
1546
1443
- state = NETDATA.chartState(element);
1547
state.updateChartPanOrZoom(after, before);
1548
return;
1549
}
@@ -1487,47 +1590,45 @@
1590
}
1591
};
1592
1490
- NETDATA.dygraphChartUpdate = function(element, data) {
1491
- if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate()');
1492
-
1493
- var dygraph = data.state.dygraph_instance;
1593
+ NETDATA.dygraphChartUpdate = function(state, data) {
1594
+ var dygraph = state.dygraph_instance;
1595
1495
- if(data.state.mode.name == 'pan') {
1496
- if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate() loose update');
1596
+ if(state.current.name == 'pan') {
1597
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartUpdate() loose update');
1598
dygraph.updateOptions({
1599
file: data.result.data,
1600
labels: data.result.labels,
1500
- labelsDivWidth: data.state.calculated_width - 70
1601
+ labelsDivWidth: state.chartWidth() - 70
1602
});
1603
}
1604
else {
1504
- if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartUpdate() strict update');
1605
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartUpdate() strict update');
1606
dygraph.updateOptions({
1607
file: data.result.data,
1608
labels: data.result.labels,
1508
- labelsDivWidth: data.state.calculated_width - 70,
1609
+ labelsDivWidth: state.chartWidth() - 70,
1610
dateWindow: null,
1611
valueRange: null
1612
});
1613
}
1614
};
1615
1515
- NETDATA.dygraphChartCreate = function(element, data) {
1516
- if(NETDATA.options.debug.dygraph || data.state.debug) console.log('dygraphChartCreate()');
1616
+ NETDATA.dygraphChartCreate = function(state, data) {
1617
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartCreate()');
1618
1518
- var self = $(element);
1519
- var title = self.data('dygraph-title') || data.state.chart.title;
1619
+ var self = $(state.element);
1620
+ var title = self.data('dygraph-title') || state.chart.title;
1621
var titleHeight = self.data('dygraph-titleheight') || 19;
1622
var labelsDiv = self.data('dygraph-labelsdiv') || undefined;
1623
var connectSeparatedPoints = self.data('dygraph-connectseparatedpoints') || false;
1624
var yLabelWidth = self.data('dygraph-ylabelwidth') || 12;
1524
- var stackedGraph = self.data('dygraph-stackedgraph') || (data.state.chart.chart_type == 'stacked')?true:false;
1625
+ var stackedGraph = self.data('dygraph-stackedgraph') || (state.chart.chart_type == 'stacked')?true:false;
1626
var stackedGraphNaNFill = self.data('dygraph-stackedgraphnanfill') || 'none';
1627
var hideOverlayOnMouseOut = self.data('dygraph-hideoverlayonmouseout') || true;
1527
- var fillGraph = self.data('dygraph-fillgraph') || (data.state.chart.chart_type == 'area')?true:false;
1628
+ var fillGraph = self.data('dygraph-fillgraph') || (state.chart.chart_type == 'area')?true:false;
1629
var drawPoints = self.data('dygraph-drawpoints') || false;
1630
var labelsDivStyles = self.data('dygraph-labelsdivstyles') || { 'fontSize':'10px' };
1530
- var labelsDivWidth = self.data('dygraph-labelsdivwidth') || self.width() - 70;
1631
+ var labelsDivWidth = self.data('dygraph-labelsdivwidth') || state.chartWidth() - 70;
1632
var labelsSeparateLines = self.data('dygraph-labelsseparatelines') || false;
1633
var labelsShowZeroValues = self.data('dygraph-labelsshowzerovalues') || true;
1634
var legend = self.data('dygraph-legend') || 'onmouseover';
@@ -1546,11 +1647,11 @@
1647
var pointSize = self.data('dygraph-pointsize') || 1;
1648
var stepPlot = self.data('dygraph-stepplot') || false;
1649
var strokeBorderColor = self.data('dygraph-strokebordercolor') || 'white';
1549
- var strokeBorderWidth = self.data('dygraph-strokeborderwidth') || (data.state.chart.chart_type == 'stacked')?0.1:0.0;
1650
+ var strokeBorderWidth = self.data('dygraph-strokeborderwidth') || (state.chart.chart_type == 'stacked')?0.1:0.0;
1651
var strokePattern = self.data('dygraph-strokepattern') || undefined;
1652
var highlightCircleSize = self.data('dygraph-highlightcirclesize') || 3;
1653
var highlightSeriesOpts = self.data('dygraph-highlightseriesopts') || null; // TOO SLOW: { strokeWidth: 1.5 };
1553
- var highlightSeriesBackgroundAlpha = self.data('dygraph-highlightseriesbackgroundalpha') || null; // TOO SLOW: (data.state.chart.chart_type == 'stacked')?0.7:0.5;
1654
+ var highlightSeriesBackgroundAlpha = self.data('dygraph-highlightseriesbackgroundalpha') || null; // TOO SLOW: (state.chart.chart_type == 'stacked')?0.7:0.5;
1655
var pointClickCallback = self.data('dygraph-pointclickcallback') || undefined;
1656
var showRangeSelector = self.data('dygraph-showrangeselector') || false;
1657
var showRoller = self.data('dygraph-showroller') || false;
@@ -1562,10 +1663,10 @@
1663
var gridLinePattern = self.data('dygraph-gridlinepattern') || null;
1664
var gridLineWidth = self.data('dygraph-gridlinewidth') || 0.3;
1665
1565
- data.state.dygraph_options = {
1666
+ state.dygraph_options = {
1667
title: title,
1668
titleHeight: titleHeight,
1568
- ylabel: data.state.chart.units,
1669
+ ylabel: state.chart.units,
1670
yLabelWidth: yLabelWidth,
1671
connectSeparatedPoints: connectSeparatedPoints,
1672
drawPoints: drawPoints,
@@ -1629,38 +1730,38 @@
1730
}
1731
},
1732
drawCallback: function(dygraph, is_initial) {
1632
- if(data.state.mode.name != 'auto') {
1633
- if(NETDATA.options.debug.dygraph) data.state.log('dygraphDrawCallback()');
1733
+ if(state.current.name != 'auto') {
1734
+ if(NETDATA.options.debug.dygraph) state.log('dygraphDrawCallback()');
1735
1736
var x_range = dygraph.xAxisRange();
1737
var after = Math.round(x_range[0]);
1738
var before = Math.round(x_range[1]);
1739
1639
- NETDATA.dygraph.zoomOrPan(element, this, after, before);
1740
+ NETDATA.dygraph.chartPanOrZoom(state, this, after, before);
1741
}
1742
},
1743
zoomCallback: function(minDate, maxDate, yRanges) {
1643
- if(NETDATA.options.debug.dygraph) data.state.log('dygraphZoomCallback()');
1644
- NETDATA.dygraph.syncStop(data.state);
1645
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1646
- NETDATA.dygraph.zoomOrPan(element, this, minDate, maxDate);
1744
+ if(NETDATA.options.debug.dygraph) state.log('dygraphZoomCallback()');
1745
+ NETDATA.dygraph.syncStop(state);
1746
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1747
+ NETDATA.dygraph.chartPanOrZoom(state, this, minDate, maxDate);
1748
},
1749
highlightCallback: function(event, x, points, row, seriesName) {
1649
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('dygraphHighlightCallback()');
1650
- data.state.pauseChart();
1651
- NETDATA.dygraph.syncStart(data.state, event, x, points, row, seriesName);
1750
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphHighlightCallback()');
1751
+ state.pauseChart();
1752
+ NETDATA.dygraph.syncStart(state, event, x, points, row, seriesName);
1753
},
1754
unhighlightCallback: function(event) {
1654
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('dygraphUnhighlightCallback()');
1655
- data.state.unpauseChart();
1656
- NETDATA.dygraph.syncStop(data.state);
1755
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphUnhighlightCallback()');
1756
+ state.unpauseChart();
1757
+ NETDATA.dygraph.syncStop(state);
1758
},
1759
interactionModel : {
1760
mousedown: function(event, dygraph, context) {
1660
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.mousedown()');
1661
- NETDATA.dygraph.syncStop(data.state);
1761
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.mousedown()');
1762
+ NETDATA.dygraph.syncStop(state);
1763
1663
- if(NETDATA.options.debug.dygraph) data.state.log('dygraphMouseDown()');
1764
+ if(NETDATA.options.debug.dygraph) state.log('dygraphMouseDown()');
1765
1766
// Right-click should not initiate a zoom.
1767
if(event.button && event.button == 2) return;
@@ -1669,79 +1770,79 @@
1770
1771
if(event.button && event.button == 1) {
1772
if (event.altKey || event.shiftKey) {
1672
- data.state.setMode('pan');
1673
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1773
+ state.setMode('pan');
1774
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1775
Dygraph.startPan(event, dygraph, context);
1776
}
1777
else {
1677
- data.state.setMode('zoom');
1678
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1778
+ state.setMode('zoom');
1779
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1780
Dygraph.startZoom(event, dygraph, context);
1781
}
1782
}
1783
else {
1784
if (event.altKey || event.shiftKey) {
1684
- data.state.setMode('zoom');
1685
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1785
+ state.setMode('zoom');
1786
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1787
Dygraph.startZoom(event, dygraph, context);
1788
}
1789
else {
1689
- data.state.setMode('pan');
1690
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1790
+ state.setMode('pan');
1791
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1792
Dygraph.startPan(event, dygraph, context);
1793
}
1794
}
1795
},
1796
mousemove: function(event, dygraph, context) {
1696
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.mousemove()');
1797
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.mousemove()');
1798
1799
if(context.isPanning) {
1699
- NETDATA.dygraph.syncStop(data.state);
1700
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1701
- data.state.setMode('pan');
1800
+ NETDATA.dygraph.syncStop(state);
1801
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1802
+ state.setMode('pan');
1803
Dygraph.movePan(event, dygraph, context);
1804
}
1805
else if(context.isZooming) {
1705
- NETDATA.dygraph.syncStop(data.state);
1706
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1707
- data.state.setMode('zoom');
1806
+ NETDATA.dygraph.syncStop(state);
1807
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1808
+ state.setMode('zoom');
1809
Dygraph.moveZoom(event, dygraph, context);
1810
}
1811
},
1812
mouseup: function(event, dygraph, context) {
1712
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.mouseup()');
1813
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.mouseup()');
1814
1815
if (context.isPanning) {
1715
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1816
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1817
Dygraph.endPan(event, dygraph, context);
1818
}
1819
else if (context.isZooming) {
1719
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1820
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1821
Dygraph.endZoom(event, dygraph, context);
1822
}
1823
},
1824
click: function(event, dygraph, context) {
1724
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.click()');
1825
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.click()');
1826
Dygraph.cancelEvent(event);
1827
},
1828
dblclick: function(event, dygraph, context) {
1728
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.dblclick()');
1729
- NETDATA.dygraph.syncStop(data.state);
1730
- NETDATA.dygraph.resetChart(data.state, dygraph, context);
1829
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.dblclick()');
1830
+ NETDATA.dygraph.syncStop(state);
1831
+ NETDATA.dygraph.resetChart(state, dygraph, context);
1832
},
1833
mousewheel: function(event, dygraph, context) {
1733
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.mousewheel()');
1834
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.mousewheel()');
1835
1735
- NETDATA.dygraph.syncStop(data.state);
1736
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1836
+ NETDATA.dygraph.syncStop(state);
1837
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1838
1839
if(event.altKey || event.shiftKey) {
1840
// http://dygraphs.com/gallery/interaction-api.js
1841
var normal = (event.detail) ? event.detail * -1 : event.wheelDelta / 40;
1842
var percentage = normal / 25;
1843
1743
- var before_old = data.state.mode.before_ms;
1744
- var after_old = data.state.mode.after_ms;
1844
+ var before_old = state.current.before_ms;
1845
+ var after_old = state.current.after_ms;
1846
var range_old = before_old - after_old;
1847
1848
var range = range_old * ( 1 - percentage );
@@ -1750,37 +1851,35 @@
1851
var before = before_old - dt;
1852
var after = after_old + dt;
1853
1753
- if(NETDATA.options.debug.dygraph) data.state.log('percent: ' + percentage + ' from ' + after_old + ' - ' + before_old + ' to ' + after + ' - ' + before + ', range from ' + (before_old - after_old).toString() + ' to ' + (before - after).toString());
1854
+ if(NETDATA.options.debug.dygraph) state.log('percent: ' + percentage + ' from ' + after_old + ' - ' + before_old + ' to ' + after + ' - ' + before + ', range from ' + (before_old - after_old).toString() + ' to ' + (before - after).toString());
1855
1755
- data.state.setMode('zoom');
1756
- NETDATA.dygraph.zoomOrPan(element, dygraph, after, before);
1856
+ state.setMode('zoom');
1857
+ NETDATA.dygraph.chartPanOrZoom(state, dygraph, after, before);
1858
}
1859
},
1860
touchstart: function(event, dygraph, context) {
1760
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.touchstart()');
1761
- NETDATA.dygraph.syncStop(data.state);
1762
- NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_delay;
1861
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.touchstart()');
1862
+ NETDATA.dygraph.syncStop(state);
1863
+ NETDATA.dygraph.dont_sync_before = new Date().getTime() + NETDATA.options.current.sync_selection_delay;
1864
Dygraph.Interaction.startTouch(event, dygraph, context);
1865
context.touchDirections = { x: true, y: false };
1765
- data.state.setMode('zoom');
1866
+ state.setMode('zoom');
1867
},
1868
touchmove: function(event, dygraph, context) {
1768
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.touchmove()');
1869
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.touchmove()');
1870
//Dygraph.cancelEvent(event);
1770
- NETDATA.dygraph.syncStop(data.state);
1871
+ NETDATA.dygraph.syncStop(state);
1872
Dygraph.Interaction.moveTouch(event, dygraph, context);
1873
},
1874
touchend: function(event, dygraph, context) {
1774
- if(NETDATA.options.debug.dygraph || data.state.debug) data.state.log('interactionModel.touchend()');
1875
+ if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.touchend()');
1876
Dygraph.Interaction.endTouch(event, dygraph, context);
1877
}
1878
}
1879
};
1880
1780
- self.html('<div class="netdata-chart-container netdata-dygraph-container" id="dygraph-' + data.state.uuid + '" style="width: 100%; height: 100%;"></div>');
1781
-
1782
- data.state.dygraph_instance = new Dygraph(document.getElementById('dygraph-' + data.state.uuid),
1783
- data.result.data, data.state.dygraph_options);
1881
+ state.dygraph_instance = new Dygraph(state.element_chart,
1882
+ data.result.data, state.dygraph_options);
1883
};
1884
1885
// ----------------------------------------------------------------------------------------------------------------
@@ -1825,16 +1924,14 @@
1924
}
1925
};
1926
1828
- NETDATA.morrisChartUpdate = function(element, data) {
1829
- data.state.morris_instance.setData(data.result.data);
1927
+ NETDATA.morrisChartUpdate = function(state, data) {
1928
+ state.morris_instance.setData(data.result.data);
1929
};
1930
1832
- NETDATA.morrisChartCreate = function(element, data) {
1931
+ NETDATA.morrisChartCreate = function(state, data) {
1932
1834
- element.innerHTML = '<div class="netdata-chart-container netdata-morris-container" id="morris-' + data.state.uuid + '" style="width: ' + data.state.calculated_width + 'px; height: ' + data.state.calculated_height + 'px;"></div>';
1835
-
1836
- var options = {
1837
- element: 'morris-' + data.state.uuid,
1933
+ state.morris_options = {
1934
+ element: state.element_chart_id,
1935
data: data.result.data,
1936
xkey: 'time',
1937
ykeys: data.dimension_names,
@@ -1848,19 +1945,15 @@
1945
behaveLikeLine: false
1946
};
1947
1851
- var morris;
1852
- if(data.state.chart.chart_type == 'line')
1853
- morris = new Morris.Line(options);
1948
+ if(state.chart.chart_type == 'line')
1949
+ state.morris_instance = new Morris.Line(state.morris_options);
1950
1855
- else if(data.state.chart.chart_type == 'area') {
1856
- options.behaveLikeLine = true;
1857
- morris = new Morris.Area(options);
1951
+ else if(state.chart.chart_type == 'area') {
1952
+ state.morris_options.behaveLikeLine = true;
1953
+ state.morris_instance = new Morris.Area(state.morris_options);
1954
}
1955
else // stacked
1860
- morris = new Morris.Area(options);
1861
-
1862
- data.state.morris_instance = morris;
1863
- data.state.morris_options = options;
1956
+ state.morris_instance = new Morris.Area(state.morris_options);
1957
};
1958
1959
// ----------------------------------------------------------------------------------------------------------------
@@ -1887,21 +1980,17 @@
1980
}
1981
};
1982
1890
- NETDATA.raphaelChartUpdate = function(element, data) {
1891
- var self = $(element);
1892
-
1893
- self.raphael(data, {
1894
- width: data.state.calculated_width,
1895
- height: data.state.calculated_height
1983
+ NETDATA.raphaelChartUpdate = function(state, data) {
1984
+ $(state.element_chart).raphael(data.result, {
1985
+ width: state.chartWidth(),
1986
+ height: state.chartHeight()
1987
})
1988
};
1989
1899
- NETDATA.raphaelChartCreate = function(element, data) {
1900
- var self = $(element);
1901
-
1902
- self.raphael(data, {
1903
- width: data.state.calculated_width,
1904
- height: data.state.calculated_height
1990
+ NETDATA.raphaelChartCreate = function(state, data) {
1991
+ $(state.element_chart).raphael(data.result, {
1992
+ width: state.chartWidth(),
1993
+ height: state.chartHeight()
1994
})
1995
};
1996
@@ -1932,20 +2021,20 @@
2021
}
2022
};
2023
1935
- NETDATA.googleChartUpdate = function(element, data) {
2024
+ NETDATA.googleChartUpdate = function(state, data) {
2025
var datatable = new google.visualization.DataTable(data.result);
1937
- data.state.google_instance.draw(datatable, data.state.google_options);
2026
+ state.google_instance.draw(datatable, state.google_options);
2027
};
2028
1940
- NETDATA.googleChartCreate = function(element, data) {
2029
+ NETDATA.googleChartCreate = function(state, data) {
2030
var datatable = new google.visualization.DataTable(data.result);
2031
1943
- var options = {
2032
+ state.google_options = {
2033
// do not set width, height - the chart resizes itself
1945
- //width: data.state.calculated_width,
1946
- //height: data.state.calculated_height,
2034
+ //width: state.chartWidth(),
2035
+ //height: state.chartHeight(),
2036
lineWidth: 1,
1948
- title: data.state.chart.title,
2037
+ title: state.chart.title,
2038
fontSize: 11,
2039
hAxis: {
2040
// title: "Time of Day",
@@ -1961,7 +2050,7 @@
2050
}
2051
},
2052
vAxis: {
1964
- title: data.state.chart.units,
2053
+ title: state.chart.units,
2054
viewWindowMode: 'pretty',
2055
minValue: -0.1,
2056
maxValue: 0.1,
@@ -2000,35 +2089,29 @@
2089
isStacked: false
2090
};
2091
2003
- element.innerHTML = '<div class="netdata-chart-container netdata-google-container" id="google-' + data.state.uuid + '" style="width: 100%; height: 100%;"></div>';
2004
-
2005
- var gchart;
2006
- switch(data.state.chart.chart_type) {
2092
+ switch(state.chart.chart_type) {
2093
case "area":
2008
- options.vAxis.viewWindowMode = 'maximized';
2009
- gchart = new google.visualization.AreaChart(document.getElementById('google-' + data.state.uuid));
2094
+ state.google_options.vAxis.viewWindowMode = 'maximized';
2095
+ state.google_instance = new google.visualization.AreaChart(state.element_chart);
2096
break;
2097
2098
case "stacked":
2013
- options.isStacked = true;
2014
- options.areaOpacity = 0.85;
2015
- options.vAxis.viewWindowMode = 'maximized';
2016
- options.vAxis.minValue = null;
2017
- options.vAxis.maxValue = null;
2018
- gchart = new google.visualization.AreaChart(document.getElementById('google-' + data.state.uuid));
2099
+ state.google_options.isStacked = true;
2100
+ state.google_options.areaOpacity = 0.85;
2101
+ state.google_options.vAxis.viewWindowMode = 'maximized';
2102
+ state.google_options.vAxis.minValue = null;
2103
+ state.google_options.vAxis.maxValue = null;
2104
+ state.google_instance = new google.visualization.AreaChart(state.element_chart);
2105
break;
2106
2107
default:
2108
case "line":
2023
- options.lineWidth = 2;
2024
- gchart = new google.visualization.LineChart(document.getElementById('google-' + data.state.uuid));
2109
+ state.google_options.lineWidth = 2;
2110
+ state.google_instance = new google.visualization.LineChart(state.element_chart);
2111
break;
2112
}
2113
2028
- gchart.draw(datatable, options);
2029
-
2030
- data.state.google_instance = gchart;
2031
- data.state.google_options = options;
2114
+ state.google_instance.draw(datatable, state.google_options);
2115
};
2116
2117
// ----------------------------------------------------------------------------------------------------------------
@@ -2046,6 +2129,9 @@
2129
format: 'json',
2130
options: 'ms|flip',
2131
jsonWrapper: true,
2132
+ legend: 'right-side',
2133
+ autoresize: true,
2134
+ max_updates_to_recreate: 5000,
2135
pixels_per_point: 2,
2136
detects_dimensions_on_update: false
2137
},
@@ -2060,6 +2146,9 @@
2146
format: 'array',
2147
options: 'flip|abs',
2148
jsonWrapper: true,
2149
+ legend: 'sparkline',
2150
+ autoresize: false,
2151
+ max_updates_to_recreate: 5000,
2152
pixels_per_point: 2,
2153
detects_dimensions_on_update: false
2154
},
@@ -2074,6 +2163,9 @@
2163
format: 'ssvcomma',
2164
options: 'null2zero|flip|abs',
2165
jsonWrapper: true,
2166
+ legend: 'sparkline',
2167
+ autoresize: false,
2168
+ max_updates_to_recreate: 5000,
2169
pixels_per_point: 2,
2170
detects_dimensions_on_update: false
2171
},
@@ -2088,6 +2180,9 @@
2180
format: 'json',
2181
options: 'objectrows|ms',
2182
jsonWrapper: true,
2183
+ legend: 'none',
2184
+ autoresize: false,
2185
+ max_updates_to_recreate: 50,
2186
pixels_per_point: 15,
2187
detects_dimensions_on_update: false
2188
},
@@ -2102,6 +2197,9 @@
2197
format: 'datatable',
2198
options: '',
2199
jsonWrapper: true,
2200
+ legend: 'none',
2201
+ autoresize: false,
2202
+ max_updates_to_recreate: 300,
2203
pixels_per_point: 4,
2204
detects_dimensions_on_update: true
2205
},
@@ -2116,6 +2214,9 @@
2214
format: 'json',
2215
options: '',
2216
jsonWrapper: true,
2217
+ legend: 'none',
2218
+ autoresize: false,
2219
+ max_updates_to_recreate: 1000,
2220
pixels_per_point: 1,
2221
detects_dimensions_on_update: false
2222
}