Commit 5f0fbbb5 by kigrig

Upload New File

parent 102deae5
Showing with 693 additions and 0 deletions
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(["chartist"], function (Chartist) {
return (root.returnExportsGlobal = factory(Chartist));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require("chartist"));
} else {
root['Chartist.plugins.ctAccessibility'] = factory(Chartist);
}
}(this, function (Chartist) {
/**
* Chartist.js plugin that generates visually hidden tables for better accessibility. It's also possible to initialize a Chart with data from an existing table.
*
*/
/* global Chartist */
(function (window, document, Chartist) {
'use strict';
// A simple recursive DOM string builder
function Element(name, attrs, parent) {
return {
elem: function (name, attrs) {
var e = Element(name, attrs, this);
this.children.push(e);
return e;
},
children: [],
name: name,
_attrs: attrs || {},
_parent: parent,
parent: function () {
return this._parent;
},
attrs: function (attrs) {
this._attrs = attrs;
return this;
},
text: function (text, after) {
if (after) {
this._textAfter = text;
} else {
this._textBefore = text;
}
return this;
},
toString: function () {
var attrs = Object.keys(this._attrs).filter(function (attrName) {
return this._attrs[attrName] || this._attrs[attrName] === 0;
}.bind(this)).map(function (attrName) {
return [attrName, '="', this._attrs[attrName], '"'].join('');
}.bind(this)).join(' ');
return ['<', this.name, attrs ? ' ' + attrs : '', '>', this._textBefore].concat(this.children.map(function (child) {
return child.toString();
})).concat([this._textAfter, '</', this.name, '>']).join('');
}
};
}
var defaultOptions = {
caption: 'A graphical chart',
seriesHeader: 'Series name',
valueTransform: Chartist.noop,
summary: undefined,
class: undefined,
elementId: function () {
return 'ct-accessibility-table-' + (+new Date());
},
visuallyHiddenStyles: 'position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden;'
};
Chartist.plugins = Chartist.plugins || {};
Chartist.plugins.ctAccessibility = function (options) {
options = Chartist.extend({}, defaultOptions, options);
return function ctAccessibility(chart) {
var elementId = typeof options.elementId === 'function' ? options.elementId() : options.elementId;
chart.on('created', function (data) {
var containerElement = data.svg._node.parentNode;
var previousElement = containerElement.querySelector('#' + elementId);
if(previousElement) {
containerElement.removeChild(previousElement);
}
// As we are now compensating the SVG graphic with the chart with an accessibility table, we hide it for ARIA
data.svg.attr({
'aria-hidden': 'true'
});
// Create wrapper element
var element = Element('div', {
style: options.visuallyHiddenStyles,
id: elementId
});
// Create table body with caption
var tBody = element.elem('table', {
summary: options.summary,
class: options.class
}).elem('caption')
.text(options.caption)
.elem('tbody');
var firstRow = tBody.elem('tr');
if (chart instanceof Chartist.Pie) {
// For pie charts we have only column headers and one series
var dataArray = Chartist.getDataArray(chart.data, chart.optionsProvider.getCurrentOptions().reverseData);
// First render the column headers with our pie chart labels
chart.data.labels.forEach(function (text) {
firstRow
.elem('th', {
scope: 'col',
role: 'columnheader'
})
.text(text);
});
var row = tBody.elem('tr');
// Add all data fields of our pie chart to the row
dataArray.forEach(function (dataValue) {
row.elem('td').text(options.valueTransform(dataValue));
});
} else {
// For line and bar charts we have multiple series and therefore also row headers
var normalizedData = Chartist.getDataArray(chart.data, chart.optionsProvider.getCurrentOptions().reverseData);
// Add column headers inclusing the series column header for the row headers
[options.seriesHeader].concat(chart.data.labels).forEach(function (text) {
firstRow
.elem('th', {
scope: 'col',
role: 'columnheader'
})
.text(text);
});
// Add all data rows including their row headers
chart.data.series.forEach(function (series, index) {
var seriesName = series.name || [index + 1, '. Series'].join('');
var row = tBody.elem('tr');
row.elem('th', {
scope: 'row',
role: 'rowheader'
}).text(seriesName);
normalizedData[index].forEach(function (dataValue) {
row.elem('td').text(options.valueTransform(dataValue));
});
});
}
// Update invisible table in DOM and update table element with newly created table
containerElement.appendChild(new DOMParser().parseFromString(element.toString(), 'text/html').getElementById(elementId));
});
};
};
}(window, document, Chartist));
return Chartist.plugins.ctAccessibility;
}));
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(["chartist"], function (Chartist) {
return (root.returnExportsGlobal = factory(Chartist));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require("chartist"));
} else {
root['Chartist.plugins.ctAxisTitle'] = factory(Chartist);
}
}(this, function (Chartist) {
/**
* Chartist.js plugin to display a title for 1 or 2 axes.
* version 0.0.7
* author: alex stanbury
*/
/* global Chartist */
(function(Chartist) {
"use strict";
var axisDefaults = {
axisTitle: "",
axisClass: "ct-axis-title",
offset: {
x: 0,
y: 0
},
textAnchor: "middle",
flipTitle: false
};
var defaultOptions = {
axisX: axisDefaults,
axisY: axisDefaults
};
var getTitle = function(title) {
if (title instanceof Function) {
return title();
}
return title;
};
var getClasses = function(classes) {
if (classes instanceof Function) {
return classes();
}
return classes;
};
Chartist.plugins = Chartist.plugins || {};
Chartist.plugins.ctAxisTitle = function(options) {
options = Chartist.extend({}, defaultOptions, options);
return function ctAxisTitle(chart) {
chart.on("created", function(data) {
if (!options.axisX.axisTitle && !options.axisY.axisTitle) {
throw new Error(
"ctAxisTitle plugin - You must provide at least one axis title"
);
} else if (!data.axisX && !data.axisY) {
throw new Error(
"ctAxisTitle plugin can only be used on charts that have at least one axis"
);
}
var xPos,
yPos,
title,
chartPadding = Chartist.normalizePadding(data.options.chartPadding); // normalize the padding in case the full padding object was not passed into the options
//position axis X title
if (options.axisX.axisTitle && data.axisX) {
xPos =
data.axisX.axisLength / 2 +
data.options.axisY.offset +
chartPadding.left;
yPos = chartPadding.top;
if (data.options.axisY.position === "end") {
xPos -= data.options.axisY.offset;
}
if (data.options.axisX.position === "end") {
yPos += data.axisY.axisLength;
}
title = new Chartist.Svg("text");
title.addClass(getClasses(options.axisX.axisClass));
title.text(getTitle(options.axisX.axisTitle));
title.attr({
x: xPos + options.axisX.offset.x,
y: yPos + options.axisX.offset.y,
"text-anchor": options.axisX.textAnchor
});
data.svg.append(title, true);
}
//position axis Y title
if (options.axisY.axisTitle && data.axisY) {
xPos = 0;
yPos = data.axisY.axisLength / 2 + chartPadding.top;
if (data.options.axisX.position === "start") {
yPos += data.options.axisX.offset;
}
if (data.options.axisY.position === "end") {
xPos = data.axisX.axisLength;
}
var transform =
"rotate(" +
(options.axisY.flipTitle ? -90 : 90) +
", " +
xPos +
", " +
yPos +
")";
title = new Chartist.Svg("text");
title.addClass(getClasses(options.axisY.axisClass));
title.text(getTitle(options.axisY.axisTitle));
title.attr({
x: xPos + options.axisY.offset.x,
y: yPos + options.axisY.offset.y,
transform: transform,
"text-anchor": options.axisY.textAnchor
});
data.svg.append(title, true);
}
});
};
};
})(Chartist);
return Chartist.plugins.ctAxisTitle;
}));
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function () {
return (root.returnExportsGlobal = factory());
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory();
} else {
root['Chartist.plugins.ctThreshold'] = factory();
}
}(this, function () {
/**
* Chartist.js plugin to display a data label on top of the points in a line chart.
*
*/
/* global Chartist */
(function (window, document, Chartist) {
'use strict';
var defaultOptions = {
threshold: 0,
classNames: {
aboveThreshold: 'ct-threshold-above',
belowThreshold: 'ct-threshold-below'
},
maskNames: {
aboveThreshold: 'ct-threshold-mask-above',
belowThreshold: 'ct-threshold-mask-below'
}
};
function createMasks(data, options) {
// Select the defs element within the chart or create a new one
var defs = data.svg.querySelector('defs') || data.svg.elem('defs');
// Project the threshold value on the chart Y axis
var projectedThreshold = data.chartRect.height() - data.axisY.projectValue(options.threshold) + data.chartRect.y2;
var width = data.svg.width();
var height = data.svg.height();
// Create mask for upper part above threshold
defs
.elem('mask', {
x: 0,
y: 0,
width: width,
height: height,
id: options.maskNames.aboveThreshold
})
.elem('rect', {
x: 0,
y: 0,
width: width,
height: projectedThreshold,
fill: 'white'
});
// Create mask for lower part below threshold
defs
.elem('mask', {
x: 0,
y: 0,
width: width,
height: height,
id: options.maskNames.belowThreshold
})
.elem('rect', {
x: 0,
y: projectedThreshold,
width: width,
height: height - projectedThreshold,
fill: 'white'
});
return defs;
}
Chartist.plugins = Chartist.plugins || {};
Chartist.plugins.ctThreshold = function (options) {
options = Chartist.extend({}, defaultOptions, options);
return function ctThreshold(chart) {
if (chart instanceof Chartist.Line || chart instanceof Chartist.Bar) {
chart.on('draw', function (data) {
if (data.type === 'point') {
// For points we can just use the data value and compare against the threshold in order to determine
// the appropriate class
data.element.addClass(
data.value.y >= options.threshold ? options.classNames.aboveThreshold : options.classNames.belowThreshold
);
} else if (data.type === 'line' || data.type === 'bar' || data.type === 'area') {
// Cloning the original line path, mask it with the upper mask rect above the threshold and add the
// class for above threshold
data.element
.parent()
.elem(data.element._node.cloneNode(true))
.attr({
mask: 'url(#' + options.maskNames.aboveThreshold + ')'
})
.addClass(options.classNames.aboveThreshold);
// Use the original line path, mask it with the lower mask rect below the threshold and add the class
// for blow threshold
data.element
.attr({
mask: 'url(#' + options.maskNames.belowThreshold + ')'
})
.addClass(options.classNames.belowThreshold);
}
});
// On the created event, create the two mask definitions used to mask the line graphs
chart.on('created', function (data) {
createMasks(data, options);
});
}
};
}
}(window, document, Chartist));
return Chartist.plugins.ctThreshold;
}));
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['chartist'], function (chartist) {
return (root.returnExportsGlobal = factory(chartist));
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require('chartist'));
} else {
root['Chartist.plugins.legend'] = factory(root.Chartist);
}
}(this, function (Chartist) {
/**
* This Chartist plugin creates a legend to show next to the chart.
*
*/
'use strict';
var defaultOptions = {
className: '',
classNames: false,
removeAll: false,
legendNames: false,
clickable: true,
onClick: null,
position: 'top'
};
Chartist.plugins = Chartist.plugins || {};
Chartist.plugins.legend = function (options) {
// Catch invalid options
if (options && options.position) {
if (!(options.position === 'top' || options.position === 'bottom' || options.position instanceof HTMLElement)) {
throw Error('The position you entered is not a valid position');
}
if (options.position instanceof HTMLElement) {
// Detatch DOM element from options object, because Chartist.extend
// currently chokes on circular references present in HTMLElements
var cachedDOMPosition = options.position;
delete options.position;
}
}
options = Chartist.extend({}, defaultOptions, options);
if (cachedDOMPosition) {
// Reattatch the DOM Element position if it was removed before
options.position = cachedDOMPosition
}
return function legend(chart) {
function removeLegendElement() {
var legendElement = chart.container.querySelector('.ct-legend');
if (legendElement) {
legendElement.parentNode.removeChild(legendElement);
}
}
// Set a unique className for each series so that when a series is removed,
// the other series still have the same color.
function setSeriesClassNames() {
chart.data.series = chart.data.series.map(function (series, seriesIndex) {
if (typeof series !== 'object') {
series = {
value: series
};
}
series.className = series.className || chart.options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex);
return series;
});
}
function createLegendElement() {
var legendElement = document.createElement('ul');
legendElement.className = 'ct-legend';
if (chart instanceof Chartist.Pie) {
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;
}
// Get the right array to use for generating the legend.
function getLegendNames(useLabels) {
return options.legendNames || (useLabels ? chart.data.labels : chart.data.series);
}
// Initialize the array that associates series with legends.
// -1 indicates that there is no legend associated with it.
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 li = document.createElement('li');
li.classList.add('ct-series-' + i);
// Append specific class to a legend element, if viable classes are given
if (classNamesViable) {
li.classList.add(options.classNames[i]);
}
li.setAttribute('data-legend', i);
li.textContent = legendText;
return li;
}
// Append the legend element to the DOM
function appendLegendToDOM(legendElement) {
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);
}
}
function addClickHandler(legendElement, legends, seriesMetadata, useLabels) {
legendElement.addEventListener('click', function(e) {
var li = e.target;
if (li.parentNode !== legendElement || !li.hasAttribute('data-legend'))
return;
e.preventDefault();
var legendIndex = parseInt(li.getAttribute('data-legend'));
var legend = legends[legendIndex];
if (!legend.active) {
legend.active = true;
li.classList.remove('inactive');
} else {
legend.active = false;
li.classList.add('inactive');
var activeCount = legends.filter(function(legend) { return legend.active; }).length;
if (!options.removeAll && activeCount == 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;
legendElement.childNodes[i].classList.remove('inactive');
}
}
}
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();
if (options.onClick) {
options.onClick(chart, e);
}
});
}
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);
});
if (options.clickable) {
setSeriesClassNames();
addClickHandler(legendElement, legends, seriesMetadata, useLabels);
}
};
};
return Chartist.plugins.legend;
}));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment