(function (root, factory){
if(typeof define==='function'&&define.amd){
define([], function (){
return (root.returnExportsGlobal=factory());
});
}else if(typeof exports==='object'){
module.exports=factory();
}else{
root['Chartist']=factory();
}}(this, function (){
var Chartist={
version: '0.5.0'
};
(function (window, document, Chartist){
'use strict';
Chartist.noop=function (n){
return n;
};
Chartist.alphaNumerate=function (n){
return String.fromCharCode(97 + n % 26);
};
Chartist.extend=function (target){
target=target||{};
var sources=Array.prototype.slice.call(arguments, 1);
sources.forEach(function(source){
for (var prop in source){
if(typeof source[prop]==='object'&&!(source[prop] instanceof Array)){
target[prop]=Chartist.extend(target[prop], source[prop]);
}else{
target[prop]=source[prop];
}}
});
return target;
};
Chartist.stripUnit=function(value){
if(typeof value==='string'){
value=value.replace(/[^0-9\+-\.]/g, '');
}
return +value;
};
Chartist.ensureUnit=function(value, unit){
if(typeof value==='number'){
value=value + unit;
}
return value;
};
Chartist.querySelector=function(query){
return query instanceof Node ? query:document.querySelector(query);
};
Chartist.times=function(length){
return Array.apply(null, new Array(length));
};
Chartist.sum=function(previous, current){
return previous + current;
};
Chartist.serialMap=function(arr, cb){
var result=[],
length=Math.max.apply(null, arr.map(function(e){
return e.length;
}));
Chartist.times(length).forEach(function(e, index){
var args=arr.map(function(e){
return e[index];
});
result[index]=cb.apply(null, args);
});
return result;
};
Chartist.createSvg=function (container, width, height, className){
var svg;
width=width||'100%';
height=height||'100%';
svg=container.querySelector('svg');
if(svg){
container.removeChild(svg);
}
svg=new Chartist.Svg('svg').attr({
width: width,
height: height
}).addClass(className).attr({
style: 'width: ' + width + '; height: ' + height + ';'
});
container.appendChild(svg._node);
return svg;
};
Chartist.getDataArray=function (data){
var array=[];
for (var i=0; i < data.series.length; i++){
array[i]=typeof(data.series[i])==='object'&&data.series[i].data!==undefined ?
data.series[i].data:data.series[i];
for (var j=0; j < array[i].length; j++){
array[i][j]=+array[i][j];
}}
return array;
};
Chartist.normalizeDataArray=function (dataArray, length){
for (var i=0; i < dataArray.length; i++){
if(dataArray[i].length===length){
continue;
}
for (var j=dataArray[i].length; j < length; j++){
dataArray[i][j]=0;
}}
return dataArray;
};
Chartist.orderOfMagnitude=function (value){
return Math.floor(Math.log(Math.abs(value)) / Math.LN10);
};
Chartist.projectLength=function (svg, length, bounds, options){
var availableHeight=Chartist.getAvailableHeight(svg, options);
return (length / bounds.range * availableHeight);
};
Chartist.getAvailableHeight=function (svg, options){
return Math.max((Chartist.stripUnit(options.height)||svg.height()) - (options.chartPadding * 2) - options.axisX.offset, 0);
};
Chartist.getHighLow=function (dataArray){
var i,
j,
highLow={
high: -Number.MAX_VALUE,
low: Number.MAX_VALUE
};
for (i=0; i < dataArray.length; i++){
for (j=0; j < dataArray[i].length; j++){
if(dataArray[i][j] > highLow.high){
highLow.high=dataArray[i][j];
}
if(dataArray[i][j] < highLow.low){
highLow.low=dataArray[i][j];
}}
}
return highLow;
};
Chartist.getBounds=function (svg, highLow, options, referenceValue){
var i,
newMin,
newMax,
bounds={
high: highLow.high,
low: highLow.low
};
bounds.high=+options.high||(options.high===0 ? 0:bounds.high);
bounds.low=+options.low||(options.low===0 ? 0:bounds.low);
if(bounds.high===bounds.low){
if(bounds.low===0){
bounds.high=1;
}else if(bounds.low < 0){
bounds.high=0;
}else{
bounds.low=0;
}}
if(referenceValue||referenceValue===0){
bounds.high=Math.max(referenceValue, bounds.high);
bounds.low=Math.min(referenceValue, bounds.low);
}
bounds.valueRange=bounds.high - bounds.low;
bounds.oom=Chartist.orderOfMagnitude(bounds.valueRange);
bounds.min=Math.floor(bounds.low / Math.pow(10, bounds.oom)) * Math.pow(10, bounds.oom);
bounds.max=Math.ceil(bounds.high / Math.pow(10, bounds.oom)) * Math.pow(10, bounds.oom);
bounds.range=bounds.max - bounds.min;
bounds.step=Math.pow(10, bounds.oom);
bounds.numberOfSteps=Math.round(bounds.range / bounds.step);
var length=Chartist.projectLength(svg, bounds.step, bounds, options),
scaleUp=length < options.axisY.scaleMinSpace;
while (true){
if(scaleUp&&Chartist.projectLength(svg, bounds.step, bounds, options) <=options.axisY.scaleMinSpace){
bounds.step *=2;
}else if(!scaleUp&&Chartist.projectLength(svg, bounds.step / 2, bounds, options) >=options.axisY.scaleMinSpace){
bounds.step /=2;
}else{
break;
}}
newMin=bounds.min;
newMax=bounds.max;
for (i=bounds.min; i <=bounds.max; i +=bounds.step){
if(i + bounds.step < bounds.low){
newMin +=bounds.step;
}
if(i - bounds.step >=bounds.high){
newMax -=bounds.step;
}}
bounds.min=newMin;
bounds.max=newMax;
bounds.range=bounds.max - bounds.min;
bounds.values=[];
for (i=bounds.min; i <=bounds.max; i +=bounds.step){
bounds.values.push(i);
}
return bounds;
};
Chartist.polarToCartesian=function (centerX, centerY, radius, angleInDegrees){
var angleInRadians=(angleInDegrees - 90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};};
Chartist.createChartRect=function (svg, options){
var yOffset=options.axisY ? options.axisY.offset:0,
xOffset=options.axisX ? options.axisX.offset:0;
return {
x1: options.chartPadding + yOffset,
y1: Math.max((Chartist.stripUnit(options.height)||svg.height()) - options.chartPadding - xOffset, options.chartPadding),
x2: Math.max((Chartist.stripUnit(options.width)||svg.width()) - options.chartPadding, options.chartPadding + yOffset),
y2: options.chartPadding,
width: function (){
return this.x2 - this.x1;
},
height: function (){
return this.y1 - this.y2;
}};};
Chartist.createLabel=function(parent, text, attributes, className, supportsForeignObject){
if(supportsForeignObject){
var content='<span class="' + className + '">' + text + '</span>';
return parent.foreignObject(content, attributes);
}else{
return parent.elem('text', attributes, className).text(text);
}};
Chartist.createXAxis=function (chartRect, data, grid, labels, options, eventEmitter, supportsForeignObject){
data.labels.forEach(function (value, index){
var interpolatedValue=options.axisX.labelInterpolationFnc(value, index),
width=chartRect.width() / (data.labels.length - (options.fullWidth ? 1:0)),
height=options.axisX.offset,
pos=chartRect.x1 + width * index;
if(!interpolatedValue&&interpolatedValue!==0){
return;
}
if(options.axisX.showGrid){
var gridElement=grid.elem('line', {
x1: pos,
y1: chartRect.y1,
x2: pos,
y2: chartRect.y2
}, [options.classNames.grid, options.classNames.horizontal].join(' '));
eventEmitter.emit('draw', {
type: 'grid',
axis: 'x',
index: index,
group: grid,
element: gridElement,
x1: pos,
y1: chartRect.y1,
x2: pos,
y2: chartRect.y2
});
}
if(options.axisX.showLabel){
var labelPosition={
x: pos + options.axisX.labelOffset.x,
y: chartRect.y1 + options.axisX.labelOffset.y + (supportsForeignObject ? 5:20)
};
var labelElement=Chartist.createLabel(labels, '' + interpolatedValue, {
x: labelPosition.x,
y: labelPosition.y,
width: width,
height: height,
style: 'overflow: visible;'
}, [options.classNames.label, options.classNames.horizontal].join(' '), supportsForeignObject);
eventEmitter.emit('draw', {
type: 'label',
axis: 'x',
index: index,
group: labels,
element: labelElement,
text: '' + interpolatedValue,
x: labelPosition.x,
y: labelPosition.y,
width: width,
height: height,
get space(){
window.console.warn('EventEmitter: space is deprecated, use width or height instead.');
return this.width;
}});
}});
};
Chartist.createYAxis=function (chartRect, bounds, grid, labels, options, eventEmitter, supportsForeignObject){
bounds.values.forEach(function (value, index){
var interpolatedValue=options.axisY.labelInterpolationFnc(value, index),
width=options.axisY.offset,
height=chartRect.height() / bounds.values.length,
pos=chartRect.y1 - height * index;
if(!interpolatedValue&&interpolatedValue!==0){
return;
}
if(options.axisY.showGrid){
var gridElement=grid.elem('line', {
x1: chartRect.x1,
y1: pos,
x2: chartRect.x2,
y2: pos
}, [options.classNames.grid, options.classNames.vertical].join(' '));
eventEmitter.emit('draw', {
type: 'grid',
axis: 'y',
index: index,
group: grid,
element: gridElement,
x1: chartRect.x1,
y1: pos,
x2: chartRect.x2,
y2: pos
});
}
if(options.axisY.showLabel){
var labelPosition={
x: options.chartPadding + options.axisY.labelOffset.x + (supportsForeignObject ? -10:0),
y: pos + options.axisY.labelOffset.y + (supportsForeignObject ? -15:0)
};
var labelElement=Chartist.createLabel(labels, '' + interpolatedValue, {
x: labelPosition.x,
y: labelPosition.y,
width: width,
height: height,
style: 'overflow: visible;'
}, [options.classNames.label, options.classNames.vertical].join(' '), supportsForeignObject);
eventEmitter.emit('draw', {
type: 'label',
axis: 'y',
index: index,
group: labels,
element: labelElement,
text: '' + interpolatedValue,
x: labelPosition.x,
y: labelPosition.y,
width: width,
height: height,
get space(){
window.console.warn('EventEmitter: space is deprecated, use width or height instead.');
return this.height;
}});
}});
};
Chartist.projectPoint=function (chartRect, bounds, data, index, options){
return {
x: chartRect.x1 + chartRect.width() / (data.length - (data.length > 1&&options.fullWidth ? 1:0)) * index,
y: chartRect.y1 - chartRect.height() * (data[index] - bounds.min) / (bounds.range + bounds.step)
};};
Chartist.optionsProvider=function (options, responsiveOptions, eventEmitter){
var baseOptions=Chartist.extend({}, options),
currentOptions,
mediaQueryListeners=[],
i;
function updateCurrentOptions(){
var previousOptions=currentOptions;
currentOptions=Chartist.extend({}, baseOptions);
if(responsiveOptions){
for (i=0; i < responsiveOptions.length; i++){
var mql=window.matchMedia(responsiveOptions[i][0]);
if(mql.matches){
currentOptions=Chartist.extend(currentOptions, responsiveOptions[i][1]);
}}
}
if(eventEmitter){
eventEmitter.emit('optionsChanged', {
previousOptions: previousOptions,
currentOptions: currentOptions
});
}}
function removeMediaQueryListeners(){
mediaQueryListeners.forEach(function(mql){
mql.removeListener(updateCurrentOptions);
});
}
if(!window.matchMedia){
throw 'window.matchMedia not found! Make sure you\'re using a polyfill.';
}else if(responsiveOptions){
for (i=0; i < responsiveOptions.length; i++){
var mql=window.matchMedia(responsiveOptions[i][0]);
mql.addListener(updateCurrentOptions);
mediaQueryListeners.push(mql);
}}
updateCurrentOptions();
return {
get currentOptions(){
return Chartist.extend({}, currentOptions);
},
removeMediaQueryListeners: removeMediaQueryListeners
};};
Chartist.catmullRom2bezier=function (crp, z){
var d=[];
for (var i=0, iLen=crp.length; iLen - 2 * !z > i; i +=2){
var p=[
{x: +crp[i - 2], y: +crp[i - 1]},
{x: +crp[i], y: +crp[i + 1]},
{x: +crp[i + 2], y: +crp[i + 3]},
{x: +crp[i + 4], y: +crp[i + 5]}
];
if(z){
if(!i){
p[0]={x: +crp[iLen - 2], y: +crp[iLen - 1]};}else if(iLen - 4===i){
p[3]={x: +crp[0], y: +crp[1]};}else if(iLen - 2===i){
p[2]={x: +crp[0], y: +crp[1]};
p[3]={x: +crp[2], y: +crp[3]};}}else{
if(iLen - 4===i){
p[3]=p[2];
}else if(!i){
p[0]={x: +crp[i], y: +crp[i + 1]};}}
d.push([
(-p[0].x + 6 * p[1].x + p[2].x) / 6,
(-p[0].y + 6 * p[1].y + p[2].y) / 6,
(p[1].x + 6 * p[2].x - p[3].x) / 6,
(p[1].y + 6 * p[2].y - p[3].y) / 6,
p[2].x,
p[2].y
]
);
}
return d;
};}(window, document, Chartist));
;
(function (window, document, Chartist){
'use strict';
Chartist.EventEmitter=function (){
var handlers=[];
function addEventHandler(event, handler){
handlers[event]=handlers[event]||[];
handlers[event].push(handler);
}
function removeEventHandler(event, handler){
if(handlers[event]){
if(handler){
handlers[event].splice(handlers[event].indexOf(handler), 1);
if(handlers[event].length===0){
delete handlers[event];
}}else{
delete handlers[event];
}}
}
function emit(event, data){
if(handlers[event]){
handlers[event].forEach(function(handler){
handler(data);
});
}
if(handlers['*']){
handlers['*'].forEach(function(starHandler){
starHandler(event, data);
});
}}
return {
addEventHandler: addEventHandler,
removeEventHandler: removeEventHandler,
emit: emit
};};
}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
function listToArray(list){
var arr=[];
if(list.length){
for (var i=0; i < list.length; i++){
arr.push(list[i]);
}}
return arr;
}
/**
* Method to extend from current prototype.
*
* @memberof Chartist.Class
* @param {Object} properties The object that serves as definition for the prototype that gets created for the new class. This object should always contain a constructor property that is the desired constructor for the newly created class.
* @param {Object} [superProtoOverride] By default extens will use the current class prototype or Chartist.class. With this parameter you can specify any super prototype that will be used.
* @returns {Function} Constructor function of the new class
*
* @example
* var Fruit=Class.extend({
* color: undefined,
*   sugar: undefined,
*
*   constructor: function(color, sugar){
*     this.color=color;
*     this.sugar=sugar;
*   },
*
*   eat: function(){
*     this.sugar=0;
*     return this;
*   }
* });
*
* var Banana=Fruit.extend({
*   length: undefined,
*
*   constructor: function(length, sugar){
*     Banana.super.constructor.call(this, 'Yellow', sugar);
*     this.length=length;
*   }
* });
*
* var banana=new Banana(20, 40);
* console.log('banana instanceof Fruit', banana instanceof Fruit);
* console.log('Fruit is prototype of banana', Fruit.prototype.isPrototypeOf(banana));
* console.log('bananas prototype is Fruit', Object.getPrototypeOf(banana)===Fruit.prototype);
* console.log(banana.sugar);
* console.log(banana.eat().sugar);
* console.log(banana.color);
*/
function extend(properties, superProtoOverride){
var superProto=superProtoOverride||this.prototype||Chartist.Class;
var proto=Object.create(superProto);
Chartist.Class.cloneDefinitions(proto, properties);
var constr=function(){
var fn=proto.constructor||function (){},
instance;
instance=this===Chartist ? Object.create(proto):this;
fn.apply(instance, Array.prototype.slice.call(arguments, 0));
return instance;
};
constr.prototype=proto;
constr.super=superProto;
constr.extend=this.extend;
return constr;
}
/**
* Creates a mixin from multiple super prototypes.
*
* @memberof Chartist.Class
* @param {Array} mixProtoArr An array of super prototypes or an array of super prototype constructors.
* @param {Object} properties The object that serves as definition for the prototype that gets created for the new class. This object should always contain a constructor property that is the desired constructor for the newly created class.
* @returns {Function} Constructor function of the newly created mixin class
*
* @example
* var Fruit=Class.extend({
* color: undefined,
*   sugar: undefined,
*
*   constructor: function(color, sugar){
*     this.color=color;
*     this.sugar=sugar;
*   },
*
*   eat: function(){
*     this.sugar=0;
*     return this;
*   }
* });
*
* var Banana=Fruit.extend({
*   length: undefined,
*
*   constructor: function(length, sugar){
*     Banana.super.constructor.call(this, 'Yellow', sugar);
*     this.length=length;
*   }
* });
*
* var banana=new Banana(20, 40);
* console.log('banana instanceof Fruit', banana instanceof Fruit);
* console.log('Fruit is prototype of banana', Fruit.prototype.isPrototypeOf(banana));
* console.log('bananas prototype is Fruit', Object.getPrototypeOf(banana)===Fruit.prototype);
* console.log(banana.sugar);
* console.log(banana.eat().sugar);
* console.log(banana.color);
*
*
* var KCal=Class.extend({
*   sugar: 0,
*
*   constructor: function(sugar){
*     this.sugar=sugar;
*   },
*
*   get kcal(){
*     return [this.sugar * 4, 'kcal'].join('');
*   }
* });
*
*      var Nameable=Class.extend({
*   name: undefined,
*
*   constructor: function(name){
*     this.name=name;
*   }
* });
*
* var NameableKCalBanana=Class.mix([Banana, KCal, Nameable], {
*   constructor: function(name, length, sugar){
*     Nameable.prototype.constructor.call(this, name);
*     Banana.prototype.constructor.call(this, length, sugar);
*   },
*
*   toString: function(){
*     return [this.name, 'with', this.length + 'cm', 'and', this.kcal].join(' ');
*   }
* });
*
*
*
* var banana=new Banana(20, 40);
* console.log('banana instanceof Fruit', banana instanceof Fruit);
* console.log('Fruit is prototype of banana', Fruit.prototype.isPrototypeOf(banana));
* console.log('bananas prototype is Fruit', Object.getPrototypeOf(banana)===Fruit.prototype);
* console.log(banana.sugar);
* console.log(banana.eat().sugar);
* console.log(banana.color);
*
* var superBanana=new NameableKCalBanana('Super Mixin Banana', 30, 80);
* console.log(superBanana.toString());
*
*/
function mix(mixProtoArr, properties){
if(this!==Chartist.Class){
throw new Error('Chartist.Class.mix should only be called on the type and never on an instance!');
}
var superPrototypes=[{}]
.concat(mixProtoArr)
.map(function (prototype){
return prototype instanceof Function ? prototype.prototype:prototype;
});
var mixedSuperProto=Chartist.Class.cloneDefinitions.apply(undefined, superPrototypes);
delete mixedSuperProto.constructor;
return this.extend(properties, mixedSuperProto);
}
function cloneDefinitions(){
var args=listToArray(arguments);
var target=args[0];
args.splice(1, args.length - 1).forEach(function (source){
Object.getOwnPropertyNames(source).forEach(function (propName){
delete target[propName];
Object.defineProperty(target, propName,
Object.getOwnPropertyDescriptor(source, propName));
});
});
return target;
}
Chartist.Class={
extend: extend,
mix: mix,
cloneDefinitions: cloneDefinitions
};}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
function update(data){
this.data=data||this.data;
this.createChart(this.optionsProvider.currentOptions);
return this;
}
function detach(){
window.removeEventListener('resize', this.resizeListener);
this.optionsProvider.removeMediaQueryListeners();
return this;
}
function on(event, handler){
this.eventEmitter.addEventHandler(event, handler);
return this;
}
function off(event, handler){
this.eventEmitter.removeEventHandler(event, handler);
return this;
}
function initialize(){
window.addEventListener('resize', this.resizeListener);
this.optionsProvider=Chartist.optionsProvider(this.options, this.responsiveOptions, this.eventEmitter);
if(this.options.plugins){
this.options.plugins.forEach(function(plugin){
if(plugin instanceof Array){
plugin[0](this, plugin[1]);
}else{
plugin(this);
}}.bind(this));
}
this.createChart(this.optionsProvider.currentOptions);
this.initializeTimeoutId=undefined;
}
function Base(query, data, options, responsiveOptions){
this.container=Chartist.querySelector(query);
this.data=data;
this.options=options;
this.responsiveOptions=responsiveOptions;
this.eventEmitter=Chartist.EventEmitter();
this.supportsForeignObject=Chartist.Svg.isSupported('Extensibility');
this.supportsAnimations=Chartist.Svg.isSupported('AnimationEventsAttribute');
this.resizeListener=function resizeListener(){
this.update();
}.bind(this);
if(this.container){
if(this.container.__chartist__){
if(this.container.__chartist__.initializeTimeoutId){
window.clearTimeout(this.container.__chartist__.initializeTimeoutId);
}else{
this.container.__chartist__.detach();
}}
this.container.__chartist__=this;
}
this.initializeTimeoutId=setTimeout(initialize.bind(this), 0);
}
Chartist.Base=Chartist.Class.extend({
constructor: Base,
optionsProvider: undefined,
container: undefined,
svg: undefined,
eventEmitter: undefined,
createChart: function(){
throw new Error('Base chart type can\'t be instantiated!');
},
update: update,
detach: detach,
on: on,
off: off,
version: Chartist.version,
supportsForeignObject: false
});
}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
var svgNs='http://www.w3.org/2000/svg',
xmlNs='http://www.w3.org/2000/xmlns/',
xhtmlNs='http://www.w3.org/1999/xhtml';
Chartist.xmlNs={
qualifiedName: 'xmlns:ct',
prefix: 'ct',
uri: 'http://gionkunz.github.com/chartist-js/ct'
};
function Svg(name, attributes, className, parent, insertFirst){
if(name instanceof SVGElement){
this._node=name;
}else{
this._node=document.createElementNS(svgNs, name);
if(name==='svg'){
this._node.setAttributeNS(xmlNs, Chartist.xmlNs.qualifiedName, Chartist.xmlNs.uri);
}
if(attributes){
this.attr(attributes);
}
if(className){
this.addClass(className);
}
if(parent){
if(insertFirst&&parent._node.firstChild){
parent._node.insertBefore(this._node, parent._node.firstChild);
}else{
parent._node.appendChild(this._node);
}}
}}
function attr(attributes, ns){
if(typeof attributes==='string'){
if(ns){
return this._node.getAttributeNS(ns, attributes);
}else{
return this._node.getAttribute(attributes);
}}
Object.keys(attributes).forEach(function(key){
if(attributes[key]===undefined){
return;
}
if(ns){
this._node.setAttributeNS(ns, [Chartist.xmlNs.prefix, ':', key].join(''), attributes[key]);
}else{
this._node.setAttribute(key, attributes[key]);
}}.bind(this));
return this;
}
function elem(name, attributes, className, insertFirst){
return new Chartist.Svg(name, attributes, className, this, insertFirst);
}
function parent(){
return this._node.parentNode instanceof SVGElement ? new Chartist.Svg(this._node.parentNode):null;
}
function root(){
var node=this._node;
while(node.nodeName!=='svg'){
node=node.parentNode;
}
return new Chartist.Svg(node);
}
function querySelector(selector){
var foundNode=this._node.querySelector(selector);
return foundNode ? new Chartist.Svg(foundNode):null;
}
function querySelectorAll(selector){
var foundNodes=this._node.querySelectorAll(selector);
return foundNodes.length ? new Chartist.Svg.List(foundNodes):null;
}
function foreignObject(content, attributes, className, insertFirst){
if(typeof content==='string'){
var container=document.createElement('div');
container.innerHTML=content;
content=container.firstChild;
}
content.setAttribute('xmlns', xhtmlNs);
var fnObj=this.elem('foreignObject', attributes, className, insertFirst);
fnObj._node.appendChild(content);
return fnObj;
}
function text(t){
this._node.appendChild(document.createTextNode(t));
return this;
}
function empty(){
while (this._node.firstChild){
this._node.removeChild(this._node.firstChild);
}
return this;
}
function remove(){
this._node.parentNode.removeChild(this._node);
return this.parent();
}
function replace(newElement){
this._node.parentNode.replaceChild(newElement._node, this._node);
return newElement;
}
function append(element, insertFirst){
if(insertFirst&&this._node.firstChild){
this._node.insertBefore(element._node, this._node.firstChild);
}else{
this._node.appendChild(element._node);
}
return this;
}
function classes(){
return this._node.getAttribute('class') ? this._node.getAttribute('class').trim().split(/\s+/):[];
}
function addClass(names){
this._node.setAttribute('class',
this.classes(this._node)
.concat(names.trim().split(/\s+/))
.filter(function(elem, pos, self){
return self.indexOf(elem)===pos;
}).join(' ')
);
return this;
}
function removeClass(names){
var removedClasses=names.trim().split(/\s+/);
this._node.setAttribute('class', this.classes(this._node).filter(function(name){
return removedClasses.indexOf(name)===-1;
}).join(' '));
return this;
}
function removeAllClasses(){
this._node.setAttribute('class', '');
return this;
}
function height(){
return this._node.clientHeight||Math.round(this._node.getBBox().height)||this._node.parentNode.clientHeight;
}
function width(){
return this._node.clientWidth||Math.round(this._node.getBBox().width)||this._node.parentNode.clientWidth;
}
function animate(animations, guided, eventEmitter){
if(guided===undefined){
guided=true;
}
Object.keys(animations).forEach(function createAnimateForAttributes(attribute){
function createAnimate(animationDefinition, guided){
var attributeProperties={},
animate,
timeout,
easing;
if(animationDefinition.easing){
easing=animationDefinition.easing instanceof Array ?
animationDefinition.easing :
Chartist.Svg.Easing[animationDefinition.easing];
delete animationDefinition.easing;
}
animationDefinition.begin=Chartist.ensureUnit(animationDefinition.begin, 'ms');
animationDefinition.dur=Chartist.ensureUnit(animationDefinition.dur, 'ms');
if(easing){
animationDefinition.calcMode='spline';
animationDefinition.keySplines=easing.join(' ');
animationDefinition.keyTimes='0;1';
}
if(guided){
animationDefinition.fill='freeze';
attributeProperties[attribute]=animationDefinition.from;
this.attr(attributeProperties);
timeout=Chartist.stripUnit(animationDefinition.begin||0);
animationDefinition.begin='indefinite';
}
animate=this.elem('animate', Chartist.extend({
attributeName: attribute
}, animationDefinition));
if(guided){
setTimeout(function(){
try {
animate._node.beginElement();
} catch(err){
attributeProperties[attribute]=animationDefinition.to;
this.attr(attributeProperties);
animate.remove();
}}.bind(this), timeout);
}
if(eventEmitter){
animate._node.addEventListener('beginEvent', function handleBeginEvent(){
eventEmitter.emit('animationBegin', {
element: this,
animate: animate._node,
params: animationDefinition
});
}.bind(this));
}
animate._node.addEventListener('endEvent', function handleEndEvent(){
if(eventEmitter){
eventEmitter.emit('animationEnd', {
element: this,
animate: animate._node,
params: animationDefinition
});
}
if(guided){
attributeProperties[attribute]=animationDefinition.to;
this.attr(attributeProperties);
animate.remove();
}}.bind(this));
}
if(animations[attribute] instanceof Array){
animations[attribute].forEach(function(animationDefinition){
createAnimate.bind(this)(animationDefinition, false);
}.bind(this));
}else{
createAnimate.bind(this)(animations[attribute], guided);
}}.bind(this));
return this;
}
Chartist.Svg=Chartist.Class.extend({
constructor: Svg,
attr: attr,
elem: elem,
parent: parent,
root: root,
querySelector: querySelector,
querySelectorAll: querySelectorAll,
foreignObject: foreignObject,
text: text,
empty: empty,
remove: remove,
replace: replace,
append: append,
classes: classes,
addClass: addClass,
removeClass: removeClass,
removeAllClasses: removeAllClasses,
height: height,
width: width,
animate: animate
});
Chartist.Svg.isSupported=function(feature){
return document.implementation.hasFeature('www.http://w3.org/TR/SVG11/feature#' + feature, '1.1');
};
var easingCubicBeziers={
easeInSine: [0.47, 0, 0.745, 0.715],
easeOutSine: [0.39, 0.575, 0.565, 1],
easeInOutSine: [0.445, 0.05, 0.55, 0.95],
easeInQuad: [0.55, 0.085, 0.68, 0.53],
easeOutQuad: [0.25, 0.46, 0.45, 0.94],
easeInOutQuad: [0.455, 0.03, 0.515, 0.955],
easeInCubic: [0.55, 0.055, 0.675, 0.19],
easeOutCubic: [0.215, 0.61, 0.355, 1],
easeInOutCubic: [0.645, 0.045, 0.355, 1],
easeInQuart: [0.895, 0.03, 0.685, 0.22],
easeOutQuart: [0.165, 0.84, 0.44, 1],
easeInOutQuart: [0.77, 0, 0.175, 1],
easeInQuint: [0.755, 0.05, 0.855, 0.06],
easeOutQuint: [0.23, 1, 0.32, 1],
easeInOutQuint: [0.86, 0, 0.07, 1],
easeInExpo: [0.95, 0.05, 0.795, 0.035],
easeOutExpo: [0.19, 1, 0.22, 1],
easeInOutExpo: [1, 0, 0, 1],
easeInCirc: [0.6, 0.04, 0.98, 0.335],
easeOutCirc: [0.075, 0.82, 0.165, 1],
easeInOutCirc: [0.785, 0.135, 0.15, 0.86],
easeInBack: [0.6, -0.28, 0.735, 0.045],
easeOutBack: [0.175, 0.885, 0.32, 1.275],
easeInOutBack: [0.68, -0.55, 0.265, 1.55]
};
Chartist.Svg.Easing=easingCubicBeziers;
function SvgList(nodeList){
var list=this;
this.svgElements=[];
for(var i=0; i < nodeList.length; i++){
this.svgElements.push(new Chartist.Svg(nodeList[i]));
}
Object.keys(Chartist.Svg.prototype).filter(function(prototypeProperty){
return ['constructor',
'parent',
'querySelector',
'querySelectorAll',
'replace',
'append',
'classes',
'height',
'width'].indexOf(prototypeProperty)===-1;
}).forEach(function(prototypeProperty){
list[prototypeProperty]=function(){
var args=Array.prototype.slice.call(arguments, 0);
list.svgElements.forEach(function(element){
Chartist.Svg.prototype[prototypeProperty].apply(element, args);
});
return list;
};});
}
Chartist.Svg.List=Chartist.Class.extend({
constructor: SvgList
});
}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
var defaultOptions={
axisX: {
offset: 30,
labelOffset: {
x: 0,
y: 0
},
showLabel: true,
showGrid: true,
labelInterpolationFnc: Chartist.noop
},
axisY: {
offset: 40,
labelOffset: {
x: 0,
y: 0
},
showLabel: true,
showGrid: true,
labelInterpolationFnc: Chartist.noop,
scaleMinSpace: 20
},
width: undefined,
height: undefined,
showLine: true,
showPoint: true,
showArea: false,
areaBase: 0,
lineSmooth: true,
low: undefined,
high: undefined,
chartPadding: 5,
fullWidth: false,
classNames: {
chart: 'ct-chart-line',
label: 'ct-label',
labelGroup: 'ct-labels',
series: 'ct-series',
line: 'ct-line',
point: 'ct-point',
area: 'ct-area',
grid: 'ct-grid',
gridGroup: 'ct-grids',
vertical: 'ct-vertical',
horizontal: 'ct-horizontal'
}};
function createChart(options){
var seriesGroups=[],
bounds,
normalizedData=Chartist.normalizeDataArray(Chartist.getDataArray(this.data), this.data.labels.length);
this.svg=Chartist.createSvg(this.container, options.width, options.height, options.classNames.chart);
bounds=Chartist.getBounds(this.svg, Chartist.getHighLow(normalizedData), options);
var chartRect=Chartist.createChartRect(this.svg, options);
var labels=this.svg.elem('g').addClass(options.classNames.labelGroup),
grid=this.svg.elem('g').addClass(options.classNames.gridGroup);
Chartist.createXAxis(chartRect, this.data, grid, labels, options, this.eventEmitter, this.supportsForeignObject);
Chartist.createYAxis(chartRect, bounds, grid, labels, options, this.eventEmitter, this.supportsForeignObject);
for (var i=0; i < this.data.series.length; i++){
seriesGroups[i]=this.svg.elem('g');
if(this.data.series[i].name){
seriesGroups[i].attr({
'series-name': this.data.series[i].name
}, Chartist.xmlNs.uri);
}
seriesGroups[i].addClass([
options.classNames.series,
(this.data.series[i].className||options.classNames.series + '-' + Chartist.alphaNumerate(i))
].join(' '));
var p,
pathCoordinates=[],
point;
for (var j=0; j < normalizedData[i].length; j++){
p=Chartist.projectPoint(chartRect, bounds, normalizedData[i], j, options);
pathCoordinates.push(p.x, p.y);
if(options.showPoint){
point=seriesGroups[i].elem('line', {
x1: p.x,
y1: p.y,
x2: p.x + 0.01,
y2: p.y
}, options.classNames.point).attr({
'value': normalizedData[i][j]
}, Chartist.xmlNs.uri);
this.eventEmitter.emit('draw', {
type: 'point',
value: normalizedData[i][j],
index: j,
group: seriesGroups[i],
element: point,
x: p.x,
y: p.y
});
}}
if(options.showLine||options.showArea){
var pathElements=['M' + pathCoordinates[0] + ',' + pathCoordinates[1]];
if(options.lineSmooth&&pathCoordinates.length > 4){
var cr=Chartist.catmullRom2bezier(pathCoordinates);
for(var k=0; k < cr.length; k++){
pathElements.push('C' + cr[k].join());
}}else{
for(var l=3; l < pathCoordinates.length; l +=2){
pathElements.push('L' + pathCoordinates[l - 1] + ',' + pathCoordinates[l]);
}}
if(options.showLine){
var line=seriesGroups[i].elem('path', {
d: pathElements.join('')
}, options.classNames.line, true).attr({
'values': normalizedData[i]
}, Chartist.xmlNs.uri);
this.eventEmitter.emit('draw', {
type: 'line',
values: normalizedData[i],
index: i,
group: seriesGroups[i],
element: line
});
}
if(options.showArea){
var areaBase=Math.max(Math.min(options.areaBase, bounds.max), bounds.min);
var areaPathElements=pathElements.slice();
var areaBaseProjected=Chartist.projectPoint(chartRect, bounds, [areaBase], 0, options);
areaPathElements.splice(0, 0, 'M' + areaBaseProjected.x + ',' + areaBaseProjected.y);
areaPathElements[1]='L' + pathCoordinates[0] + ',' + pathCoordinates[1];
areaPathElements.push('L' + pathCoordinates[pathCoordinates.length - 2] + ',' + areaBaseProjected.y);
var area=seriesGroups[i].elem('path', {
d: areaPathElements.join('')
}, options.classNames.area, true).attr({
'values': normalizedData[i]
}, Chartist.xmlNs.uri);
this.eventEmitter.emit('draw', {
type: 'area',
values: normalizedData[i],
index: i,
group: seriesGroups[i],
element: area
});
}}
}
this.eventEmitter.emit('created', {
bounds: bounds,
chartRect: chartRect,
svg: this.svg,
options: options
});
}
/**
* This method creates a new line chart.
*
* @memberof Chartist.Line
* @param {String|Node} query A selector query string or directly a DOM element
* @param {Object} data The data object that needs to consist of a labels and a series array
* @param {Object} [options] The options object with options that override the default options. Check the examples for a detailed list.
* @param {Array} [responsiveOptions] Specify an array of responsive option arrays which are a media query and options object pair=> [[mediaQueryString, optionsObject],[more...]]
* @return {Object} An object which exposes the API for the created chart
*
* @example
*
* var data={
*
*   labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
*
*   series: [
*     [5, 2, 4, 2, 0]
*   ]
* };
*
*
* var options={
*   width: '300px',
*   height: '200px'
* };
*
*
* new Chartist.Line('.ct-chart', data, options);
*
* @example
*
*
* var data={
*
*   labels: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
*
*   series: [
*     [5, 2, 4, 2, 0]
*   ]
* };
*
*
* var responsiveOptions=[
*   ['screen and (min-width: 641px) and (max-width: 1024px)', {
*     showPoint: false,
*     axisX: {
*       labelInterpolationFnc: function(value){
*
*         return value.slice(0, 3);
*       }
*     }
*   }],
*   ['screen and (max-width: 640px)', {
*     showLine: false,
*     axisX: {
*       labelInterpolationFnc: function(value){
*
*         return value[0];
*       }
*     }
*   }]
* ];
*
* new Chartist.Line('.ct-chart', data, null, responsiveOptions);
*
*/
function Line(query, data, options, responsiveOptions){
Chartist.Line.super.constructor.call(this,
query,
data,
Chartist.extend({}, defaultOptions, options),
responsiveOptions);
}
Chartist.Line=Chartist.Base.extend({
constructor: Line,
createChart: createChart
});
}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
var defaultOptions={
axisX: {
offset: 30,
labelOffset: {
x: 0,
y: 0
},
showLabel: true,
showGrid: true,
labelInterpolationFnc: Chartist.noop
},
axisY: {
offset: 40,
labelOffset: {
x: 0,
y: 0
},
showLabel: true,
showGrid: true,
labelInterpolationFnc: Chartist.noop,
scaleMinSpace: 20
},
width: undefined,
height: undefined,
high: undefined,
low: undefined,
chartPadding: 5,
seriesBarDistance: 15,
fullWidth: false,
centerBars: true,
stackBars: false,
classNames: {
chart: 'ct-chart-bar',
label: 'ct-label',
labelGroup: 'ct-labels',
series: 'ct-series',
bar: 'ct-bar',
grid: 'ct-grid',
gridGroup: 'ct-grids',
vertical: 'ct-vertical',
horizontal: 'ct-horizontal'
}};
function createChart(options){
var seriesGroups=[],
bounds,
normalizedData=Chartist.normalizeDataArray(Chartist.getDataArray(this.data), this.data.labels.length),
highLow;
this.svg=Chartist.createSvg(this.container, options.width, options.height, options.classNames.chart);
if(options.stackBars){
var serialSums=Chartist.serialMap(normalizedData, function serialSums(){
return Array.prototype.slice.call(arguments).reduce(Chartist.sum, 0);
});
highLow=Chartist.getHighLow([serialSums]);
}else{
highLow=Chartist.getHighLow(normalizedData);
}
bounds=Chartist.getBounds(this.svg, highLow, options, 0);
var chartRect=Chartist.createChartRect(this.svg, options);
var labels=this.svg.elem('g').addClass(options.classNames.labelGroup),
grid=this.svg.elem('g').addClass(options.classNames.gridGroup),
zeroPoint=Chartist.projectPoint(chartRect, bounds, [0], 0, options),
stackedBarValues=[];
Chartist.createXAxis(chartRect, this.data, grid, labels, options, this.eventEmitter, this.supportsForeignObject);
Chartist.createYAxis(chartRect, bounds, grid, labels, options, this.eventEmitter, this.supportsForeignObject);
for (var i=0; i < this.data.series.length; i++){
var biPol=i - (this.data.series.length - 1) / 2,
periodHalfWidth=chartRect.width() / (normalizedData[i].length - (options.fullWidth ? 1:0)) / 2;
seriesGroups[i]=this.svg.elem('g');
if(this.data.series[i].name){
seriesGroups[i].attr({
'series-name': this.data.series[i].name
}, Chartist.xmlNs.uri);
}
seriesGroups[i].addClass([
options.classNames.series,
(this.data.series[i].className||options.classNames.series + '-' + Chartist.alphaNumerate(i))
].join(' '));
for(var j=0; j < normalizedData[i].length; j++){
var p=Chartist.projectPoint(chartRect, bounds, normalizedData[i], j, options),
bar,
previousStack,
y1,
y2;
p.x +=(options.centerBars ? periodHalfWidth:0);
p.x +=options.stackBars ? 0:biPol * options.seriesBarDistance;
previousStack=stackedBarValues[j]||zeroPoint.y;
stackedBarValues[j]=previousStack - (zeroPoint.y - p.y);
y1=options.stackBars ? previousStack:zeroPoint.y;
y2=options.stackBars ? stackedBarValues[j]:p.y;
bar=seriesGroups[i].elem('line', {
x1: p.x,
y1: y1,
x2: p.x,
y2: y2
}, options.classNames.bar).attr({
'value': normalizedData[i][j]
}, Chartist.xmlNs.uri);
this.eventEmitter.emit('draw', {
type: 'bar',
value: normalizedData[i][j],
index: j,
group: seriesGroups[i],
element: bar,
x1: p.x,
y1: y1,
x2: p.x,
y2: y2
});
}}
this.eventEmitter.emit('created', {
bounds: bounds,
chartRect: chartRect,
svg: this.svg,
options: options
});
}
function Bar(query, data, options, responsiveOptions){
Chartist.Bar.super.constructor.call(this,
query,
data,
Chartist.extend({}, defaultOptions, options),
responsiveOptions);
}
Chartist.Bar=Chartist.Base.extend({
constructor: Bar,
createChart: createChart
});
}(window, document, Chartist));
;
(function(window, document, Chartist){
'use strict';
var defaultOptions={
width: undefined,
height: undefined,
chartPadding: 5,
classNames: {
chart: 'ct-chart-pie',
series: 'ct-series',
slice: 'ct-slice',
donut: 'ct-donut',
label: 'ct-label'
},
startAngle: 0,
total: undefined,
donut: false,
donutWidth: 60,
showLabel: true,
labelOffset: 0,
labelInterpolationFnc: Chartist.noop,
labelDirection: 'neutral'
};
function determineAnchorPosition(center, label, direction){
var toTheRight=label.x > center.x;
if(toTheRight&&direction==='explode' ||
!toTheRight&&direction==='implode'){
return 'start';
}else if(toTheRight&&direction==='implode' ||
!toTheRight&&direction==='explode'){
return 'end';
}else{
return 'middle';
}}
function createChart(options){
var seriesGroups=[],
chartRect,
radius,
labelRadius,
totalDataSum,
startAngle=options.startAngle,
dataArray=Chartist.getDataArray(this.data);
this.svg=Chartist.createSvg(this.container, options.width, options.height, options.classNames.chart);
chartRect=Chartist.createChartRect(this.svg, options, 0, 0);
radius=Math.min(chartRect.width() / 2, chartRect.height() / 2);
totalDataSum=options.total||dataArray.reduce(function(previousValue, currentValue){
return previousValue + currentValue;
}, 0);
radius -=options.donut ? options.donutWidth / 2:0;
labelRadius=options.donut ? radius:radius / 2;
labelRadius +=options.labelOffset;
var center={
x: chartRect.x1 + chartRect.width() / 2,
y: chartRect.y2 + chartRect.height() / 2
};
var hasSingleValInSeries=this.data.series.filter(function(val){
return val!==0;
}).length===1;
for (var i=0; i < this.data.series.length; i++){
seriesGroups[i]=this.svg.elem('g', null, null, true);
if(this.data.series[i].name){
seriesGroups[i].attr({
'series-name': this.data.series[i].name
}, Chartist.xmlNs.uri);
}
seriesGroups[i].addClass([
options.classNames.series,
(this.data.series[i].className||options.classNames.series + '-' + Chartist.alphaNumerate(i))
].join(' '));
var endAngle=startAngle + dataArray[i] / totalDataSum * 360;
if(endAngle - startAngle===360){
endAngle -=0.01;
}
var start=Chartist.polarToCartesian(center.x, center.y, radius, startAngle - (i===0||hasSingleValInSeries ? 0:0.2)),
end=Chartist.polarToCartesian(center.x, center.y, radius, endAngle),
arcSweep=endAngle - startAngle <=180 ? '0':'1',
d=[
'M', end.x, end.y,
'A', radius, radius, 0, arcSweep, 0, start.x, start.y
];
if(options.donut===false){
d.push('L', center.x, center.y);
}
var path=seriesGroups[i].elem('path', {
d: d.join(' ')
}, options.classNames.slice + (options.donut ? ' ' + options.classNames.donut:''));
path.attr({
'value': dataArray[i]
}, Chartist.xmlNs.uri);
if(options.donut===true){
path.attr({
'style': 'stroke-width: ' + (+options.donutWidth) + 'px'
});
}
this.eventEmitter.emit('draw', {
type: 'slice',
value: dataArray[i],
totalDataSum: totalDataSum,
index: i,
group: seriesGroups[i],
element: path,
center: center,
radius: radius,
startAngle: startAngle,
endAngle: endAngle
});
if(options.showLabel){
var labelPosition=Chartist.polarToCartesian(center.x, center.y, labelRadius, startAngle + (endAngle - startAngle) / 2),
interpolatedValue=options.labelInterpolationFnc(this.data.labels ? this.data.labels[i]:dataArray[i], i);
var labelElement=seriesGroups[i].elem('text', {
dx: labelPosition.x,
dy: labelPosition.y,
'text-anchor': determineAnchorPosition(center, labelPosition, options.labelDirection)
}, options.classNames.label).text('' + interpolatedValue);
this.eventEmitter.emit('draw', {
type: 'label',
index: i,
group: seriesGroups[i],
element: labelElement,
text: '' + interpolatedValue,
x: labelPosition.x,
y: labelPosition.y
});
}
startAngle=endAngle;
}
this.eventEmitter.emit('created', {
chartRect: chartRect,
svg: this.svg,
options: options
});
}
function Pie(query, data, options, responsiveOptions){
Chartist.Pie.super.constructor.call(this,
query,
data,
Chartist.extend({}, defaultOptions, options),
responsiveOptions);
}
Chartist.Pie=Chartist.Base.extend({
constructor: Pie,
createChart: createChart,
determineAnchorPosition: determineAnchorPosition
});
}(window, document, Chartist));
return Chartist;
}));