@cryptotaxi247 / netdata-1 / commits / f20882de4

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 = '&nbsp;';
2005 - elements.title_time.innerHTML = state.chart.name;
2006 - elements.title_units.innerHTML = '&nbsp;';
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