Commit fc647ece authored by Cecilia Vela Gurovic's avatar Cecilia Vela Gurovic Committed by Gerrit Code Review

Merge "Bug 1779020: upgrade charts.js library to v2.7.3"

parents 1d255dd4 0b091cb8
......@@ -274,7 +274,7 @@ JS;
$smarty = smarty(array('paginator','js/chartjs/Chart.min.js'));
$smarty = smarty(array('paginator','js/chartjs/dist/Chart.min.js'));
setpageicon($smarty, 'icon-pie-chart');
$smarty->assign('INLINEJAVASCRIPT', $js);
$smarty->assign('institutiondata', $institutiondata);
Contributing to Chart.js
Contributions to Chart.js are welcome and encouraged, but please have a look through the guidelines in this document before raising an issue, or writing code for the project.
Using issues
The [issue tracker]( is the preferred channel for reporting bugs, requesting new features and submitting pull requests.
If you're suggesting a new chart type, please take a look at [writing new chart types]( in the documentation, and some of the [community extensions]( that have been created already.
To keep the library lightweight for everyone, it's unlikely we'll add many more chart types to the core of Chart.js, but issues are a good medium to design and spec out how new chart types could work and look.
Please do not use issues for support requests. For help using Chart.js, please take a look at the [`chartjs`]( tag on Stack Overflow.
Reporting bugs
Well structured, detailed bug reports are hugely valuable for the project.
Guidlines for reporting bugs:
- Check the issue search to see if it has already been reported
- Isolate the problem to a simple test case
- Provide a demonstration of the problem on [JS Bin]( or similar
Please provide any additional details associated with the bug, if it's browser or screen density specific, or only happens with a certain configuration or data.
Pull requests
Clear, concise pull requests are excellent at continuing the project's community driven growth. But please review [these guidelines]( and the guidelines below before starting work on the project.
- Please create an issue first:
- For bugs, we can discuss the fixing approach
- For enhancements, we can discuss if it is within the project scope and avoid duplicate effort
- Please make changes to the files in [`/src`](, not `Chart.js` or `Chart.min.js` in the repo root directory, this avoids merge conflicts
- Tabs for indentation, not spaces please
- If adding new functionality, please also update the relevant `.md` file in [`/docs`](
- Please make your commits in logical sections with clear commit messages
Joining the Project
- Active committers and contributors are invited to introduce yourself and request commit access to this project. Please send an email to or file an issue.
By contributing your code, you agree to license your contribution under the [MIT license](
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Copyright (c) 2013-2015 Nick Downie
The MIT License (MIT)
Copyright (c) 2018 Chart.js Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# Maintaining
## Release Process
Chart.js relies on [Travis CI]( to automate the library [releases](
### Releasing a New Version
1. draft release notes on [GitHub]( for the upcoming tag
1. update `master` `package.json` version using [semver]( semantic
1. merge `master` into the `release` branch
1. follow the build process on [Travis CI](
> **Note:** if `master` is merged in `release` with a `package.json` version that already exists, the tag
creation fails and the release process is aborted.
### Automated Tasks
Merging into the `release` branch kicks off the automated release process:
* build of the `dist/*.js` files
* `bower.json` is generated from `package.json`
* `dist/*.js` and `bower.json` are added to a detached branch
* a tag is created from the `package.json` version
* tag (with dist files) is pushed to GitHub
Creation of this tag triggers a new build:
* `` package is generated, containing dist files and examples
* `dist/*.js` and `` are attached to the GitHub release (downloads)
* a new npm package is published on [npmjs](
Finally, [cdnjs]( is automatically updated from the npm release.
### Further Reading
* [Travis GitHub releases](
* [Bower support and dist/* files](
* [cdnjs npm auto update](
......@@ -2,12 +2,20 @@ Chart.js in Mahara
Version: 1.1.0
Version: 2.7.3
Removed the samples/ docs/ package.json gulpfile.js bower.jsonfiles
Removed the samples/ docs/ scripts/ src/ test/
.codeclimate.yml .editorconfig .eslintignore .eslintrc.yml
.gitignore .htmllintrc .npmignore .travis.yml
book.json bower.json composer.json gulpfile.js
karma.conf.js package.json files
that are not needed for this plugin
Removed Chart.bundle.js, Chart.bundle.min.js:
The bundled build includes Moment.js in a single file.
You should not use this build if your application already included Moment.js.
We are using Moment js already so it can be deleted.
* None
# Chart.js
[![Build Status](]( [![Code Climate](](
# Chart.js
[![travis](]( [![coveralls](]( [![codeclimate](]( [![slack](](
*Simple HTML5 Charts using the canvas element* [](
## Installation
You can download the latest version of Chart.js from the [GitHub releases]( or use a [Chart.js CDN](
To install via npm:
npm install chart.js --save
To install via bower:
bower install chart.js --save
### Selecting the Correct Build
Chart.js provides two different builds for you to choose: `Stand-Alone Build`, `Bundled Build`.
#### Stand-Alone Build
* `dist/Chart.js`
* `dist/Chart.min.js`
The stand-alone build includes Chart.js as well as the color parsing library. If this version is used, you are required to include [Moment.js]( before Chart.js for the functionality of the time axis.
#### Bundled Build
* `dist/Chart.bundle.js`
* `dist/Chart.bundle.min.js`
The bundled build includes Moment.js in a single file. You should use this version if you require time axes and want to include a single file. You should not use this build if your application already included Moment.js. Otherwise, Moment.js will be included twice which results in increasing page load time and possible version compatibility issues. The Moment.js version in the bundled build is private to Chart.js so if you want to use Moment.js yourself, it's better to use Chart.js (non bundled) and import Moment.js manually.
## Documentation
You can find documentation at []( The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard.
You can find documentation at []( The markdown files that build the site are available under `/docs`. Previous version documentation is available at [](
## Contributing
## Bugs, issues and contributing
Before submitting an issue or a pull request, please take a moment to look over the [contributing guidelines]( first. For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](
Before submitting an issue or a pull request to the project, please take a moment to look over the [contributing guidelines]( first.
## Building
Instructions on building and testing Chart.js can be found in [the documentation](
For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](
## Thanks
- [BrowserStack]( for allowing our team to test on thousands of browsers.
- [@n8agrin]( for the Twitter handle donation.
## License
This source diff could not be displayed because it is too large. You can view the blob instead.
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero : true,
//Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth : 1,
//Boolean - Whether to show horizontal lines (except X axis)
scaleShowHorizontalLines: true,
//Boolean - Whether to show vertical lines (except Y axis)
scaleShowVerticalLines: true,
//Boolean - If there is a stroke on each bar
barShowStroke : true,
//Number - Pixel width of the bar stroke
barStrokeWidth : 2,
//Number - Spacing between each of the X value sets
barValueSpacing : 5,
//Number - Spacing between data sets within X values
barDatasetSpacing : 1,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></span></li><%}%></ul>"
name: "Bar",
defaults : defaultConfig,
initialize: function(data){
//Expose options as a scope variable here so we can access it in the ScaleClass
var options = this.options;
this.ScaleClass = Chart.Scale.extend({
offsetGridLines : true,
calculateBarX : function(datasetCount, datasetIndex, barIndex){
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
var xWidth = this.calculateBaseWidth(),
xAbsolute = this.calculateX(barIndex) - (xWidth/2),
barWidth = this.calculateBarWidth(datasetCount);
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
calculateBaseWidth : function(){
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
calculateBarWidth : function(datasetCount){
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
return (baseWidth / datasetCount);
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
bar.restore(['fillColor', 'strokeColor']);
helpers.each(activeBars, function(activeBar){
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.BarClass = Chart.Rectangle.extend({
strokeWidth : this.options.barStrokeWidth,
showStroke : this.options.barShowStroke,
ctx : this.chart.ctx
//Iterate through each of the datasets, and build this into a property of the chart
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
bars : []
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.bars.push(new this.BarClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.strokeColor,
fillColor : dataset.fillColor,
highlightFill : dataset.highlightFill || dataset.fillColor,
highlightStroke : dataset.highlightStroke || dataset.strokeColor
this.BarClass.prototype.base = this.scale.endPoint;
this.eachBars(function(bar, index, datasetIndex){
helpers.extend(bar, {
width : this.scale.calculateBarWidth(this.datasets.length),
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y: this.scale.endPoint
}, this);
update : function(){
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
eachBars : function(callback){
helpers.each(this.datasets,function(dataset, datasetIndex){
helpers.each(dataset.bars, callback, this, datasetIndex);
getBarsAtEvent : function(e){
var barsArray = [],
eventPosition = helpers.getRelativePosition(e),
datasetIterator = function(dataset){
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
helpers.each(this.datasets, datasetIterator);
return barsArray;
return barsArray;
buildScale : function(labels){
var self = this;
var dataTotal = function(){
var values = [];
return values;
var scaleOptions = {
templateString : this.options.scaleLabel,
height : this.chart.height,
width : this.chart.width,
ctx : this.chart.ctx,
textColor : this.options.scaleFontColor,
fontSize : this.options.scaleFontSize,
fontStyle : this.options.scaleFontStyle,
fontFamily : this.options.scaleFontFamily,
valuesCount : labels.length,
beginAtZero : this.options.scaleBeginAtZero,
integersOnly : this.options.scaleIntegersOnly,
calculateYRange: function(currentHeight){
var updatedRanges = helpers.calculateScaleRange(
helpers.extend(this, updatedRanges);
xLabels : labels,
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
showHorizontalLines : this.options.scaleShowHorizontalLines,
showVerticalLines : this.options.scaleShowVerticalLines,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
showLabels : this.options.scaleShowLabels,
display : this.options.showScale
if (this.options.scaleOverride){
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
this.scale = new this.ScaleClass(scaleOptions);
addData : function(valuesArray,label){
//Map the values array for each of the datasets
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].bars.push(new this.BarClass({
value : value,
label : label,
datasetLabel: this.datasets[datasetIndex].label,
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
y: this.scale.endPoint,
width : this.scale.calculateBarWidth(this.datasets.length),
base : this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].strokeColor,
fillColor : this.datasets[datasetIndex].fillColor
//Then re-render the chart.
removeData : function(){
//Then re-render the chart.
reflow : function(){
y: this.scale.endPoint,
base : this.scale.endPoint
var newScaleProps = helpers.extend({
height : this.chart.height,
width : this.chart.width
draw : function(ease){
var easingDecimal = ease || 1;
var ctx = this.chart.ctx;
//Draw all the bars for each dataset
if (bar.hasValue()){
bar.base = this.scale.endPoint;
//Transition then draw
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y : this.scale.calculateY(bar.value),
width : this.scale.calculateBarWidth(this.datasets.length)
}, easingDecimal).draw();
This diff is collapsed.
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 2,
//The percentage of the chart that we cut out of the middle.
percentageInnerCutout : 50,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect
animationEasing : "easeOutBounce",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"><%if(segments[i].label){%><%=segments[i].label%><%}%></span></li><%}%></ul>"
//Passing in a name registers this chart in the Chart namespace
name: "Doughnut",
//Providing a defaults will also register the deafults in the chart namespace
defaults : defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function(data){
//Declare segments as a static property to prevent inheriting across the Chart type prototype
this.segments = [];
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
this.SegmentArc = Chart.Arc.extend({
ctx : this.chart.ctx,
x : this.chart.width/2,
y : this.chart.height/2
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
activeSegment.fillColor = activeSegment.highlightColor;
helpers.each(data,function(datapoint, index){
if (!datapoint.color) {
datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
this.addData(datapoint, index, true);
getSegmentsAtEvent : function(e){
var segmentsArray = [];
var location = helpers.getRelativePosition(e);
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
return segmentsArray;
addData : function(segment, atIndex, silent){
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value : segment.value,
outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
fillColor : segment.color,
highlightColor : segment.highlight || segment.color,
showStroke : this.options.segmentShowStroke,
strokeWidth : this.options.segmentStrokeWidth,
strokeColor : this.options.segmentStrokeColor,
startAngle : Math.PI * 1.5,
circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label : segment.label
if (!silent){
calculateCircumference : function(value) {
if ( > 0 ) {