From 5bc86614a2dface8ed31ad2f2449478c15616aa2 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 21 Apr 2020 08:48:39 +1200 Subject: [PATCH] MDL-68477 libraries: support for Chart.js legend options. --- lib/amd/build/chart_base.min.js | 2 +- lib/amd/build/chart_base.min.js.map | 2 +- lib/amd/build/chart_output_chartjs.min.js | 2 +- lib/amd/build/chart_output_chartjs.min.js.map | 2 +- lib/amd/src/chart_base.js | 32 +++++++++++++++++++ lib/amd/src/chart_output_chartjs.js | 5 +++ lib/classes/chart_base.php | 26 +++++++++++++++ 7 files changed, 67 insertions(+), 4 deletions(-) diff --git a/lib/amd/build/chart_base.min.js b/lib/amd/build/chart_base.min.js index f6170bb03a0..1d3b68b6bad 100644 --- a/lib/amd/build/chart_base.min.js +++ b/lib/amd/build/chart_base.min.js @@ -1,2 +1,2 @@ -define ("core/chart_base",["core/chart_series","core/chart_axis"],function(a,b){function c(){this._series=[];this._labels=[];this._xaxes=[];this._yaxes=[];this._setDefaults()}c.prototype._series=null;c.prototype._labels=null;c.prototype._title=null;c.prototype._xaxes=null;c.prototype._yaxes=null;c.prototype.COLORSET=["#f3c300","#875692","#f38400","#a1caf1","#be0032","#c2b280","#7f180d","#008856","#e68fac","#0067a5"];c.prototype._configColorSet=null;c.prototype.TYPE=null;c.prototype.addSeries=function(a){this._validateSeries(a);this._series.push(a);if(null===a.getColor()){var b=this.getConfigColorSet()||c.prototype.COLORSET;a.setColor(b[this._series.length%b.length])}};c.prototype.create=function(c,d){var e=new c;e.setConfigColorSet(d.config_colorset);e.setLabels(d.labels);e.setTitle(d.title);d.series.forEach(function(b){e.addSeries(a.prototype.create(b))});d.axes.x.forEach(function(a,c){e.setXAxis(b.prototype.create(a),c)});d.axes.y.forEach(function(a,c){e.setYAxis(b.prototype.create(a),c)});return e};c.prototype.__getAxis=function(a,c,d){var e="x"===a?this._xaxes:this._yaxes,f=("x"===a?this.setXAxis:this.setYAxis).bind(this),g;c="undefined"==typeof c?0:c;d="undefined"==typeof d?!1:d;g=e[c];if("undefined"==typeof g){if(!d){throw new Error("Unknown axis.")}g=new b;f(g,c)}return g};c.prototype.getConfigColorSet=function(){return this._configColorSet};c.prototype.getLabels=function(){return this._labels};c.prototype.getSeries=function(){return this._series};c.prototype.getTitle=function(){return this._title};c.prototype.getType=function(){if(!this.TYPE){throw new Error("The TYPE property has not been set.")}return this.TYPE};c.prototype.getXAxes=function(){return this._xaxes};c.prototype.getXAxis=function(a,b){return this.__getAxis("x",a,b)};c.prototype.getYAxes=function(){return this._yaxes};c.prototype.getYAxis=function(a,b){return this.__getAxis("y",a,b)};c.prototype.setConfigColorSet=function(a){this._configColorSet=a};c.prototype._setDefaults=function(){};c.prototype.setLabels=function(a){if(a.length&&this._series.length&&this._series[0].length!=a.length){throw new Error("Series must match label values.")}this._labels=a};c.prototype.setTitle=function(a){this._title=a};c.prototype.setXAxis=function(a,b){b="undefined"==typeof b?0:b;this._validateAxis("x",a,b);this._xaxes[b]=a};c.prototype.setYAxis=function(a,b){b="undefined"==typeof b?0:b;this._validateAxis("y",a,b);this._yaxes[b]=a};c.prototype._validateAxis=function(a,b,c){c="undefined"==typeof c?0:c;if(0.\n\n/**\n * Chart base.\n *\n * @package core\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @module core/chart_base\n */\ndefine(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {\n\n /**\n * Chart base.\n *\n * The constructor of a chart must never take any argument.\n *\n * {@link module:core/chart_base#_setDefault} to set the defaults on instantiation.\n *\n * @alias module:core/chart_base\n * @class\n */\n function Base() {\n this._series = [];\n this._labels = [];\n this._xaxes = [];\n this._yaxes = [];\n\n this._setDefaults();\n }\n\n /**\n * The series constituting this chart.\n *\n * @protected\n * @type {module:core/chart_series[]}\n */\n Base.prototype._series = null;\n\n /**\n * The labels of the X axis when categorised.\n *\n * @protected\n * @type {String[]}\n */\n Base.prototype._labels = null;\n\n /**\n * The title of the chart.\n *\n * @protected\n * @type {String}\n */\n Base.prototype._title = null;\n\n /**\n * The X axes.\n *\n * @protected\n * @type {module:core/chart_axis[]}\n */\n Base.prototype._xaxes = null;\n\n /**\n * The Y axes.\n *\n * @protected\n * @type {module:core/chart_axis[]}\n */\n Base.prototype._yaxes = null;\n\n /**\n * Colours to pick from when automatically assigning them.\n *\n * @const\n * @type {String[]}\n */\n Base.prototype.COLORSET = ['#f3c300', '#875692', '#f38400', '#a1caf1', '#be0032', '#c2b280', '#7f180d', '#008856',\n '#e68fac', '#0067a5'];\n\n /**\n * Set of colours defined by setting $CFG->chart_colorset to be picked when automatically assigning them.\n *\n * @type {String[]}\n * @protected\n */\n Base.prototype._configColorSet = null;\n\n /**\n * The type of chart.\n *\n * @abstract\n * @type {String}\n * @const\n */\n Base.prototype.TYPE = null;\n\n /**\n * Add a series to the chart.\n *\n * This will automatically assign a color to the series if it does not have one.\n *\n * @param {module:core/chart_series} series The series to add.\n */\n Base.prototype.addSeries = function(series) {\n this._validateSeries(series);\n this._series.push(series);\n\n // Give a default color from the set.\n if (series.getColor() === null) {\n var configColorSet = this.getConfigColorSet() || Base.prototype.COLORSET;\n series.setColor(configColorSet[this._series.length % configColorSet.length]);\n }\n };\n\n /**\n * Create a new instance of a chart from serialised data.\n *\n * the serialised attributes they offer and support.\n *\n * @static\n * @method create\n * @param {module:core/chart_base} Klass The class oject representing the type of chart to instantiate.\n * @param {Object} data The data of the chart.\n * @return {module:core/chart_base}\n */\n Base.prototype.create = function(Klass, data) {\n // TODO Not convinced about the usage of Klass here but I can't figure out a way\n // to have a reference to the class in the sub classes, in PHP I'd do new self().\n var Chart = new Klass();\n Chart.setConfigColorSet(data.config_colorset);\n Chart.setLabels(data.labels);\n Chart.setTitle(data.title);\n data.series.forEach(function(seriesData) {\n Chart.addSeries(Series.prototype.create(seriesData));\n });\n data.axes.x.forEach(function(axisData, i) {\n Chart.setXAxis(Axis.prototype.create(axisData), i);\n });\n data.axes.y.forEach(function(axisData, i) {\n Chart.setYAxis(Axis.prototype.create(axisData), i);\n });\n return Chart;\n };\n\n /**\n * Get an axis.\n *\n * @private\n * @param {String} xy Accepts the values 'x' or 'y'.\n * @param {Number} [index=0] The index of the axis of its type.\n * @param {Bool} [createIfNotExists=false] When true, create an instance if it does not exist.\n * @return {module:core/chart_axis}\n */\n Base.prototype.__getAxis = function(xy, index, createIfNotExists) {\n var axes = xy === 'x' ? this._xaxes : this._yaxes,\n setAxis = (xy === 'x' ? this.setXAxis : this.setYAxis).bind(this),\n axis;\n\n index = typeof index === 'undefined' ? 0 : index;\n createIfNotExists = typeof createIfNotExists === 'undefined' ? false : createIfNotExists;\n axis = axes[index];\n\n if (typeof axis === 'undefined') {\n if (!createIfNotExists) {\n throw new Error('Unknown axis.');\n }\n axis = new Axis();\n setAxis(axis, index);\n }\n\n return axis;\n };\n\n /**\n * Get colours defined by setting.\n *\n * @return {String[]}\n */\n Base.prototype.getConfigColorSet = function() {\n return this._configColorSet;\n };\n\n /**\n * Get the labels of the X axis.\n *\n * @return {String[]}\n */\n Base.prototype.getLabels = function() {\n return this._labels;\n };\n\n /**\n * Get the series.\n *\n * @return {module:core/chart_series[]}\n */\n Base.prototype.getSeries = function() {\n return this._series;\n };\n\n /**\n * Get the title of the chart.\n *\n * @return {String}\n */\n Base.prototype.getTitle = function() {\n return this._title;\n };\n\n /**\n * Get the type of chart.\n *\n * @see module:core/chart_base#TYPE\n * @return {String}\n */\n Base.prototype.getType = function() {\n if (!this.TYPE) {\n throw new Error('The TYPE property has not been set.');\n }\n return this.TYPE;\n };\n\n /**\n * Get the X axes.\n *\n * @return {module:core/chart_axis[]}\n */\n Base.prototype.getXAxes = function() {\n return this._xaxes;\n };\n\n /**\n * Get an X axis.\n *\n * @param {Number} [index=0] The index of the axis.\n * @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.\n * @return {module:core/chart_axis}\n */\n Base.prototype.getXAxis = function(index, createIfNotExists) {\n return this.__getAxis('x', index, createIfNotExists);\n };\n\n /**\n * Get the Y axes.\n *\n * @return {module:core/chart_axis[]}\n */\n Base.prototype.getYAxes = function() {\n return this._yaxes;\n };\n\n /**\n * Get an Y axis.\n *\n * @param {Number} [index=0] The index of the axis.\n * @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.\n * @return {module:core/chart_axis}\n */\n Base.prototype.getYAxis = function(index, createIfNotExists) {\n return this.__getAxis('y', index, createIfNotExists);\n };\n\n /**\n * Set colours defined by setting.\n *\n * @param {String[]} colorset An array of css colours.\n * @protected\n */\n Base.prototype.setConfigColorSet = function(colorset) {\n this._configColorSet = colorset;\n };\n\n /**\n * Set the defaults for this chart type.\n *\n * Child classes can extend this to set defaults values on instantiation.\n *\n * emphasize and self-document the defaults values set by the chart type.\n *\n * @protected\n */\n Base.prototype._setDefaults = function() {\n // For the children to extend.\n };\n\n /**\n * Set the labels of the X axis.\n *\n * This requires for each series to contain strictly as many values as there\n * are labels.\n *\n * @param {String[]} labels The labels.\n */\n Base.prototype.setLabels = function(labels) {\n if (labels.length && this._series.length && this._series[0].length != labels.length) {\n throw new Error('Series must match label values.');\n }\n this._labels = labels;\n };\n\n /**\n * Set the title of the chart.\n *\n * @param {String} title The title.\n */\n Base.prototype.setTitle = function(title) {\n this._title = title;\n };\n\n /**\n * Set an X axis.\n *\n * Note that this will override any predefined axis without warning.\n *\n * @param {module:core/chart_axis} axis The axis.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype.setXAxis = function(axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n this._validateAxis('x', axis, index);\n this._xaxes[index] = axis;\n };\n\n /**\n * Set a Y axis.\n *\n * Note that this will override any predefined axis without warning.\n *\n * @param {module:core/chart_axis} axis The axis.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype.setYAxis = function(axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n this._validateAxis('y', axis, index);\n this._yaxes[index] = axis;\n };\n\n /**\n * Validate an axis.\n *\n * @protected\n * @param {String} xy X or Y axis.\n * @param {module:core/chart_axis} axis The axis to validate.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype._validateAxis = function(xy, axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n if (index > 0) {\n var axes = xy == 'x' ? this._xaxes : this._yaxes;\n if (typeof axes[index - 1] === 'undefined') {\n throw new Error('Missing ' + xy + ' axis at index lower than ' + index);\n }\n }\n };\n\n /**\n * Validate a series.\n *\n * @protected\n * @param {module:core/chart_series} series The series to validate.\n */\n Base.prototype._validateSeries = function(series) {\n if (this._series.length && this._series[0].getCount() != series.getCount()) {\n throw new Error('Series do not have an equal number of values.');\n\n } else if (this._labels.length && this._labels.length != series.getCount()) {\n throw new Error('Series must match label values.');\n }\n };\n\n return Base;\n\n});\n"],"file":"chart_base.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/chart_base.js"],"names":["define","Series","Axis","Base","_series","_labels","_xaxes","_yaxes","_setDefaults","prototype","_legendOptions","_title","COLORSET","_configColorSet","TYPE","addSeries","series","_validateSeries","push","getColor","configColorSet","getConfigColorSet","setColor","length","create","Klass","data","Chart","setConfigColorSet","config_colorset","setLabels","labels","setTitle","title","legend_options","setLegendOptions","forEach","seriesData","axes","x","axisData","i","setXAxis","y","setYAxis","__getAxis","xy","index","createIfNotExists","setAxis","bind","axis","Error","getLabels","getLegendOptions","getSeries","getTitle","getType","getXAxes","getXAxis","getYAxes","getYAxis","colorset","legendOptions","_validateAxis","getCount"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Chart base.\n *\n * @package core\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @module core/chart_base\n */\ndefine(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {\n\n /**\n * Chart base.\n *\n * The constructor of a chart must never take any argument.\n *\n * {@link module:core/chart_base#_setDefault} to set the defaults on instantiation.\n *\n * @alias module:core/chart_base\n * @class\n */\n function Base() {\n this._series = [];\n this._labels = [];\n this._xaxes = [];\n this._yaxes = [];\n\n this._setDefaults();\n }\n\n /**\n * The series constituting this chart.\n *\n * @protected\n * @type {module:core/chart_series[]}\n */\n Base.prototype._series = null;\n\n /**\n * The labels of the X axis when categorised.\n *\n * @protected\n * @type {String[]}\n */\n Base.prototype._labels = null;\n\n /**\n * Options for chart legend display.\n *\n * @protected\n * @type {Object}\n */\n Base.prototype._legendOptions = null;\n\n /**\n * The title of the chart.\n *\n * @protected\n * @type {String}\n */\n Base.prototype._title = null;\n\n /**\n * The X axes.\n *\n * @protected\n * @type {module:core/chart_axis[]}\n */\n Base.prototype._xaxes = null;\n\n /**\n * The Y axes.\n *\n * @protected\n * @type {module:core/chart_axis[]}\n */\n Base.prototype._yaxes = null;\n\n /**\n * Colours to pick from when automatically assigning them.\n *\n * @const\n * @type {String[]}\n */\n Base.prototype.COLORSET = ['#f3c300', '#875692', '#f38400', '#a1caf1', '#be0032', '#c2b280', '#7f180d', '#008856',\n '#e68fac', '#0067a5'];\n\n /**\n * Set of colours defined by setting $CFG->chart_colorset to be picked when automatically assigning them.\n *\n * @type {String[]}\n * @protected\n */\n Base.prototype._configColorSet = null;\n\n /**\n * The type of chart.\n *\n * @abstract\n * @type {String}\n * @const\n */\n Base.prototype.TYPE = null;\n\n /**\n * Add a series to the chart.\n *\n * This will automatically assign a color to the series if it does not have one.\n *\n * @param {module:core/chart_series} series The series to add.\n */\n Base.prototype.addSeries = function(series) {\n this._validateSeries(series);\n this._series.push(series);\n\n // Give a default color from the set.\n if (series.getColor() === null) {\n var configColorSet = this.getConfigColorSet() || Base.prototype.COLORSET;\n series.setColor(configColorSet[this._series.length % configColorSet.length]);\n }\n };\n\n /**\n * Create a new instance of a chart from serialised data.\n *\n * the serialised attributes they offer and support.\n *\n * @static\n * @method create\n * @param {module:core/chart_base} Klass The class oject representing the type of chart to instantiate.\n * @param {Object} data The data of the chart.\n * @return {module:core/chart_base}\n */\n Base.prototype.create = function(Klass, data) {\n // TODO Not convinced about the usage of Klass here but I can't figure out a way\n // to have a reference to the class in the sub classes, in PHP I'd do new self().\n var Chart = new Klass();\n Chart.setConfigColorSet(data.config_colorset);\n Chart.setLabels(data.labels);\n Chart.setTitle(data.title);\n if (data.legend_options) {\n Chart.setLegendOptions(data.legend_options);\n }\n data.series.forEach(function(seriesData) {\n Chart.addSeries(Series.prototype.create(seriesData));\n });\n data.axes.x.forEach(function(axisData, i) {\n Chart.setXAxis(Axis.prototype.create(axisData), i);\n });\n data.axes.y.forEach(function(axisData, i) {\n Chart.setYAxis(Axis.prototype.create(axisData), i);\n });\n return Chart;\n };\n\n /**\n * Get an axis.\n *\n * @private\n * @param {String} xy Accepts the values 'x' or 'y'.\n * @param {Number} [index=0] The index of the axis of its type.\n * @param {Bool} [createIfNotExists=false] When true, create an instance if it does not exist.\n * @return {module:core/chart_axis}\n */\n Base.prototype.__getAxis = function(xy, index, createIfNotExists) {\n var axes = xy === 'x' ? this._xaxes : this._yaxes,\n setAxis = (xy === 'x' ? this.setXAxis : this.setYAxis).bind(this),\n axis;\n\n index = typeof index === 'undefined' ? 0 : index;\n createIfNotExists = typeof createIfNotExists === 'undefined' ? false : createIfNotExists;\n axis = axes[index];\n\n if (typeof axis === 'undefined') {\n if (!createIfNotExists) {\n throw new Error('Unknown axis.');\n }\n axis = new Axis();\n setAxis(axis, index);\n }\n\n return axis;\n };\n\n /**\n * Get colours defined by setting.\n *\n * @return {String[]}\n */\n Base.prototype.getConfigColorSet = function() {\n return this._configColorSet;\n };\n\n /**\n * Get the labels of the X axis.\n *\n * @return {String[]}\n */\n Base.prototype.getLabels = function() {\n return this._labels;\n };\n\n /**\n * Get whether to display the chart legend.\n *\n * @return {Bool}\n */\n Base.prototype.getLegendOptions = function() {\n return this._legendOptions;\n };\n\n /**\n * Get the series.\n *\n * @return {module:core/chart_series[]}\n */\n Base.prototype.getSeries = function() {\n return this._series;\n };\n\n /**\n * Get the title of the chart.\n *\n * @return {String}\n */\n Base.prototype.getTitle = function() {\n return this._title;\n };\n\n /**\n * Get the type of chart.\n *\n * @see module:core/chart_base#TYPE\n * @return {String}\n */\n Base.prototype.getType = function() {\n if (!this.TYPE) {\n throw new Error('The TYPE property has not been set.');\n }\n return this.TYPE;\n };\n\n /**\n * Get the X axes.\n *\n * @return {module:core/chart_axis[]}\n */\n Base.prototype.getXAxes = function() {\n return this._xaxes;\n };\n\n /**\n * Get an X axis.\n *\n * @param {Number} [index=0] The index of the axis.\n * @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.\n * @return {module:core/chart_axis}\n */\n Base.prototype.getXAxis = function(index, createIfNotExists) {\n return this.__getAxis('x', index, createIfNotExists);\n };\n\n /**\n * Get the Y axes.\n *\n * @return {module:core/chart_axis[]}\n */\n Base.prototype.getYAxes = function() {\n return this._yaxes;\n };\n\n /**\n * Get an Y axis.\n *\n * @param {Number} [index=0] The index of the axis.\n * @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.\n * @return {module:core/chart_axis}\n */\n Base.prototype.getYAxis = function(index, createIfNotExists) {\n return this.__getAxis('y', index, createIfNotExists);\n };\n\n /**\n * Set colours defined by setting.\n *\n * @param {String[]} colorset An array of css colours.\n * @protected\n */\n Base.prototype.setConfigColorSet = function(colorset) {\n this._configColorSet = colorset;\n };\n\n /**\n * Set the defaults for this chart type.\n *\n * Child classes can extend this to set defaults values on instantiation.\n *\n * emphasize and self-document the defaults values set by the chart type.\n *\n * @protected\n */\n Base.prototype._setDefaults = function() {\n // For the children to extend.\n };\n\n /**\n * Set the labels of the X axis.\n *\n * This requires for each series to contain strictly as many values as there\n * are labels.\n *\n * @param {String[]} labels The labels.\n */\n Base.prototype.setLabels = function(labels) {\n if (labels.length && this._series.length && this._series[0].length != labels.length) {\n throw new Error('Series must match label values.');\n }\n this._labels = labels;\n };\n\n /**\n * Set options for chart legend display.\n *\n * @param {Object} legendOptions\n */\n Base.prototype.setLegendOptions = function(legendOptions) {\n if (typeof legendOptions !== 'object') {\n throw new Error('Setting legend with non-object value:' + legendOptions);\n }\n this._legendOptions = legendOptions;\n };\n\n /**\n * Set the title of the chart.\n *\n * @param {String} title The title.\n */\n Base.prototype.setTitle = function(title) {\n this._title = title;\n };\n\n /**\n * Set an X axis.\n *\n * Note that this will override any predefined axis without warning.\n *\n * @param {module:core/chart_axis} axis The axis.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype.setXAxis = function(axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n this._validateAxis('x', axis, index);\n this._xaxes[index] = axis;\n };\n\n /**\n * Set a Y axis.\n *\n * Note that this will override any predefined axis without warning.\n *\n * @param {module:core/chart_axis} axis The axis.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype.setYAxis = function(axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n this._validateAxis('y', axis, index);\n this._yaxes[index] = axis;\n };\n\n /**\n * Validate an axis.\n *\n * @protected\n * @param {String} xy X or Y axis.\n * @param {module:core/chart_axis} axis The axis to validate.\n * @param {Number} [index=0] The index of the axis.\n */\n Base.prototype._validateAxis = function(xy, axis, index) {\n index = typeof index === 'undefined' ? 0 : index;\n if (index > 0) {\n var axes = xy == 'x' ? this._xaxes : this._yaxes;\n if (typeof axes[index - 1] === 'undefined') {\n throw new Error('Missing ' + xy + ' axis at index lower than ' + index);\n }\n }\n };\n\n /**\n * Validate a series.\n *\n * @protected\n * @param {module:core/chart_series} series The series to validate.\n */\n Base.prototype._validateSeries = function(series) {\n if (this._series.length && this._series[0].getCount() != series.getCount()) {\n throw new Error('Series do not have an equal number of values.');\n\n } else if (this._labels.length && this._labels.length != series.getCount()) {\n throw new Error('Series must match label values.');\n }\n };\n\n return Base;\n\n});\n"],"file":"chart_base.min.js"} \ No newline at end of file diff --git a/lib/amd/build/chart_output_chartjs.min.js b/lib/amd/build/chart_output_chartjs.min.js index b6f1a7196fe..0f6373b79a0 100644 --- a/lib/amd/build/chart_output_chartjs.min.js +++ b/lib/amd/build/chart_output_chartjs.min.js @@ -1,2 +1,2 @@ -define ("core/chart_output_chartjs",["jquery","core/chartjs","core/chart_axis","core/chart_bar","core/chart_output_base","core/chart_line","core/chart_pie","core/chart_series"],function(a,b,c,d,e,f,g,h){var j=function(a,b){return"axis-"+a+"-"+b};function i(){e.prototype.constructor.apply(this,arguments);this._canvas=this._node;if("CANVAS"!=this._canvas.prop("tagName")){this._canvas=a("");this._node.append(this._canvas)}this._build()}i.prototype=Object.create(e.prototype);i.prototype._config=null;i.prototype._chartjs=null;i.prototype._canvas=null;i.prototype._build=function(){this._config=this._makeConfig();this._chartjs=new b(this._canvas[0],this._config)};i.prototype._cleanData=function(b){if(b instanceof Array){return b.map(function(b){return a("").html(b).text()})}else{return a("").html(b).text()}};i.prototype._getChartType=function(){var a=this._chart.getType();if(this._chart.getType()===d.prototype.TYPE&&!0===this._chart.getHorizontal()){a="horizontalBar"}else if(this._chart.getType()===g.prototype.TYPE&&!0===this._chart.getDoughnut()){a="doughnut"}return a};i.prototype._makeAxisConfig=function(a,b,d){var e={id:j(b,d)};if(a.getPosition()!==c.prototype.POS_DEFAULT){e.position=a.getPosition()}if(null!==a.getLabel()){e.scaleLabel={display:!0,labelString:this._cleanData(a.getLabel())}}if(null!==a.getStepSize()){e.ticks=e.ticks||{};e.ticks.stepSize=a.getStepSize()}if(null!==a.getMax()){e.ticks=e.ticks||{};e.ticks.max=a.getMax()}if(null!==a.getMin()){e.ticks=e.ticks||{};e.ticks.min=a.getMin()}return e};i.prototype._makeConfig=function(){var a={type:this._getChartType(),data:{labels:this._cleanData(this._chart.getLabels()),datasets:this._makeDatasetsConfig()},options:{title:{display:null!==this._chart.getTitle(),text:this._cleanData(this._chart.getTitle())}}};this._chart.getXAxes().forEach(function(b,c){var d=b.getLabels();a.options.scales=a.options.scales||{};a.options.scales.xAxes=a.options.scales.xAxes||[];a.options.scales.xAxes[c]=this._makeAxisConfig(b,"x",c);if(null!==d){a.options.scales.xAxes[c].ticks.callback=function(a,b){return d[b]||""}}a.options.scales.xAxes[c].stacked=this._isStacked()}.bind(this));this._chart.getYAxes().forEach(function(b,c){var d=b.getLabels();a.options.scales=a.options.scales||{};a.options.scales.yAxes=a.options.scales.yAxes||[];a.options.scales.yAxes[c]=this._makeAxisConfig(b,"y",c);if(null!==d){a.options.scales.yAxes[c].ticks.callback=function(a){return d[parseInt(a,10)]||""}}a.options.scales.yAxes[c].stacked=this._isStacked()}.bind(this));a.options.tooltips={callbacks:{label:this._makeTooltip.bind(this)}};return a};i.prototype._makeDatasetsConfig=function(){var a=this._chart.getSeries().map(function(a){var b=a.hasColoredValues()?a.getColors():a.getColor(),c={label:this._cleanData(a.getLabel()),data:a.getValues(),type:a.getType(),fill:a.getFill(),backgroundColor:b,borderColor:this._chart.getType()==g.prototype.TYPE?"#fff":b,lineTension:this._isSmooth(a)?.3:0};if(null!==a.getXAxis()){c.xAxisID=j("x",a.getXAxis())}if(null!==a.getYAxis()){c.yAxisID=j("y",a.getYAxis())}return c}.bind(this));return a};i.prototype._makeTooltip=function(a,b){var c=this._chart.getSeries()[a.datasetIndex],d=c.getLabel(),e=c.getLabels(),f=b.datasets[a.datasetIndex].data,g=f[a.index],h=[];if(""==a.xLabel&&""==a.yLabel){var i=this._cleanData(this._chart.getLabels());h.push(i[a.index])}if(null!==e){h.push(this._cleanData(e[a.index]))}else{h.push(this._cleanData(d)+": "+g)}return h};i.prototype._isSmooth=function(a){var b=!1;if(this._chart.getType()===f.prototype.TYPE){b=a.getSmooth();if(null===b){b=this._chart.getSmooth()}}else if(a.getType()===h.prototype.TYPE_LINE){b=a.getSmooth()}return b};i.prototype._isStacked=function(){var a=!1;if(this._chart.getType()===d.prototype.TYPE){a=this._chart.getStacked()}return a};i.prototype.update=function(){a.extend(!0,this._config,this._makeConfig());this._chartjs.update()};return i}); +define ("core/chart_output_chartjs",["jquery","core/chartjs","core/chart_axis","core/chart_bar","core/chart_output_base","core/chart_line","core/chart_pie","core/chart_series"],function(a,b,c,d,e,f,g,h){var j=function(a,b){return"axis-"+a+"-"+b};function i(){e.prototype.constructor.apply(this,arguments);this._canvas=this._node;if("CANVAS"!=this._canvas.prop("tagName")){this._canvas=a("");this._node.append(this._canvas)}this._build()}i.prototype=Object.create(e.prototype);i.prototype._config=null;i.prototype._chartjs=null;i.prototype._canvas=null;i.prototype._build=function(){this._config=this._makeConfig();this._chartjs=new b(this._canvas[0],this._config)};i.prototype._cleanData=function(b){if(b instanceof Array){return b.map(function(b){return a("").html(b).text()})}else{return a("").html(b).text()}};i.prototype._getChartType=function(){var a=this._chart.getType();if(this._chart.getType()===d.prototype.TYPE&&!0===this._chart.getHorizontal()){a="horizontalBar"}else if(this._chart.getType()===g.prototype.TYPE&&!0===this._chart.getDoughnut()){a="doughnut"}return a};i.prototype._makeAxisConfig=function(a,b,d){var e={id:j(b,d)};if(a.getPosition()!==c.prototype.POS_DEFAULT){e.position=a.getPosition()}if(null!==a.getLabel()){e.scaleLabel={display:!0,labelString:this._cleanData(a.getLabel())}}if(null!==a.getStepSize()){e.ticks=e.ticks||{};e.ticks.stepSize=a.getStepSize()}if(null!==a.getMax()){e.ticks=e.ticks||{};e.ticks.max=a.getMax()}if(null!==a.getMin()){e.ticks=e.ticks||{};e.ticks.min=a.getMin()}return e};i.prototype._makeConfig=function(){var a={type:this._getChartType(),data:{labels:this._cleanData(this._chart.getLabels()),datasets:this._makeDatasetsConfig()},options:{title:{display:null!==this._chart.getTitle(),text:this._cleanData(this._chart.getTitle())}}},b=this._chart.getLegendOptions();if(b){a.options.legend=b}this._chart.getXAxes().forEach(function(b,c){var d=b.getLabels();a.options.scales=a.options.scales||{};a.options.scales.xAxes=a.options.scales.xAxes||[];a.options.scales.xAxes[c]=this._makeAxisConfig(b,"x",c);if(null!==d){a.options.scales.xAxes[c].ticks.callback=function(a,b){return d[b]||""}}a.options.scales.xAxes[c].stacked=this._isStacked()}.bind(this));this._chart.getYAxes().forEach(function(b,c){var d=b.getLabels();a.options.scales=a.options.scales||{};a.options.scales.yAxes=a.options.scales.yAxes||[];a.options.scales.yAxes[c]=this._makeAxisConfig(b,"y",c);if(null!==d){a.options.scales.yAxes[c].ticks.callback=function(a){return d[parseInt(a,10)]||""}}a.options.scales.yAxes[c].stacked=this._isStacked()}.bind(this));a.options.tooltips={callbacks:{label:this._makeTooltip.bind(this)}};return a};i.prototype._makeDatasetsConfig=function(){var a=this._chart.getSeries().map(function(a){var b=a.hasColoredValues()?a.getColors():a.getColor(),c={label:this._cleanData(a.getLabel()),data:a.getValues(),type:a.getType(),fill:a.getFill(),backgroundColor:b,borderColor:this._chart.getType()==g.prototype.TYPE?"#fff":b,lineTension:this._isSmooth(a)?.3:0};if(null!==a.getXAxis()){c.xAxisID=j("x",a.getXAxis())}if(null!==a.getYAxis()){c.yAxisID=j("y",a.getYAxis())}return c}.bind(this));return a};i.prototype._makeTooltip=function(a,b){var c=this._chart.getSeries()[a.datasetIndex],d=c.getLabel(),e=c.getLabels(),f=b.datasets[a.datasetIndex].data,g=f[a.index],h=[];if(""==a.xLabel&&""==a.yLabel){var i=this._cleanData(this._chart.getLabels());h.push(i[a.index])}if(null!==e){h.push(this._cleanData(e[a.index]))}else{h.push(this._cleanData(d)+": "+g)}return h};i.prototype._isSmooth=function(a){var b=!1;if(this._chart.getType()===f.prototype.TYPE){b=a.getSmooth();if(null===b){b=this._chart.getSmooth()}}else if(a.getType()===h.prototype.TYPE_LINE){b=a.getSmooth()}return b};i.prototype._isStacked=function(){var a=!1;if(this._chart.getType()===d.prototype.TYPE){a=this._chart.getStacked()}return a};i.prototype.update=function(){a.extend(!0,this._config,this._makeConfig());this._chartjs.update()};return i}); //# sourceMappingURL=chart_output_chartjs.min.js.map diff --git a/lib/amd/build/chart_output_chartjs.min.js.map b/lib/amd/build/chart_output_chartjs.min.js.map index 1dfb6f5cde7..00452c680ef 100644 --- a/lib/amd/build/chart_output_chartjs.min.js.map +++ b/lib/amd/build/chart_output_chartjs.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/chart_output_chartjs.js"],"names":["define","$","Chartjs","Axis","Bar","Base","Line","Pie","Series","makeAxisId","xy","index","Output","prototype","constructor","apply","arguments","_canvas","_node","prop","append","_build","Object","create","_config","_chartjs","_makeConfig","_cleanData","data","Array","map","value","html","text","_getChartType","type","_chart","getType","TYPE","getHorizontal","getDoughnut","_makeAxisConfig","axis","scaleData","id","getPosition","POS_DEFAULT","position","getLabel","scaleLabel","display","labelString","getStepSize","ticks","stepSize","getMax","max","getMin","min","config","labels","getLabels","datasets","_makeDatasetsConfig","options","title","getTitle","getXAxes","forEach","i","axisLabels","scales","xAxes","callback","stacked","_isStacked","bind","getYAxes","yAxes","parseInt","tooltips","callbacks","label","_makeTooltip","sets","getSeries","series","colors","hasColoredValues","getColors","getColor","dataset","getValues","fill","getFill","backgroundColor","borderColor","lineTension","_isSmooth","getXAxis","xAxisID","getYAxis","yAxisID","tooltipItem","datasetIndex","serieLabel","serieLabels","chartData","tooltipData","tooltip","xLabel","yLabel","chartLabels","push","smooth","getSmooth","TYPE_LINE","getStacked","update","extend"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Chart output for chart.js.\n *\n * @package core\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @module core/chart_output_chartjs\n */\ndefine([\n 'jquery',\n 'core/chartjs',\n 'core/chart_axis',\n 'core/chart_bar',\n 'core/chart_output_base',\n 'core/chart_line',\n 'core/chart_pie',\n 'core/chart_series'\n], function($, Chartjs, Axis, Bar, Base, Line, Pie, Series) {\n\n /**\n * Makes an axis ID.\n *\n * @param {String} xy Accepts 'x' and 'y'.\n * @param {Number} index The axis index.\n * @return {String}\n */\n var makeAxisId = function(xy, index) {\n return 'axis-' + xy + '-' + index;\n };\n\n /**\n * Chart output for Chart.js.\n *\n * @class\n * @alias module:core/chart_output_chartjs\n * @extends {module:core/chart_output_base}\n */\n function Output() {\n Base.prototype.constructor.apply(this, arguments);\n\n // Make sure that we've got a canvas tag.\n this._canvas = this._node;\n if (this._canvas.prop('tagName') != 'CANVAS') {\n this._canvas = $('');\n this._node.append(this._canvas);\n }\n\n this._build();\n }\n Output.prototype = Object.create(Base.prototype);\n\n /**\n * Reference to the chart config object.\n *\n * @type {Object}\n * @protected\n */\n Output.prototype._config = null;\n\n /**\n * Reference to the instance of chart.js.\n *\n * @type {Object}\n * @protected\n */\n Output.prototype._chartjs = null;\n\n /**\n * Reference to the canvas node.\n *\n * @type {Jquery}\n * @protected\n */\n Output.prototype._canvas = null;\n\n /**\n * Builds the config and the chart.\n *\n * @protected\n */\n Output.prototype._build = function() {\n this._config = this._makeConfig();\n this._chartjs = new Chartjs(this._canvas[0], this._config);\n };\n\n /**\n * Clean data.\n *\n * @param {(String|String[])} data A single string or an array of strings.\n * @returns {(String|String[])}\n * @protected\n */\n Output.prototype._cleanData = function(data) {\n if (data instanceof Array) {\n return data.map(function(value) {\n return $('').html(value).text();\n });\n } else {\n return $('').html(data).text();\n }\n };\n\n /**\n * Get the chart type and handles the Chart.js specific chart types.\n *\n * By default returns the current chart TYPE value. Also does the handling of specific chart types, for example\n * check if the bar chart should be horizontal and the pie chart should be displayed as a doughnut.\n *\n * @method getChartType\n * @returns {String} the chart type.\n * @protected\n */\n Output.prototype._getChartType = function() {\n var type = this._chart.getType();\n\n // Bars can be displayed vertically and horizontally, defining horizontalBar type.\n if (this._chart.getType() === Bar.prototype.TYPE && this._chart.getHorizontal() === true) {\n type = 'horizontalBar';\n } else if (this._chart.getType() === Pie.prototype.TYPE && this._chart.getDoughnut() === true) {\n // Pie chart can be displayed as doughnut.\n type = 'doughnut';\n }\n\n return type;\n };\n\n /**\n * Make the axis config.\n *\n * @protected\n * @param {module:core/chart_axis} axis The axis.\n * @param {String} xy Accepts 'x' or 'y'.\n * @param {Number} index The axis index.\n * @return {Object} The axis config.\n */\n Output.prototype._makeAxisConfig = function(axis, xy, index) {\n var scaleData = {\n id: makeAxisId(xy, index)\n };\n\n if (axis.getPosition() !== Axis.prototype.POS_DEFAULT) {\n scaleData.position = axis.getPosition();\n }\n\n if (axis.getLabel() !== null) {\n scaleData.scaleLabel = {\n display: true,\n labelString: this._cleanData(axis.getLabel())\n };\n }\n\n if (axis.getStepSize() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.stepSize = axis.getStepSize();\n }\n\n if (axis.getMax() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.max = axis.getMax();\n }\n\n if (axis.getMin() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.min = axis.getMin();\n }\n\n return scaleData;\n };\n\n /**\n * Make the config config.\n *\n * @protected\n * @param {module:core/chart_axis} axis The axis.\n * @return {Object} The axis config.\n */\n Output.prototype._makeConfig = function() {\n var config = {\n type: this._getChartType(),\n data: {\n labels: this._cleanData(this._chart.getLabels()),\n datasets: this._makeDatasetsConfig()\n },\n options: {\n title: {\n display: this._chart.getTitle() !== null,\n text: this._cleanData(this._chart.getTitle())\n }\n }\n };\n\n this._chart.getXAxes().forEach(function(axis, i) {\n var axisLabels = axis.getLabels();\n\n config.options.scales = config.options.scales || {};\n config.options.scales.xAxes = config.options.scales.xAxes || [];\n config.options.scales.xAxes[i] = this._makeAxisConfig(axis, 'x', i);\n\n if (axisLabels !== null) {\n config.options.scales.xAxes[i].ticks.callback = function(value, index) {\n return axisLabels[index] || '';\n };\n }\n config.options.scales.xAxes[i].stacked = this._isStacked();\n }.bind(this));\n\n this._chart.getYAxes().forEach(function(axis, i) {\n var axisLabels = axis.getLabels();\n\n config.options.scales = config.options.scales || {};\n config.options.scales.yAxes = config.options.scales.yAxes || [];\n config.options.scales.yAxes[i] = this._makeAxisConfig(axis, 'y', i);\n\n if (axisLabels !== null) {\n config.options.scales.yAxes[i].ticks.callback = function(value) {\n return axisLabels[parseInt(value, 10)] || '';\n };\n }\n config.options.scales.yAxes[i].stacked = this._isStacked();\n }.bind(this));\n\n config.options.tooltips = {\n callbacks: {\n label: this._makeTooltip.bind(this)\n }\n };\n\n return config;\n };\n\n /**\n * Get the datasets configurations.\n *\n * @protected\n * @return {Object[]}\n */\n Output.prototype._makeDatasetsConfig = function() {\n var sets = this._chart.getSeries().map(function(series) {\n var colors = series.hasColoredValues() ? series.getColors() : series.getColor();\n var dataset = {\n label: this._cleanData(series.getLabel()),\n data: series.getValues(),\n type: series.getType(),\n fill: series.getFill(),\n backgroundColor: colors,\n // Pie charts look better without borders.\n borderColor: this._chart.getType() == Pie.prototype.TYPE ? '#fff' : colors,\n lineTension: this._isSmooth(series) ? 0.3 : 0\n };\n\n if (series.getXAxis() !== null) {\n dataset.xAxisID = makeAxisId('x', series.getXAxis());\n }\n if (series.getYAxis() !== null) {\n dataset.yAxisID = makeAxisId('y', series.getYAxis());\n }\n\n return dataset;\n }.bind(this));\n return sets;\n };\n\n /**\n * Get the chart data, add labels and rebuild the tooltip.\n *\n * @param {Object[]} tooltipItem The tooltip item data.\n * @param {Object[]} data The chart data.\n * @returns {String}\n * @protected\n */\n Output.prototype._makeTooltip = function(tooltipItem, data) {\n\n // Get series and chart data to rebuild the tooltip and add labels.\n var series = this._chart.getSeries()[tooltipItem.datasetIndex];\n var serieLabel = series.getLabel();\n var serieLabels = series.getLabels();\n var chartData = data.datasets[tooltipItem.datasetIndex].data;\n var tooltipData = chartData[tooltipItem.index];\n\n // Build default tooltip.\n var tooltip = [];\n\n // Pie and doughnut charts does not have axis.\n if (tooltipItem.xLabel == '' && tooltipItem.yLabel == '') {\n var chartLabels = this._cleanData(this._chart.getLabels());\n tooltip.push(chartLabels[tooltipItem.index]);\n }\n\n // Add series labels to the tooltip if any.\n if (serieLabels !== null) {\n tooltip.push(this._cleanData(serieLabels[tooltipItem.index]));\n } else {\n tooltip.push(this._cleanData(serieLabel) + ': ' + tooltipData);\n }\n\n return tooltip;\n };\n\n /**\n * Verify if the chart line is smooth or not.\n *\n * @protected\n * @param {module:core/chart_series} series The series.\n * @returns {Bool}\n */\n Output.prototype._isSmooth = function(series) {\n var smooth = false;\n if (this._chart.getType() === Line.prototype.TYPE) {\n smooth = series.getSmooth();\n if (smooth === null) {\n smooth = this._chart.getSmooth();\n }\n } else if (series.getType() === Series.prototype.TYPE_LINE) {\n smooth = series.getSmooth();\n }\n\n return smooth;\n };\n\n /**\n * Verify if the bar chart is stacked or not.\n *\n * @protected\n * @returns {Bool}\n */\n Output.prototype._isStacked = function() {\n var stacked = false;\n\n // Stacking is (currently) only supported for bar charts.\n if (this._chart.getType() === Bar.prototype.TYPE) {\n stacked = this._chart.getStacked();\n }\n\n return stacked;\n };\n\n /** @override */\n Output.prototype.update = function() {\n $.extend(true, this._config, this._makeConfig());\n this._chartjs.update();\n };\n\n return Output;\n\n});\n"],"file":"chart_output_chartjs.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/chart_output_chartjs.js"],"names":["define","$","Chartjs","Axis","Bar","Base","Line","Pie","Series","makeAxisId","xy","index","Output","prototype","constructor","apply","arguments","_canvas","_node","prop","append","_build","Object","create","_config","_chartjs","_makeConfig","_cleanData","data","Array","map","value","html","text","_getChartType","type","_chart","getType","TYPE","getHorizontal","getDoughnut","_makeAxisConfig","axis","scaleData","id","getPosition","POS_DEFAULT","position","getLabel","scaleLabel","display","labelString","getStepSize","ticks","stepSize","getMax","max","getMin","min","config","labels","getLabels","datasets","_makeDatasetsConfig","options","title","getTitle","legendOptions","getLegendOptions","legend","getXAxes","forEach","i","axisLabels","scales","xAxes","callback","stacked","_isStacked","bind","getYAxes","yAxes","parseInt","tooltips","callbacks","label","_makeTooltip","sets","getSeries","series","colors","hasColoredValues","getColors","getColor","dataset","getValues","fill","getFill","backgroundColor","borderColor","lineTension","_isSmooth","getXAxis","xAxisID","getYAxis","yAxisID","tooltipItem","datasetIndex","serieLabel","serieLabels","chartData","tooltipData","tooltip","xLabel","yLabel","chartLabels","push","smooth","getSmooth","TYPE_LINE","getStacked","update","extend"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Chart output for chart.js.\n *\n * @package core\n * @copyright 2016 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @module core/chart_output_chartjs\n */\ndefine([\n 'jquery',\n 'core/chartjs',\n 'core/chart_axis',\n 'core/chart_bar',\n 'core/chart_output_base',\n 'core/chart_line',\n 'core/chart_pie',\n 'core/chart_series'\n], function($, Chartjs, Axis, Bar, Base, Line, Pie, Series) {\n\n /**\n * Makes an axis ID.\n *\n * @param {String} xy Accepts 'x' and 'y'.\n * @param {Number} index The axis index.\n * @return {String}\n */\n var makeAxisId = function(xy, index) {\n return 'axis-' + xy + '-' + index;\n };\n\n /**\n * Chart output for Chart.js.\n *\n * @class\n * @alias module:core/chart_output_chartjs\n * @extends {module:core/chart_output_base}\n */\n function Output() {\n Base.prototype.constructor.apply(this, arguments);\n\n // Make sure that we've got a canvas tag.\n this._canvas = this._node;\n if (this._canvas.prop('tagName') != 'CANVAS') {\n this._canvas = $('');\n this._node.append(this._canvas);\n }\n\n this._build();\n }\n Output.prototype = Object.create(Base.prototype);\n\n /**\n * Reference to the chart config object.\n *\n * @type {Object}\n * @protected\n */\n Output.prototype._config = null;\n\n /**\n * Reference to the instance of chart.js.\n *\n * @type {Object}\n * @protected\n */\n Output.prototype._chartjs = null;\n\n /**\n * Reference to the canvas node.\n *\n * @type {Jquery}\n * @protected\n */\n Output.prototype._canvas = null;\n\n /**\n * Builds the config and the chart.\n *\n * @protected\n */\n Output.prototype._build = function() {\n this._config = this._makeConfig();\n this._chartjs = new Chartjs(this._canvas[0], this._config);\n };\n\n /**\n * Clean data.\n *\n * @param {(String|String[])} data A single string or an array of strings.\n * @returns {(String|String[])}\n * @protected\n */\n Output.prototype._cleanData = function(data) {\n if (data instanceof Array) {\n return data.map(function(value) {\n return $('').html(value).text();\n });\n } else {\n return $('').html(data).text();\n }\n };\n\n /**\n * Get the chart type and handles the Chart.js specific chart types.\n *\n * By default returns the current chart TYPE value. Also does the handling of specific chart types, for example\n * check if the bar chart should be horizontal and the pie chart should be displayed as a doughnut.\n *\n * @method getChartType\n * @returns {String} the chart type.\n * @protected\n */\n Output.prototype._getChartType = function() {\n var type = this._chart.getType();\n\n // Bars can be displayed vertically and horizontally, defining horizontalBar type.\n if (this._chart.getType() === Bar.prototype.TYPE && this._chart.getHorizontal() === true) {\n type = 'horizontalBar';\n } else if (this._chart.getType() === Pie.prototype.TYPE && this._chart.getDoughnut() === true) {\n // Pie chart can be displayed as doughnut.\n type = 'doughnut';\n }\n\n return type;\n };\n\n /**\n * Make the axis config.\n *\n * @protected\n * @param {module:core/chart_axis} axis The axis.\n * @param {String} xy Accepts 'x' or 'y'.\n * @param {Number} index The axis index.\n * @return {Object} The axis config.\n */\n Output.prototype._makeAxisConfig = function(axis, xy, index) {\n var scaleData = {\n id: makeAxisId(xy, index)\n };\n\n if (axis.getPosition() !== Axis.prototype.POS_DEFAULT) {\n scaleData.position = axis.getPosition();\n }\n\n if (axis.getLabel() !== null) {\n scaleData.scaleLabel = {\n display: true,\n labelString: this._cleanData(axis.getLabel())\n };\n }\n\n if (axis.getStepSize() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.stepSize = axis.getStepSize();\n }\n\n if (axis.getMax() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.max = axis.getMax();\n }\n\n if (axis.getMin() !== null) {\n scaleData.ticks = scaleData.ticks || {};\n scaleData.ticks.min = axis.getMin();\n }\n\n return scaleData;\n };\n\n /**\n * Make the config config.\n *\n * @protected\n * @param {module:core/chart_axis} axis The axis.\n * @return {Object} The axis config.\n */\n Output.prototype._makeConfig = function() {\n var config = {\n type: this._getChartType(),\n data: {\n labels: this._cleanData(this._chart.getLabels()),\n datasets: this._makeDatasetsConfig()\n },\n options: {\n title: {\n display: this._chart.getTitle() !== null,\n text: this._cleanData(this._chart.getTitle())\n }\n }\n };\n var legendOptions = this._chart.getLegendOptions();\n if (legendOptions) {\n config.options.legend = legendOptions;\n }\n\n\n this._chart.getXAxes().forEach(function(axis, i) {\n var axisLabels = axis.getLabels();\n\n config.options.scales = config.options.scales || {};\n config.options.scales.xAxes = config.options.scales.xAxes || [];\n config.options.scales.xAxes[i] = this._makeAxisConfig(axis, 'x', i);\n\n if (axisLabels !== null) {\n config.options.scales.xAxes[i].ticks.callback = function(value, index) {\n return axisLabels[index] || '';\n };\n }\n config.options.scales.xAxes[i].stacked = this._isStacked();\n }.bind(this));\n\n this._chart.getYAxes().forEach(function(axis, i) {\n var axisLabels = axis.getLabels();\n\n config.options.scales = config.options.scales || {};\n config.options.scales.yAxes = config.options.scales.yAxes || [];\n config.options.scales.yAxes[i] = this._makeAxisConfig(axis, 'y', i);\n\n if (axisLabels !== null) {\n config.options.scales.yAxes[i].ticks.callback = function(value) {\n return axisLabels[parseInt(value, 10)] || '';\n };\n }\n config.options.scales.yAxes[i].stacked = this._isStacked();\n }.bind(this));\n\n config.options.tooltips = {\n callbacks: {\n label: this._makeTooltip.bind(this)\n }\n };\n\n return config;\n };\n\n /**\n * Get the datasets configurations.\n *\n * @protected\n * @return {Object[]}\n */\n Output.prototype._makeDatasetsConfig = function() {\n var sets = this._chart.getSeries().map(function(series) {\n var colors = series.hasColoredValues() ? series.getColors() : series.getColor();\n var dataset = {\n label: this._cleanData(series.getLabel()),\n data: series.getValues(),\n type: series.getType(),\n fill: series.getFill(),\n backgroundColor: colors,\n // Pie charts look better without borders.\n borderColor: this._chart.getType() == Pie.prototype.TYPE ? '#fff' : colors,\n lineTension: this._isSmooth(series) ? 0.3 : 0\n };\n\n if (series.getXAxis() !== null) {\n dataset.xAxisID = makeAxisId('x', series.getXAxis());\n }\n if (series.getYAxis() !== null) {\n dataset.yAxisID = makeAxisId('y', series.getYAxis());\n }\n\n return dataset;\n }.bind(this));\n return sets;\n };\n\n /**\n * Get the chart data, add labels and rebuild the tooltip.\n *\n * @param {Object[]} tooltipItem The tooltip item data.\n * @param {Object[]} data The chart data.\n * @returns {String}\n * @protected\n */\n Output.prototype._makeTooltip = function(tooltipItem, data) {\n\n // Get series and chart data to rebuild the tooltip and add labels.\n var series = this._chart.getSeries()[tooltipItem.datasetIndex];\n var serieLabel = series.getLabel();\n var serieLabels = series.getLabels();\n var chartData = data.datasets[tooltipItem.datasetIndex].data;\n var tooltipData = chartData[tooltipItem.index];\n\n // Build default tooltip.\n var tooltip = [];\n\n // Pie and doughnut charts does not have axis.\n if (tooltipItem.xLabel == '' && tooltipItem.yLabel == '') {\n var chartLabels = this._cleanData(this._chart.getLabels());\n tooltip.push(chartLabels[tooltipItem.index]);\n }\n\n // Add series labels to the tooltip if any.\n if (serieLabels !== null) {\n tooltip.push(this._cleanData(serieLabels[tooltipItem.index]));\n } else {\n tooltip.push(this._cleanData(serieLabel) + ': ' + tooltipData);\n }\n\n return tooltip;\n };\n\n /**\n * Verify if the chart line is smooth or not.\n *\n * @protected\n * @param {module:core/chart_series} series The series.\n * @returns {Bool}\n */\n Output.prototype._isSmooth = function(series) {\n var smooth = false;\n if (this._chart.getType() === Line.prototype.TYPE) {\n smooth = series.getSmooth();\n if (smooth === null) {\n smooth = this._chart.getSmooth();\n }\n } else if (series.getType() === Series.prototype.TYPE_LINE) {\n smooth = series.getSmooth();\n }\n\n return smooth;\n };\n\n /**\n * Verify if the bar chart is stacked or not.\n *\n * @protected\n * @returns {Bool}\n */\n Output.prototype._isStacked = function() {\n var stacked = false;\n\n // Stacking is (currently) only supported for bar charts.\n if (this._chart.getType() === Bar.prototype.TYPE) {\n stacked = this._chart.getStacked();\n }\n\n return stacked;\n };\n\n /** @override */\n Output.prototype.update = function() {\n $.extend(true, this._config, this._makeConfig());\n this._chartjs.update();\n };\n\n return Output;\n\n});\n"],"file":"chart_output_chartjs.min.js"} \ No newline at end of file diff --git a/lib/amd/src/chart_base.js b/lib/amd/src/chart_base.js index 3c718e15633..1cf0ff5e728 100644 --- a/lib/amd/src/chart_base.js +++ b/lib/amd/src/chart_base.js @@ -58,6 +58,14 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) { */ Base.prototype._labels = null; + /** + * Options for chart legend display. + * + * @protected + * @type {Object} + */ + Base.prototype._legendOptions = null; + /** * The title of the chart. * @@ -144,6 +152,9 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) { Chart.setConfigColorSet(data.config_colorset); Chart.setLabels(data.labels); Chart.setTitle(data.title); + if (data.legend_options) { + Chart.setLegendOptions(data.legend_options); + } data.series.forEach(function(seriesData) { Chart.addSeries(Series.prototype.create(seriesData)); }); @@ -203,6 +214,15 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) { return this._labels; }; + /** + * Get whether to display the chart legend. + * + * @return {Bool} + */ + Base.prototype.getLegendOptions = function() { + return this._legendOptions; + }; + /** * Get the series. * @@ -312,6 +332,18 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) { this._labels = labels; }; + /** + * Set options for chart legend display. + * + * @param {Object} legendOptions + */ + Base.prototype.setLegendOptions = function(legendOptions) { + if (typeof legendOptions !== 'object') { + throw new Error('Setting legend with non-object value:' + legendOptions); + } + this._legendOptions = legendOptions; + }; + /** * Set the title of the chart. * diff --git a/lib/amd/src/chart_output_chartjs.js b/lib/amd/src/chart_output_chartjs.js index 3d6180eb516..024cd0c742e 100644 --- a/lib/amd/src/chart_output_chartjs.js +++ b/lib/amd/src/chart_output_chartjs.js @@ -203,6 +203,11 @@ define([ } } }; + var legendOptions = this._chart.getLegendOptions(); + if (legendOptions) { + config.options.legend = legendOptions; + } + this._chart.getXAxes().forEach(function(axis, i) { var axisLabels = axis.getLabels(); diff --git a/lib/classes/chart_base.php b/lib/classes/chart_base.php index 1cb3160c2ab..e052efdba96 100644 --- a/lib/classes/chart_base.php +++ b/lib/classes/chart_base.php @@ -48,6 +48,8 @@ class chart_base implements JsonSerializable, renderable { protected $xaxes = []; /** @var chart_axis[] The Y axes. */ protected $yaxes = []; + /** @var array Options for the chart legend. */ + protected $legendoptions = []; /** * Constructor. @@ -86,6 +88,7 @@ class chart_base implements JsonSerializable, renderable { 'x' => $this->xaxes, 'y' => $this->yaxes, ], + 'legend_options' => !empty($this->legendoptions) ? $this->legendoptions : null, 'config_colorset' => !empty($CFG->chart_colorset) ? $CFG->chart_colorset : null ]; } @@ -131,6 +134,15 @@ class chart_base implements JsonSerializable, renderable { return $this->labels; } + /** + * Get an array of options for the chart legend. + * + * @return array + */ + public function get_legend_options() { + return $this->legendoptions; + } + /** * Get the series. * @@ -221,6 +233,20 @@ class chart_base implements JsonSerializable, renderable { $this->labels = $labels; } + /** + * Set options for the chart legend. + * See https://www.chartjs.org/docs/2.7.0/configuration/legend.html for options. + * + * Note: Setting onClick and onHover events is not directly supported through + * this method. These config options must be set directly within Javascript + * on the page. + * + * @param array $legendoptions Whether or not to display the chart's legend. + */ + public function set_legend_options(array $legendoptions) { + $this->legendoptions = $legendoptions; + } + /** * Set the title. *