diff --git a/API.md b/API.md index 2215c2f..bcf5d25 100644 --- a/API.md +++ b/API.md @@ -669,6 +669,10 @@ series: { fillColor: null or color/gradient } + lines, bars: { + zero: boolean + } + points: { radius: number symbol: "circle" or function @@ -737,6 +741,13 @@ y axis instead of the x axis; note that the bar end points are still defined in the same way so you'll probably want to swap the coordinates if you've been plotting vertical bars first. +Area and bar charts normally start from zero, regardless of the data's range. +This is because they convey information through size, and starting from a +different value would distort their meaning. In cases where the fill is purely +for decorative purposes, however, "zero" allows you to override this behavior. +It defaults to true for filled lines and bars; setting it to false tells the +series to use the same automatic scaling as an un-filled line. + For lines, "steps" specifies whether two adjacent data points are connected with a straight (possibly diagonal) line or with first a horizontal and then a vertical line. Note that this transforms the @@ -1236,9 +1247,21 @@ hooks in the plugins bundled with Flot. In any case, you might be interested in setting datapoints.format, an array of objects for specifying how a point is normalized and - how it interferes with axis scaling. + how it interferes with axis scaling. It accepts the following options: - The default format array for points is something along the lines of: + ```js + { + x, y: boolean, + number: boolean, + required: boolean, + defaultValue: value, + autoscale: boolean + } + ``` + + "x" and "y" specify whether the value is plotted against the x or y axis, + and is currently used only to calculate axis min-max ranges. The default + format array, for example, looks like this: ```js [ @@ -1247,14 +1270,22 @@ hooks in the plugins bundled with Flot. ] ``` - The first object means that for the first coordinate it should be - taken into account when scaling the x axis, that it must be a - number, and that it is required - so if it is null or cannot be - converted to a number, the whole point will be zeroed out with - nulls. Beyond these you can also specify "defaultValue", a value to - use if the coordinate is null. This is for instance handy for bars - where one can omit the third coordinate (the bottom of the bar) - which then defaults to 0. + This indicates that a point, i.e. [0, 25], consists of two values, with the + first being plotted on the x axis and the second on the y axis. + + If "number" is true, then the value must be numeric, and is set to null if + it cannot be converted to a number. + + "defaultValue" provides a fallback in case the original value is null. This + is for instance handy for bars, where one can omit the third coordinate + (the bottom of the bar), which then defaults to zero. + + If "required" is true, then the value must exist (be non-null) for the + point as a whole to be valid. If no value is provided, then the entire + point is cleared out with nulls, turning it into a gap in the series. + + "autoscale" determines whether the value is considered when calculating an + automatic min-max range for the axes that the value is plotted against. - processDatapoints [phase 3] diff --git a/NEWS.md b/NEWS.md index b4c70ed..92d20c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -101,6 +101,9 @@ The base and overlay canvas are now using the CSS classes "flot-base" and - The selection plugin's getSelection now returns null when the selection has been cleared. (patch by Nick Campbell, pull request #852) + - Added a new option called 'zero' to bars and filled lines series, to control + whether the y-axis minimum is scaled to fit the data or set to zero. + ### Bug fixes ### - Fix problem with null values and pie plugin. (patch by gcruxifix, diff --git a/jquery.flot.categories.js b/jquery.flot.categories.js index 5bc2396..ec314bf 100644 --- a/jquery.flot.categories.js +++ b/jquery.flot.categories.js @@ -74,7 +74,8 @@ as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories. format.push({ y: true, number: true, required: true }); if (s.bars.show || (s.lines.show && s.lines.fill)) { - format.push({ y: true, number: true, required: false, defaultValue: 0 }); + var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero)); + format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale }); if (s.bars.horizontal) { delete format[format.length - 1].y; format[format.length - 1].x = true; diff --git a/jquery.flot.js b/jquery.flot.js index 650a215..1df9898 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -106,6 +106,8 @@ Licensed under the MIT license. fill: false, fillColor: null, steps: false + // Omit 'zero', so we can later default its value to + // match that of the 'fill' option. }, bars: { show: false, @@ -114,7 +116,8 @@ Licensed under the MIT license. fill: true, fillColor: null, align: "left", // "left", "right", or "center" - horizontal: false + horizontal: false, + zero: true }, shadowSize: 3, highlightColor: null @@ -498,6 +501,13 @@ Licensed under the MIT license. s.lines.show = true; } + // If nothing was provided for lines.zero, default it to match + // lines.fill, since areas by default should extend to zero. + + if (s.lines.zero == null) { + s.lines.zero = !!s.lines.fill; + } + // setup axes s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x")); s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y")); @@ -547,7 +557,8 @@ Licensed under the MIT license. format.push({ y: true, number: true, required: true }); if (s.bars.show || (s.lines.show && s.lines.fill)) { - format.push({ y: true, number: true, required: false, defaultValue: 0 }); + var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero)); + format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale }); if (s.bars.horizontal) { delete format[format.length - 1].y; format[format.length - 1].x = true; @@ -661,7 +672,7 @@ Licensed under the MIT license. for (m = 0; m < ps; ++m) { val = points[j + m]; f = format[m]; - if (!f || val == fakeInfinity || val == -fakeInfinity) + if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity) continue; if (f.x) {