]> arthur.barton.de Git - netdata.git/blobdiff - web/dashboard.js
Merge branch 'master' into ab-debian
[netdata.git] / web / dashboard.js
index 739f8de3b949da7bc23f516553c4ffbcd24b1bae..b34accdecb0948a45a1769631e1f2d5a02681b8a 100644 (file)
@@ -130,7 +130,7 @@ var NETDATA = window.NETDATA || {};
     NETDATA.peity_js            = NETDATA.serverDefault + 'lib/jquery.peity-3.2.0.min.js';
     NETDATA.sparkline_js        = NETDATA.serverDefault + 'lib/jquery.sparkline-2.1.2.min.js';
     NETDATA.easypiechart_js     = NETDATA.serverDefault + 'lib/jquery.easypiechart-97b5824.min.js';
-    NETDATA.gauge_js            = NETDATA.serverDefault + 'lib/gauge-d5260c3.min.js';
+    NETDATA.gauge_js            = NETDATA.serverDefault + 'lib/gauge-1.3.2.min.js';
     NETDATA.dygraph_js          = NETDATA.serverDefault + 'lib/dygraph-combined-dd74404.js';
     NETDATA.dygraph_smooth_js   = NETDATA.serverDefault + 'lib/dygraph-smooth-plotter-dd74404.js';
     NETDATA.raphael_js          = NETDATA.serverDefault + 'lib/raphael-2.2.4-min.js';
@@ -218,6 +218,29 @@ var NETDATA = window.NETDATA || {};
     if(netdataRegistry === false && typeof netdataRegistryCallback === 'function')
         netdataRegistry = true;
 
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // detect if this is probably a slow device
+
+    var isSlowDeviceResult = undefined;
+    var isSlowDevice = function() {
+        if(isSlowDeviceResult !== undefined)
+            return isSlowDeviceResult;
+
+        try {
+            var ua = navigator.userAgent.toLowerCase();
+
+            var iOS = /ipad|iphone|ipod/.test(ua) && !window.MSStream;
+            var android = /android/.test(ua) && !window.MSStream;
+            isSlowDeviceResult = (iOS === true || android === true);
+        }
+        catch (e) {
+            isSlowDeviceResult = false;
+        }
+
+        return isSlowDeviceResult;
+    };
+
     // ----------------------------------------------------------------------------------------------------------------
     // the defaults for all charts
 
