made all charts update the legend on chart update; added easy-pie-chart (not active yet); fixed javascript == to ===; added nanoscroller (not active yet); fixed legend re-generation
Costa Tsaousis (ktsaou) committed
Dec 12, 2015 at 15:13 UTC
f20882de434d05a662acca4b38385c34d47c06fc
6 files changed
+459
-192
src/rrd2json.c
+39
@@ -494,6 +494,45 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t opti
494
buffer_strcat(wb, sq);
495
i++;
496
}
497
+ buffer_sprintf(wb, "],\n"
498
+ " %slatest_values%s: ["
499
+ , kq, kq);
500
+
501
+ for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
502
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
503
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
504
+
505
+ if(i) buffer_strcat(wb, ", ");
506
+ i++;
507
+
508
+ storage_number n = rd->values[rrdset_last_slot(r->st)];
509
+
510
+ if(!does_storage_number_exist(n))
511
+ buffer_strcat(wb, "null");
512
+ else
513
+ buffer_rrd_value(wb, unpack_storage_number(n));
514
+ }
515
+ buffer_sprintf(wb, "],\n"
516
+ " %sresult_latest_values%s: ["
517
+ , kq, kq);
518
+
519
+ if(rrdr_rows(r)) {
520
+ for(c = 0, i = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) {
521
+ if(unlikely(r->od[c] & RRDR_HIDDEN)) continue;
522
+ if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_NONZERO))) continue;
523
+
524
+ if(i) buffer_strcat(wb, ", ");
525
+ i++;
526
+
527
+ calculated_number *cn = &r->v[ (0) * r->d ];
528
+ uint8_t *co = &r->o[ (0) * r->d ];
529
+
530
+ if(co[c] & RRDR_EMPTY)
531
+ buffer_strcat(wb, "null");
532
+ else
533
+ buffer_rrd_value(wb, cn[c]);
534
+ }
535
+ }
536
buffer_sprintf(wb, "],\n"
537
" %sdimensions%s: %d,\n"
538
" %spoints%s: %d,\n"
web/Makefile.am
+2
@@ -27,4 +27,6 @@ dist_weblib_DATA = \
27
css/morris.css \
28
lib/raphael-min.js \
29
lib/visible.js \
30
+ lib/jquery.easypiechart.min.js \
31
+ lib/jquery.nanoscroller.min.js \
32
$(NULL)
web/dashboard.css
+5
@@ -79,6 +79,11 @@ html {
79
font-size: 10px;
80
margin-top: 0px;
81
}
82
+/*
83
+.netdata-legend-series > .netdata-legend-series-content { padding: 10px; }
84
+.netdata-legend-series > .netdata-legend-series-pane { background: #888; }
85
+.netdata-legend-series > .netdata-legend-series-pane > .netdata-legend-series-slider { background: #111; }
86
+*/
87
.netdata-legend-name-table-line {
88
display: inline-block;
89
width: 13px;
web/dashboard.js
+400
-192
@@ -28,7 +28,7 @@
28
NETDATA._scriptSource = function(scripts) {
29
var script = null, base = null;
30
31
- if(typeof document.currentScript != 'undefined') {
31
+ if(typeof document.currentScript !== 'undefined') {
32
script = document.currentScript;
33
}
34
else {
@@ -36,7 +36,7 @@
36
script = all_scripts[all_scripts.length - 1];
37
}
38
39
- if (script.getAttribute.length != 'undefined')
39
+ if (typeof script.getAttribute.length !== 'undefined')
40
script = script.src;
41
else
42
script = script.getAttribute('src', -1);
@@ -56,12 +56,12 @@
56
return base;
57
};
58
59
- if(typeof netdataServer != 'undefined')
59
+ if(typeof netdataServer !== 'undefined')
60
NETDATA.serverDefault = netdataServer;
61
else
62
NETDATA.serverDefault = NETDATA._scriptSource();
63
64
- if(NETDATA.serverDefault.slice(-1) != '/')
64
+ if(NETDATA.serverDefault.slice(-1) !== '/')
65
NETDATA.serverDefault += '/';
66
67
// default URLs for all the external files we need
@@ -70,6 +70,7 @@
70
NETDATA.jQuery = NETDATA.serverDefault + 'lib/jquery-1.11.3.min.js';
71
NETDATA.peity_js = NETDATA.serverDefault + 'lib/jquery.peity.min.js';
72
NETDATA.sparkline_js = NETDATA.serverDefault + 'lib/jquery.sparkline.min.js';
73
+ NETDATA.easypiechart_js = NETDATA.serverDefault + 'lib/jquery.easypiechart.min.js';
74
NETDATA.dygraph_js = NETDATA.serverDefault + 'lib/dygraph-combined.js';
75
NETDATA.dygraph_smooth_js = NETDATA.serverDefault + 'lib/dygraph-smooth-plotter.js';
76
NETDATA.raphael_js = NETDATA.serverDefault + 'lib/raphael-min.js';
@@ -159,16 +160,18 @@
160
idle_lost_focus: 500, // ms - when the window does not have focus, check
161
// if focus has been regained, every this time
162
162
- global_pan_sync_time: 1000, // ms - when you pan or zoon a chart, the background
163
+ global_pan_sync_time: 1500, // ms - when you pan or zoon a chart, the background
164
// autorefreshing of charts is paused for this amount
165
// of time
166
166
- sync_selection_delay: 1500, // ms - when you pan or zoom a chart, wait this amount
167
+ sync_selection_delay: 2500, // ms - when you pan or zoom a chart, wait this amount
168
// of time before setting up synchronized selections
169
// on hover.
170
171
sync_selection: true, // enable or disable selection sync
172
173
+ pan_and_zoom_delay: 50, // when panning or zooming, how ofter to update the chart
174
+
175
sync_pan_and_zoom: true, // enable or disable pan and zoom sync
176
177
update_only_visible: true, // enable or disable visibility management
@@ -252,7 +255,7 @@
255
host = host.replace(/:/g, "_").replace(/\//g, "_");
256
id = id.replace(/:/g, "_").replace(/\//g, "_");
257
255
- if(typeof this.charts[host] == 'undefined')
258
+ if(typeof this.charts[host] === 'undefined')
259
this.charts[host] = {};
260
261
this.charts[host][id] = data;
@@ -262,10 +265,10 @@
265
host = host.replace(/:/g, "_").replace(/\//g, "_");
266
id = id.replace(/:/g, "_").replace(/\//g, "_");
267
265
- if(typeof this.charts[host] == 'undefined')
268
+ if(typeof this.charts[host] === 'undefined')
269
return null;
270
268
- if(typeof this.charts[host][id] == 'undefined')
271
+ if(typeof this.charts[host][id] === 'undefined')
272
return null;
273
274
return this.charts[host][id];
@@ -297,58 +300,58 @@
300
setMaster: function(state, after, before) {
301
if(!NETDATA.options.current.sync_pan_and_zoom) return;
302
300
- if(this.master && this.master != state)
303
+ if(this.master !== null && this.master !== state)
304
this.master.resetChart();
305
306
+ var now = new Date().getTime();
307
this.master = state;
304
- this.seq = new Date().getTime();
308
+ this.seq = now;
309
this.force_after_ms = after;
310
this.force_before_ms = before;
311
+ NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.global_pan_sync_time;
312
},
313
314
// clear the master
315
clearMaster: function() {
316
if(!NETDATA.options.current.sync_pan_and_zoom) return;
317
313
- if(this.master) {
318
+ if(this.master !== null) {
319
var state = this.master;
320
this.master = null; // prevent infinite recursion
321
this.seq = 0;
322
state.resetChart();
323
NETDATA.options.auto_refresher_stop_until = 0;
324
}
320
-
325
+
326
this.master = null;
327
this.seq = 0;
323
- this.after_ms = 0;
324
- this.before_ms = 0;
325
- this.force_after_ms = 0;
326
- this.force_before_ms = 0;
328
+ this.force_after_ms = null;
329
+ this.force_before_ms = null;
330
},
331
332
// is the given state the master of the global
333
// pan and zoom sync?
334
isMaster: function(state) {
332
- if(this.master == state) return true;
335
+ if(this.master === state) return true;
336
return false;
337
},
338
339
// are we currently have a global pan and zoom sync?
340
isActive: function() {
338
- if(this.master) return true;
341
+ if(this.master !== null && this.force_before_ms !== null && this.force_after_ms !== null && this.seq !== 0) return true;
342
return false;
343
},
344
345
// check if a chart, other than the master
346
// needs to be refreshed, due to the global pan and zoom
347
shouldBeAutoRefreshed: function(state) {
345
- if(!this.master || !this.seq)
348
+ if(this.master === null || this.seq === 0)
349
return false;
350
351
if(state.needsResize())
352
return true;
353
351
- if(state.follows_global == this.seq)
354
+ if(state.follows_global === this.seq)
355
return false;
356
357
return true;
@@ -395,7 +398,13 @@
398
element_chart_id: null,
399
element_legend: null, // the element with the legend of the chart (if created by us)
400
element_legend_id: null,
398
- element_legend_childs: { hidden: null },
401
+ element_legend_childs: {
402
+ hidden: null,
403
+ title_date: null,
404
+ title_time: null,
405
+ title_units: null,
406
+ series: {}
407
+ },
408
409
chart_url: null, // string - the url to download chart info
410
chart: null, // object - the chart as downloaded from the server
@@ -430,6 +439,7 @@
439
before_ms: 0, // milliseconds - the last timestamp of the data
440
points: 0, // number - the number of points in the data
441
data: null, // the last downloaded data
442
+ force_update_at: 0, // the timestamp to force the update at
443
force_before_ms: null,
444
force_after_ms: null,
445
requested_before_ms: null,
@@ -447,6 +457,7 @@
457
before_ms: 0, // milliseconds - the last timestamp of the data
458
points: 0, // number - the number of points in the data
459
data: null, // the last downloaded data
460
+ force_update_at: 0, // the timestamp to force the update at
461
force_before_ms: null,
462
force_after_ms: null,
463
requested_before_ms: null,
@@ -464,6 +475,7 @@
475
before_ms: 0, // milliseconds - the last timestamp of the data
476
points: 0, // number - the number of points in the data
477
data: null, // the last downloaded data
478
+ force_update_at: 0, // the timestamp to force the update at
479
force_before_ms: null,
480
force_after_ms: null,
481
requested_before_ms: null,
@@ -503,7 +515,7 @@
515
// this chart is the master of the global selection sync
516
chartState.prototype.globalSelectionSyncBeMaster = function() {
517
// am I the master?
506
- if(NETDATA.globalSelectionSync.state == this) {
518
+ if(NETDATA.globalSelectionSync.state === this) {
519
if(this.debug) this.log('sync: I am the master already.');
520
return;
521
}
@@ -522,7 +534,7 @@
534
var self = this;
535
$.each(NETDATA.options.targets, function(i, target) {
536
var st = NETDATA.chartState(target);
525
- if(st == self) {
537
+ if(st === self) {
538
if(self.debug) st.log('sync: not adding me to sync');
539
}
540
else if(st.globalSelectionSyncIsEligible()) {
@@ -534,14 +546,14 @@
546
547
// can the chart participate to the global selection sync as a slave?
548
chartState.prototype.globalSelectionSyncIsEligible = function() {
537
- if(this.library != null && typeof this.library.setSelection == 'function' && this.isVisible())
549
+ if(this.library !== null && typeof this.library.setSelection === 'function' && this.isVisible())
550
return true;
551
return false;
552
}
553
554
// this chart is a slave of the global selection sync
555
chartState.prototype.globalSelectionSyncBeSlave = function() {
544
- if(NETDATA.globalSelectionSync.state != this)
556
+ if(NETDATA.globalSelectionSync.state !== this)
557
NETDATA.globalSelectionSync.slaves.push(this);
558
}
559
@@ -558,7 +570,7 @@
570
571
var self = this;
572
$.each(NETDATA.globalSelectionSync.slaves, function(i, st) {
561
- if(st == self) {
573
+ if(st === self) {
574
// since we are the sync master, we should not call state.setSelection()
575
// the chart library is taking care of visualizing our selection.
576
if(self.debug) st.log('sync: ignoring me from set selection');
@@ -576,7 +588,7 @@
588
if(this.debug) this.log('sync: cleaning up...');
589
var self = this;
590
$.each(NETDATA.globalSelectionSync.slaves, function(i, st) {
579
- if(st == self) {
591
+ if(st === self) {
592
if(self.debug) st.log('sync: not adding me to sync stop');
593
}
594
else {
@@ -595,7 +607,7 @@
607
}
608
609
chartState.prototype.setSelection = function(t) {
598
- if(typeof this.library.setSelection == 'function') {
610
+ if(typeof this.library.setSelection === 'function') {
611
if(this.library.setSelection(this, t))
612
this.selected = true;
613
else
@@ -610,7 +622,7 @@
622
623
chartState.prototype.clearSelection = function() {
624
if(this.selected) {
613
- if(typeof this.library.clearSelection == 'function') {
625
+ if(typeof this.library.clearSelection === 'function') {
626
if(this.library.clearSelection(this))
627
this.selected = false;
628
else
@@ -621,6 +633,7 @@
633
if(!this.selected && this.debug) this.log('selection cleared');
634
}
635
636
+ this.legendReset();
637
return this.selected;
638
}
639
@@ -664,6 +677,7 @@
677
this.clearSelection();
678
679
this.setMode('auto');
680
+ this.current.force_update_at = 0;
681
this.current.force_before_ms = null;
682
this.current.force_after_ms = null;
683
this.current.last_autorefreshed = 0;
@@ -682,7 +696,7 @@
696
697
chartState.prototype.setMode = function(m) {
698
if(this.current) {
685
- if(this.current.name == m) return;
699
+ if(this.current.name === m) return;
700
701
this[m].url = this.current.url;
702
this[m].last_autorefreshed = this.current.last_autorefreshed;
@@ -697,15 +711,16 @@
711
this[m].last_entry_ms = this.current.last_entry_ms;
712
}
713
700
- if(m == 'auto')
714
+ if(m === 'auto')
715
this.current = this.auto;
702
- else if(m == 'pan')
716
+ else if(m === 'pan')
717
this.current = this.pan;
704
- else if(m == 'zoom')
718
+ else if(m === 'zoom')
719
this.current = this.zoom;
720
else
721
this.current = this.auto;
722
723
+ this.current.force_update_at = 0;
724
this.current.force_before_ms = null;
725
this.current.force_after_ms = null;
726
@@ -742,10 +757,10 @@
757
}
758
}
759
745
- chartState.prototype.updateChartPanOrZoom = function(after, before, callback) {
760
+ chartState.prototype.updateChartPanOrZoom = function(after, before) {
761
var move = false;
762
748
- if(this.current.name == 'auto') {
763
+ if(this.current.name === 'auto') {
764
if(this.debug) this.log('updateChartPanOrZoom(): caller did not set proper mode');
765
this.setMode('pan');
766
}
@@ -764,40 +779,125 @@
779
}
780
781
if(move) {
767
- var now = new Date().getTime();
768
- NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.global_pan_sync_time;
769
- NETDATA.globalPanAndZoom.setMaster(this, after, before);
770
-
782
+ this.current.force_update_at = new Date().getTime() + NETDATA.options.current.pan_and_zoom_delay;
783
this.current.force_after_ms = after;
784
this.current.force_before_ms = before;
773
- this.updateChart(callback);
785
+ NETDATA.globalPanAndZoom.setMaster(this, after, before);
786
+ //this.updateChart(function() {
787
+ // NETDATA.globalPanAndZoom.setMaster(this, after, before);
788
+ // if(typeof callback === 'function')
789
+ // callback();
790
+ //});
791
return true;
792
}
793
794
if(this.debug) this.log('updateChartPanOrZoom(' + (after / 1000).toString() + ' - ' + (before / 1000).toString() + '): IGNORE');
778
- if(typeof callback != 'undefined') callback();
795
return false;
796
}
797
782
- chartState.prototype.updateLegendDOM = function() {
798
+ chartState.prototype.legendFormatValue = function(value) {
799
+ if(typeof value !== 'number' || value === null) return '';
800
+
801
+ var abs = Math.abs(value);
802
+ if(abs >= 1) return (Math.round(value * 100) / 100).toLocaleString();
803
+ if(abs >= 0.1) return (Math.round(value * 1000) / 1000).toLocaleString();
804
+ return (Math.round(value * 10000) / 10000).toLocaleString();
805
+ }
806
+
807
+ chartState.prototype.legendSetLabelValue = function(label, string) {
808
+ if(typeof this.element_legend_childs.series[label] === 'undefined')
809
+ return;
810
+
811
+ if(this.element_legend_childs.series[label].value !== null)
812
+ this.element_legend_childs.series[label].value.innerHTML = string;
813
+
814
+ if(this.element_legend_childs.series[label].user !== null)
815
+ this.element_legend_childs.series[label].user.innerHTML = string;
816
+ }
817
+
818
+ chartState.prototype.legendSetDate = function(ms) {
819
+ if(typeof ms !== 'number') {
820
+ this.legendUndefined();
821
+ return;
822
+ }
823
+
824
+ var d = new Date(ms);
825
+
826
+ if(this.element_legend_childs.title_date)
827
+ this.element_legend_childs.title_date.innerHTML = d.toLocaleDateString();
828
+
829
+ if(this.element_legend_childs.title_time)
830
+ this.element_legend_childs.title_time.innerHTML = d.toLocaleTimeString();
831
+
832
+ if(this.element_legend_childs.title_units)
833
+ this.element_legend_childs.title_units.innerHTML = this.chart.units;
834
+ }
835
+
836
+ chartState.prototype.legendUndefined = function() {
837
+ if(this.element_legend_childs.title_date)
838
+ this.element_legend_childs.title_date.innerHTML = ' ';
839
+
840
+ if(this.element_legend_childs.title_time)
841
+ this.element_legend_childs.title_time.innerHTML = this.chart.name;
842
+
843
+ if(this.element_legend_childs.title_units)
844
+ this.element_legend_childs.title_units.innerHTML = ' ';
845
+ }
846
+
847
+ chartState.prototype.legendShowLatestValues = function() {
848
+ if(!this.chart) return;
849
+ if(this.selected) return;
850
+
851
+ if(!this.current.data) {
852
+ this.legendUndefined();
853
+ return;
854
+ }
855
+
856
+ if(Math.abs(this.current.data.last_entry_t - this.current.data.before) <= this.current.data.view_update_every)
857
+ this.legendSetDate(this.current.data.before * 1000);
858
+ else
859
+ this.legendUndefined();
860
+
861
+ for(var i = 0; i < this.current.data.dimension_names.length; i++) {
862
+ if(typeof this.element_legend_childs.series[this.current.data.dimension_names[i]] === 'undefined')
863
+ continue;
864
+
865
+ if(Math.abs(this.current.data.last_entry_t - this.current.data.before) <= this.current.data.view_update_every)
866
+ this.legendSetLabelValue(this.current.data.dimension_names[i], this.legendFormatValue(this.current.data.result_latest_values[i]));
867
+ else
868
+ this.legendSetLabelValue(this.current.data.dimension_names[i], '');
869
+ }
870
+ }
871
+
872
+ chartState.prototype.legendReset = function() {
873
+ this.legendShowLatestValues();
874
+ }
875
+
876
+ chartState.prototype.legendUpdateDOM = function() {
877
if(!this.hasLegend()) return;
878
879
var needed = false;
880
881
// check that the legend DOM is up to date for the downloaded dimensions
788
- if(typeof this.element_legend_childs.series != 'object')
882
+ if(typeof this.element_legend_childs.series !== 'object') {
883
+ // this.log('the legend does not have any series - requesting legend update');
884
needed = true;
790
- else if(!this.current.data)
885
+ }
886
+ else if(!this.current.data) {
887
+ // this.log('the chart does not have any data - requesting legend update');
888
needed = true;
889
+ }
890
else {
891
+ // this.log('checking existing legend');
892
for(var i = 0; i < this.current.data.dimension_names.length; i++) {
794
- if(typeof this.element_legend_childs.series[this.current.data.dimension_names[i]] == 'undefined') {
893
+ if(typeof this.element_legend_childs.series[this.current.data.dimension_names[i]] === 'undefined') {
894
+ // this.log('legend is incosistent - missing dimension:' + this.current.data.dimension_names[i]);
895
needed = true;
896
break;
897
}
798
- else if(!this.follows_global) {
799
- // FIXME update to latest value
800
- ;
898
+ else if(Math.abs(this.current.data.last_entry_t - this.current.data.before) <= this.current.data.view_update_every) {
899
+ // this.log('setting legend of ' + this.current.data.dimension_names[i] + ' to ' + this.current.data.latest_values[i]);
900
+ this.legendSetLabelValue(this.current.data.dimension_names[i], this.legendFormatValue(this.current.data.latest_values[i]));
901
}
902
}
903
}
@@ -806,6 +906,8 @@
906
907
if(this.debug) this.log('updating Legend DOM');
908
909
+ this.element_legend.innerHTML = '';
910
+
911
this.element_legend_childs = {
912
title_date: document.createElement('span'),
913
title_time: document.createElement('span'),
@@ -828,16 +930,26 @@
930
931
this.element_legend.appendChild(document.createElement('br'));
932
831
- var el = document.createElement('div');
832
- el.className += "netdata-legend-series";
833
- this.element_legend.appendChild(el);
933
+ var nano = document.createElement('div');
934
+ nano.className = 'netdata-legend-series';
935
+ this.element_legend.appendChild(nano);
936
+
937
+ var content = document.createElement('div');
938
+ content.className = 'netdata-legend-series-content';
939
+ nano.appendChild(content);
940
941
+ self = $(this);
942
var genLabel = function(state, parent, name, count) {
943
var c = count % NETDATA.colors.length;
944
945
+ var user_element = null;
946
+ var user_id = self.data('show-value-of-' + name + '-at') || null;
947
+ if(user_id) user_element = document.getElementById(user_id);
948
+
949
state.element_legend_childs.series[name] = {
950
name: document.createElement('span'),
840
- value: document.createElement('span')
951
+ value: document.createElement('span'),
952
+ user: user_element
953
};
954
955
var label = state.element_legend_childs.series[name];
@@ -871,24 +983,36 @@
983
if(this.current.data) {
984
var me = this;
985
$.each(me.current.data.dimension_names, function(i, d) {
874
- genLabel(me, el, d, i);
986
+ genLabel(me, content, d, i);
987
});
988
}
989
else {
990
var me = this;
991
$.each(me.chart.dimensions, function(i, d) {
880
- genLabel(me, el, d.name, i);
992
+ genLabel(me, content, d.name, i);
993
});
994
}
995
996
// create a hidden div to be used for hidding
997
// the original legend of the chart library
886
- el = document.createElement('div');
998
+ var el = document.createElement('div');
999
this.element_legend.appendChild(el);
1000
el.style.display = 'none';
1001
1002
this.element_legend_childs.hidden = document.createElement('div');
1003
el.appendChild(this.element_legend_childs.hidden);
1004
+ nano.appendChild(el);
1005
+/*
1006
+ $(nano).nanoScroller({
1007
+ paneClass: 'netdata-legend-series-pane',
1008
+ sliderClass: 'netdata-legend-series-slider',
1009
+ contentClass: 'netdata-legend-series-content',
1010
+ enabledClass: '__enabled',
1011
+ flashedClass: '__flashed',
1012
+ activeClass: '__active'
1013
+ });
1014
+*/
1015
+ this.legendShowLatestValues();
1016
}
1017
1018
chartState.prototype.createChartDOM = function() {
@@ -923,16 +1047,16 @@
1047
if(this.hasLegend()) {
1048
this.element_legend = document.getElementById(this.element_legend_id);
1049
$(this.element_legend).data('netdata-state-object', this);
926
- this.updateLegendDOM();
1050
+ this.legendUpdateDOM();
1051
}
1052
}
1053
1054
chartState.prototype.hasLegend = function() {
1055
if(this.element_legend) return true;
1056
933
- if(this.library && this.library.legend(this) == 'right-side') {
1057
+ if(this.library && this.library.legend(this) === 'right-side') {
1058
var legend = $(this.element).data('legend') || 'yes';
935
- if(legend == 'no') return false;
1059
+ if(legend === 'no') return false;
1060
return true;
1061
}
1062
@@ -989,8 +1113,8 @@
1113
this.follows_global = NETDATA.globalPanAndZoom.seq;
1114
}
1115
else {
992
- before = this.current.force_before_ms != null ? Math.round(this.current.force_before_ms / 1000) : this.before;
993
- after = this.current.force_after_ms != null ? Math.round(this.current.force_after_ms / 1000) : this.after;
1116
+ before = this.current.force_before_ms !== null ? Math.round(this.current.force_before_ms / 1000) : this.before;
1117
+ after = this.current.force_after_ms !== null ? Math.round(this.current.force_after_ms / 1000) : this.after;
1118
this.follows_global = 0;
1119
}
1120
@@ -1026,23 +1150,23 @@
1150
var started = new Date().getTime();
1151
1152
// if the result is JSON, find the latest update-every
1029
- if(typeof data == 'object') {
1030
- if(typeof data.view_update_every != 'undefined')
1153
+ if(typeof data === 'object') {
1154
+ if(typeof data.view_update_every !== 'undefined')
1155
this.current.view_update_every = data.view_update_every * 1000;
1156
1033
- if(typeof data.after != 'undefined')
1157
+ if(typeof data.after !== 'undefined')
1158
this.current.after_ms = data.after * 1000;
1159
1036
- if(typeof data.before != 'undefined')
1160
+ if(typeof data.before !== 'undefined')
1161
this.current.before_ms = data.before * 1000;
1162
1039
- if(typeof data.first_entry_t != 'undefined')
1163
+ if(typeof data.first_entry_t !== 'undefined')
1164
this.current.first_entry_ms = data.first_entry_t * 1000;
1165
1042
- if(typeof data.last_entry_t != 'undefined')
1166
+ if(typeof data.last_entry_t !== 'undefined')
1167
this.current.last_entry_ms = data.last_entry_t * 1000;
1168
1045
- if(typeof data.points != 'undefined')
1169
+ if(typeof data.points !== 'undefined')
1170
this.current.points = data.points;
1171
1172
data.state = this;
@@ -1071,11 +1195,11 @@
1195
this.created_ms = 0;
1196
}
1197
1074
- if(this.created_ms && typeof this.library.update == 'function') {
1198
+ if(this.created_ms && typeof this.library.update === 'function') {
1199
if(this.debug) this.log('updating chart...');
1200
1201
// check and update the legend
1078
- this.updateLegendDOM();
1202
+ this.legendUpdateDOM();
1203
1204
this.updates_since_last_creation++;
1205
if(NETDATA.options.debug.chart_errors) {
@@ -1110,10 +1234,11 @@
1234
}
1235
}
1236
}
1237
+ this.legendShowLatestValues();
1238
1239
// update the performance counters
1240
var now = new Date().getTime();
1116
-
1241
+
1242
// don't update last_autorefreshed if this chart is
1243
// forced to be updated with global PanAndZoom
1244
if(NETDATA.globalPanAndZoom.isActive())
@@ -1129,32 +1254,15 @@
1254
}
1255
1256
chartState.prototype.updateChart = function(callback) {
1132
- if(!this.library || !this.library.enabled) {
1133
- this.error('charting library "' + this.library_name + '" is not available');
1134
- if(typeof callback != 'undefined') callback();
1135
- return;
1136
- }
1137
-
1138
- if(!this.enabled) {
1139
- if(this.debug) this.error('chart "' + this.id + '" is not enabled');
1140
- if(typeof callback != 'undefined') callback();
1141
- return;
1142
- }
1143
-
1144
- if(!this.isVisible()) {
1145
- if(NETDATA.options.debug.visibility || this.debug) this.log('is not visible');
1146
- if(typeof callback != 'undefined') callback();
1147
- return;
1148
- }
1257
if(!this.chart) {
1150
- var this_state_object = this;
1151
- this.getChart(function() { this_state_object.updateChart(callback); });
1258
+ var self = this;
1259
+ this.getChart(function() { self.updateChart(callback); });
1260
return;
1261
}
1262
1263
if(!this.library.initialized) {
1156
- var this_state_object = this;
1157
- this.library.initialize(function() { this_state_object.updateChart(callback); });
1264
+ var self = this;
1265
+ this.library.initialize(function() { self.updateChart(callback); });
1266
return;
1267
}
1268
@@ -1162,20 +1270,22 @@
1270
this.chartURL();
1271
if(this.debug) this.log('updating from ' + this.current.url);
1272
1165
- var this_state_object = this;
1166
- $.ajax( {
1273
+ var self = this;
1274
+ this.xhr = $.ajax( {
1275
url: this.current.url,
1276
crossDomain: true,
1169
- cache: false
1277
+ cache: false,
1278
+ async: true
1279
})
1171
- .then(function(data) {
1172
- this_state_object.updateChartWithData(data);
1280
+ .success(function(data) {
1281
+ if(self.debug) self.log('data received. updating chart.');
1282
+ self.updateChartWithData(data);
1283
})
1284
.fail(function() {
1175
- this_state_object.error('cannot download chart from ' + this_state_object.current.url);
1285
+ self.error('data download failed for url: ' + self.current.url);
1286
})
1287
.always(function() {
1178
- if(typeof callback == 'function') callback();
1288
+ if(typeof callback === 'function') callback();
1289
});
1290
}
1291
@@ -1187,25 +1297,43 @@
1297
}
1298
1299
chartState.prototype.isAutoRefreshed = function() {
1190
- return this.current.autorefresh;
1300
+ return (this.current.autorefresh);
1301
}
1302
1303
chartState.prototype.canBeAutoRefreshed = function() {
1194
- if(this.isAutoRefreshed()) {
1195
- var now = new Date().getTime();
1304
+ now = new Date().getTime();
1305
+
1306
+ if(!this.library || !this.library.enabled) {
1307
+ this.error('charting library "' + this.library_name + '" is not available');
1308
+ if(this.debug) this.log('My chart library ' + this.library_name + ' is not available');
1309
+ return false;
1310
+ }
1311
1312
+ if(!this.enabled) {
1313
+ if(this.debug) this.log('I am not enabled');
1314
+ return false;
1315
+ }
1316
+
1317
+ if(!this.isVisible()) {
1318
+ if(NETDATA.options.debug.visibility || this.debug) this.log('I am not visible');
1319
+ return;
1320
+ }
1321
+
1322
+ if(this.current.force_update_at !== 0 && this.current.force_update_at < now) {
1323
+ if(this.debug) this.log('timed force update detecting - allowing this update');
1324
+ this.current.force_update_at = 0;
1325
+ return true;
1326
+ }
1327
+
1328
+ if(this.isAutoRefreshed()) {
1329
+ // allow the first update, even if the page is not visible
1330
if(this.updates_counter && !NETDATA.options.page_is_visible) {
1331
if(NETDATA.options.debug.focus || this.debug) this.log('canBeAutoRefreshed(): page does not have focus');
1332
return false;
1333
}
1334
1202
- if(!this.isVisible()) {
1203
- if(this.debug) this.log('canBeAutoRefreshed(): I am not visible.');
1204
- return false;
1205
- }
1206
-
1335
// options valid only for autoRefresh()
1208
- if(NETDATA.options.auto_refresher_stop_until == 0 || NETDATA.options.auto_refresher_stop_until < now) {
1336
+ if(NETDATA.options.auto_refresher_stop_until === 0 || NETDATA.options.auto_refresher_stop_until < now) {
1337
if(NETDATA.globalPanAndZoom.isActive()) {
1338
if(NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this)) {
1339
if(this.debug) this.log('canBeAutoRefreshed(): global panning: I need an update.');
@@ -1242,7 +1370,7 @@
1370
this.updateChart(callback);
1371
}
1372
else {
1245
- if(typeof callback != 'undefined')
1373
+ if(typeof callback !== 'undefined')
1374
callback();
1375
}
1376
}
@@ -1259,7 +1387,7 @@
1387
this.chart = NETDATA.chartRegistry.get(this.host, this.id);
1388
if(this.chart) {
1389
this._defaultsFromDownloadedChart(this.chart);
1262
- if(typeof callback == 'function') callback();
1390
+ if(typeof callback === 'function') callback();
1391
}
1392
else {
1393
this.chart_url = this.host + "/api/v1/chart?chart=" + this.id;
@@ -1282,7 +1410,7 @@
1410
this_state_object.error('chart "' + this_state_object.id + '" not found on url "' + this_state_object.chart_url + '"');
1411
})
1412
.always(function() {
1285
- if(typeof callback == 'function') callback();
1413
+ if(typeof callback === 'function') callback();
1414
});
1415
}
1416
}
@@ -1334,13 +1462,13 @@
1462
1463
// make sure the host does not end with /
1464
// all netdata API requests use absolute paths
1337
- while(this.host.slice(-1) == '/')
1465
+ while(this.host.slice(-1) === '/')
1466
this.host = this.host.substring(0, this.host.length - 1);
1467
1468
// check the requested library is available
1469
// we don't initialize it here - it will be initialized when
1470
// this chart will be first used
1343
- if(typeof NETDATA.chartLibraries[this.library_name] == 'undefined') {
1471
+ if(typeof NETDATA.chartLibraries[this.library_name] === 'undefined') {
1472
NETDATA.error(402, this.library_name);
1473
this.error('chart library "' + this.library_name + '" is not found');
1474
}
@@ -1377,7 +1505,7 @@
1505
// Load a script without jquery
1506
// This is used to load jquery - after it is loaded, we use jquery
1507
NETDATA._loadjQuery = function(callback) {
1380
- if(typeof jQuery == 'undefined') {
1508
+ if(typeof jQuery === 'undefined') {
1509
var script = document.createElement('script');
1510
script.type = 'text/javascript';
1511
script.async = true;
@@ -1385,13 +1513,13 @@
1513
1514
// script.onabort = onError;
1515
script.onerror = function(err, t) { NETDATA.error(101, NETDATA.jQuery); };
1388
- if(typeof callback == "function")
1516
+ if(typeof callback === "function")
1517
script.onload = callback;
1518
1519
var s = document.getElementsByTagName('script')[0];
1520
s.parentNode.insertBefore(script, s);
1521
}
1394
- else if(typeof callback == "function")
1522
+ else if(typeof callback === "function")
1523
callback();
1524
}
1525
@@ -1401,7 +1529,7 @@
1529
fileref.setAttribute("type", "text/css");
1530
fileref.setAttribute("href", filename);
1531
1404
- if (typeof fileref != "undefined")
1532
+ if (typeof fileref !== 'undefined')
1533
document.getElementsByTagName("head")[0].appendChild(fileref);
1534
}
1535
@@ -1475,7 +1603,7 @@
1603
return;
1604
}
1605
var target = NETDATA.options.targets.get(index);
1478
- if(target == null) {
1606
+ if(target === null) {
1607
if(NETDATA.options.debug.main_loop) console.log('waiting to restart main loop...');
1608
NETDATA.options.auto_refresher_fast_weight = 0;
1609
@@ -1514,7 +1642,7 @@
1642
return;
1643
}
1644
1517
- if(NETDATA.options.sequencial.length == 0)
1645
+ if(NETDATA.options.sequencial.length === 0)
1646
NETDATA.chartRefresher();
1647
else {
1648
var state = NETDATA.options.sequencial.pop();
@@ -1556,12 +1684,11 @@
1684
1685
if(NETDATA.options.parallel.length > 0) {
1686
NETDATA.options.parallel_jobs = NETDATA.options.parallel.length;
1559
- console.log('PARALLEL: ' + NETDATA.options.parallel.length);
1687
1688
$(NETDATA.options.parallel).each(function() {
1689
this.autoRefresh(function() {
1690
NETDATA.options.parallel_jobs--;
1564
- if(NETDATA.options.parallel_jobs == 0) {
1691
+ if(NETDATA.options.parallel_jobs === 0) {
1692
setTimeout(NETDATA.chartRefresher_sequencial,
1693
NETDATA.options.current.idle_between_charts);
1694
}
@@ -1590,7 +1717,7 @@
1717
var state = NETDATA.chartState(target);
1718
});
1719
1593
- if(typeof callback == 'function') callback();
1720
+ if(typeof callback === 'function') callback();
1721
}
1722
1723
// this is the main function - where everything starts
@@ -1609,7 +1736,7 @@
1736
if(NETDATA.options.debug.focus) console.log('Focus restored!');
1737
});
1738
1612
- if(typeof document.hasFocus == 'function' && !document.hasFocus()) {
1739
+ if(typeof document.hasFocus === 'function' && !document.hasFocus()) {
1740
NETDATA.options.page_is_visible = false;
1741
if(NETDATA.options.debug.focus) console.log('Document has no focus!');
1742
}
@@ -1623,7 +1750,7 @@
1750
// peity
1751
1752
NETDATA.peityInitialize = function(callback) {
1626
- if(typeof netdataNoPeitys == 'undefined' || !netdataNoPeitys) {
1753
+ if(typeof netdataNoPeitys === 'undefined' || !netdataNoPeitys) {
1754
$.ajax({
1755
url: NETDATA.peity_js,
1756
cache: true,
@@ -1636,13 +1763,13 @@
1763
NETDATA.error(100, NETDATA.peity_js);
1764
})
1765
.always(function() {
1639
- if(typeof callback == "function")
1766
+ if(typeof callback === "function")
1767
callback();
1768
})
1769
}
1770
else {
1771
NETDATA.chartLibraries.peity.enabled = false;
1645
- if(typeof callback == "function")
1772
+ if(typeof callback === "function")
1773
callback();
1774
}
1775
};
@@ -1664,7 +1791,7 @@
1791
// sparkline
1792
1793
NETDATA.sparklineInitialize = function(callback) {
1667
- if(typeof netdataNoSparklines == 'undefined' || !netdataNoSparklines) {
1794
+ if(typeof netdataNoSparklines === 'undefined' || !netdataNoSparklines) {
1795
$.ajax({
1796
url: NETDATA.sparkline_js,
1797
cache: true,
@@ -1677,13 +1804,13 @@
1804
NETDATA.error(100, NETDATA.sparkline_js);
1805
})
1806
.always(function() {
1680
- if(typeof callback == "function")
1807
+ if(typeof callback === "function")
1808
callback();
1809
})
1810
}
1811
else {
1812
NETDATA.chartLibraries.sparkline.enabled = false;
1686
- if(typeof callback == "function")
1813
+ if(typeof callback === "function")
1814
callback();
1815
}
1816
};
@@ -1699,7 +1826,7 @@
1826
var self = $(state.element);
1827
var type = self.data('sparkline-type') || 'line';
1828
var lineColor = self.data('sparkline-linecolor') || NETDATA.colors[0];
1702
- var fillColor = self.data('sparkline-fillcolor') || (state.chart.chart_type == 'line')?'#FFF':NETDATA.colorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1829
+ var fillColor = self.data('sparkline-fillcolor') || (state.chart.chart_type === 'line')?'#FFF':NETDATA.colorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance);
1830
var chartRangeMin = self.data('sparkline-chartrangemin') || undefined;
1831
var chartRangeMax = self.data('sparkline-chartrangemax') || undefined;
1832
var composite = self.data('sparkline-composite') || undefined;
@@ -1806,9 +1933,9 @@
1933
};
1934
1935
NETDATA.dygraphSetSelection = function(state, t) {
1809
- if(typeof state.dygraph_instance != 'undefined') {
1936
+ if(typeof state.dygraph_instance !== 'undefined') {
1937
var r = state.calculateRowForTime(t);
1811
- if(r != -1) {
1938
+ if(r !== -1) {
1939
state.dygraph_instance.setSelection(r);
1940
return true;
1941
}
@@ -1820,7 +1947,7 @@
1947
}
1948
1949
NETDATA.dygraphClearSelection = function(state, t) {
1823
- if(typeof state.dygraph_instance != 'undefined') {
1950
+ if(typeof state.dygraph_instance !== 'undefined') {
1951
state.dygraph_instance.clearSelection();
1952
}
1953
return true;
@@ -1837,13 +1964,13 @@
1964
smoothPlotter.smoothing = 0.3;
1965
})
1966
.always(function() {
1840
- if(typeof callback == "function")
1967
+ if(typeof callback === "function")
1968
callback();
1969
})
1970
};
1971
1972
NETDATA.dygraphInitialize = function(callback) {
1846
- if(typeof netdataNoDygraphs == 'undefined' || !netdataNoDygraphs) {
1973
+ if(typeof netdataNoDygraphs === 'undefined' || !netdataNoDygraphs) {
1974
$.ajax({
1975
url: NETDATA.dygraph_js,
1976
cache: true,
@@ -1855,13 +1982,13 @@
1982
})
1983
.fail(function() {
1984
NETDATA.error(100, NETDATA.dygraph_js);
1858
- if(typeof callback == "function")
1985
+ if(typeof callback === "function")
1986
callback();
1987
})
1988
}
1989
else {
1990
NETDATA.chartLibraries.dygraph.enabled = false;
1864
- if(typeof callback == "function")
1991
+ if(typeof callback === "function")
1992
callback();
1993
}
1994
};
@@ -1869,7 +1996,7 @@
1996
NETDATA.dygraphChartUpdate = function(state, data) {
1997
var dygraph = state.dygraph_instance;
1998
1872
- if(state.current.name == 'pan') {
1999
+ if(state.current.name === 'pan') {
2000
if(NETDATA.options.debug.dygraph || state.debug) state.log('dygraphChartUpdate() loose update');
2001
dygraph.updateOptions({
2002
file: data.result.data,
@@ -1924,7 +2051,7 @@
2051
plotter: null,
2052
2053
// The width of the lines connecting data points. This can be used to increase the contrast or some graphs.
1927
- strokeWidth: self.data('dygraph-strokewidth') || (state.chart.chart_type == 'stacked')?0.0:1.0,
2054
+ strokeWidth: self.data('dygraph-strokewidth') || (state.chart.chart_type === 'stacked')?0.0:1.0,
2055
strokePattern: self.data('dygraph-strokepattern') || undefined,
2056
2057
// The size of the dot to draw on each point in pixels (see drawPoints). A dot is always drawn when a point is "isolated",
@@ -1942,11 +2069,11 @@
2069
2070
// Draw a border around graph lines to make crossing lines more easily distinguishable. Useful for graphs with many lines.
2071
strokeBorderColor: self.data('dygraph-strokebordercolor') || 'white',
1945
- strokeBorderWidth: self.data('dygraph-strokeborderwidth') || (state.chart.chart_type == 'stacked')?0.0:0.0,
2072
+ strokeBorderWidth: self.data('dygraph-strokeborderwidth') || (state.chart.chart_type === 'stacked')?0.0:0.0,
2073
1947
- fillGraph: self.data('dygraph-fillgraph') || (state.chart.chart_type == 'area')?true:false,
1948
- fillAlpha: self.data('dygraph-fillalpha') || (state.chart.chart_type == 'stacked')?0.8:0.2,
1949
- stackedGraph: self.data('dygraph-stackedgraph') || (state.chart.chart_type == 'stacked')?true:false,
2074
+ fillGraph: self.data('dygraph-fillgraph') || (state.chart.chart_type === 'area')?true:false,
2075
+ fillAlpha: self.data('dygraph-fillalpha') || (state.chart.chart_type === 'stacked')?0.8:0.2,
2076
+ stackedGraph: self.data('dygraph-stackedgraph') || (state.chart.chart_type === 'stacked')?true:false,
2077
stackedGraphNaNFill: self.data('dygraph-stackedgraphnanfill') || 'none',
2078
2079
drawAxis: self.data('dygraph-drawaxis') || true,
@@ -1968,7 +2095,7 @@
2095
2096
highlightCircleSize: self.data('dygraph-highlightcirclesize') || 4,
2097
highlightSeriesOpts: self.data('dygraph-highlightseriesopts') || null, // TOO SLOW: { strokeWidth: 1.5 },
1971
- highlightSeriesBackgroundAlpha: self.data('dygraph-highlightseriesbackgroundalpha') || null, // TOO SLOW: (state.chart.chart_type == 'stacked')?0.7:0.5,
2098
+ highlightSeriesBackgroundAlpha: self.data('dygraph-highlightseriesbackgroundalpha') || null, // TOO SLOW: (state.chart.chart_type === 'stacked')?0.7:0.5,
2099
2100
pointClickCallback: self.data('dygraph-pointclickcallback') || undefined,
2101
axes: {
@@ -1987,7 +2114,8 @@
2114
y: {
2115
pixelsPerLabel: 15,
2116
valueFormatter: function (x) {
1990
- return (Math.round(x*100) / 100).toLocaleString();
2117
+ // return (Math.round(x*100) / 100).toLocaleString();
2118
+ return state.legendFormatValue(x);
2119
}
2120
}
2121
},
@@ -1998,36 +2126,25 @@
2126
2127
// if the hidden div is not there
2128
// state is not managing the legend
2001
- if(elements.hidden == null) return;
2002
-
2003
- if (typeof(data.x) === 'undefined') {
2004
- elements.title_date.innerHTML = ' ';
2005
- elements.title_time.innerHTML = state.chart.name;
2006
- elements.title_units.innerHTML = ' ';
2129
+ if(elements.hidden === null) return;
2130
2008
- for (var i = 0; i < data.series.length; i++) {
2009
- var series = data.series[i];
2010
- //elements.series[series.label].name.innerHTML = series.dashHTML + ' ' + series.labelHTML;
2011
- elements.series[series.label].value.innerHTML = '';
2012
- }
2131
+ if (typeof data.x === 'undefined') {
2132
+ state.legendReset();
2133
}
2134
else {
2015
- var d = new Date(data.x);
2016
- elements.title_date.innerHTML = d.toLocaleDateString();
2017
- elements.title_time.innerHTML = d.toLocaleTimeString();
2018
- elements.title_units.innerHTML = state.chart.units;
2019
-
2135
+ state.legendSetDate(data.x);
2136
for (var i = 0; i < data.series.length; i++) {
2137
var series = data.series[i];
2138
if(!series.isVisible) continue;
2023
- elements.series[series.label].value.innerHTML = series.yHTML;
2139
+ state.legendSetLabelValue(series.label, series.yHTML);
2140
+ // elements.series[series.label].value.innerHTML = series.yHTML;
2141
}
2142
}
2143
2027
- return 'hidden original dygraph legend';
2144
+ return '';
2145
},
2146
drawCallback: function(dygraph, is_initial) {
2030
- if(state.current.name != 'auto') {
2147
+ if(state.current.name !== 'auto') {
2148
if(NETDATA.options.debug.dygraph) state.log('dygraphDrawCallback()');
2149
2150
var x_range = dygraph.xAxisRange();
@@ -2052,7 +2169,7 @@
2169
// here we calculate the time t based on the row number selected
2170
// which is ok
2171
var t = state.current.after_ms + row * state.current.view_update_every;
2055
- // console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t == x)?'SAME':'DIFFERENT') + ', rows in db: ' + state.current.data.points + ' visible(x) = ' + state.timeIsVisible(x) + ' visible(t) = ' + state.timeIsVisible(t) + ' r(x) = ' + state.calculateRowForTime(x) + ' r(t) = ' + state.calculateRowForTime(t) + ' range: ' + state.current.after_ms + ' - ' + state.current.before_ms + ' real: ' + state.current.data.after + ' - ' + state.current.data.before + ' every: ' + state.current.view_update_every);
2172
+ // console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t === x)?'SAME':'DIFFERENT') + ', rows in db: ' + state.current.data.points + ' visible(x) = ' + state.timeIsVisible(x) + ' visible(t) = ' + state.timeIsVisible(t) + ' r(x) = ' + state.calculateRowForTime(x) + ' r(t) = ' + state.calculateRowForTime(t) + ' range: ' + state.current.after_ms + ' - ' + state.current.before_ms + ' real: ' + state.current.data.after + ' - ' + state.current.data.before + ' every: ' + state.current.view_update_every);
2173
2174
state.globalSelectionSync(t);
2175
@@ -2073,11 +2190,11 @@
2190
if(NETDATA.options.debug.dygraph) state.log('dygraphMouseDown()');
2191
2192
// Right-click should not initiate a zoom.
2076
- if(event.button && event.button == 2) return;
2193
+ if(event.button && event.button === 2) return;
2194
2195
context.initializeMouseDown(event, dygraph, context);
2196
2080
- if(event.button && event.button == 1) {
2197
+ if(event.button && event.button === 1) {
2198
if (event.altKey || event.shiftKey) {
2199
state.setMode('pan');
2200
state.globalSelectionSyncDelay();
@@ -2142,10 +2259,10 @@
2259
mousewheel: function(event, dygraph, context) {
2260
if(NETDATA.options.debug.dygraph || state.debug) state.log('interactionModel.mousewheel()');
2261
2145
- state.globalSelectionSyncStop();
2146
- state.globalSelectionSyncDelay();
2147
-
2262
if(event.altKey || event.shiftKey) {
2263
+ state.globalSelectionSyncStop();
2264
+ state.globalSelectionSyncDelay();
2265
+
2266
// http://dygraphs.com/gallery/interaction-api.js
2267
var normal = (event.detail) ? event.detail * -1 : event.wheelDelta / 40;
2268
var percentage = normal / 25;
@@ -2202,7 +2319,7 @@
2319
state.dygraph_options.rightGap = 0;
2320
state.dygraph_options.strokeWidth = 1.0;
2321
}
2205
- else if(NETDATA.dygraph.smooth && state.chart.chart_type == 'line') {
2322
+ else if(NETDATA.dygraph.smooth && state.chart.chart_type === 'line') {
2323
// smooth lines patch
2324
state.dygraph_options.plotter = smoothPlotter;
2325
state.dygraph_options.strokeWidth = 1.5;
@@ -2218,7 +2335,7 @@
2335
// morris
2336
2337
NETDATA.morrisInitialize = function(callback) {
2221
- if(typeof netdataNoMorris == 'undefined' || !netdataNoMorris) {
2338
+ if(typeof netdataNoMorris === 'undefined' || !netdataNoMorris) {
2339
2340
// morris requires raphael
2341
if(!NETDATA.chartLibraries.raphael.initialized) {
@@ -2229,7 +2346,7 @@
2346
}
2347
else {
2348
NETDATA.chartLibraries.morris.enabled = false;
2232
- if(typeof callback == "function")
2349
+ if(typeof callback === "function")
2350
callback();
2351
}
2352
}
@@ -2248,14 +2365,14 @@
2365
NETDATA.error(100, NETDATA.morris_js);
2366
})
2367
.always(function() {
2251
- if(typeof callback == "function")
2368
+ if(typeof callback === "function")
2369
callback();
2370
})
2371
}
2372
}
2373
else {
2374
NETDATA.chartLibraries.morris.enabled = false;
2258
- if(typeof callback == "function")
2375
+ if(typeof callback === "function")
2376
callback();
2377
}
2378
};
@@ -2281,10 +2398,10 @@
2398
behaveLikeLine: false
2399
};
2400
2284
- if(state.chart.chart_type == 'line')
2401
+ if(state.chart.chart_type === 'line')
2402
state.morris_instance = new Morris.Line(state.morris_options);
2403
2287
- else if(state.chart.chart_type == 'area') {
2404
+ else if(state.chart.chart_type === 'area') {
2405
state.morris_options.behaveLikeLine = true;
2406
state.morris_instance = new Morris.Area(state.morris_options);
2407
}
@@ -2296,7 +2413,7 @@
2413
// raphael
2414
2415
NETDATA.raphaelInitialize = function(callback) {
2299
- if(typeof netdataStopRaphael == 'undefined') {
2416
+ if(typeof netdataStopRaphael === 'undefined') {
2417
$.ajax({
2418
url: NETDATA.raphael_js,
2419
cache: true,
@@ -2309,13 +2426,13 @@
2426
NETDATA.error(100, NETDATA.raphael_js);
2427
})
2428
.always(function() {
2312
- if(typeof callback == "function")
2429
+ if(typeof callback === "function")
2430
callback();
2431
})
2432
}
2433
else {
2434
NETDATA.chartLibraries.raphael.enabled = false;
2318
- if(typeof callback == "function")
2435
+ if(typeof callback === "function")
2436
callback();
2437
}
2438
};
@@ -2338,7 +2455,7 @@
2455
// google charts
2456
2457
NETDATA.googleInitialize = function(callback) {
2341
- if(typeof netdataNoGoogleCharts == 'undefined' || !netdataNoGoogleCharts) {
2458
+ if(typeof netdataNoGoogleCharts === 'undefined' || !netdataNoGoogleCharts) {
2459
$.ajax({
2460
url: NETDATA.google_js,
2461
cache: true,
@@ -2354,13 +2471,13 @@
2471
})
2472
.fail(function() {
2473
NETDATA.error(100, NETDATA.google_js);
2357
- if(typeof callback == "function")
2474
+ if(typeof callback === "function")
2475
callback();
2476
})
2477
}
2478
else {
2479
NETDATA.chartLibraries.google.enabled = false;
2363
- if(typeof callback == "function")
2480
+ if(typeof callback === "function")
2481
callback();
2482
}
2483
};
@@ -2458,6 +2575,63 @@
2575
state.google_instance.draw(datatable, state.google_options);
2576
};
2577
2578
+ // ----------------------------------------------------------------------------------------------------------------
2579
+ // easy-pie-chart
2580
+
2581
+ NETDATA.easypiechartInitialize = function(callback) {
2582
+ if(typeof netdataStopEasypiechart === 'undefined') {
2583
+ $.ajax({
2584
+ url: NETDATA.easypiechart_js,
2585
+ cache: true,
2586
+ dataType: "script"
2587
+ })
2588
+ .done(function() {
2589
+ NETDATA.registerChartLibrary('easypiechart', NETDATA.easypiechart_js);
2590
+ })
2591
+ .fail(function() {
2592
+ NETDATA.error(100, NETDATA.easypiechart_js);
2593
+ })
2594
+ .always(function() {
2595
+ if(typeof callback === "function")
2596
+ callback();
2597
+ })
2598
+ }
2599
+ else {
2600
+ NETDATA.chartLibraries.easypiechart.enabled = false;
2601
+ if(typeof callback === "function")
2602
+ callback();
2603
+ }
2604
+ };
2605
+
2606
+ NETDATA.easypiechartChartUpdate = function(state, data) {
2607
+
2608
+ state.easypiechart_instance.update();
2609
+ };
2610
+
2611
+ NETDATA.easypiechartChartCreate = function(state, data) {
2612
+ var self = $(state.element);
2613
+
2614
+ var value = 10;
2615
+ var pcent = 10;
2616
+
2617
+ $(state.element_chart).data('data-percent', pcent);
2618
+ data.element_chart.innerHTML = value.toString();
2619
+
2620
+ state.easypiechart_instance = new EasyPieChart(state.element_chart, {
2621
+ barColor: self.data('easypiechart-barcolor') || '#ef1e25',
2622
+ trackColor: self.data('easypiechart-trackcolor') || '#f2f2f2',
2623
+ scaleColor: self.data('easypiechart-scalecolor') || '#dfe0e0',
2624
+ scaleLength: self.data('easypiechart-scalelength') || 5,
2625
+ lineCap: self.data('easypiechart-linecap') || 'round',
2626
+ lineWidth: self.data('easypiechart-linewidth') || 3,
2627
+ trackWidth: self.data('easypiechart-trackwidth') || undefined,
2628
+ size: self.data('easypiechart-size') || Math.min(state.chartWidth(), state.chartHeight()),
2629
+ rotate: self.data('easypiechart-rotate') || 0,
2630
+ animate: self.data('easypiechart-rotate') || {duration: 0, enabled: false},
2631
+ easing: self.data('easypiechart-easing') || undefined
2632
+ })
2633
+ };
2634
+
2635
// ----------------------------------------------------------------------------------------------------------------
2636
// Charts Libraries Registration
2637
@@ -2488,9 +2662,9 @@
2662
},
2663
2664
isSparkline: function(state) {
2491
- if(typeof state.dygraph_sparkline == 'undefined') {
2665
+ if(typeof state.dygraph_sparkline === 'undefined') {
2666
var t = $(state.element).data('dygraph-theme');
2493
- if(t == 'sparkline')
2667
+ if(t === 'sparkline')
2668
state.dygraph_sparkline = true;
2669
else
2670
state.dygraph_sparkline = false;
@@ -2572,6 +2746,21 @@
2746
autoresize: function(state) { return false; },
2747
max_updates_to_recreate: function(state) { return 5000; },
2748
pixels_per_point: function(state) { return 3; }
2749
+ },
2750
+ "easypiechart": {
2751
+ initialize: NETDATA.easypiechartInitialize,
2752
+ create: NETDATA.easypiechartChartCreate,
2753
+ update: NETDATA.easypiechartChartUpdate,
2754
+ setSelection: null,
2755
+ clearSelection: null,
2756
+ initialized: false,
2757
+ enabled: true,
2758
+ format: function(state) { return 'json'; },
2759
+ options: function(state) { return ''; },
2760
+ legend: function(state) { return null; },
2761
+ autoresize: function(state) { return false; },
2762
+ max_updates_to_recreate: function(state) { return 5000; },
2763
+ pixels_per_point: function(state) { return 3; }
2764
}
2765
};
2766
@@ -2587,19 +2776,38 @@
2776
// ----------------------------------------------------------------------------------------------------------------
2777
// Start up
2778
2590
- NETDATA.errorReset();
2591
- NETDATA._loadjQuery(function() {
2779
+ NETDATA.requiredJs = [
2780
+ NETDATA.serverDefault + 'lib/visible.js',
2781
+ NETDATA.serverDefault + 'lib/jquery.nanoscroller.min.js'
2782
+ ];
2783
+
2784
+ NETDATA.loadRequiredJs = function(index, callback) {
2785
+ if(index >= NETDATA.requiredJs.length) {
2786
+ if(typeof callback === 'function')
2787
+ callback();
2788
+ return;
2789
+ }
2790
+
2791
$.ajax({
2593
- url: NETDATA.serverDefault + 'lib/visible.js',
2792
+ url: NETDATA.requiredJs[index],
2793
cache: true,
2794
dataType: "script"
2795
})
2597
- .then(function() {
2598
- NETDATA._loadCSS(NETDATA.dashboard_css);
2796
+ .success(function() {
2797
+ NETDATA.loadRequiredJs(++index, callback);
2798
+ })
2799
+ .fail(function() {
2800
+ alert('Cannot load required JS library: ' + NETDATA.requiredJs[index]);
2801
+ })
2802
+ }
2803
2600
- if(typeof netdataDontStart == 'undefined' || !netdataDontStart)
2804
+ NETDATA.errorReset();
2805
+ NETDATA._loadjQuery(function() {
2806
+ NETDATA.loadRequiredJs(0, function() {
2807
+ NETDATA._loadCSS(NETDATA.dashboard_css);
2808
+ if(typeof netdataDontStart === 'undefined' || !netdataDontStart)
2809
NETDATA.start();
2602
- })
2810
+ });
2811
});
2812
2813
})(window);
web/lib/jquery.easypiechart.min.js
new
+9
@@ -0,0 +1,9 @@
1
+/**!
2
+ * easy-pie-chart
3
+ * Lightweight plugin to render simple, animated and retina optimized pie charts
4
+ *
5
+ * @license
6
+ * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
7
+ * @version 2.1.7
8
+ **/
9
+!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-0.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=0>=c?!0:!1;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;d="function"==typeof b.barColor?b.barColor(a):b.barColor,h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,1>b?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};a.fn.easyPieChart=function(b){return this.each(function(){var d;a.data(this,"easyPieChart")||(d=a.extend({},b,a(this).data()),a.data(this,"easyPieChart",new c(this,d)))})}});
\ No newline at end of file
web/lib/jquery.nanoscroller.min.js
new
+4
@@ -0,0 +1,4 @@
1
+/*! nanoScrollerJS - v0.8.7 - (c) 2015 James Florentino; Licensed MIT */
2
+
3
+!function(a){return"function"==typeof define&&define.amd?define(["jquery"],function(b){return a(b,window,document)}):"object"==typeof exports?module.exports=a(require("jquery"),window,document):a(jQuery,window,document)}(function(a,b,c){"use strict";var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H;z={paneClass:"nano-pane",sliderClass:"nano-slider",contentClass:"nano-content",enabledClass:"has-scrollbar",flashedClass:"flashed",activeClass:"active",iOSNativeScrolling:!1,preventPageScrolling:!1,disableResize:!1,alwaysVisible:!1,flashDelay:1500,sliderMinHeight:20,sliderMaxHeight:null,documentContext:null,windowContext:null},u="scrollbar",t="scroll",l="mousedown",m="mouseenter",n="mousemove",p="mousewheel",o="mouseup",s="resize",h="drag",i="enter",w="up",r="panedown",f="DOMMouseScroll",g="down",x="wheel",j="keydown",k="keyup",v="touchmove",d="Microsoft Internet Explorer"===b.navigator.appName&&/msie 7./i.test(b.navigator.appVersion)&&b.ActiveXObject,e=null,D=b.requestAnimationFrame,y=b.cancelAnimationFrame,F=c.createElement("div").style,H=function(){var a,b,c,d,e,f;for(d=["t","webkitT","MozT","msT","OT"],a=e=0,f=d.length;f>e;a=++e)if(c=d[a],b=d[a]+"ransform",b in F)return d[a].substr(0,d[a].length-1);return!1}(),G=function(a){return H===!1?!1:""===H?a:H+a.charAt(0).toUpperCase()+a.substr(1)},E=G("transform"),B=E!==!1,A=function(){var a,b,d;return a=c.createElement("div"),b=a.style,b.position="absolute",b.width="100px",b.height="100px",b.overflow=t,b.top="-9999px",c.body.appendChild(a),d=a.offsetWidth-a.clientWidth,c.body.removeChild(a),d},C=function(){var a,c,d;return c=b.navigator.userAgent,(a=/(?=.+Mac OS X)(?=.+Firefox)/.test(c))?(d=/Firefox\/\d{2}\./.exec(c),d&&(d=d[0].replace(/\D+/g,"")),a&&+d>23):!1},q=function(){function j(d,f){this.el=d,this.options=f,e||(e=A()),this.$el=a(this.el),this.doc=a(this.options.documentContext||c),this.win=a(this.options.windowContext||b),this.body=this.doc.find("body"),this.$content=this.$el.children("."+this.options.contentClass),this.$content.attr("tabindex",this.options.tabIndex||0),this.content=this.$content[0],this.previousPosition=0,this.options.iOSNativeScrolling&&null!=this.el.style.WebkitOverflowScrolling?this.nativeScrolling():this.generate(),this.createEvents(),this.addEvents(),this.reset()}return j.prototype.preventScrolling=function(a,b){if(this.isActive)if(a.type===f)(b===g&&a.originalEvent.detail>0||b===w&&a.originalEvent.detail<0)&&a.preventDefault();else if(a.type===p){if(!a.originalEvent||!a.originalEvent.wheelDelta)return;(b===g&&a.originalEvent.wheelDelta<0||b===w&&a.originalEvent.wheelDelta>0)&&a.preventDefault()}},j.prototype.nativeScrolling=function(){this.$content.css({WebkitOverflowScrolling:"touch"}),this.iOSNativeScrolling=!0,this.isActive=!0},j.prototype.updateScrollValues=function(){var a,b;a=this.content,this.maxScrollTop=a.scrollHeight-a.clientHeight,this.prevScrollTop=this.contentScrollTop||0,this.contentScrollTop=a.scrollTop,b=this.contentScrollTop>this.previousPosition?"down":this.contentScrollTop<this.previousPosition?"up":"same",this.previousPosition=this.contentScrollTop,"same"!==b&&this.$el.trigger("update",{position:this.contentScrollTop,maximum:this.maxScrollTop,direction:b}),this.iOSNativeScrolling||(this.maxSliderTop=this.paneHeight-this.sliderHeight,this.sliderTop=0===this.maxScrollTop?0:this.contentScrollTop*this.maxSliderTop/this.maxScrollTop)},j.prototype.setOnScrollStyles=function(){var a;B?(a={},a[E]="translate(0, "+this.sliderTop+"px)"):a={top:this.sliderTop},D?(y&&this.scrollRAF&&y(this.scrollRAF),this.scrollRAF=D(function(b){return function(){return b.scrollRAF=null,b.slider.css(a)}}(this))):this.slider.css(a)},j.prototype.createEvents=function(){this.events={down:function(a){return function(b){return a.isBeingDragged=!0,a.offsetY=b.pageY-a.slider.offset().top,a.slider.is(b.target)||(a.offsetY=0),a.pane.addClass(a.options.activeClass),a.doc.bind(n,a.events[h]).bind(o,a.events[w]),a.body.bind(m,a.events[i]),!1}}(this),drag:function(a){return function(b){return a.sliderY=b.pageY-a.$el.offset().top-a.paneTop-(a.offsetY||.5*a.sliderHeight),a.scroll(),a.contentScrollTop>=a.maxScrollTop&&a.prevScrollTop!==a.maxScrollTop?a.$el.trigger("scrollend"):0===a.contentScrollTop&&0!==a.prevScrollTop&&a.$el.trigger("scrolltop"),!1}}(this),up:function(a){return function(b){return a.isBeingDragged=!1,a.pane.removeClass(a.options.activeClass),a.doc.unbind(n,a.events[h]).unbind(o,a.events[w]),a.body.unbind(m,a.events[i]),!1}}(this),resize:function(a){return function(b){a.reset()}}(this),panedown:function(a){return function(b){return a.sliderY=(b.offsetY||b.originalEvent.layerY)-.5*a.sliderHeight,a.scroll(),a.events.down(b),!1}}(this),scroll:function(a){return function(b){a.updateScrollValues(),a.isBeingDragged||(a.iOSNativeScrolling||(a.sliderY=a.sliderTop,a.setOnScrollStyles()),null!=b&&(a.contentScrollTop>=a.maxScrollTop?(a.options.preventPageScrolling&&a.preventScrolling(b,g),a.prevScrollTop!==a.maxScrollTop&&a.$el.trigger("scrollend")):0===a.contentScrollTop&&(a.options.preventPageScrolling&&a.preventScrolling(b,w),0!==a.prevScrollTop&&a.$el.trigger("scrolltop"))))}}(this),wheel:function(a){return function(b){var c;if(null!=b)return c=b.delta||b.wheelDelta||b.originalEvent&&b.originalEvent.wheelDelta||-b.detail||b.originalEvent&&-b.originalEvent.detail,c&&(a.sliderY+=-c/3),a.scroll(),!1}}(this),enter:function(a){return function(b){var c;if(a.isBeingDragged)return 1!==(b.buttons||b.which)?(c=a.events)[w].apply(c,arguments):void 0}}(this)}},j.prototype.addEvents=function(){var a;this.removeEvents(),a=this.events,this.options.disableResize||this.win.bind(s,a[s]),this.iOSNativeScrolling||(this.slider.bind(l,a[g]),this.pane.bind(l,a[r]).bind(""+p+" "+f,a[x])),this.$content.bind(""+t+" "+p+" "+f+" "+v,a[t])},j.prototype.removeEvents=function(){var a;a=this.events,this.win.unbind(s,a[s]),this.iOSNativeScrolling||(this.slider.unbind(),this.pane.unbind()),this.$content.unbind(""+t+" "+p+" "+f+" "+v,a[t])},j.prototype.generate=function(){var a,c,d,f,g,h,i;return f=this.options,h=f.paneClass,i=f.sliderClass,a=f.contentClass,(g=this.$el.children("."+h)).length||g.children("."+i).length||this.$el.append('<div class="'+h+'"><div class="'+i+'" /></div>'),this.pane=this.$el.children("."+h),this.slider=this.pane.find("."+i),0===e&&C()?(d=b.getComputedStyle(this.content,null).getPropertyValue("padding-right").replace(/[^0-9.]+/g,""),c={right:-14,paddingRight:+d+14}):e&&(c={right:-e},this.$el.addClass(f.enabledClass)),null!=c&&this.$content.css(c),this},j.prototype.restore=function(){this.stopped=!1,this.iOSNativeScrolling||this.pane.show(),this.addEvents()},j.prototype.reset=function(){var a,b,c,f,g,h,i,j,k,l,m,n;return this.iOSNativeScrolling?void(this.contentHeight=this.content.scrollHeight):(this.$el.find("."+this.options.paneClass).length||this.generate().stop(),this.stopped&&this.restore(),a=this.content,f=a.style,g=f.overflowY,d&&this.$content.css({height:this.$content.height()}),b=a.scrollHeight+e,l=parseInt(this.$el.css("max-height"),10),l>0&&(this.$el.height(""),this.$el.height(a.scrollHeight>l?l:a.scrollHeight)),i=this.pane.outerHeight(!1),k=parseInt(this.pane.css("top"),10),h=parseInt(this.pane.css("bottom"),10),j=i+k+h,n=Math.round(j/b*i),n<this.options.sliderMinHeight?n=this.options.sliderMinHeight:null!=this.options.sliderMaxHeight&&n>this.options.sliderMaxHeight&&(n=this.options.sliderMaxHeight),g===t&&f.overflowX!==t&&(n+=e),this.maxSliderTop=j-n,this.contentHeight=b,this.paneHeight=i,this.paneOuterHeight=j,this.sliderHeight=n,this.paneTop=k,this.slider.height(n),this.events.scroll(),this.pane.show(),this.isActive=!0,a.scrollHeight===a.clientHeight||this.pane.outerHeight(!0)>=a.scrollHeight&&g!==t?(this.pane.hide(),this.isActive=!1):this.el.clientHeight===a.scrollHeight&&g===t?this.slider.hide():this.slider.show(),this.pane.css({opacity:this.options.alwaysVisible?1:"",visibility:this.options.alwaysVisible?"visible":""}),c=this.$content.css("position"),("static"===c||"relative"===c)&&(m=parseInt(this.$content.css("right"),10),m&&this.$content.css({right:"",marginRight:m})),this)},j.prototype.scroll=function(){return this.isActive?(this.sliderY=Math.max(0,this.sliderY),this.sliderY=Math.min(this.maxSliderTop,this.sliderY),this.$content.scrollTop(this.maxScrollTop*this.sliderY/this.maxSliderTop),this.iOSNativeScrolling||(this.updateScrollValues(),this.setOnScrollStyles()),this):void 0},j.prototype.scrollBottom=function(a){return this.isActive?(this.$content.scrollTop(this.contentHeight-this.$content.height()-a).trigger(p),this.stop().restore(),this):void 0},j.prototype.scrollTop=function(a){return this.isActive?(this.$content.scrollTop(+a).trigger(p),this.stop().restore(),this):void 0},j.prototype.scrollTo=function(a){return this.isActive?(this.scrollTop(this.$el.find(a).get(0).offsetTop),this):void 0},j.prototype.stop=function(){return y&&this.scrollRAF&&(y(this.scrollRAF),this.scrollRAF=null),this.stopped=!0,this.removeEvents(),this.iOSNativeScrolling||this.pane.hide(),this},j.prototype.destroy=function(){return this.stopped||this.stop(),!this.iOSNativeScrolling&&this.pane.length&&this.pane.remove(),d&&this.$content.height(""),this.$content.removeAttr("tabindex"),this.$el.hasClass(this.options.enabledClass)&&(this.$el.removeClass(this.options.enabledClass),this.$content.css({right:""})),this},j.prototype.flash=function(){return!this.iOSNativeScrolling&&this.isActive?(this.reset(),this.pane.addClass(this.options.flashedClass),setTimeout(function(a){return function(){a.pane.removeClass(a.options.flashedClass)}}(this),this.options.flashDelay),this):void 0},j}(),a.fn.nanoScroller=function(b){return this.each(function(){var c,d;if((d=this.nanoscroller)||(c=a.extend({},z,b),this.nanoscroller=d=new q(this,c)),b&&"object"==typeof b){if(a.extend(d.options,b),null!=b.scrollBottom)return d.scrollBottom(b.scrollBottom);if(null!=b.scrollTop)return d.scrollTop(b.scrollTop);if(b.scrollTo)return d.scrollTo(b.scrollTo);if("bottom"===b.scroll)return d.scrollBottom(0);if("top"===b.scroll)return d.scrollTop(0);if(b.scroll&&b.scroll instanceof a)return d.scrollTo(b.scroll);if(b.stop)return d.stop();if(b.destroy)return d.destroy();if(b.flash)return d.flash()}return d.reset()})},a.fn.nanoScroller.Constructor=q});
4
+//# sourceMappingURL=jquery.nanoscroller.min.js.map
\ No newline at end of file