Initialize date adapter with chart options (#6016)

This commit is contained in:
Ben McCann 2019-02-20 23:11:32 -08:00 committed by Simon Brunel
parent 20c26455ba
commit f2b099b835
6 changed files with 53 additions and 29 deletions

View File

@ -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)

View File

@ -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

View File

@ -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',
@ -19,7 +18,7 @@ var FORMATS = {
year: 'YYYY'
};
helpers.merge(adapter, moment ? {
adapters._date.override(moment ? {
_id: 'moment', // DEBUG ONLY
formats: function() {

View File

@ -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 ' +
@ -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.
@ -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;

View File

@ -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');
@ -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;
@ -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;
@ -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;
}
}
@ -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);
@ -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,
@ -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/
@ -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) {
@ -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;
@ -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
@ -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;
}
@ -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;
@ -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) {
@ -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) {
@ -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);
@ -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] : '';
@ -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);
},
/**
@ -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];
@ -696,7 +705,7 @@ module.exports = Scale.extend({
}
if (time === null) {
time = parse(value, me);
time = parse(me, value);
}
if (time !== null) {
@ -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);
},
/**

View File

@ -76,6 +76,7 @@ describe('Time scale tests', function() {
scaleLabel: Chart.defaults.scale.scaleLabel,
bounds: 'data',
distribution: 'linear',
adapters: {},
ticks: {
beginAtZero: false,
minRotation: 0,