mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 06:18:28 +01:00
MDL-55108 core: Document the charting library
Part of MDL-54987 epic.
This commit is contained in:
parent
6ce35fe0e1
commit
601da0e693
2
lib/amd/build/chart_builder.min.js
vendored
2
lib/amd/build/chart_builder.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery"],function(a){return{make:function(b){var c=a.Deferred();return require(["core/chart_"+b.type],function(a){var d=a.prototype.create(a,b);c.resolve(d)}),c.promise()}}});
|
||||
define(["jquery"],function(a){var b={make:function(b){var c=a.Deferred();return require(["core/chart_"+b.type],function(a){var d=a.prototype.create(a,b);c.resolve(d)}),c.promise()}};return b});
|
2
lib/amd/build/chart_output.min.js
vendored
2
lib/amd/build/chart_output.min.js
vendored
@ -1 +1 @@
|
||||
define(["core/chart_output_chartjs"],function(a){return a});
|
||||
define(["core/chart_output_chartjs"],function(a){var b=a;return b});
|
2
lib/amd/build/chart_output_chartjs.min.js
vendored
2
lib/amd/build/chart_output_chartjs.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/chartjs","core/chart_axis","core/chart_output_base"],function(a,b,c,d){function e(){d.prototype.constructor.apply(this,arguments),this._canvas=this._node,"CANVAS"!=this._canvas.prop("tagName")&&(this._canvas=a("<canvas>"),this._node.append(this._canvas)),this._build()}return e.prototype=Object.create(d.prototype),e.prototype._config=null,e.prototype._chartjs=null,e.prototype._canvas=null,e.prototype.getDatasets=function(){var a=this._chart.getSeries().map(function(a){return{label:a.getLabel(),data:a.getValues(),type:a.getType(),fill:!1,borderColor:a.getColor(),backgroundColor:a.getColor()}});return a},e.prototype._build=function(){this._config=this._makeConfig(),this._chartjs=new b(this._canvas[0],this._config)},e.prototype._makeAxisConfig=function(a){var b={};return a.getPosition()!==c.prototype.POS_DEFAULT&&(b.position=a.getPosition()),null!==a.getLabel()&&(b.scaleLabel={display:!0,labelString:a.getLabel()}),null!==a.getStepSize()&&(b.ticks=b.ticks||{},b.ticks.stepSize=a.getStepSize()),null!==a.getMax()&&(b.ticks=b.ticks||{},b.ticks.max=a.getMax()),null!==a.getMin()&&(b.ticks=b.ticks||{},b.ticks.min=a.getMin()),b},e.prototype._makeConfig=function(){var a={type:this._chart.getType(),data:{labels:this._chart.getLabels(),datasets:this.getDatasets()},options:{title:{display:null!==this._chart.getTitle(),text:this._chart.getTitle()}}};return this._chart.getXAxes().forEach(function(b,c){a.options.scales=a.options.scales||{},a.options.scales.xAxes=a.options.scales.xAxes||[],a.options.scales.xAxes[c]=this._makeAxisConfig(b)}.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),null!==d&&(a.options.scales.yAxes[c].ticks.callback=function(a){return d[parseInt(a,10)]||""})}.bind(this)),a},e.prototype.update=function(){a.extend(!0,this._config,this._makeConfig()),this._chartjs.update()},e});
|
||||
define(["jquery","core/chartjs","core/chart_axis","core/chart_output_base"],function(a,b,c,d){function e(){d.prototype.constructor.apply(this,arguments),this._canvas=this._node,"CANVAS"!=this._canvas.prop("tagName")&&(this._canvas=a("<canvas>"),this._node.append(this._canvas)),this._build()}return e.prototype=Object.create(d.prototype),e.prototype._config=null,e.prototype._chartjs=null,e.prototype._canvas=null,e.prototype._build=function(){this._config=this._makeConfig(),this._chartjs=new b(this._canvas[0],this._config)},e.prototype._makeAxisConfig=function(a){var b={};return a.getPosition()!==c.prototype.POS_DEFAULT&&(b.position=a.getPosition()),null!==a.getLabel()&&(b.scaleLabel={display:!0,labelString:a.getLabel()}),null!==a.getStepSize()&&(b.ticks=b.ticks||{},b.ticks.stepSize=a.getStepSize()),null!==a.getMax()&&(b.ticks=b.ticks||{},b.ticks.max=a.getMax()),null!==a.getMin()&&(b.ticks=b.ticks||{},b.ticks.min=a.getMin()),b},e.prototype._makeConfig=function(){var a={type:this._chart.getType(),data:{labels:this._chart.getLabels(),datasets:this._makeDatasetsConfig()},options:{title:{display:null!==this._chart.getTitle(),text:this._chart.getTitle()}}};return this._chart.getXAxes().forEach(function(b,c){a.options.scales=a.options.scales||{},a.options.scales.xAxes=a.options.scales.xAxes||[],a.options.scales.xAxes[c]=this._makeAxisConfig(b)}.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),null!==d&&(a.options.scales.yAxes[c].ticks.callback=function(a){return d[parseInt(a,10)]||""})}.bind(this)),a},e.prototype._makeDatasetsConfig=function(){var a=this._chart.getSeries().map(function(a){return{label:a.getLabel(),data:a.getValues(),type:a.getType(),fill:!1,borderColor:a.getColor(),backgroundColor:a.getColor()}});return a},e.prototype.update=function(){a.extend(!0,this._config,this._makeConfig()),this._chartjs.update()},e});
|
@ -19,29 +19,102 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_axis
|
||||
*/
|
||||
define([], function() {
|
||||
|
||||
/**
|
||||
* Chart axis.
|
||||
* Chart axis class.
|
||||
*
|
||||
* This is used to represent an axis, whether X or Y.
|
||||
*
|
||||
* @alias module:core/chart_axis
|
||||
* @class
|
||||
*/
|
||||
function Axis() {
|
||||
// Please eslint no-empty-function.
|
||||
}
|
||||
|
||||
/**
|
||||
* Default axis position.
|
||||
* @const {Null}
|
||||
*/
|
||||
Axis.prototype.POS_DEFAULT = null;
|
||||
|
||||
/**
|
||||
* Bottom axis position.
|
||||
* @const {String}
|
||||
*/
|
||||
Axis.prototype.POS_BOTTOM = 'bottom';
|
||||
|
||||
/**
|
||||
* Left axis position.
|
||||
* @const {String}
|
||||
*/
|
||||
Axis.prototype.POS_LEFT = 'left';
|
||||
|
||||
/**
|
||||
* Right axis position.
|
||||
* @const {String}
|
||||
*/
|
||||
Axis.prototype.POS_RIGHT = 'right';
|
||||
|
||||
/**
|
||||
* Top axis position.
|
||||
* @const {String}
|
||||
*/
|
||||
Axis.prototype.POS_TOP = 'top';
|
||||
|
||||
/**
|
||||
* Label of the axis.
|
||||
* @type {String}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._label = null;
|
||||
|
||||
/**
|
||||
* Labels of the ticks.
|
||||
* @type {String[]}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._labels = null;
|
||||
|
||||
/**
|
||||
* Maximum value of the axis.
|
||||
* @type {Number}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._max = null;
|
||||
|
||||
/**
|
||||
* Minimum value of the axis.
|
||||
* @type {Number}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._min = null;
|
||||
|
||||
/**
|
||||
* Position of the axis.
|
||||
* @type {String}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._position = null;
|
||||
|
||||
/**
|
||||
* Steps on the axis.
|
||||
* @type {Number}
|
||||
* @protected
|
||||
*/
|
||||
Axis.prototype._stepSize = null;
|
||||
|
||||
/**
|
||||
* Create a new instance of an axis from serialised data.
|
||||
*
|
||||
* @static
|
||||
* @method create
|
||||
* @param {Object} obj The data of the axis.
|
||||
* @return {module:core/chart_axis}
|
||||
*/
|
||||
Axis.prototype.create = function(obj) {
|
||||
var s = new Axis();
|
||||
s.setPosition(obj.position);
|
||||
@ -53,34 +126,90 @@ define([], function() {
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the label of the axis.
|
||||
*
|
||||
* @method getLabel
|
||||
* @return {String}
|
||||
*/
|
||||
Axis.prototype.getLabel = function() {
|
||||
return this._label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the labels of the ticks of the axis.
|
||||
*
|
||||
* @method getLabels
|
||||
* @return {String[]}
|
||||
*/
|
||||
Axis.prototype.getLabels = function() {
|
||||
return this._labels;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the maximum value of the axis.
|
||||
*
|
||||
* @method getMax
|
||||
* @return {Number}
|
||||
*/
|
||||
Axis.prototype.getMax = function() {
|
||||
return this._max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the minimum value of the axis.
|
||||
*
|
||||
* @method getMin
|
||||
* @return {Number}
|
||||
*/
|
||||
Axis.prototype.getMin = function() {
|
||||
return this._min;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the position of the axis.
|
||||
*
|
||||
* @method getPosition
|
||||
* @return {String}
|
||||
*/
|
||||
Axis.prototype.getPosition = function() {
|
||||
return this._position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the step size of the axis.
|
||||
*
|
||||
* @method getStepSize
|
||||
* @return {Number}
|
||||
*/
|
||||
Axis.prototype.getStepSize = function() {
|
||||
return this._stepSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the label of the axis.
|
||||
*
|
||||
* @method setLabel
|
||||
* @param {String} label The label.
|
||||
*/
|
||||
Axis.prototype.setLabel = function(label) {
|
||||
this._label = label || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the labels of the values on the axis.
|
||||
*
|
||||
* This automatically sets the [_stepSize]{@link module:core/chart_axis#_stepSize},
|
||||
* [_min]{@link module:core/chart_axis#_min} and [_max]{@link module:core/chart_axis#_max}
|
||||
* to define a scale from 0 to the number of labels when none of the previously
|
||||
* mentioned values have been modified.
|
||||
*
|
||||
* You can use other values so long that your values in a series are mapped
|
||||
* to the values represented by your _min, _max and _stepSize.
|
||||
*
|
||||
* @method setLabels
|
||||
* @param {String[]} labels The labels.
|
||||
*/
|
||||
Axis.prototype.setLabels = function(labels) {
|
||||
this._labels = labels || null;
|
||||
|
||||
@ -95,14 +224,45 @@ define([], function() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the maximum value on the axis.
|
||||
*
|
||||
* When this is not set (or set to null) it is left for the output
|
||||
* library to best guess what should be used.
|
||||
*
|
||||
* @method setMax
|
||||
* @param {Number} max The value.
|
||||
*/
|
||||
Axis.prototype.setMax = function(max) {
|
||||
this._max = typeof max !== 'undefined' ? max : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the minimum value on the axis.
|
||||
*
|
||||
* When this is not set (or set to null) it is left for the output
|
||||
* library to best guess what should be used.
|
||||
*
|
||||
* @method setMin
|
||||
* @param {Number} min The value.
|
||||
*/
|
||||
Axis.prototype.setMin = function(min) {
|
||||
this._min = typeof min !== 'undefined' ? min : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the position of the axis.
|
||||
*
|
||||
* This does not validate whether or not the constant used is valid
|
||||
* as the axis itself is not aware whether it represents the X or Y axis.
|
||||
*
|
||||
* The output library has to have a fallback in case the values are incorrect.
|
||||
* When this is not set to {@link module:core/chart_axis#POS_DEFAULT} it is up
|
||||
* to the output library to choose what position fits best.
|
||||
*
|
||||
* @method setPosition
|
||||
* @param {String} position The value.
|
||||
*/
|
||||
Axis.prototype.setPosition = function(position) {
|
||||
if (position != this.POS_DEFAULT
|
||||
&& position != this.POS_BOTTOM
|
||||
@ -114,6 +274,14 @@ define([], function() {
|
||||
this._position = position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the stepSize on the axis.
|
||||
*
|
||||
* This is used to determine where ticks are displayed on the axis between min and max.
|
||||
*
|
||||
* @method setStepSize
|
||||
* @param {Number} stepSize The value.
|
||||
*/
|
||||
Axis.prototype.setStepSize = function(stepSize) {
|
||||
if (typeof stepSize === 'undefined' || stepSize === null) {
|
||||
stepSize = null;
|
||||
|
@ -19,19 +19,26 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_bar
|
||||
*/
|
||||
define(['core/chart_base'], function(Base) {
|
||||
|
||||
/**
|
||||
* Bar chart.
|
||||
*
|
||||
* @alias module:core/chart_bar
|
||||
* @extends {module:core/chart_base}
|
||||
* @class
|
||||
*/
|
||||
function Bar() {
|
||||
Base.prototype.constructor.apply(this, arguments);
|
||||
}
|
||||
Bar.prototype = Object.create(Base.prototype);
|
||||
|
||||
/** @override */
|
||||
Bar.prototype.TYPE = 'bar';
|
||||
|
||||
/** @override */
|
||||
Bar.prototype._setDefaults = function() {
|
||||
Base.prototype._setDefaults.apply(this, arguments);
|
||||
var axis = this.getYAxis(0, true);
|
||||
|
@ -19,11 +19,19 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_base
|
||||
*/
|
||||
define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
|
||||
/**
|
||||
* Chart base.
|
||||
*
|
||||
* The constructor of a chart must never take any argument.
|
||||
*
|
||||
* {@link module:core/chart_base#_setDefault} to set the defaults on instantiation.
|
||||
*
|
||||
* @alias module:core/chart_base
|
||||
* @class
|
||||
*/
|
||||
function Base() {
|
||||
this._series = [];
|
||||
@ -33,25 +41,92 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
|
||||
this._setDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* The series constituting this chart.
|
||||
*
|
||||
* @protected
|
||||
* @type {module:core/chart_series[]}
|
||||
*/
|
||||
Base.prototype._series = null;
|
||||
|
||||
/**
|
||||
* The labels of the X axis when categorised.
|
||||
*
|
||||
* @protected
|
||||
* @type {String[]}
|
||||
*/
|
||||
Base.prototype._labels = null;
|
||||
|
||||
/**
|
||||
* The title of the chart.
|
||||
*
|
||||
* @protected
|
||||
* @type {String}
|
||||
*/
|
||||
Base.prototype._title = null;
|
||||
|
||||
/**
|
||||
* The X axes.
|
||||
*
|
||||
* @protected
|
||||
* @type {module:core/chart_axis[]}
|
||||
*/
|
||||
Base.prototype._xaxes = null;
|
||||
|
||||
/**
|
||||
* The Y axes.
|
||||
*
|
||||
* @protected
|
||||
* @type {module:core/chart_axis[]}
|
||||
*/
|
||||
Base.prototype._yaxes = null;
|
||||
|
||||
/**
|
||||
* Colours to pick from when automatically assigning them.
|
||||
*
|
||||
* @const
|
||||
* @type {String[]}
|
||||
*/
|
||||
Base.prototype.COLORSET = ['red', 'green', 'blue', 'yellow', 'pink', 'orange'];
|
||||
|
||||
/**
|
||||
* The type of chart.
|
||||
*
|
||||
* @abstract
|
||||
* @type {String}
|
||||
* @const
|
||||
*/
|
||||
Base.prototype.TYPE = null;
|
||||
|
||||
Base.prototype.addSeries = function(serie) {
|
||||
this._validateSerie(serie);
|
||||
this._series.push(serie);
|
||||
/**
|
||||
* Add a series to the chart.
|
||||
*
|
||||
* This will automatically assign a color to the series if it does not have one.
|
||||
*
|
||||
* @param {module:core/chart_series} series The series to add.
|
||||
*/
|
||||
Base.prototype.addSeries = function(series) {
|
||||
this._validateSerie(series);
|
||||
this._series.push(series);
|
||||
|
||||
// Give a default color from the set.
|
||||
if (serie.getColor() === null) {
|
||||
serie.setColor(Base.prototype.COLORSET[this._series.length % Base.prototype.COLORSET.length]);
|
||||
if (series.getColor() === null) {
|
||||
series.setColor(Base.prototype.COLORSET[this._series.length % Base.prototype.COLORSET.length]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new instance of a chart from serialised data.
|
||||
*
|
||||
* the serialised attributes they offer and support.
|
||||
*
|
||||
* @static
|
||||
* @method create
|
||||
* @param {module:core/chart_base} Klass The class oject representing the type of chart to instantiate.
|
||||
* @param {Object} data The data of the chart.
|
||||
* @return {module:core/chart_base}
|
||||
*/
|
||||
Base.prototype.create = function(Klass, data) {
|
||||
// TODO Not convinced about the usage of Klass here but I can't figure out a way
|
||||
// to have a reference to the class in the sub classes, in PHP I'd do new self().
|
||||
@ -71,6 +146,15 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
return Chart;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an axis.
|
||||
*
|
||||
* @private
|
||||
* @param {String} xy Accepts the values 'x' or 'y'.
|
||||
* @param {Number} [index=0] The index of the axis of its type.
|
||||
* @param {Bool} [createIfNotExists=false] When true, create an instance if it does not exist.
|
||||
* @return {module:core/chart_axis}
|
||||
*/
|
||||
Base.prototype.__getAxis = function(xy, index, createIfNotExists) {
|
||||
var axes = xy === 'x' ? this._xaxes : this._yaxes,
|
||||
setAxis = (xy === 'x' ? this.setXAxis : this.setYAxis).bind(this),
|
||||
@ -91,18 +175,39 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
return axis;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the labels of the X axis.
|
||||
*
|
||||
* @return {String[]}
|
||||
*/
|
||||
Base.prototype.getLabels = function() {
|
||||
return this._labels;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the series.
|
||||
*
|
||||
* @return {module:core/chart_series[]}
|
||||
*/
|
||||
Base.prototype.getSeries = function() {
|
||||
return this._series;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the title of the chart.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
Base.prototype.getTitle = function() {
|
||||
return this._title;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the type of chart.
|
||||
*
|
||||
* @see module:core/chart_base#TYPE
|
||||
* @return {String}
|
||||
*/
|
||||
Base.prototype.getType = function() {
|
||||
if (!this.TYPE) {
|
||||
throw new Error('The TYPE property has not been set.');
|
||||
@ -110,26 +215,67 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
return this.TYPE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the X axes.
|
||||
*
|
||||
* @return {module:core/chart_axis[]}
|
||||
*/
|
||||
Base.prototype.getXAxes = function() {
|
||||
return this._xaxes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an X axis.
|
||||
*
|
||||
* @param {Number} [index=0] The index of the axis.
|
||||
* @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.
|
||||
* @return {module:core/chart_axis}
|
||||
*/
|
||||
Base.prototype.getXAxis = function(index, createIfNotExists) {
|
||||
return this.__getAxis('x', index, createIfNotExists);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the Y axes.
|
||||
*
|
||||
* @return {module:core/chart_axis[]}
|
||||
*/
|
||||
Base.prototype.getYAxes = function() {
|
||||
return this._yaxes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an Y axis.
|
||||
*
|
||||
* @param {Number} [index=0] The index of the axis.
|
||||
* @param {Bool} [createIfNotExists=false] Create the instance of it does not exist at index.
|
||||
* @return {module:core/chart_axis}
|
||||
*/
|
||||
Base.prototype.getYAxis = function(index, createIfNotExists) {
|
||||
return this.__getAxis('y', index, createIfNotExists);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the defaults for this chart type.
|
||||
*
|
||||
* Child classes can extend this to set defaults values on instantiation.
|
||||
*
|
||||
* emphasize and self-document the defaults values set by the chart type.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
Base.prototype._setDefaults = function() {
|
||||
// For the children to extend.
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the labels of the X axis.
|
||||
*
|
||||
* This requires for each series to contain strictly as many values as there
|
||||
* are labels.
|
||||
*
|
||||
* @param {String[]} labels The labels.
|
||||
*/
|
||||
Base.prototype.setLabels = function(labels) {
|
||||
if (labels.length && this._series.length && this._series[0].length != labels.length) {
|
||||
throw new Error('Series must match label values.');
|
||||
@ -137,25 +283,52 @@ define(['core/chart_series', 'core/chart_axis'], function(Series, Axis) {
|
||||
this._labels = labels;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the title of the chart.
|
||||
*
|
||||
* @param {String} title The title.
|
||||
*/
|
||||
Base.prototype.setTitle = function(title) {
|
||||
this._title = title;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set an X axis.
|
||||
*
|
||||
* Note that this will override any predefined axis without warning.
|
||||
*
|
||||
* @param {module:core/chart_axis} axis The axis.
|
||||
* @param {Number} [index=0] The index of the axis.
|
||||
*/
|
||||
Base.prototype.setXAxis = function(axis, index) {
|
||||
index = typeof index === 'undefined' ? 0 : index;
|
||||
this._xaxes[index] = axis;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a Y axis.
|
||||
*
|
||||
* Note that this will override any predefined axis without warning.
|
||||
*
|
||||
* @param {module:core/chart_axis} axis The axis.
|
||||
* @param {Number} [index=0] The index of the axis.
|
||||
*/
|
||||
Base.prototype.setYAxis = function(axis, index) {
|
||||
index = typeof index === 'undefined' ? 0 : index;
|
||||
this._yaxes[index] = axis;
|
||||
};
|
||||
|
||||
Base.prototype._validateSerie = function(serie) {
|
||||
if (this._series.length && this._series[0].getCount() != serie.getCount()) {
|
||||
/**
|
||||
* Validate a series.
|
||||
*
|
||||
* @protected
|
||||
* @param {module:core/chart_series} series The series to validate.
|
||||
*/
|
||||
Base.prototype._validateSerie = function(series) {
|
||||
if (this._series.length && this._series[0].getCount() != series.getCount()) {
|
||||
throw new Error('Series do not have an equal number of values.');
|
||||
|
||||
} else if (this._labels.length && this._labels.length != serie.getCount()) {
|
||||
} else if (this._labels.length && this._labels.length != series.getCount()) {
|
||||
throw new Error('Series must match label values.');
|
||||
}
|
||||
};
|
||||
|
@ -16,15 +16,28 @@
|
||||
/**
|
||||
* Chart builder.
|
||||
*
|
||||
* This takes data, most likely generated in PHP, and creates a chart instance.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery'], function($) {
|
||||
|
||||
return {
|
||||
/**
|
||||
* Chart builder.
|
||||
*
|
||||
* @exports core/chart_builder
|
||||
*/
|
||||
var module = {
|
||||
|
||||
/**
|
||||
* Make a chart instance.
|
||||
*
|
||||
* This takes data, most likely generated in PHP, and creates a chart instance from it
|
||||
* deferring most of the logic to {@link module:core/chart_base.create}.
|
||||
*
|
||||
* @param {Object} data The data.
|
||||
* @return {Promise} A promise resolved with the chart instance.
|
||||
*/
|
||||
make: function(data) {
|
||||
var deferred = $.Deferred();
|
||||
require(['core/chart_' + data.type], function(Klass) {
|
||||
@ -35,4 +48,6 @@ define(['jquery'], function($) {
|
||||
}
|
||||
};
|
||||
|
||||
return module;
|
||||
|
||||
});
|
||||
|
@ -19,17 +19,23 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_line
|
||||
*/
|
||||
define(['core/chart_base'], function(Base) {
|
||||
|
||||
/**
|
||||
* Line chart.
|
||||
*
|
||||
* @alias module:core/chart_line
|
||||
* @extends {module:core/chart_base}
|
||||
* @class
|
||||
*/
|
||||
function Line() {
|
||||
Base.prototype.constructor.apply(this, arguments);
|
||||
}
|
||||
Line.prototype = Object.create(Base.prototype);
|
||||
|
||||
/** @override */
|
||||
Line.prototype.TYPE = 'line';
|
||||
|
||||
return Line;
|
||||
|
@ -24,6 +24,12 @@
|
||||
*/
|
||||
define(['core/chart_output_chartjs'], function(Output) {
|
||||
|
||||
return Output;
|
||||
/**
|
||||
* @exports module:core/chart_output
|
||||
* @extends {module:core/chart_output_chartjs}
|
||||
*/
|
||||
var defaultModule = Output;
|
||||
|
||||
return defaultModule;
|
||||
|
||||
});
|
||||
|
@ -21,12 +21,24 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_output_base
|
||||
*/
|
||||
define(['jquery'], function($) {
|
||||
|
||||
/**
|
||||
* Chart output base.
|
||||
*
|
||||
* The constructor of an output class must instantly generate and display the
|
||||
* chart. It is also the responsability of the output module to check that
|
||||
* the node received is of the appropriate type, if not a new node can be
|
||||
* added within.
|
||||
*
|
||||
* The output module has total control over the content of the node and can
|
||||
* clear it or output anything to it at will. A node should not be shared by
|
||||
* two simultaneous output modules.
|
||||
*
|
||||
* @class
|
||||
* @alias module:core/chart_output_base
|
||||
* @param {Node} node The node to output with/in.
|
||||
* @param {Chart} chart A chart object.
|
||||
*/
|
||||
@ -35,6 +47,16 @@ define(['jquery'], function($) {
|
||||
this._chart = chart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update method.
|
||||
*
|
||||
* This is the public method through which an output instance in informed
|
||||
* that the chart instance has been updated and they need to update the
|
||||
* chart rendering.
|
||||
*
|
||||
* @abstract
|
||||
* @return {Void}
|
||||
*/
|
||||
Base.prototype.update = function() {
|
||||
throw new Error('Not supported.');
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_output_chartjs
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
@ -29,6 +30,10 @@ define([
|
||||
|
||||
/**
|
||||
* Chart output for Chart.js.
|
||||
*
|
||||
* @class
|
||||
* @alias module:core/chart_output_chartjs
|
||||
* @extends {module:core/chart_output_base}
|
||||
*/
|
||||
function Output() {
|
||||
Base.prototype.constructor.apply(this, arguments);
|
||||
@ -42,32 +47,49 @@ define([
|
||||
|
||||
this._build();
|
||||
}
|
||||
|
||||
Output.prototype = Object.create(Base.prototype);
|
||||
|
||||
/**
|
||||
* Reference to the chart config object.
|
||||
*
|
||||
* @type {Object}
|
||||
* @protected
|
||||
*/
|
||||
Output.prototype._config = null;
|
||||
|
||||
/**
|
||||
* Reference to the instance of chart.js.
|
||||
*
|
||||
* @type {Object}
|
||||
* @protected
|
||||
*/
|
||||
Output.prototype._chartjs = null;
|
||||
|
||||
/**
|
||||
* Reference to the canvas node.
|
||||
*
|
||||
* @type {Jquery}
|
||||
* @protected
|
||||
*/
|
||||
Output.prototype._canvas = null;
|
||||
|
||||
Output.prototype.getDatasets = function() {
|
||||
var sets = this._chart.getSeries().map(function(series) {
|
||||
return {
|
||||
label: series.getLabel(),
|
||||
data: series.getValues(),
|
||||
type: series.getType(),
|
||||
fill: false,
|
||||
borderColor: series.getColor(),
|
||||
backgroundColor: series.getColor()
|
||||
};
|
||||
});
|
||||
return sets;
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds the config and the chart.
|
||||
*
|
||||
* @protected
|
||||
*/
|
||||
Output.prototype._build = function() {
|
||||
this._config = this._makeConfig();
|
||||
this._chartjs = new Chartjs(this._canvas[0], this._config);
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the axis config.
|
||||
*
|
||||
* @protected
|
||||
* @param {module:core/chart_axis} axis The axis.
|
||||
* @return {Object} The axis config.
|
||||
*/
|
||||
Output.prototype._makeAxisConfig = function(axis) {
|
||||
var scaleData = {};
|
||||
|
||||
@ -100,12 +122,19 @@ define([
|
||||
return scaleData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the config config.
|
||||
*
|
||||
* @protected
|
||||
* @param {module:core/chart_axis} axis The axis.
|
||||
* @return {Object} The axis config.
|
||||
*/
|
||||
Output.prototype._makeConfig = function() {
|
||||
var config = {
|
||||
type: this._chart.getType(),
|
||||
data: {
|
||||
labels: this._chart.getLabels(),
|
||||
datasets: this.getDatasets()
|
||||
datasets: this._makeDatasetsConfig()
|
||||
},
|
||||
options: {
|
||||
title: {
|
||||
@ -138,6 +167,27 @@ define([
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the datasets configurations.
|
||||
*
|
||||
* @protected
|
||||
* @return {Object[]}
|
||||
*/
|
||||
Output.prototype._makeDatasetsConfig = function() {
|
||||
var sets = this._chart.getSeries().map(function(series) {
|
||||
return {
|
||||
label: series.getLabel(),
|
||||
data: series.getValues(),
|
||||
type: series.getType(),
|
||||
fill: false,
|
||||
borderColor: series.getColor(),
|
||||
backgroundColor: series.getColor()
|
||||
};
|
||||
});
|
||||
return sets;
|
||||
};
|
||||
|
||||
/** @override */
|
||||
Output.prototype.update = function() {
|
||||
$.extend(true, this._config, this._makeConfig());
|
||||
this._chartjs.update();
|
||||
|
@ -19,19 +19,33 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_pie
|
||||
*/
|
||||
define(['core/chart_base'], function(Base) {
|
||||
|
||||
/**
|
||||
* Pie chart.
|
||||
*
|
||||
* @class
|
||||
* @alias module:core/chart_pie
|
||||
* @extends {module:core/chart_base}
|
||||
*/
|
||||
function Pie() {
|
||||
Base.prototype.constructor.apply(this, arguments);
|
||||
}
|
||||
Pie.prototype = Object.create(Base.prototype);
|
||||
|
||||
/** @override */
|
||||
Pie.prototype.TYPE = 'pie';
|
||||
|
||||
/**
|
||||
* Validate a series.
|
||||
*
|
||||
* Overrides parent implementation to validate that there is only
|
||||
* one series per chart instance.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
Pie.prototype._validateSerie = function() {
|
||||
if (this._series.length >= 1) {
|
||||
throw new Error('Pie charts only support one serie.');
|
||||
|
@ -19,12 +19,15 @@
|
||||
* @package core
|
||||
* @copyright 2016 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @module core/chart_series
|
||||
*/
|
||||
define([], function() {
|
||||
|
||||
/**
|
||||
* Chart data series.
|
||||
*
|
||||
* @class
|
||||
* @alias module:core/chart_series
|
||||
* @param {String} label The series label.
|
||||
* @param {Number[]} values The values.
|
||||
*/
|
||||
@ -43,14 +46,62 @@ define([], function() {
|
||||
this._values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default type of series.
|
||||
*
|
||||
* @type {Null}
|
||||
* @const
|
||||
*/
|
||||
Series.prototype.TYPE_DEFAULT = null;
|
||||
|
||||
/**
|
||||
* Type of series 'line'.
|
||||
*
|
||||
* @type {String}
|
||||
* @const
|
||||
*/
|
||||
Series.prototype.TYPE_LINE = 'line';
|
||||
|
||||
/**
|
||||
* The color of the series.
|
||||
*
|
||||
* @type {String}
|
||||
* @protected
|
||||
*/
|
||||
Series.prototype._color = null;
|
||||
|
||||
/**
|
||||
* The label of the series.
|
||||
*
|
||||
* @type {String}
|
||||
* @protected
|
||||
*/
|
||||
Series.prototype._label = null;
|
||||
|
||||
/**
|
||||
* The type of the series.
|
||||
*
|
||||
* @type {String}
|
||||
* @protected
|
||||
*/
|
||||
Series.prototype._type = Series.prototype.TYPE_DEFAULT;
|
||||
|
||||
/**
|
||||
* The values in the series.
|
||||
*
|
||||
* @type {Number[]}
|
||||
* @protected
|
||||
*/
|
||||
Series.prototype._values = null;
|
||||
|
||||
/**
|
||||
* Create a new instance of a series from serialised data.
|
||||
*
|
||||
* @static
|
||||
* @method create
|
||||
* @param {Object} obj The data of the series.
|
||||
* @return {module:core/chart_series}
|
||||
*/
|
||||
Series.prototype.create = function(obj) {
|
||||
var s = new Series(obj.label, obj.values);
|
||||
s.setColor(obj.color);
|
||||
@ -58,30 +109,65 @@ define([], function() {
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the color.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
Series.prototype.getColor = function() {
|
||||
return this._color;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the number of values in the series.
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
Series.prototype.getCount = function() {
|
||||
return this._values.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the series label.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
Series.prototype.getLabel = function() {
|
||||
return this._label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the series type.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
Series.prototype.getType = function() {
|
||||
return this._type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the series values.
|
||||
*
|
||||
* @return {Number[]}
|
||||
*/
|
||||
Series.prototype.getValues = function() {
|
||||
return this._values;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the series color.
|
||||
*
|
||||
* @param {String} color A CSS-compatible color.
|
||||
*/
|
||||
Series.prototype.setColor = function(color) {
|
||||
this._color = color || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the type of the series.
|
||||
*
|
||||
* @param {String} type A type constant value.
|
||||
*/
|
||||
Series.prototype.setType = function(type) {
|
||||
if (type != this.TYPE_DEFAULT && type != this.TYPE_LINE) {
|
||||
throw new Error('Invalid serie type.');
|
||||
|
@ -38,46 +38,97 @@ use renderable;
|
||||
*/
|
||||
class chart_axis implements JsonSerializable {
|
||||
|
||||
/** Default axis position. */
|
||||
const POS_DEFAULT = null;
|
||||
/** Bottom axis position. */
|
||||
const POS_BOTTOM = 'bottom';
|
||||
/** Left axis position. */
|
||||
const POS_LEFT = 'left';
|
||||
/** Right axis position. */
|
||||
const POS_RIGHT = 'right';
|
||||
/** Top axis position. */
|
||||
const POS_TOP = 'top';
|
||||
|
||||
/** @var string The axis label. */
|
||||
protected $label = null;
|
||||
/** @var string[] The axis labels, tick values. */
|
||||
protected $labels = null;
|
||||
/** @var float The maximum tick value. */
|
||||
protected $max = null;
|
||||
/** @var float The minimum tick value. */
|
||||
protected $min = null;
|
||||
/** @var string The axis position. */
|
||||
protected $position = self::POS_DEFAULT;
|
||||
/** @var float The stepsize between ticks. */
|
||||
protected $stepsize = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Must not take any argument.
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_label() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the labels.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_labels() {
|
||||
return $this->labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max value.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function get_max() {
|
||||
return $this->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the min value.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function get_min() {
|
||||
return $this->min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the axis position.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_position() {
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the step size.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function get_stepsize() {
|
||||
return $this->stepsize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
'label' => $this->label,
|
||||
@ -89,28 +140,58 @@ class chart_axis implements JsonSerializable {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the label.
|
||||
*
|
||||
* @param string $label The label.
|
||||
*/
|
||||
public function set_label($label) {
|
||||
return $this->label = $label;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the labels.
|
||||
*
|
||||
* @param string[] $labels The labels.
|
||||
*/
|
||||
public function set_labels($labels) {
|
||||
return $this->labels = $labels;
|
||||
$this->labels = $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the max value.
|
||||
*
|
||||
* @param float $max The max value.
|
||||
*/
|
||||
public function set_max($max) {
|
||||
return $this->max = $max;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the min value.
|
||||
*
|
||||
* @param float $min The min value.
|
||||
*/
|
||||
public function set_min($min) {
|
||||
return $this->min = $min;
|
||||
$this->min = $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position.
|
||||
*
|
||||
* @param string $position Use constant self::POS_*.
|
||||
*/
|
||||
public function set_position($position) {
|
||||
return $this->position = $position;
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the step size.
|
||||
*
|
||||
* @param float $stepsize The step size.
|
||||
*/
|
||||
public function set_stepsize($stepsize) {
|
||||
return $this->stepsize = $stepsize;
|
||||
$this->stepsize = $stepsize;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class chart_bar extends chart_base {
|
||||
|
||||
/**
|
||||
* Set the defaults.
|
||||
*/
|
||||
protected function set_defaults() {
|
||||
parent::set_defaults();
|
||||
$yaxis = $this->get_yaxis(0, true);
|
||||
|
@ -38,20 +38,43 @@ use renderable;
|
||||
*/
|
||||
class chart_base implements JsonSerializable, renderable {
|
||||
|
||||
/** @var chart_series[] The series constituting this chart. */
|
||||
protected $series = [];
|
||||
/** @var string[] The labels for the X axis when categorised. */
|
||||
protected $labels = [];
|
||||
/** @var string The title of the chart. */
|
||||
protected $title = null;
|
||||
/** @var chart_axis[] The X axes. */
|
||||
protected $xaxes = [];
|
||||
/** @var chart_axis[] The Y axes. */
|
||||
protected $yaxes = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Must not take any argument.
|
||||
*
|
||||
* Most of the time you do not want to extend this, rather extend the
|
||||
* method {@link self::set_defaults} to set the defaults on instantiation.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->set_defaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a series to the chart.
|
||||
*
|
||||
* @param chart_series $serie The serie.
|
||||
*/
|
||||
public function add_series(chart_series $serie) {
|
||||
$this->series[] = $serie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
'type' => $this->get_type(),
|
||||
@ -65,6 +88,14 @@ class chart_base implements JsonSerializable, renderable {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an axis.
|
||||
*
|
||||
* @param string $type Accepts values 'x' or 'y'.
|
||||
* @param int $index The index of this axis.
|
||||
* @param bool $createifnotexists Whether to create the axis if not found.
|
||||
* @return chart_axis
|
||||
*/
|
||||
private function get_axis($type, $index, $createifnotexists) {
|
||||
$isx = $type === 'x';
|
||||
if ($isx) {
|
||||
@ -89,55 +120,134 @@ class chart_base implements JsonSerializable, renderable {
|
||||
return $axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the labels of the X axis.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_labels() {
|
||||
return $this->labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the series.
|
||||
*
|
||||
* @return chart_series[]
|
||||
*/
|
||||
public function get_series() {
|
||||
return $this->series;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the chart type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_type() {
|
||||
$classname = get_class($this);
|
||||
return substr($classname, strpos($classname, '_') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X axes.
|
||||
*
|
||||
* @return chart_axis[]
|
||||
*/
|
||||
public function get_xaxes() {
|
||||
return $this->xaxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an X axis.
|
||||
*
|
||||
* @param int $index The index of the axis.
|
||||
* @param bool $createifnotexists When true, create an instance of the axis if none exist at this index yet.
|
||||
* @return chart_axis
|
||||
*/
|
||||
public function get_xaxis($index = 0, $createifnotexists = false) {
|
||||
return $this->get_axis('x', $index, $createifnotexists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y axes.
|
||||
*
|
||||
* @return chart_axis[]
|
||||
*/
|
||||
public function get_yaxes() {
|
||||
return $this->yaxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Y axis.
|
||||
*
|
||||
* @param int $index The index of the axis.
|
||||
* @param bool $createifnotexists When true, create an instance of the axis if none exist at this index yet.
|
||||
* @return chart_axis
|
||||
*/
|
||||
public function get_yaxis($index = 0, $createifnotexists = false) {
|
||||
return $this->get_axis('y', $index, $createifnotexists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the defaults for this chart type.
|
||||
*
|
||||
* Child classes can extend this to set default values on instantiation.
|
||||
*
|
||||
* In general the constructor could be used, but this method is here to
|
||||
* emphasize and self-document the default values set by the chart type.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function set_defaults() {
|
||||
// For the child classes to extend.
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the chart labels.
|
||||
*
|
||||
* @param string[] $labels The labels.
|
||||
*/
|
||||
public function set_labels(array $labels) {
|
||||
$this->labels = $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title.
|
||||
*
|
||||
* @param string $title The title.
|
||||
*/
|
||||
public function set_title($title) {
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an X axis.
|
||||
*
|
||||
* Note that this will override any predefined axis without warning.
|
||||
*
|
||||
* @param chart_axis $axis The axis.
|
||||
* @param int $index The index of the axis.
|
||||
*/
|
||||
public function set_xaxis(chart_axis $axis, $index = 0) {
|
||||
return $this->xaxes[$index] = $axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an Y axis.
|
||||
*
|
||||
* Note that this will override any predefined axis without warning.
|
||||
*
|
||||
* @param chart_axis $axis The axis.
|
||||
* @param int $index The index of the axis.
|
||||
*/
|
||||
public function set_yaxis(chart_axis $axis, $index = 0) {
|
||||
return $this->yaxes[$index] = $axis;
|
||||
}
|
||||
|
@ -37,39 +37,81 @@ use JsonSerializable;
|
||||
*/
|
||||
class chart_series implements JsonSerializable {
|
||||
|
||||
/** Default type for a series. */
|
||||
const TYPE_DEFAULT = null;
|
||||
/** Series of type line. */
|
||||
const TYPE_LINE = 'line';
|
||||
|
||||
/** @var string Color of the series. */
|
||||
protected $color;
|
||||
/** @var string Label for this series. */
|
||||
protected $label;
|
||||
/** @var string Type of the series. */
|
||||
protected $type = self::TYPE_DEFAULT;
|
||||
/** @var float[] Values of the series. */
|
||||
protected $values = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $label The label of the series.
|
||||
* @param float[] $values The values of this series.
|
||||
*/
|
||||
public function __construct($label, $values) {
|
||||
$this->values = $values;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the color.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_color() {
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of values in this series.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_count() {
|
||||
return count($this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label of the series.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_label() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of series.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the values of the series.
|
||||
*
|
||||
* @return [type]
|
||||
*/
|
||||
public function get_values() {
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
$data = [
|
||||
'label' => $this->label,
|
||||
@ -80,10 +122,20 @@ class chart_series implements JsonSerializable {
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of the series.
|
||||
*
|
||||
* @param string $color CSS compatible color.
|
||||
*/
|
||||
public function set_color($color) {
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the series.
|
||||
*
|
||||
* @param string $type Constant value from self::TYPE_*.
|
||||
*/
|
||||
public function set_type($type) {
|
||||
if (!in_array($type, [self::TYPE_DEFAULT, self::TYPE_LINE])) {
|
||||
throw new coding_exception('Invalid serie type.');
|
||||
|
Loading…
x
Reference in New Issue
Block a user