4

enter image description here

I have a dimple graph with th ecode

var svg = dimple.newSvg("#chartContainer", 800, 600);

var myChart = new dimple.chart(svg, data);
myChart.setBounds(120, 30, 750, 550);
var x = myChart.addCategoryAxis("x", "time");
x.showGridlines = true;
x.addOrderRule("time");

var y = myChart.addMeasureAxis("y", "height", null);
//.overrideMax=(max);
y.overrideMin = 0;
y.overrideMax = 1000;
y.tickFormat = "d";

var s = myChart.addSeries("row", dimple.plot.line);
s.lineWeight = 1;
s.lineMarkers = true;
s.addOrderRule(function(n){
    console.log('n:', n);
    return n.row;
});


myChart.addLegend(0, 0, 900, 100, "left", s);
myChart.draw();

and the legend order is wonky.

the data is in the form

[
   },
{
    "row": "1",
    "height": -1,
    "time": 607
},
{
    "row": "1",
    "height": -11,
    "time": 709
},
{
    "row": "1",
    "height": -22,
    "time": 809
},
{
    "row": "1",
    "height": -32,
    "time": 910
},
{
    "row": "1",
    "height": -42,
    "time": 1011
},
{
    "row": "1",
    "height": -52,
    "time": 1113...

].

I'd like the row series to be in order in the legend.

Thanks.

Dave Edelhart
  • 1,051
  • 1
  • 9
  • 13

2 Answers2

8

Another, possibly less fragile way of overriding the _getEntries method leverages the original method using function.apply()

// first, store a copy of the original _getEntries method.
legend._getEntries_old = legend._getEntries;

// now override the method
legend._getEntries = function()
{
    // but call the original version,
    // then sort the returned array before returning it.
    return legend._getEntries_old.apply(this, arguments).reverse();
}

Incidentally: Thanks, Dave, for your original answer - it was driving me crazy that the legend in an area chart was reversed from the stacking order of the area shapes.

5

I thought I had put legend ordering in dimple but it turns out I didn't, oops! I'm afraid the only option here is to override the _getEntries method on your legend. The method is supposed to be internal to dimple but it's only used in legend drawing. You can override it like this:

myLegend._getEntries = function () {
    var entries = [];
    if (this.series) {
        this.series.forEach(function (series) {
            var data = series._positionData;
            data.forEach(function (row) {
                var index = -1,
                    j,
                    field = ((series.plot.grouped && !series.x._hasCategories() && !series.y._hasCategories() && row.aggField.length < 2 ? "All" : row.aggField.slice(-1)[0]));
                for (j = 0; j < entries.length; j += 1) {
                    if (entries[j].key === field) {
                        index = j;
                        break;
                    }
                }
                if (index === -1 && series.chart._assignedColors[field]) {
                    entries.push({
                        key: field,
                        fill: series.chart._assignedColors[field].fill,
                        stroke: series.chart._assignedColors[field].stroke,
                        opacity: series.chart._assignedColors[field].opacity,
                        series: series,
                        aggField: row.aggField
                    });
                    index = entries.length - 1;
                }
            });
        }, this);
    }

    // PUT YOUR SORTING LOGIC HERE
    // For example to sort numeric values ascending
    entries.sort(function (a, b) { return parseFloat(a.key) - parseFloat(b.key); });

    return entries;
};

Here's an example before: http://jsbin.com/dezaq/1/edit?js,output

And here's one with the fix above: http://jsbin.com/dezaq/2/edit?js,output

If you want a fix which is simpler to read, but is specific to your instance of the chart, you can hard code the response:

myLegend._getEntries = function () {
    var orderedValues = ["1", "2", "3"];
    var entries = [];
    orderedValues.forEach(function (v) {
        entries.push(
        {
                key: v,
                fill: myChart.getColor(v).fill,
                stroke: myChart.getColor(v).stroke,
                opacity: myChart.getColor(v).opacity,
                series: s,
                aggField: [v]
            }
        );
    }, this);

    return entries;
};

Here is that one in action: http://jsbin.com/dezaq/4/edit?js,output

John Kiernander
  • 4,904
  • 1
  • 15
  • 29
  • Is this still the solution or has dimple been updated to support ordering the legend? – BVernon Feb 25 '21 at 17:24
  • @BVernon: No, dimple has not been updated yet ; the current version is the 2.3.0 from 2016/12/16. But all what you have to do is: 1) Download dimple's full javascript library with comments (i.e. the non-minified version). 2) In the this._getEntries = function () {}, at line 2543, just before the `return entries;`, paste: `entries.sort(function (a, b) { return parseFloat(a.key) - parseFloat(b.key); });`. 3) Save the file, and possibly rename it to dimple.v3.2.1.js. The fix suggested by John simply works. – OuzoPower Mar 24 '21 at 09:49