rawgit.com/CodeYellowBV/chartist-plugin-legend/master/chartist-plugin-legend.js VS unpkg.com/chartist-plugin-legend@0.6.2/chartist-plugin-legend.js

Created Diff never expires
167 removals
237 lines
133 additions
217 lines
(function (root, factory) {
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
// AMD. Register as an anonymous module.
define(['chartist'], function (chartist) {
define(['chartist'], function (chartist) {
return (root.returnExportsGlobal = factory(chartist));
return (root.returnExportsGlobal = factory(chartist));
});
});
} else if (typeof exports === 'object') {
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// only CommonJS-like enviroments that support module.exports,
// like Node.
// like Node.
module.exports = factory(require('chartist'));
module.exports = factory(require('chartist'));
} else {
} else {
root['Chartist.plugins.legend'] = factory(root.Chartist);
root['Chartist.plugins.legend'] = factory(root.Chartist);
}
}
}(this, function (Chartist) {
}(this, function (Chartist) {
/**
/**
* This Chartist plugin creates a legend to show next to the chart.
* This Chartist plugin creates a legend to show next to the chart.
*
*
*/
*/
'use strict';
'use strict';


var defaultOptions = {
var defaultOptions = {
className: '',
className: '',
classNames: false,
classNames: false,
removeAll: false,
removeAll: false,
legendNames: false,
legendNames: false,
clickable: true,
clickable: true,
onClick: null,
onClick: null,
position: 'top'
position: 'top'
};
};


Chartist.plugins = Chartist.plugins || {};
Chartist.plugins = Chartist.plugins || {};


Chartist.plugins.legend = function (options) {
Chartist.plugins.legend = function (options) {


function compareNumbers(a, b) {
return a - b;
}

// Catch invalid options
// Catch invalid options
if (options && options.position) {
if (options && options.position) {
if (!(options.position === 'top' || options.position === 'bottom' || options.position instanceof HTMLElement)) {
if (!(options.position === 'top' || options.position === 'bottom' || options.position instanceof HTMLElement)) {
throw Error('The position you entered is not a valid position');
throw Error('The position you entered is not a valid position');
}
}
if (options.position instanceof HTMLElement) {
if(options.position instanceof HTMLElement){
// Detatch DOM element from options object, because Chartist.extend
// Detatch DOM element from options object, because Chartist.extend currently chokes on circular references present in HTMLElements
// currently chokes on circular references present in HTMLElements
var cachedDOMPosition = options.position;
var cachedDOMPosition = options.position;
delete options.position;
delete options.position;
}
}
}
}


options = Chartist.extend({}, defaultOptions, options);
options = Chartist.extend({}, defaultOptions, options);


if (cachedDOMPosition) {
if(cachedDOMPosition){
// Reattatch the DOM Element position if it was removed before
// Reattatch the DOM Element position if it was removed before
options.position = cachedDOMPosition
options.position = cachedDOMPosition
}
}


return function legend(chart) {
return function legend(chart) {

var existingLegendElement = chart.container.querySelector('.ct-legend');
function removeLegendElement() {
if (existingLegendElement) {
var legendElement = chart.container.querySelector('.ct-legend');
// Clear legend if already existing.
if (legendElement) {
existingLegendElement.parentNode.removeChild(existingLegendElement);
legendElement.parentNode.removeChild(legendElement);
}
}
}


// Set a unique className for each series so that when a series is removed,
// Set a unique className for each series so that when a series is removed,
// the other series still have the same color.
// the other series still have the same color.
function setSeriesClassNames() {
if (options.clickable) {
chart.data.series = chart.data.series.map(function (series, seriesIndex) {
var newSeries = chart.data.series.map(function (series, seriesIndex) {
if (typeof series !== 'object') {
if (typeof series !== 'object') {
series = {
series = {
value: series
value: series
};
};
}
}

series.className = series.className || chart.options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex);
series.className = series.className || chart.options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex);
return series;
return series;
});
});
chart.data.series = newSeries;
}
}


function createLegendElement() {
var legendElement = document.createElement('ul'),
var legendElement = document.createElement('ul');
isPieChart = chart instanceof Chartist.Pie;
legendElement.className = 'ct-legend';
legendElement.className = 'ct-legend';
if (chart instanceof Chartist.Pie) {
if (chart instanceof Chartist.Pie) {
legendElement.classList.add('ct-legend-inside');
legendElement.classList.add('ct-legend-inside');
}
if (typeof options.className === 'string' && options.className.length > 0) {
legendElement.classList.add(options.className);
}
if (chart.options.width) {
legendElement.style.cssText = 'width: ' + chart.options.width + 'px;margin: 0 auto;';
}
return legendElement;
}
}

if (typeof options.className === 'string' && options.className.length > 0) {
// Get the right array to use for generating the legend.
legendElement.classList.add(options.className);
function getLegendNames(useLabels) {
return options.legendNames || (useLabels ? chart.data.labels : chart.data.series);
}
}


// Initialize the array that associates series with legends.
if (chart.options.width) {
// -1 indicates that there is no legend associated with it.
legendElement.style.cssText = 'width: ' + chart.options.width + 'px;margin: 0 auto;';
function initSeriesMetadata(useLabels) {
var seriesMetadata = new Array(chart.data.series.length);
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
};
}
return seriesMetadata;
}
}


function createNameElement(i, legendText, classNamesViable) {
var removedSeries = [],
var li = document.createElement('li');
originalSeries = chart.data.series.slice(0);
li.classList.add('ct-series-' + i);

// Append specific class to a legend element, if viable classes are given
// Get the right array to use for generating the legend.
if (classNamesViable) {
var legendNames = chart.data.series,
li.classList.add(options.classNames[i]);
useLabels = isPieChart && chart.data.labels && chart.data.labels.length;
}
if (useLabels) {
li.setAttribute('data-legend', i);
var originalLabels = chart.data.labels.slice(0);
li.textContent = legendText;
legendNames = chart.data.labels;
return li;
}
}
legendNames = options.legendNames || legendNames;


// Append the legend element to the DOM
// Check if given class names are viable to append to legends
function appendLegendToDOM(legendElement) {
var classNamesViable = (Array.isArray(options.classNames) && (options.classNames.length === legendNames.length));
if (!(options.position instanceof HTMLElement)) {
switch (options.position) {
case 'top':
chart.container.insertBefore(legendElement, chart.container.childNodes[0]);
break;


case 'bottom':
// Loop through all legends to set each name in a list item.
chart.container.insertBefore(legendElement, null);
legendNames.forEach(function (legend, i) {
break;
var li = document.createElement('li');
}
li.className = 'ct-series-' + i;
} else {
// Append specific class to a legend element, if viable classes are given
// Appends the legend element as the last child of a given HTMLElement
if (classNamesViable) {
options.position.insertBefore(legendElement, null);
li.className += ' ' + options.classNames[i];
}
}
}
li.setAttribute('data-legend', i);
li.textContent = legend.name || legend;
legendElement.appendChild(li);
});


function addClickHandler(legendElement, legends, seriesMetadata, useLabels) {
chart.on('created', function (data) {
legendElement.addEventListener('click', function(e) {
// Append the legend element to the DOM
if(!(options.position instanceof HTMLElement))
{
switch (options.position) {
case 'top':
chart.container.insertBefore(legendElement, chart.container.childNodes[0]);
break;

case 'bottom':
chart.container.insertBefore(legendElement, null);
break;
}
}
else {
// Appends the legend element as the last child of a given HTMLElement
options.position.insertBefore(legendElement, null);
}
Text moved from lines 226-228
});

if (options.clickable) {
legendElement.addEventListener('click', function (e) {
var li = e.target;
var li = e.target;
if (li.parentNode !== legendElement || !li.hasAttribute('data-legend'))
if (li.parentNode !== legendElement || !li.hasAttribute('data-legend'))
return;
return;
e.preventDefault();
e.preventDefault();


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


if (!legend.active) {
if (removedSeriesIndex > -1) {
legend.active = true;
// Add to series again.
removedSeries.splice(removedSeriesIndex, 1);
li.classList.remove('inactive');
li.classList.remove('inactive');
} else {
} else {
legend.active = false;
if (!options.removeAll) {
li.classList.add('inactive');
// Remove from series, only if a minimum of one series is still visible.

if ( chart.data.series.length > 1) {
var activeCount = legends.filter(function(legend) { return legend.active; }).length;
removedSeries.push(seriesIndex);
if (!options.removeAll && activeCount == 0) {
li.classList.add('inactive');
// If we can't disable all series at the same time, let's
}
// reenable all of them:
// Set all series as active.
for (var i = 0; i < legends.length; i++) {
else {
legends[i].active = true;
removedSeries = [];
legendElement.childNodes[i].classList.remove('inactive');
var seriesItems = Array.prototype.slice.call(legendElement.childNodes);
}
seriesItems.forEach(function (item) {
}
item.classList.remove('inactive');
}
});

}
var newSeries = [];
}
var newLabels = [];
else {

// Remove series unaffected if it is the last or not
for (var i = 0; i < seriesMetadata.length; i++) {
removedSeries.push(seriesIndex);
if (seriesMetadata[i].legend != -1 && legends[seriesMetadata[i].legend].active) {
li.classList.add('inactive');
newSeries.push(seriesMetadata[i].data);
}
newLabels.push(seriesMetadata[i].label);
}
}
}


chart.data.series = newSeries;
// 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) {
if (useLabels) {
chart.data.labels = newLabels;
var labelsCopy = originalLabels.slice(0);
}
}


chart.update();
// 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);
}
});


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

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

chart.update();
});
});
}
}


removeLegendElement();

var legendElement = createLegendElement();
var useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length;
var legendNames = getLegendNames(useLabels);
var seriesMetadata = initSeriesMetadata(useLabels);
var legends = [];

// 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 = createNameElement(i, legendText, classNamesViable);
legendElement.appendChild(li);

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

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

chart.on('created', function (data) {
appendLegendToDOM(legendElement);
Text moved to lines 142-144
});

if (options.clickable) {
setSeriesClassNames();
addClickHandler(legendElement, legends, seriesMetadata, useLabels);
}
};
};

};
};


return Chartist.plugins.legend;
return Chartist.plugins.legend;


}));
}));