Skip to content

Commit

Permalink
Initialize date adapter with chart options (chartjs#6016)
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann authored and simonbrunel committed Feb 21, 2019
1 parent c58d630 commit c27619f
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 29 deletions.
1 change: 1 addition & 0 deletions docs/axes/cartesian/time.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The following options are provided by the time scale. You may also set options p

| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| `adapters.date` | `object` | `{}` | Options for adapter for external date library if that adapter needs or supports options
| `distribution` | `string` | `'linear'` | How data is plotted. [more...](#scale-distribution)
| `bounds` | `string` | `'data'` | Determines the scale bounds. [more...](#scale-bounds)
| `ticks.source` | `string` | `'auto'` | How ticks are generated. [more...](#ticks-source)
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Chart from 'chart.js';
var myChart = new Chart(ctx, {...});
```

**Note:** Moment.js is installed along Chart.js as dependency. If you don't want to use Momemt.js (either because you use a different date adapter or simply because don't need time functionalities), you will have to configure your bundler to exclude this dependency (e.g. using [`externals` for Webpack](https://webpack.js.org/configuration/externals/) or [`external` for Rollup](https://rollupjs.org/guide/en#peer-dependencies)).
**Note:** Moment.js is installed along Chart.js as dependency. If you don't want to use Moment.js (either because you use a different date adapter or simply because don't need time functionalities), you will have to configure your bundler to exclude this dependency (e.g. using [`externals` for Webpack](https://webpack.js.org/configuration/externals/) or [`external` for Rollup](https://rollupjs.org/guide/en#peer-dependencies)).

```javascript
// Webpack
Expand Down
5 changes: 2 additions & 3 deletions src/adapters/adapter.moment.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
'use strict';

var moment = require('moment');
var adapter = require('../core/core.adapters')._date;
var helpers = require('../helpers/helpers.core');
var adapters = require('../core/core.adapters');

var FORMATS = {
datetime: 'MMM D, YYYY, h:mm:ss a',
Expand All @@ -19,7 +18,7 @@ var FORMATS = {
year: 'YYYY'
};

helpers.merge(adapter, moment ? {
adapters._date.override(moment ? {
_id: 'moment', // DEBUG ONLY

formats: function() {
Expand Down
18 changes: 16 additions & 2 deletions src/core/core.adapters.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

'use strict';

var helpers = require('../helpers/index');

function abstract() {
throw new Error(
'This method is not implemented: either no adapter can ' +
Expand All @@ -27,8 +29,14 @@ function abstract() {
* @name Unit
*/

/** @lends Chart._adapters._date */
module.exports._date = {
/**
* @class
*/
function DateAdapter(options) {
this.options = options || {};
}

helpers.extend(DateAdapter.prototype, /** @lends DateAdapter */ {
/**
* Returns a map of time formats for the supported formatting units defined
* in Unit as well as 'datetime' representing a detailed date/time string.
Expand Down Expand Up @@ -104,4 +112,10 @@ module.exports._date = {
_create: function(value) {
return value;
}
});

DateAdapter.override = function(members) {
helpers.extend(DateAdapter.prototype, members);
};

module.exports._date = DateAdapter;
55 changes: 32 additions & 23 deletions src/scales/scale.time.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

var adapter = require('../core/core.adapters')._date;
var adapters = require('../core/core.adapters');
var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
var Scale = require('../core/core.scale');
Expand Down Expand Up @@ -177,7 +177,9 @@ function interpolate(table, skey, sval, tkey) {
return prev[tkey] + offset;
}

function toTimestamp(input, options) {
function toTimestamp(scale, input) {
var adapter = scale._adapter;
var options = scale.options.time;
var parser = options.parser;
var format = parser || options.format;
var value = input;
Expand Down Expand Up @@ -211,19 +213,19 @@ function toTimestamp(input, options) {
return value;
}

function parse(input, scale) {
function parse(scale, input) {
if (helpers.isNullOrUndef(input)) {
return null;
}

var options = scale.options.time;
var value = toTimestamp(scale.getRightValue(input), options);
var value = toTimestamp(scale, scale.getRightValue(input));
if (value === null) {
return value;
}

if (options.round) {
value = +adapter.startOf(value, options.round);
value = +scale._adapter.startOf(value, options.round);
}

return value;
Expand Down Expand Up @@ -276,13 +278,13 @@ function determineUnitForAutoTicks(minUnit, min, max, capacity) {
/**
* Figures out what unit to format a set of ticks with
*/
function determineUnitForFormatting(ticks, minUnit, min, max) {
function determineUnitForFormatting(scale, ticks, minUnit, min, max) {
var ilen = UNITS.length;
var i, unit;

for (i = ilen - 1; i >= UNITS.indexOf(minUnit); i--) {
unit = UNITS[i];
if (INTERVALS[unit].common && adapter.diff(max, min, unit) >= ticks.length) {
if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= ticks.length) {
return unit;
}
}
Expand All @@ -304,7 +306,9 @@ function determineMajorUnit(unit) {
* Important: this method can return ticks outside the min and max range, it's the
* responsibility of the calling code to clamp values if needed.
*/
function generate(min, max, capacity, options) {
function generate(scale, min, max, capacity) {
var adapter = scale._adapter;
var options = scale.options;
var timeOpts = options.time;
var minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, capacity);
var major = determineMajorUnit(minor);
Expand Down Expand Up @@ -388,13 +392,13 @@ function computeOffsets(table, ticks, min, max, options) {
return {start: start, end: end};
}

function ticksFromTimestamps(values, majorUnit) {
function ticksFromTimestamps(scale, values, majorUnit) {
var ticks = [];
var i, ilen, value, major;

for (i = 0, ilen = values.length; i < ilen; ++i) {
value = values[i];
major = majorUnit ? value === +adapter.startOf(value, majorUnit) : false;
major = majorUnit ? value === +scale._adapter.startOf(value, majorUnit) : false;

ticks.push({
value: value,
Expand Down Expand Up @@ -426,6 +430,7 @@ var defaultConfig = {
*/
bounds: 'data',

adapters: {},
time: {
parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from https://momentjs.com/docs/#/parsing/string-format/
Expand Down Expand Up @@ -465,6 +470,7 @@ module.exports = Scale.extend({
var me = this;
var options = me.options;
var time = options.time || (options.time = {});
var adapter = me._adapter = new adapters._date(options.adapters.date);

// DEPRECATIONS: output a message only one time per update
if (time.format) {
Expand Down Expand Up @@ -493,6 +499,7 @@ module.exports = Scale.extend({
determineDataLimits: function() {
var me = this;
var chart = me.chart;
var adapter = me._adapter;
var timeOpts = me.options.time;
var unit = timeOpts.unit || 'day';
var min = MAX_INTEGER;
Expand All @@ -505,7 +512,7 @@ module.exports = Scale.extend({

// Convert labels to timestamps
for (i = 0, ilen = dataLabels.length; i < ilen; ++i) {
labels.push(parse(dataLabels[i], me));
labels.push(parse(me, dataLabels[i]));
}

// Convert data to timestamps
Expand All @@ -518,7 +525,7 @@ module.exports = Scale.extend({
datasets[i] = [];

for (j = 0, jlen = data.length; j < jlen; ++j) {
timestamp = parse(data[j], me);
timestamp = parse(me, data[j]);
timestamps.push(timestamp);
datasets[i][j] = timestamp;
}
Expand Down Expand Up @@ -546,8 +553,8 @@ module.exports = Scale.extend({
max = Math.max(max, timestamps[timestamps.length - 1]);
}

min = parse(timeOpts.min, me) || min;
max = parse(timeOpts.max, me) || max;
min = parse(me, timeOpts.min) || min;
max = parse(me, timeOpts.max) || max;

// In case there is no valid min/max, set limits based on unit time option
min = min === MAX_INTEGER ? +adapter.startOf(Date.now(), unit) : min;
Expand Down Expand Up @@ -586,7 +593,7 @@ module.exports = Scale.extend({
break;
case 'auto':
default:
timestamps = generate(min, max, me.getLabelCapacity(min), options);
timestamps = generate(me, min, max, me.getLabelCapacity(min), options);
}

if (options.bounds === 'ticks' && timestamps.length) {
Expand All @@ -595,8 +602,8 @@ module.exports = Scale.extend({
}

// Enforce limits with user min/max options
min = parse(timeOpts.min, me) || min;
max = parse(timeOpts.max, me) || max;
min = parse(me, timeOpts.min) || min;
max = parse(me, timeOpts.max) || max;

// Remove ticks outside the min/max range
for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
Expand All @@ -610,7 +617,7 @@ module.exports = Scale.extend({
me.max = max;

// PRIVATE
me._unit = timeOpts.unit || determineUnitForFormatting(ticks, timeOpts.minUnit, me.min, me.max);
me._unit = timeOpts.unit || determineUnitForFormatting(me, ticks, timeOpts.minUnit, me.min, me.max);
me._majorUnit = determineMajorUnit(me._unit);
me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution);
me._offsets = computeOffsets(me._table, ticks, min, max, options);
Expand All @@ -619,11 +626,12 @@ module.exports = Scale.extend({
ticks.reverse();
}

return ticksFromTimestamps(ticks, me._majorUnit);
return ticksFromTimestamps(me, ticks, me._majorUnit);
},

getLabelForIndex: function(index, datasetIndex) {
var me = this;
var adapter = me._adapter;
var data = me.chart.data;
var timeOpts = me.options.time;
var label = data.labels && index < data.labels.length ? data.labels[index] : '';
Expand All @@ -633,12 +641,12 @@ module.exports = Scale.extend({
label = me.getRightValue(value);
}
if (timeOpts.tooltipFormat) {
return adapter.format(toTimestamp(label, timeOpts), timeOpts.tooltipFormat);
return adapter.format(toTimestamp(me, label), timeOpts.tooltipFormat);
}
if (typeof label === 'string') {
return label;
}
return adapter.format(toTimestamp(label, timeOpts), timeOpts.displayFormats.datetime);
return adapter.format(toTimestamp(me, label), timeOpts.displayFormats.datetime);
},

/**
Expand All @@ -647,6 +655,7 @@ module.exports = Scale.extend({
*/
tickFormatFunction: function(time, index, ticks, format) {
var me = this;
var adapter = me._adapter;
var options = me.options;
var formats = options.time.displayFormats;
var minorFormat = formats[me._unit];
Expand Down Expand Up @@ -696,7 +705,7 @@ module.exports = Scale.extend({
}

if (time === null) {
time = parse(value, me);
time = parse(me, value);
}

if (time !== null) {
Expand All @@ -719,7 +728,7 @@ module.exports = Scale.extend({
var time = interpolate(me._table, 'pos', pos, 'time');

// DEPRECATION, we should return time directly
return adapter._create(time);
return me._adapter._create(time);
},

/**
Expand Down
1 change: 1 addition & 0 deletions test/specs/scale.time.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe('Time scale tests', function() {
scaleLabel: Chart.defaults.scale.scaleLabel,
bounds: 'data',
distribution: 'linear',
adapters: {},
ticks: {
beginAtZero: false,
minRotation: 0,
Expand Down

0 comments on commit c27619f

Please sign in to comment.