@@ -271,7 +294,7 @@ var NETDATA = window.NETDATA || {};
         // the current profile
         // we may have many...
         current: {
-            pixels_per_point: 1,        // the minimum pixels per point for all charts
+            pixels_per_point: isSlowDevice()?5:1, // the minimum pixels per point for all charts
                                         // increase this to speed javascript up
                                         // each chart library has its own limit too
                                         // the max of this and the chart library is used
@@ -313,11 +336,11 @@ var NETDATA = window.NETDATA || {};
 
             update_only_visible: true,  // enable or disable visibility management
 
-            parallel_refresher: true,   // enable parallel refresh of charts
+            parallel_refresher: (isSlowDevice() === false), // enable parallel refresh of charts
 
             concurrent_refreshes: true, // when parallel_refresher is enabled, sync also the charts
 
-            destroy_on_hide: false,     // destroy charts when they are not visible
+            destroy_on_hide: (isSlowDevice() === true), // destroy charts when they are not visible
 
             show_help: netdataShowHelp, // when enabled the charts will show some help
             show_help_delay_show_ms: 500,
@@ -330,7 +353,7 @@ var NETDATA = window.NETDATA || {};
 
             double_click_speed: 500,    // ms - time between clicks / taps to detect double click/tap
 
-            smooth_plot: true,          // enable smooth plot, where possible
+            smooth_plot: (isSlowDevice() === false), // enable smooth plot, where possible
 
             charts_selection_animation_delay: 50, // delay to animate charts when syncing selection
 
@@ -1340,9 +1363,7 @@ var NETDATA = window.NETDATA || {};
         this.value_decimal_detail = -1;
         var d = self.data('decimal-digits');
         if(typeof d === 'number') {
-            this.value_decimal_detail = 1;
-            while(d-- > 0)
-                this.value_decimal_detail *= 10;
+            this.value_decimal_detail = d;
         }
 
         this.auto = {
@@ -2224,19 +2245,69 @@ var NETDATA = window.NETDATA || {};
             return ret;
         };
 
+        var __legendFormatValueChartDecimalsLastMin = undefined;
+        var __legendFormatValueChartDecimalsLastMax = undefined;
+        var __legendFormatValueChartDecimals = -1;
+        this.legendFormatValueDecimalsFromMinMax = function(min, max) {
+            if(min === __legendFormatValueChartDecimalsLastMin && max === __legendFormatValueChartDecimalsLastMax)
+                return;
+
+            __legendFormatValueChartDecimalsLastMin = min;
+            __legendFormatValueChartDecimalsLastMax = max;
+
+            if(this.data !== null && this.data.min === this.data.max)
+                __legendFormatValueChartDecimals = -1;
+
+            else if(this.value_decimal_detail !== -1)
+                __legendFormatValueChartDecimals = this.value_decimal_detail;
+
+            else {
+                var delta;
+
+                if (min === max)
+                    delta = Math.abs(min);
+                else
+                    delta = Math.abs(max - min);
+
+                if (delta > 1000)     __legendFormatValueChartDecimals = 0;
+                else if (delta > 10)  __legendFormatValueChartDecimals = 1;
+                else if (delta > 1)   __legendFormatValueChartDecimals = 2;
+                else if (delta > 0.1) __legendFormatValueChartDecimals = 2;
+                else                  __legendFormatValueChartDecimals = 4;
+            }
+        };
+
         this.legendFormatValue = function(value) {
-            if(value === null || value === 'undefined') return '-';
-            if(typeof value !== 'number') return value;
-
-            if(this.value_decimal_detail !== -1)
-                return (Math.round(value * this.value_decimal_detail) / this.value_decimal_detail).toLocaleString();
-
-            var abs = Math.abs(value);
-            if(abs >= 1000) return (Math.round(value)).toLocaleString();
-            if(abs >= 100 ) return (Math.round(value * 10) / 10).toLocaleString();
-            if(abs >= 1   ) return (Math.round(value * 100) / 100).toLocaleString();
-            if(abs >= 0.1 ) return (Math.round(value * 1000) / 1000).toLocaleString();
-            return (Math.round(value * 10000) / 10000).toLocaleString();
+            if(typeof value !== 'number') return '-';
+
+            var dmin, dmax;
+
+            if(__legendFormatValueChartDecimals < 0) {
+                dmin = 0;
+                var abs = value;
+                if(abs > 1000)      dmax = 0;
+                else if(abs > 10 )  dmax = 1;
+                else if(abs > 1)    dmax = 2;
+                else if(abs > 0.1)  dmax = 2;
+                else                dmax = 4;
+            }
+            else {
+                dmin = dmax = __legendFormatValueChartDecimals;
+            }
+
+            if(this.value_decimal_detail !== -1) {
+                dmin = dmax = this.value_decimal_detail;
+            }
+
+            return value.toLocaleString(undefined, {
+                // style: 'decimal',
+                // minimumIntegerDigits: 1,
+                // minimumSignificantDigits: 1,
+                // maximumSignificantDigits: 1,
+                useGrouping: true,
+                minimumFractionDigits: dmin,
+                maximumFractionDigits: dmax
+            });
         };
 
         this.legendSetLabelValue = function(label, value) {
@@ -2306,32 +2377,43 @@ var NETDATA = window.NETDATA || {};
             }
         };
 
