[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/amd/src/ -> chart_output_chartjs.js (source)

   1  // This file is part of Moodle - http://moodle.org/
   2  //
   3  // Moodle is free software: you can redistribute it and/or modify
   4  // it under the terms of the GNU General Public License as published by
   5  // the Free Software Foundation, either version 3 of the License, or
   6  // (at your option) any later version.
   7  //
   8  // Moodle is distributed in the hope that it will be useful,
   9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11  // GNU General Public License for more details.
  12  //
  13  // You should have received a copy of the GNU General Public License
  14  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  15  
  16  /**
  17   * Chart output for chart.js.
  18   *
  19   * @package    core
  20   * @copyright  2016 Frédéric Massart - FMCorz.net
  21   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   * @module     core/chart_output_chartjs
  23   */
  24  define([
  25      'jquery',
  26      'core/chartjs',
  27      'core/chart_axis',
  28      'core/chart_bar',
  29      'core/chart_output_base',
  30      'core/chart_line',
  31      'core/chart_pie',
  32      'core/chart_series'
  33  ], function($, Chartjs, Axis, Bar, Base, Line, Pie, Series) {
  34  
  35      /**
  36       * Makes an axis ID.
  37       *
  38       * @param {String} xy Accepts 'x' and 'y'.
  39       * @param {Number} index The axis index.
  40       * @return {String}
  41       */
  42      var makeAxisId = function(xy, index) {
  43          return 'axis-' + xy + '-' + index;
  44      };
  45  
  46      /**
  47       * Chart output for Chart.js.
  48       *
  49       * @class
  50       * @alias module:core/chart_output_chartjs
  51       * @extends {module:core/chart_output_base}
  52       */
  53      function Output() {
  54          Base.prototype.constructor.apply(this, arguments);
  55  
  56          // Make sure that we've got a canvas tag.
  57          this._canvas = this._node;
  58          if (this._canvas.prop('tagName') != 'CANVAS') {
  59              this._canvas = $('<canvas>');
  60              this._node.append(this._canvas);
  61          }
  62  
  63          this._build();
  64      }
  65      Output.prototype = Object.create(Base.prototype);
  66  
  67      /**
  68       * Reference to the chart config object.
  69       *
  70       * @type {Object}
  71       * @protected
  72       */
  73      Output.prototype._config = null;
  74  
  75      /**
  76       * Reference to the instance of chart.js.
  77       *
  78       * @type {Object}
  79       * @protected
  80       */
  81      Output.prototype._chartjs = null;
  82  
  83      /**
  84       * Reference to the canvas node.
  85       *
  86       * @type {Jquery}
  87       * @protected
  88       */
  89      Output.prototype._canvas = null;
  90  
  91      /**
  92       * Builds the config and the chart.
  93       *
  94       * @protected
  95       */
  96      Output.prototype._build = function() {
  97          this._config = this._makeConfig();
  98          this._chartjs = new Chartjs(this._canvas[0], this._config);
  99      };
 100  
 101      /**
 102       * Get the chart type.
 103       *
 104       * It also handles the bar charts positioning, deciding if the bars should be displayed horizontally.
 105       * Otherwise, get the chart TYPE value.
 106       *
 107       * @returns {String} the chart type.
 108       * @protected
 109       */
 110      Output.prototype._getChartType = function() {
 111          var type = this._chart.getType();
 112  
 113          // Bars can be displayed vertically and horizontally, defining horizontalBar type.
 114          if (this._chart.getType() === Bar.prototype.TYPE && this._chart.getHorizontal() === true) {
 115              type = 'horizontalBar';
 116          }
 117  
 118          return type;
 119      };
 120  
 121      /**
 122       * Make the axis config.
 123       *
 124       * @protected
 125       * @param {module:core/chart_axis} axis The axis.
 126       * @param {String} xy Accepts 'x' or 'y'.
 127       * @param {Number} index The axis index.
 128       * @return {Object} The axis config.
 129       */
 130      Output.prototype._makeAxisConfig = function(axis, xy, index) {
 131          var scaleData = {
 132              id: makeAxisId(xy, index)
 133          };
 134  
 135          if (axis.getPosition() !== Axis.prototype.POS_DEFAULT) {
 136              scaleData.position = axis.getPosition();
 137          }
 138  
 139          if (axis.getLabel() !== null) {
 140              scaleData.scaleLabel = {
 141                  display: true,
 142                  labelString: axis.getLabel()
 143              };
 144          }
 145  
 146          if (axis.getStepSize() !== null) {
 147              scaleData.ticks = scaleData.ticks || {};
 148              scaleData.ticks.stepSize = axis.getStepSize();
 149          }
 150  
 151          if (axis.getMax() !== null) {
 152              scaleData.ticks = scaleData.ticks || {};
 153              scaleData.ticks.max = axis.getMax();
 154          }
 155  
 156          if (axis.getMin() !== null) {
 157              scaleData.ticks = scaleData.ticks || {};
 158              scaleData.ticks.min = axis.getMin();
 159          }
 160  
 161          return scaleData;
 162      };
 163  
 164      /**
 165       * Make the config config.
 166       *
 167       * @protected
 168       * @param {module:core/chart_axis} axis The axis.
 169       * @return {Object} The axis config.
 170       */
 171      Output.prototype._makeConfig = function() {
 172          var config = {
 173              type: this._getChartType(),
 174              data: {
 175                  labels: this._chart.getLabels(),
 176                  datasets: this._makeDatasetsConfig()
 177              },
 178              options: {
 179                  title: {
 180                      display: this._chart.getTitle() !== null,
 181                      text: this._chart.getTitle()
 182                  }
 183              }
 184          };
 185  
 186          this._chart.getXAxes().forEach(function(axis, i) {
 187              var axisLabels = axis.getLabels();
 188  
 189              config.options.scales = config.options.scales || {};
 190              config.options.scales.xAxes = config.options.scales.xAxes || [];
 191              config.options.scales.xAxes[i] = this._makeAxisConfig(axis, 'x', i);
 192  
 193              if (axisLabels !== null) {
 194                  config.options.scales.xAxes[i].ticks.callback = function(value, index) {
 195                      return axisLabels[index] || '';
 196                  };
 197              }
 198          }.bind(this));
 199  
 200          this._chart.getYAxes().forEach(function(axis, i) {
 201              var axisLabels = axis.getLabels();
 202  
 203              config.options.scales = config.options.scales || {};
 204              config.options.scales.yAxes = config.options.scales.yAxes || [];
 205              config.options.scales.yAxes[i] = this._makeAxisConfig(axis, 'y', i);
 206  
 207              if (axisLabels !== null) {
 208                  config.options.scales.yAxes[i].ticks.callback = function(value) {
 209                      return axisLabels[parseInt(value, 10)] || '';
 210                  };
 211              }
 212          }.bind(this));
 213  
 214          config.options.tooltips = {
 215              callbacks: {
 216                  label: this._makeTooltip.bind(this)
 217              }
 218          };
 219  
 220          return config;
 221      };
 222  
 223      /**
 224       * Get the datasets configurations.
 225       *
 226       * @protected
 227       * @return {Object[]}
 228       */
 229      Output.prototype._makeDatasetsConfig = function() {
 230          var sets = this._chart.getSeries().map(function(series) {
 231              var colors = series.hasColoredValues() ? series.getColors() : series.getColor();
 232              var dataset = {
 233                  label: series.getLabel(),
 234                  data: series.getValues(),
 235                  type: series.getType(),
 236                  fill: false,
 237                  backgroundColor: colors,
 238                  // Pie charts look better without borders.
 239                  borderColor: this._chart.getType() == Pie.prototype.TYPE ? null : colors,
 240                  lineTension: this._isSmooth(series) ? 0.3 : 0
 241              };
 242  
 243              if (series.getXAxis() !== null) {
 244                  dataset.xAxisID = makeAxisId('x', series.getXAxis());
 245              }
 246              if (series.getYAxis() !== null) {
 247                  dataset.yAxisID = makeAxisId('y', series.getYAxis());
 248              }
 249  
 250              return dataset;
 251          }.bind(this));
 252          return sets;
 253      };
 254  
 255      /**
 256       * Get the chart data, add labels and rebuild the tooltip.
 257       *
 258       * @param {Object[]} tooltipItem The tooltip item data.
 259       * @param {Object[]} data The chart data.
 260       * @returns {String}
 261       * @protected
 262       */
 263      Output.prototype._makeTooltip = function(tooltipItem, data) {
 264  
 265          // Get series and chart data to rebuild the tooltip and add labels.
 266          var series = this._chart.getSeries()[tooltipItem.datasetIndex];
 267          var serieLabel = series.getLabel();
 268          var serieLabels = series.getLabels();
 269          var chartData = data.datasets[tooltipItem.datasetIndex].data;
 270          var tooltipData = chartData[tooltipItem.index];
 271  
 272          // Build default tooltip.
 273          var tooltip = serieLabel + ': ' + tooltipData;
 274  
 275          // Add serie labels to the tooltip if any.
 276          if (serieLabels !== null) {
 277              tooltip = serieLabels[tooltipItem.index];
 278          }
 279  
 280          return tooltip;
 281      };
 282  
 283      /**
 284       * Verify if the chart line is smooth or not.
 285       *
 286       * @protected
 287       * @param {module:core/chart_series} series The series.
 288       * @returns {Bool}
 289       */
 290      Output.prototype._isSmooth = function(series) {
 291          var smooth = false;
 292          if (this._chart.getType() === Line.prototype.TYPE) {
 293              smooth = series.getSmooth();
 294              if (smooth === null) {
 295                  smooth = this._chart.getSmooth();
 296              }
 297          } else if (series.getType() === Series.prototype.TYPE_LINE) {
 298              smooth = series.getSmooth();
 299          }
 300  
 301          return smooth;
 302      };
 303  
 304      /** @override */
 305      Output.prototype.update = function() {
 306          $.extend(true, this._config, this._makeConfig());
 307          this._chartjs.update();
 308      };
 309  
 310      return Output;
 311  
 312  });


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1