phoenix7360
phoenix7360

Reputation: 2907

Primefaces chart + jqplot extender - rounded value in the y-axis

Background

I have a primefaces line chart (date on x, integer >= 0 on y) extended with jqplot options:

function extender() {
        this.cfg.axes = {
            xaxis : {
                renderer : $.jqplot.DateAxisRenderer, 
                rendererOptions : {
                    tickRenderer:$.jqplot.CanvasAxisTickRenderer
                },
                tickOptions : { 
                    fontSize:'10pt',
                    fontFamily:'Tahoma', 
                    angle:-40,                     
                    formatString:'%b-%y'
                },
                tickInterval:'2592000000'
            },
            yaxis : {
                min: 0,
                rendererOptions : {
                    tickRenderer:$.jqplot.CanvasAxisTickRenderer,
                },
                tickOptions: {
                    fontSize:'10pt', 
                    fontFamily:'Tahoma', 
                    angle:0,
                    formatString: '%d'
                }
            },
        };
        this.cfg.axes.xaxis.ticks = this.cfg.categories;
    }

I'm using the jqplot extender to have custom date interval on the x-axis and this is working fine:

Working fine

Problem

When I use the option min: 0 in the y-axis the formatting of numbers goes really funky, especially when there are small values:

Fraction number

Note that the minY attribute in primefaces doesn't work (probably because the extender overwrites it)

To fix that, I use formatString: %d. It works but it creates problem with the number of ticks:

enter image description here

As you see on the screenshot, there are several times the line for the value 1.

Question

How can make sure I don't get several times the same value on the y-axis?

I can't really have a static number of ticks because when the data grows large (let's say around 100), I do want several values on the y-axis (e.g 20, 40, etc...)

Upvotes: 7

Views: 10709

Answers (2)

Mark E. Haase
Mark E. Haase

Reputation: 26891

I was surprised when I first started using JQPlot that it doesn't pick reasonable axis labels out of the box. It's actually easy to fix.

I'm going to assume that you want your y axis to start at zero. If that's not true, you'll need to modify this code a bit.

// This is YOUR data set
var series = [882, 38, 66, 522, 123, 400, 777];

// Instead of letting JQPlot pick the scale on the y-axis, let's figure out our own.
var series_max =  Math.max.apply(null, series);
var digits = max.toString().length;
var scale = Math.pow(10, max_digits - 1);

var max = (Math.ceil(series_max / scale)) * scale;

$.jqplot(
    'foo',
    [series],
    {
        axes: {
            yaxis: {
                min: 0,
                max: max
            }
        }
        // Put your other config stuff here
    }
)

The basic idea here is that we want to round up to some nice, round value near the maximum value in our series. In particular, we round up to the nearest number that has zeroes in all digits except the left-most. So the max 882 will result in a y-axis max of 1000.

Upvotes: 2

phoenix7360
phoenix7360

Reputation: 2907

I managed to solve my issue using ideas from Mehasse's post.

Defining the max value like suggested by Mehasse didn't remove the unwanted tick lines but helped me to find the answer.

By default, primefaces/jqplot wants to have 4 y-axis tick lines. Thus, if the max value is below 4, there will be duplication in the y-axis label when they are rounded up (formatString: '%d').

What I basically want, is the tick interval to be either Max(y) \ 4 when Max(y) > 4, or 1 otherwise:

function actionPlanExtender() {
        var series_max =maxSeries(this.cfg.data);
        var numberOfTicks =4;
        var tickInterval = Math.max(1, Math.ceil(series_max/numberOfTicks));
        this.cfg.axes = {
            xaxis : {
                renderer : $.jqplot.DateAxisRenderer, 
                rendererOptions : {
                    tickRenderer:$.jqplot.CanvasAxisTickRenderer
                },
                tickOptions : { 
                    fontSize:'10pt',
                    fontFamily:'Tahoma', 
                    angle:-40,                     
                    formatString:'%b-%y'
                },
                tickInterval:'2592000000'
            },
            yaxis : {
                min: 0,
                rendererOptions : {
                    tickRenderer:$.jqplot.CanvasAxisTickRenderer,
                },
                tickOptions: {
                    fontSize:'10pt', 
                    fontFamily:'Tahoma', 
                    angle:0,
                    formatString: '%d',
                },
                tickInterval: tickInterval
            },
        };
        this.cfg.axes.xaxis.ticks = this.cfg.categories;
    }

To compute the y-max value, I'm getting the plot value using this.cfg.data which is of the form [series_1,..., series_n] with series_i = [[x_1, y_1],..., [x_m, y_m]]

The maxSeries function looks like:

function maxSeries(datas) {
    var maxY = null;
    var dataLength = datas.length;
    for ( var dataIdx = 0; dataIdx < dataLength; dataIdx++) {
        var data = datas[dataIdx];
        var l = data.length;
        for ( var pointIdx = 0; pointIdx < l; pointIdx++) {
            var point = data[pointIdx];
            var y = point[1];
            if (maxY == null || maxY < y) {
                maxY = y;
            }
        }
    }
    return maxY;
}

Note that in my case I know my case I don't have value below 0. This code should be updated if this is not the case.

Upvotes: 6

Related Questions