// Set unit override if applicable
if (this.options.time.unit) {
this.tickUnit = this.options.time.unit || 'day';
- this.displayFormat = time.unit.day.display;
+ this.displayFormat = time.unit[this.tickUnit].display;
this.tickRange = Math.ceil(this.lastTick.diff(this.firstTick, this.tickUnit, true));
} else {
// Determine the smallest needed unit of the time
this.smallestLabelSeparation = Math.min(this.smallestLabelSeparation, this.labelMoments[i].diff(this.labelMoments[i - 1], this.tickUnit, true));
}
-
// Tick displayFormat override
if (this.options.time.displayFormat) {
this.displayFormat = this.options.time.displayFormat;
}
// For every unit in between the first and last moment, create a moment and add it to the ticks tick
- if (this.options.ticks.userCallback) {
- for (i = 0; i <= this.tickRange; i++) {
- this.ticks.push(
- this.options.ticks.userCallback(this.firstTick.clone()
- .add(i, this.tickUnit)
- .format(this.options.time.displayFormat ? this.options.time.displayFormat : time.unit[this.tickUnit].display)
- )
- );
- }
- } else {
- for (i = 0; i <= this.tickRange; i++) {
- this.ticks.push(this.firstTick.clone()
- .add(i, this.tickUnit)
- .format(this.options.time.displayFormat ? this.options.time.displayFormat : time.unit[this.tickUnit].display)
- );
- }
+ for (i = 0; i <= this.tickRange; ++i) {
+ this.ticks.push(this.firstTick.clone().add(i, this.tickUnit));
}
},
+ convertTicksToLabels: function() {
+ this.ticks = this.ticks.map(function(tick, index, ticks) {
+ var formattedTick = tick.format(this.options.time.displayFormat ? this.options.time.displayFormat : time.unit[this.tickUnit].display);
+
+ if (this.options.ticks.userCallback) {
+ return this.options.ticks.userCallback(formattedTick, index, ticks);
+ } else {
+ return formattedTick;
+ }
+ }, this);
+ },
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
var offset = this.labelMoments[index].diff(this.firstTick, this.tickUnit, true);
return this.left + Math.round(valueOffset);
} else {
- return this.top + (decimal * (this.height / this.ticks.length));
+ //return this.top + (decimal * (this.height / this.ticks.length));
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
+ var valueHeight = innerHeight / Math.max(this.ticks.length - 1, 1);
+ var heightOffset = (innerHeight * decimal) + this.paddingTop;
+
+ return this.top + Math.round(heightOffset);
}
},
parseTime: function(label) {
--- /dev/null
+// Time scale tests
+describe('Time scale tests', function() {
+ it('Should register the constructor with the scale service', function() {
+ var Constructor = Chart.scaleService.getScaleConstructor('time');
+ expect(Constructor).not.toBe(undefined);
+ expect(typeof Constructor).toBe('function');
+ });
+
+ it('Should have the correct default config', function() {
+ var defaultConfig = Chart.scaleService.getScaleDefaults('time');
+ expect(defaultConfig).toEqual({
+ display: true,
+ gridLines: {
+ color: "rgba(0, 0, 0, 0.1)",
+ drawOnChartArea: true,
+ drawTicks: true,
+ lineWidth: 1,
+ offsetGridLines: false,
+ show: true,
+ zeroLineColor: "rgba(0,0,0,0.25)",
+ zeroLineWidth: 1,
+ },
+ position: "bottom",
+ scaleLabel: {
+ fontColor: '#666',
+ fontFamily: 'Helvetica Neue',
+ fontSize: 12,
+ fontStyle: 'normal',
+ labelString: '',
+ show: false,
+ },
+ ticks: {
+ beginAtZero: false,
+ fontColor: "#666",
+ fontFamily: "Helvetica Neue",
+ fontSize: 12,
+ fontStyle: "normal",
+ maxRotation: 90,
+ minRotation: 20,
+ mirror: false,
+ padding: 10,
+ reverse: false,
+ show: true,
+ template: "<%=value%>"
+ },
+ time: {
+ format: false,
+ unit: false,
+ round: false,
+ displayFormat: false,
+ }
+ });
+ });
+
+ it ('should build ticks using days', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
+ };
+
+ var mockContext = window.createMockContext();
+ var Constructor = Chart.scaleService.getScaleConstructor('time');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
+ data: mockData,
+ id: scaleID
+ });
+
+ //scale.buildTicks();
+ scale.update(400, 50);
+
+ // Counts down because the lines are drawn top to bottom
+ expect(scale.ticks).toEqual(['Jan 1, 2015', 'Jan 2, 2015', 'Jan 3, 2015', 'Jan 4, 2015', 'Jan 5, 2015', 'Jan 6, 2015', 'Jan 7, 2015', 'Jan 8, 2015', 'Jan 9, 2015', 'Jan 10, 2015', 'Jan 11, 2015']);
+ });
+
+ it ('should build ticks using the config unit', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00"], // days
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.scaleService.getScaleDefaults('time');
+ config.time.unit = 'hour';
+ var Constructor = Chart.scaleService.getScaleConstructor('time');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config, // use default config for scale
+ data: mockData,
+ id: scaleID
+ });
+
+ //scale.buildTicks();
+ scale.update(400, 50);
+ expect(scale.ticks).toEqual(['Jan 1, 8PM', 'Jan 1, 9PM', 'Jan 1, 10PM', 'Jan 1, 11PM', 'Jan 2, 12AM', 'Jan 2, 1AM', 'Jan 2, 2AM', 'Jan 2, 3AM', 'Jan 2, 4AM', 'Jan 2, 5AM', 'Jan 2, 6AM', 'Jan 2, 7AM', 'Jan 2, 8AM', 'Jan 2, 9AM', 'Jan 2, 10AM', 'Jan 2, 11AM', 'Jan 2, 12PM', 'Jan 2, 1PM', 'Jan 2, 2PM', 'Jan 2, 3PM', 'Jan 2, 4PM', 'Jan 2, 5PM', 'Jan 2, 6PM', 'Jan 2, 7PM', 'Jan 2, 8PM', 'Jan 2, 9PM']);
+ });
+
+ it ('should build ticks using the config diff', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ labels: ["2015-01-01T20:00:00", "2015-02-02T21:00:00", "2015-02-21T01:00:00"], // days
+ };
+
+ var mockContext = window.createMockContext();
+ var config = Chart.scaleService.getScaleDefaults('time');
+ config.time.unit = 'week';
+ config.time.round = 'week';
+ var Constructor = Chart.scaleService.getScaleConstructor('time');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: config, // use default config for scale
+ data: mockData,
+ id: scaleID
+ });
+
+ //scale.buildTicks();
+ scale.update(400, 50);
+ expect(scale.ticks).toEqual(['Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015', 'Jan 18, 2015', 'Jan 25, 2015', 'Feb 1, 2015', 'Feb 8, 2015', 'Feb 15, 2015']);
+ });
+
+ it ('should get the correct pixel for a value', function() {
+ var scaleID = 'myScale';
+
+ var mockData = {
+ labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
+ };
+
+ var mockContext = window.createMockContext();
+ var Constructor = Chart.scaleService.getScaleConstructor('time');
+ var scale = new Constructor({
+ ctx: mockContext,
+ options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
+ data: mockData,
+ id: scaleID
+ });
+
+ //scale.buildTicks();
+ scale.update(400, 50);
+
+ expect(scale.width).toBe(400);
+ expect(scale.height).toBe(28);
+ scale.left = 0;
+ scale.right = 400;
+ scale.top = 10;
+ scale.bottom = 38;
+
+ expect(scale.getPixelForValue('', 0, 0)).toBe(63);
+ expect(scale.getPixelForValue('', 6, 0)).toBe(342);
+
+ var verticalScaleConfig = Chart.scaleService.getScaleDefaults('time');
+ verticalScaleConfig.position = "left";
+
+ var verticalScale = new Constructor({
+ ctx: mockContext,
+ options: verticalScaleConfig,
+ data: mockData,
+ id: scaleID
+ });
+ verticalScale.update(50, 400);
+ expect(verticalScale.width).toBe(50);
+ expect(verticalScale.height).toBe(400);
+ verticalScale.top = 0;
+ verticalScale.left = 0;
+ verticalScale.right = 50;
+ verticalScale.bottom = 400;
+
+ expect(verticalScale.getPixelForValue('', 0, 0)).toBe(6);
+ expect(verticalScale.getPixelForValue('', 6, 0)).toBe(394);
+ });
+});
\ No newline at end of file