Skip to content

Commit

Permalink
Legend grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
guimeira authored and tarekis committed Dec 21, 2017
1 parent 4e86f43 commit cd9a332
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 55 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ new Chartist.Bar('.ct-chart', data, {
| --- | --- | --- | --- |
| `className` | Adds a class to the `ul` element. | `string` | `''` |
| `clickable` | Sets the legends clickable state; setting this value to `false` disables toggling graphs on legend click. | `bool` | `true` |
| `legendNames` | Sets custom legend names. By default the `name` property of the series will be used if none are given. | `mixed` | `false` |
| `legendNames` | Sets custom legend names. By default the `name` property of the series will be used if none are given. Multiple series can be associated with a legend item using this property as well. See examples for more details. | `mixed` | `false` |
| `onClick` | Accepts a function that gets invoked if `clickable` is true. The function has the `chart`, and the click event (`e`), as arguments. | `mixed` | `false` |
| `classNames` | Accepts a array of strings as long as the chart's series, those will be added as classes to the `li` elements. | `mixed` | `false` |
| `removeAll` | Allow all series to be removed at once. | `bool` | `false` |
Expand Down
125 changes: 71 additions & 54 deletions chartist-plugin-legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@
}

return function legend(chart) {
function updateChart() {
var newSeries = [];
var newLabels = [];

for (var i = 0; i < seriesMetadata.length; i++) {
if(seriesMetadata[i].legend != -1 && legends[seriesMetadata[i].legend].active) {
newSeries.push(seriesMetadata[i].data);
newLabels.push(seriesMetadata[i].label);
}
}

chart.data.series = newSeries;
if (useLabels) {
chart.data.labels = newLabels;
}

chart.update();
}

var existingLegendElement = chart.container.querySelector('.ct-legend');
if (existingLegendElement) {
// Clear legend if already existing.
Expand Down Expand Up @@ -93,9 +112,6 @@
legendElement.style.cssText = 'width: ' + chart.options.width + 'px;margin: 0 auto;';
}

var removedSeries = [],
originalSeries = chart.data.series.slice(0);

// Get the right array to use for generating the legend.
var legendNames = chart.data.series,
useLabels = isPieChart && chart.data.labels && chart.data.labels.length;
Expand All @@ -104,21 +120,50 @@
legendNames = chart.data.labels;
}
legendNames = options.legendNames || legendNames;

var legends = [];
var seriesMetadata = new Array(chart.data.series.length);
var activeLegendCount = 0;

// Initialize the array that associates series with legends.
// -1 indicates that there is no legend associated with it.
for (var i = 0; i < chart.data.series.length; i++) {
seriesMetadata[i] = {
data: chart.data.series[i],
label: useLabels ? chart.data.labels[i] : null,
legend: -1
};
}

// Check if given class names are viable to append to legends
var classNamesViable = (Array.isArray(options.classNames) && (options.classNames.length === legendNames.length));

// Loop through all legends to set each name in a list item.
legendNames.forEach(function (legend, i) {
var legendText = legend.name || legend;
var legendSeries = legend.series || [i];

var li = document.createElement('li');
li.className = 'ct-series-' + i;
// Append specific class to a legend element, if viable classes are given
if (classNamesViable) {
li.className += ' ' + options.classNames[i];
}
li.setAttribute('data-legend', i);
li.textContent = legend.name || legend;
li.textContent = legendText;
legendElement.appendChild(li);

legendSeries.forEach(function(seriesIndex) {
seriesMetadata[seriesIndex].legend = i;
});

legends.push({
text: legendText,
series: legendSeries,
active: true
});

activeLegendCount++;
});

chart.on('created', function (data) {
Expand Down Expand Up @@ -148,66 +193,38 @@
return;
e.preventDefault();

var seriesIndex = parseInt(li.getAttribute('data-legend')),
removedSeriesIndex = removedSeries.indexOf(seriesIndex);
var legendIndex = parseInt(li.getAttribute('data-legend'));
var legend = legends[legendIndex];

if (removedSeriesIndex > -1) {
// Add to series again.
removedSeries.splice(removedSeriesIndex, 1);
if (!legends[legendIndex].active) {
legend.active = true;
activeLegendCount++;
li.classList.remove('inactive');
} else {
if (!options.removeAll) {
// Remove from series, only if a minimum of one series is still visible.
if ( chart.data.series.length > 1) {
removedSeries.push(seriesIndex);
li.classList.add('inactive');
}
// Set all series as active.
else {
removedSeries = [];
var seriesItems = Array.prototype.slice.call(legendElement.childNodes);
seriesItems.forEach(function (item) {
item.classList.remove('inactive');
});
}
legend.active = false;
activeLegendCount--;
li.classList.add('inactive');

if (!options.removeAll && activeLegendCount == 0) {
//If we can't disable all series at the same time, let's
//reenable all of them:
for (var i = 0; i < legends.length; i++) {
legends[i].active = true;
activeLegendCount++;
legendElement.childNodes[i].classList.remove('inactive');
}
}
else {
// Remove series unaffected if it is the last or not
removedSeries.push(seriesIndex);
li.classList.add('inactive');
}
}

// Reset the series to original and remove each series that
// is still removed again, to remain index order.
var seriesCopy = originalSeries.slice(0);
if (useLabels) {
var labelsCopy = originalLabels.slice(0);
}

// Reverse sort the removedSeries to prevent removing the wrong index.
removedSeries.sort(compareNumbers).reverse();

removedSeries.forEach(function (series) {
seriesCopy.splice(series, 1);
if (useLabels) {
labelsCopy.splice(series, 1);
}
});


updateChart();

if (options.onClick) {
options.onClick(chart, e);
}

chart.data.series = seriesCopy;
if (useLabels) {
chart.data.labels = labelsCopy;
}

chart.update();
});
}


updateChart();
};

};
Expand Down
55 changes: 55 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@
background-color: #453d3f;
border-color: #453d3f;
}