+        this.legendSetDateLast = {
+            ms: 0,
+            date: undefined,
+            time: undefined
+        };
+
         this.legendSetDate = function(ms) {
             if(typeof ms !== 'number') {
                 this.legendShowUndefined();
                 return;
             }
 
-            var d = new Date(ms);
+            if(this.legendSetDateLast.ms !== ms) {
+                var d = new Date(ms);
+                this.legendSetDateLast.ms = ms;
+                this.legendSetDateLast.date = d.toLocaleDateString();
+                this.legendSetDateLast.time = d.toLocaleTimeString();
+            }
 
-            if(this.element_legend_childs.title_date)
-                this.__legendSetDateString(d.toLocaleDateString());
+            if(this.element_legend_childs.title_date !== null)
+                this.__legendSetDateString(this.legendSetDateLast.date);
 
-            if(this.element_legend_childs.title_time)
-                this.__legendSetTimeString(d.toLocaleTimeString());
+            if(this.element_legend_childs.title_time !== null)
+                this.__legendSetTimeString(this.legendSetDateLast.time);
 
-            if(this.element_legend_childs.title_units)
+            if(this.element_legend_childs.title_units !== null)
                 this.__legendSetUnitsString(this.units)
         };
 
         this.legendShowUndefined = function() {
-            if(this.element_legend_childs.title_date)
+            if(this.element_legend_childs.title_date !== null)
                 this.__legendSetDateString(' ');
 
-            if(this.element_legend_childs.title_time)
+            if(this.element_legend_childs.title_time !== null)
                 this.__legendSetTimeString(this.chart.name);
 
-            if(this.element_legend_childs.title_units)
+            if(this.element_legend_childs.title_units !== null)
                 this.__legendSetUnitsString(' ');
 
             if(this.data && this.element_legend_childs.series !== null) {
@@ -2340,8 +2422,7 @@ var NETDATA = window.NETDATA || {};
                 while(i--) {
                     var label = labels[i];
 
-                    if(typeof label === 'undefined') continue;
-                    if(typeof this.element_legend_childs.series[label] === 'undefined') continue;
+                    if(typeof label === 'undefined' || typeof this.element_legend_childs.series[label] === 'undefined') continue;
                     this.legendSetLabelValue(label, null);
                 }
             }
@@ -2753,16 +2834,19 @@ var NETDATA = window.NETDATA || {};
 
                 this.element_legend_childs.title_date.className += " netdata-legend-title-date";
                 this.element_legend.appendChild(this.element_legend_childs.title_date);
+                this.__last_shown_legend_date = undefined;
 
                 this.element_legend.appendChild(document.createElement('br'));
 
                 this.element_legend_childs.title_time.className += " netdata-legend-title-time";
                 this.element_legend.appendChild(this.element_legend_childs.title_time);
+                this.__last_shown_legend_time = undefined;
 
                 this.element_legend.appendChild(document.createElement('br'));
 
                 this.element_legend_childs.title_units.className += " netdata-legend-title-units";
                 this.element_legend.appendChild(this.element_legend_childs.title_units);
+                this.__last_shown_legend_units = undefined;
 
                 this.element_legend.appendChild(document.createElement('br'));
 
@@ -3055,7 +3139,8 @@ var NETDATA = window.NETDATA || {};
                 if(this.debug === true)
                     this.log('max updates of ' + this.updates_since_last_creation.toString() + ' reached. Forcing re-generation.');
 
-                this.chart_created = false;
+                init();
+                return;
             }
 
             // check and update the legend
@@ -4186,101 +4271,185 @@ var NETDATA = window.NETDATA || {};
 
         var self = $(state.element);
 
-        var chart_type = state.chart.chart_type;
+        var chart_type = self.data('dygraph-type') || state.chart.chart_type;
         if(chart_type === 'stacked' && data.dimensions === 1) chart_type = 'area';
-        chart_type = self.data('dygraph-type') || chart_type;
 
-        var smooth = (chart_type === 'line' && NETDATA.chartLibraries.dygraph.isSparkline(state) === false);
-        smooth = self.data('dygraph-smooth') || smooth;
+        var highlightCircleSize = (NETDATA.chartLibraries.dygraph.isSparkline(state) === true)?3:4;
 
