diff --git a/API.txt b/API.txt index daf2317..ae2c396 100644 --- a/API.txt +++ b/API.txt @@ -141,6 +141,7 @@ Customizing the legend backgroundColor: null or color backgroundOpacity: number between 0 and 1 container: null or jQuery object/DOM element/jQuery expression + sorted: null/false, true, "ascending", "descending" or a comparator } The legend is generated as a table with the data series labels and @@ -167,6 +168,21 @@ specify "container" as a jQuery object/expression to put the legend table into. The "position" and "margin" etc. options will then be ignored. Note that Flot will overwrite the contents of the container. +Legend entries appear in the same order as their series by default. To +sort them alphabetically, you can specify "sorted" as tue, "ascending" +or "descending", where true and "ascending" are equivalent. + +You can also provide your own comparator function that accepts two +objects with "label" and "color" properties, and returns zero if they +are equal, a positive value if the first is greater than the second, +and a negative value if the first is less than the second. + + sorted: function(a, b) { + // sort alphabetically in ascending order + return a.label == b.label ? 0 : ( + a.label > b.label ? 1 : -1 + ) + } Customizing the axes ==================== diff --git a/NEWS.txt b/NEWS.txt index 31d3228..a91d899 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -75,6 +75,9 @@ Changes: - Added to a more helpful error when using a time-mode axis without including the flot.time plugin. (patch by Yael Elmatad) +- Added a legend "sorted" option to control sorting of legend entries + independent of their series order. (patch by Tom Cleaveland) + Bug fixes - Fix problem with null values and pie plugin (patch by gcruxifix, diff --git a/jquery.flot.js b/jquery.flot.js index 3c089dd..8908bf7 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -51,7 +51,8 @@ position: "ne", // position of default legend container within plot margin: 5, // distance from grid edge to default legend container within plot backgroundColor: null, // null means auto-detect - backgroundOpacity: 0.85 // set to 0 to avoid background + backgroundOpacity: 0.85, // set to 0 to avoid background + sorted: null // default to no legend sorting }, xaxis: { show: null, // null = auto-detect, true = always, false = never @@ -2105,21 +2106,50 @@ c.normalize(); return c.toString(); } - + function insertLegend() { + placeholder.find(".legend").remove(); if (!options.legend.show) return; - - var fragments = [], rowStarted = false, + + var fragments = [], entries = [], rowStarted = false, lf = options.legend.labelFormatter, s, label; + + // Build a list of legend entries, with each having a label and a color + for (var i = 0; i < series.length; ++i) { s = series[i]; - label = s.label; - if (!label) - continue; - + if (s.label) { + entries.push({ + label: lf ? lf(s.label, s) : s.label, + color: s.color + }); + } + } + + // Sort the legend using either the default or a custom comparator + + if (options.legend.sorted) { + if ($.isFunction(options.legend.sorted)) { + entries.sort(options.legend.sorted); + } else { + var ascending = options.legend.sorted != "descending"; + entries.sort(function(a, b) { + return a.label == b.label ? 0 : ( + (a.label < b.label) != ascending ? 1 : -1 // Logical XOR + ); + }); + } + } + + // Generate markup for the list of entries, in their final order + + for (var i = 0; i < entries.length; ++i) { + + entry = entries[i]; + if (i % options.legend.noColumns == 0) { if (rowStarted) fragments.push(''); @@ -2127,16 +2157,15 @@ rowStarted = true; } - if (lf) - label = lf(label, s); - fragments.push( - '