.ct-chart-line-multipleseries .ct-legend .ct-series-0:before {
background-color: #d70206;
border-color: #d70206;
}

.ct-chart-line-multipleseries .ct-legend .ct-series-1:before {
background-color: #f4c63d;
border-color: #f4c63d;
}

.ct-chart-line-multipleseries .ct-legend li.inactive:before {
background: transparent;
}

.crazyPink li.ct-series-0:before {
background-color: #C2185B;
Expand Down Expand Up @@ -341,6 +355,28 @@ <h3>Chart with <i>legendNames</i>:</h3>
legendNames: ['Custom title', 'Another one', 'And the last one'],
})
]
});</code></pre>
<h3>Chart with multiple series per item:</h3>
<span>The <code>legendNames</code> property can be used to associate multiple series with a legend item.</span>
<div class="ct-chart-line-multipleseries"></div>
<button class="button-showcode">Show Code</button>
<pre class="codeblock-hidden"><code class="javascript">new Chartist.Line('.ct-chart-line-multipleseries', {
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
series: [
[12, 9, 7, 8, 5],
[2, 1, 3.5, 7, 3],
[1, 3, 4, 5, 6]
]
}, {
fullWidth: true,
chartPadding: {
right: 40
},
plugins: [
Chartist.plugins.legend({
legendNames: [{name: 'Red-ish', series: [0,1]}, {name: 'Yellow', series: [2]}],
})
]
});</code></pre>
<h3>Chart with <i>onClick</i>:</h3>
<span>Accepts a function that gets invoked if <code>clickable</code> is true. The function has the <code>chart</code>, and the click event (<code>e</code>), as arguments.</span>
Expand Down Expand Up @@ -564,6 +600,25 @@ <h3>Chart with <i>position</i>:</h3>
})
]
});

new Chartist.Line('.ct-chart-line-multipleseries', {
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
series: [
[12, 9, 7, 8, 5],
[2, 1, 3.5, 7, 3],
[1, 3, 4, 5, 6]
]
}, {
fullWidth: true,
chartPadding: {
right: 40
},
plugins: [
Chartist.plugins.legend({
legendNames: [{name: 'Red-ish', series: [0,1]}, {name: 'Yellow', series: [2]}],
})
]
});

new Chartist.Line('.ct-chart-line-onclick', {
labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
Expand Down

0 comments on commit cd9a332

Please sign in to comment.