-        if(NETDATA.dygraph.smooth === false)
-            smooth = false;
-
-        var strokeWidth = (chart_type === 'stacked')?0.1:((smooth)?1.5:0.7);
-        var highlightCircleSize = (NETDATA.chartLibraries.dygraph.isSparkline(state))?3:4;
+        var smooth = (NETDATA.dygraph.smooth === true)
+            ?(self.data('dygraph-smooth') || (chart_type === 'line' && NETDATA.chartLibraries.dygraph.isSparkline(state) === false))
+            :false;
 
         state.dygraph_options = {
-            colors: self.data('dygraph-colors') || state.chartColors(),
+            colors:                 self.data('dygraph-colors') || state.chartColors(),
 
             // leave a few pixels empty on the right of the chart
-            rightGap: self.data('dygraph-rightgap') || 5,
-            showRangeSelector: self.data('dygraph-showrangeselector') || false,
-            showRoller: self.data('dygraph-showroller') || false,
-
-            title: self.data('dygraph-title') || state.title,
-            titleHeight: self.data('dygraph-titleheight') || 19,
-
-            legend: self.data('dygraph-legend') || 'always', // we need this to get selection events
-            labels: data.result.labels,
-            labelsDiv: self.data('dygraph-labelsdiv') || state.element_legend_childs.hidden,
-            labelsDivStyles: self.data('dygraph-labelsdivstyles') || { 'fontSize':'1px' },
-            labelsDivWidth: self.data('dygraph-labelsdivwidth') || state.chartWidth() - 70,
-            labelsSeparateLines: self.data('dygraph-labelsseparatelines') || true,
-            labelsShowZeroValues: self.data('dygraph-labelsshowzerovalues') || true,
-            labelsKMB: false,
-            labelsKMG2: false,
-            showLabelsOnHighlight: self.data('dygraph-showlabelsonhighlight') || true,
-            hideOverlayOnMouseOut: self.data('dygraph-hideoverlayonmouseout') || true,
-
-            includeZero: self.data('dygraph-includezero') || (chart_type === 'stacked'),
-            xRangePad: self.data('dygraph-xrangepad') || 0,
-            yRangePad: self.data('dygraph-yrangepad') || 1,
-
-            valueRange: self.data('dygraph-valuerange') || [ null, null ],
-
-            ylabel: state.units,
-            yLabelWidth: self.data('dygraph-ylabelwidth') || 12,
-
-            // the function to plot the chart
-            plotter: null,
-
-            // The width of the lines connecting data points. This can be used to increase the contrast or some graphs.
-            strokeWidth: self.data('dygraph-strokewidth') || strokeWidth,
-            strokePattern: self.data('dygraph-strokepattern') || undefined,
-
-            // The size of the dot to draw on each point in pixels (see drawPoints). A dot is always drawn when a point is "isolated",
-            // i.e. there is a missing point on either side of it. This also controls the size of those dots.
-            drawPoints: self.data('dygraph-drawpoints') || false,
-
-            // Draw points at the edges of gaps in the data. This improves visibility of small data segments or other data irregularities.
-            drawGapEdgePoints: self.data('dygraph-drawgapedgepoints') || true,
-
-            connectSeparatedPoints: self.data('dygraph-connectseparatedpoints') || false,
-            pointSize: self.data('dygraph-pointsize') || 1,
-
-            // enabling this makes the chart with little square lines
-            stepPlot: self.data('dygraph-stepplot') || false,
-
-            // Draw a border around graph lines to make crossing lines more easily distinguishable. Useful for graphs with many lines.
-            strokeBorderColor: self.data('dygraph-strokebordercolor') || NETDATA.themes.current.background,
-            strokeBorderWidth: self.data('dygraph-strokeborderwidth') || (chart_type === 'stacked')?0.0:0.0,
-
-            fillGraph: self.data('dygraph-fillgraph') || (chart_type === 'area' || chart_type === 'stacked'),
-            fillAlpha: self.data('dygraph-fillalpha') || ((chart_type === 'stacked')?NETDATA.options.current.color_fill_opacity_stacked:NETDATA.options.current.color_fill_opacity_area),
-            stackedGraph: self.data('dygraph-stackedgraph') || (chart_type === 'stacked'),
-            stackedGraphNaNFill: self.data('dygraph-stackedgraphnanfill') || 'none',
-
-            drawAxis: self.data('dygraph-drawaxis') || true,
-            axisLabelFontSize: self.data('dygraph-axislabelfontsize') || 10,
-            axisLineColor: self.data('dygraph-axislinecolor') || NETDATA.themes.current.axis,
-            axisLineWidth: self.data('dygraph-axislinewidth') || 1.0,
-
-            drawGrid: self.data('dygraph-drawgrid') || true,
-            gridLinePattern: self.data('dygraph-gridlinepattern') || null,
-            gridLineWidth: self.data('dygraph-gridlinewidth') || 1.0,
-            gridLineColor: self.data('dygraph-gridlinecolor') || NETDATA.themes.current.grid,
-
-            maxNumberWidth: self.data('dygraph-maxnumberwidth') || 8,
-            sigFigs: self.data('dygraph-sigfigs') || null,
-            digitsAfterDecimal: self.data('dygraph-digitsafterdecimal') || 2,
-            valueFormatter: self.data('dygraph-valueformatter') || function(x){ return x.toFixed(2); },
-
-            highlightCircleSize: self.data('dygraph-highlightcirclesize') || highlightCircleSize,
-            highlightSeriesOpts: self.data('dygraph-highlightseriesopts') || null, // TOO SLOW: { strokeWidth: 1.5 },
-            highlightSeriesBackgroundAlpha: self.data('dygraph-highlightseriesbackgroundalpha') || null, // TOO SLOW: (chart_type === 'stacked')?0.7:0.5,
-
-            pointClickCallback: self.data('dygraph-pointclickcallback') || undefined,
-            visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names),
+            rightGap:               self.data('dygraph-rightgap')
+                                    || 5,
+
+            showRangeSelector:      self.data('dygraph-showrangeselector')
+                                    || false,
+
+            showRoller:             self.data('dygraph-showroller')
+                                    || false,
+
+            title:                  self.data('dygraph-title')
+                                    || state.title,
+
+            titleHeight:            self.data('dygraph-titleheight')
+                                    || 19,
+
+            legend:                 self.data('dygraph-legend')
+                                    || 'always', // we need this to get selection events
+
+            labels:                 data.result.labels,
+
+            labelsDiv:              self.data('dygraph-labelsdiv')
+                                    || state.element_legend_childs.hidden,
+
+            labelsDivStyles:        self.data('dygraph-labelsdivstyles')
+                                    || { 'fontSize':'1px' },
+
+            labelsDivWidth:         self.data('dygraph-labelsdivwidth')
+                                    || state.chartWidth() - 70,
+
+            labelsSeparateLines:    self.data('dygraph-labelsseparatelines')
+                                    || true,
+
+            labelsShowZeroValues:   self.data('dygraph-labelsshowzerovalues')
+                                    || true,
+
+            labelsKMB:              false,
+            labelsKMG2:             false,
+
+            showLabelsOnHighlight:  self.data('dygraph-showlabelsonhighlight')
+                                    || true,
+
+            hideOverlayOnMouseOut:  self.data('dygraph-hideoverlayonmouseout')
+                                    || true,
+
+            includeZero:            self.data('dygraph-includezero')
+                                    || (chart_type === 'stacked'),
+
+            xRangePad:              self.data('dygraph-xrangepad')
+                                    || 0,
+
+            yRangePad:              self.data('dygraph-yrangepad')
+                                    || 1,
+
+            valueRange:             self.data('dygraph-valuerange')
+                                    || [ null, null ],
+
+            ylabel:                 state.units,
+
+            yLabelWidth:            self.data('dygraph-ylabelwidth')
+                                    || 12,
+
+                                    // the function to plot the chart
+            plotter:                null,
+
+                                    // The width of the lines connecting data points.
+                                    // This can be used to increase the contrast or some graphs.
+            strokeWidth:            self.data('dygraph-strokewidth')
+                                    || ((chart_type === 'stacked')?0.1:((smooth === true)?1.5:0.7)),
+
+            strokePattern:          self.data('dygraph-strokepattern')
+                                    || undefined,
+
+                                    // The size of the dot to draw on each point in pixels (see drawPoints).
+                                    // A dot is always drawn when a point is "isolated",
+                                    // i.e. there is a missing point on either side of it.
+                                    // This also controls the size of those dots.
+            drawPoints:             self.data('dygraph-drawpoints')
+                                    || false,
+
+                                    // Draw points at the edges of gaps in the data.
+                                    // This improves visibility of small data segments or other data irregularities.
+            drawGapEdgePoints:      self.data('dygraph-drawgapedgepoints')
+                                    || true,
+
+            connectSeparatedPoints: self.data('dygraph-connectseparatedpoints')
+                                    || false,
+
+            pointSize:              self.data('dygraph-pointsize')
+                                    || 1,
+
+                                    // enabling this makes the chart with little square lines
+            stepPlot:               self.data('dygraph-stepplot')
+                                    || false,
+
+                                    // Draw a border around graph lines to make crossing lines more easily
+                                    // distinguishable. Useful for graphs with many lines.
+            strokeBorderColor:      self.data('dygraph-strokebordercolor')
+                                    || NETDATA.themes.current.background,
+
+            strokeBorderWidth:      self.data('dygraph-strokeborderwidth')
+                                    || (chart_type === 'stacked')?0.0:0.0,
+
+            fillGraph:              self.data('dygraph-fillgraph')
+                                    || (chart_type === 'area' || chart_type === 'stacked'),
+
+            fillAlpha:              self.data('dygraph-fillalpha')
+                                    || ((chart_type === 'stacked')
+                                        ?NETDATA.options.current.color_fill_opacity_stacked
+                                        :NETDATA.options.current.color_fill_opacity_area),
+
+            stackedGraph:           self.data('dygraph-stackedgraph')
+                                    || (chart_type === 'stacked'),
+
+            stackedGraphNaNFill:    self.data('dygraph-stackedgraphnanfill')
+                                    || 'none',
+
+            drawAxis:               self.data('dygraph-drawaxis')
+                                    || true,
+
+            axisLabelFontSize:      self.data('dygraph-axislabelfontsize')
+                                    || 10,
+
+            axisLineColor:          self.data('dygraph-axislinecolor')
+                                    || NETDATA.themes.current.axis,
+
+            axisLineWidth:          self.data('dygraph-axislinewidth')
+                                    || 1.0,
+
+            drawGrid:               self.data('dygraph-drawgrid')
+                                    || true,
+
+            gridLinePattern:        self.data('dygraph-gridlinepattern')
+                                    || null,
+
+            gridLineWidth:          self.data('dygraph-gridlinewidth')
+                                    || 1.0,
+
+            gridLineColor:          self.data('dygraph-gridlinecolor')
+                                    || NETDATA.themes.current.grid,
+
+            maxNumberWidth:         self.data('dygraph-maxnumberwidth')
+                                    || 8,
+
+            sigFigs:                self.data('dygraph-sigfigs')
+                                    || null,
+
+            digitsAfterDecimal:     self.data('dygraph-digitsafterdecimal')
+                                    || 2,
+
+            valueFormatter:         self.data('dygraph-valueformatter')
+                                    || undefined,
+
+            highlightCircleSize:    self.data('dygraph-highlightcirclesize')
+                                    || highlightCircleSize,
+
+            highlightSeriesOpts:    self.data('dygraph-highlightseriesopts')
+                                    || null, // TOO SLOW: { strokeWidth: 1.5 },
+
+            highlightSeriesBackgroundAlpha: self.data('dygraph-highlightseriesbackgroundalpha')
+                                    || null, // TOO SLOW: (chart_type === 'stacked')?0.7:0.5,
+
+            pointClickCallback:     self.data('dygraph-pointclickcallback')
+                                    || undefined,
+
+            visibility:             state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names),
+
             axes: {
                 x: {
                     pixelsPerLabel: 50,
@@ -4288,25 +4457,19 @@ var NETDATA = window.NETDATA || {};
                     axisLabelFormatter: function (d, gran) {
                         void(gran);
                         return NETDATA.zeropad(d.getHours()) + ":" + NETDATA.zeropad(d.getMinutes()) + ":" + NETDATA.zeropad(d.getSeconds());
-                    },
-                    valueFormatter: function (ms) {
-                        void(ms);
-                        //var d = new Date(ms);
-                        //return d.toLocaleDateString() + ' ' + d.toLocaleTimeString();
-
-                        // no need to return anything here
-                        return ' ';
-
                     }
                 },
                 y: {
                     pixelsPerLabel: 15,
-                    valueFormatter: function (x) {
-                        // we format legends with the state object
-                        // no need to do anything here
-                        // return (Math.round(x*100) / 100).toLocaleString();
-                        // return state.legendFormatValue(x);
-                        return x;
+                    axisLabelFormatter: function (y) {
+
+                        // unfortunately, we have to call this every single time
+                        state.legendFormatValueDecimalsFromMinMax(
+                            this.axes_[0].extremeRange[0],
+                            this.axes_[0].extremeRange[1]
+                        );
+
+                        return state.legendFormatValue(y);
                     }
                 }
             },
@@ -5433,9 +5596,10 @@ var NETDATA = window.NETDATA || {};
         // is always between min and max
         var pcent = (value - min) * 100 / (max - min);
 
-        // these should never happen
-        if(pcent < 0) pcent = 0;
-        if(pcent > 100) pcent = 100;
+        // bug fix for gauge.js 1.3.1
+        // if the value is the absolute min or max, the chart is broken
+        if(pcent < 0.001) pcent = 0.001;
+        if(pcent > 99.999) pcent = 99.999;
 
         state.gauge_instance.set(pcent);
         // console.log('gauge set ' + pcent + ', value ' + value + ', min ' + min + ', max ' + max);
@@ -5596,19 +5760,22 @@ var NETDATA = window.NETDATA || {};
 
         var options = {
             lines: 12,                  // The number of lines to draw
-            angle: 0.15,                // The length of each line
-            lineWidth: 0.44,            // 0.44 The line thickness
+            angle: 0.15,                // The span of the gauge arc
+            lineWidth: 0.50,            // The line thickness
+            radiusScale: 0.85,          // Relative radius
             pointer: {
                 length: 0.8,            // 0.9 The radius of the inner circle
                 strokeWidth: 0.035,     // The rotation offset
                 color: pointerColor     // Fill color
             },
+            limitMax: true,             // If false, the max value of the gauge will be updated if value surpass max
+            limitMin: true,             // If true, the min value of the gauge will be fixed unless you set it manually
             colorStart: startColor,     // Colors
             colorStop: stopColor,       // just experiment with them
             strokeColor: strokeColor,   // to see which ones work best for you
-            limitMax: true,
             generateGradient: (generateGradient === true),
-            gradientType: 0
+            gradientType: 0,
+            highDpiSupport: true        // High resolution support
         };
 
         if (generateGradient.constructor === Array) {
@@ -5622,7 +5789,7 @@ var NETDATA = window.NETDATA || {};
             var len = generateGradient.length;
             while(len--) {
                 var pcent = generateGradient[len];
-                var color = self.data('gauge-gradient-percent-color-' + pcent.toString()) || false;
+                var color = self.attr('data-gauge-gradient-percent-color-' + pcent.toString()) || false;
                 if(color !== false) {
                     var a = [];
                     a[0] = pcent / 100;
@@ -6067,7 +6234,7 @@ var NETDATA = window.NETDATA || {};
             if(NETDATA.alarms.current !== null) {
                 // get the current value_string
                 var t = NETDATA.alarms.current.alarms[entry.chart + '.' + entry.name];
-                if(typeof t !== 'undefined' && entry.status === t.status)
+                if(typeof t !== 'undefined' && entry.status === t.status && typeof t.value_string !== 'undefined')
                     value_string = t.value_string;
             }