Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ script:

notifications:
slack: chartjs:pcfCZR6ugg5TEcaLtmIfQYuA

sudo: false
3 changes: 2 additions & 1 deletion src/controllers/controller.bubble.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,14 @@
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.point.backgroundColor),
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.point.borderColor),
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.point.borderWidth),
skip: point.custom && point.custom.skip ? point.custom.skip : this.getDataset().data[index] === null,

// Tooltip
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius),
},
});

point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));

point.pivot();
},

Expand Down
6 changes: 2 additions & 4 deletions src/controllers/controller.line.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@
borderDashOffset: line.custom && line.custom.borderDashOffset ? line.custom.borderDashOffset : (this.getDataset().borderDashOffset || this.chart.options.elements.line.borderDashOffset),
borderJoinStyle: line.custom && line.custom.borderJoinStyle ? line.custom.borderJoinStyle : (this.getDataset().borderJoinStyle || this.chart.options.elements.line.borderJoinStyle),
fill: line.custom && line.custom.fill ? line.custom.fill : (this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill),
skipNull: this.getDataset().skipNull !== undefined ? this.getDataset().skipNull : this.chart.options.elements.line.skipNull,
drawNull: this.getDataset().drawNull !== undefined ? this.getDataset().drawNull : this.chart.options.elements.line.drawNull,
// Scale
scaleTop: yScale.top,
scaleBottom: yScale.bottom,
Expand Down Expand Up @@ -202,12 +200,12 @@
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
skip: point.custom && point.custom.skip ? point.custom.skip : this.getDataset().data[index] === null,

// Tooltip
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius),
},
});

point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
},

updateBezierControlPoints: function() {
Expand Down
5 changes: 2 additions & 3 deletions src/controllers/controller.radar.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@
borderWidth: this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth,
borderColor: this.getDataset().borderColor || this.chart.options.elements.line.borderColor,
fill: this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill, // use the value from the this.getDataset() if it was provided. else fall back to the default
skipNull: this.getDataset().skipNull !== undefined ? this.getDataset().skipNull : this.chart.options.elements.line.skipNull,
drawNull: this.getDataset().drawNull !== undefined ? this.getDataset().drawNull : this.chart.options.elements.line.drawNull,

// Scale
scaleTop: scale.top,
Expand Down Expand Up @@ -181,12 +179,13 @@
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
skip: point.custom && point.custom.skip ? point.custom.skip : this.getDataset().data[index] === null,

// Tooltip
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius),
},
});

point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
},
updateBezierControlPoints: function() {
helpers.each(this.getDataset().metaData, function(point, index) {
Expand Down
26 changes: 20 additions & 6 deletions src/core/core.helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,18 +324,32 @@
splineCurve = helpers.splineCurve = function(FirstPoint, MiddlePoint, AfterPoint, t) {
//Props to Rob Spencer at scaled innovation for his post on splining between points
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
var d01 = Math.sqrt(Math.pow(MiddlePoint.x - FirstPoint.x, 2) + Math.pow(MiddlePoint.y - FirstPoint.y, 2)),
d12 = Math.sqrt(Math.pow(AfterPoint.x - MiddlePoint.x, 2) + Math.pow(AfterPoint.y - MiddlePoint.y, 2)),

// This function must also respect "skipped" points

var previous = FirstPoint,
current = MiddlePoint,
next = AfterPoint;

if (previous.skip) {
previous = current;
}
if (next.skip) {
next = current;
}

var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)),
d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)),
fa = t * d01 / (d01 + d12), // scaling factor for triangle Ta
fb = t * d12 / (d01 + d12);
return {
previous: {
x: MiddlePoint.x - fa * (AfterPoint.x - FirstPoint.x),
y: MiddlePoint.y - fa * (AfterPoint.y - FirstPoint.y)
x: current.x - fa * (next.x - previous.x),
y: current.y - fa * (next.y - previous.y)
},
next: {
x: MiddlePoint.x + fb * (AfterPoint.x - FirstPoint.x),
y: MiddlePoint.y + fb * (AfterPoint.y - FirstPoint.y)
x: current.x + fb * (next.x - previous.x),
y: current.y + fb * (next.y - previous.y)
}
};
},
Expand Down
22 changes: 18 additions & 4 deletions src/core/core.scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,24 @@
isHorizontal: function() {
return this.options.position == "top" || this.options.position == "bottom";
},

// Get the correct value. If the value type is object get the x or y based on whether we are horizontal or not
getRightValue: function(rawValue) {
return (typeof(rawValue) === "object" && rawValue !== null) ? (this.isHorizontal() ? rawValue.x : rawValue.y) : rawValue;

// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
getRightValue: function getRightValue(rawValue) {
// Null and undefined values first
if (rawValue === null || typeof(rawValue) === 'undefined') {
return NaN;
}
// isNaN(object) returns true, so make sure NaN is checking for a number
if (typeof(rawValue) === 'number' && isNaN(rawValue)) {
return NaN;
}
// If it is in fact an object, dive in one more level
if (typeof(rawValue) === "object") {
return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
}

// Value is good, return it
return rawValue;
},

// Used to get the value to display in the tooltip for the data at the given index
Expand Down
111 changes: 55 additions & 56 deletions src/elements/element.line.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
fill: true, // do we fill in the area between the line and its base axis
skipNull: true,
drawNull: false,
};


Expand All @@ -44,50 +42,51 @@

// Draw the background first (so the border is always on top)
helpers.each(this._children, function(point, index) {

var previous = helpers.previousItem(this._children, index);
var next = helpers.nextItem(this._children, index);

// First point only
if (index === 0) {
ctx.moveTo(point._view.x, point._view.y);
return;
// First point moves to it's starting position no matter what
if (!index) {
ctx.moveTo(point._view.x, vm.scaleZero);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to lose the return?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah

}

// Start Skip and drag along scale baseline
if (point._view.skip && vm.skipNull && !this._loop) {
ctx.lineTo(previous._view.x, point._view.y);
ctx.moveTo(next._view.x, point._view.y);
// Skip this point, draw to scaleZero, move to next point, and draw to next point
if (point._view.skip && !this.loop) {
ctx.lineTo(previous._view.x, vm.scaleZero);
ctx.moveTo(next._view.x, vm.scaleZero);
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is adding a return correct here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I adopted a return fast pattern instead of a bunch of nested if else statements.

}
// End Skip Stright line from the base line
else if (previous._view.skip && vm.skipNull && !this._loop) {
ctx.moveTo(point._view.x, previous._view.y);

// The previous line was skipped, so just draw a normal straight line to the point
if (previous._view.skip) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we consciously losing the distinction between skipNull and drawNull?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I believe so for now. Both features were broken to some extent. I think it's better we go with a solid base. If someone down the line needs to draw falsey values as zeros I think they would probably just scrub their data for that and then expect chartjs to deliver accurately.

ctx.lineTo(point._view.x, point._view.y);
return;
}

if (previous._view.skip && vm.skipNull) {
ctx.moveTo(point._view.x, point._view.y);
}
// Normal Bezier Curve
else {
if (vm.tension > 0) {
ctx.bezierCurveTo(
previous._view.controlPointNextX,
previous._view.controlPointNextY,
point._view.controlPointPreviousX,
point._view.controlPointPreviousY,
point._view.x,
point._view.y
);
} else {
ctx.lineTo(point._view.x, point._view.y);
}
// Draw a bezier to point
if (vm.tension > 0 && index) {
//ctx.lineTo(point._view.x, point._view.y);
ctx.bezierCurveTo(
previous._view.controlPointNextX,
previous._view.controlPointNextY,
point._view.controlPointPreviousX,
point._view.controlPointPreviousY,
point._view.x,
point._view.y
);
return;
}

// Draw a straight line to the point
ctx.lineTo(point._view.x, point._view.y);

}, this);

// For radial scales, loop back around to the first point
if (this._loop) {
// Draw a bezier line
if (vm.tension > 0 && !first._view.skip) {

ctx.bezierCurveTo(
last._view.controlPointNextX,
last._view.controlPointNextY,
Expand All @@ -96,9 +95,10 @@
first._view.x,
first._view.y
);
} else {
ctx.lineTo(first._view.x, first._view.y);
return;
}
// Draw a straight line
ctx.lineTo(first._view.x, first._view.y);
}

// If we had points and want to fill this line, do so.
Expand Down Expand Up @@ -130,31 +130,24 @@
var previous = helpers.previousItem(this._children, index);
var next = helpers.nextItem(this._children, index);

// First point only
if (index === 0) {
ctx.moveTo(point._view.x, point._view.y);
return;
if (!index) {
ctx.moveTo(point._view.x, vm.scaleZero);
}

// Start Skip and drag along scale baseline
if (point._view.skip && vm.skipNull && !this._loop) {
ctx.moveTo(previous._view.x, point._view.y);
ctx.moveTo(next._view.x, point._view.y);
return;
}
// End Skip Stright line from the base line
if (previous._view.skip && vm.skipNull && !this._loop) {
ctx.moveTo(point._view.x, previous._view.y);
ctx.moveTo(point._view.x, point._view.y);
// Skip this point and move to the next points zeroPoint
if (point._view.skip && !this.loop) {
ctx.moveTo(next._view.x, vm.scaleZero);
return;
}

if (previous._view.skip && vm.skipNull) {
// Previous point was skipped, just move to the point
if (previous._view.skip) {
ctx.moveTo(point._view.x, point._view.y);
return;
}
// Normal Bezier Curve
if (vm.tension > 0) {

// Draw a bezier line to the point
if (vm.tension > 0 && index) {
ctx.bezierCurveTo(
previous._view.controlPointNextX,
previous._view.controlPointNextY,
Expand All @@ -163,14 +156,18 @@
point._view.x,
point._view.y
);
} else {
ctx.lineTo(point._view.x, point._view.y);
return;
}

// Draw a straight line to the point
ctx.lineTo(point._view.x, point._view.y);

}, this);

if (this._loop && !first._view.skip) {
if (vm.tension > 0) {

// Draw a bezier line to the first point
if (vm.tension > 0) {
ctx.bezierCurveTo(
last._view.controlPointNextX,
last._view.controlPointNextY,
Expand All @@ -179,14 +176,16 @@
first._view.x,
first._view.y
);
} else {
ctx.lineTo(first._view.x, first._view.y);
return;
}

// Draw a straight line to the first point
ctx.lineTo(first._view.x, first._view.y);
}

ctx.stroke();
ctx.restore();
},
});

}).call(this);
}).call(this);
11 changes: 9 additions & 2 deletions src/scales/scale.linear.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
helpers.each(dataset.data, function(rawValue, index) {

var value = this.getRightValue(rawValue);
if (isNaN(value)) {
return;
}

positiveValues[index] = positiveValues[index] || 0;
negativeValues[index] = negativeValues[index] || 0;
Expand All @@ -51,6 +54,9 @@
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
helpers.each(dataset.data, function(rawValue, index) {
var value = this.getRightValue(rawValue);
if (isNaN(value)) {
return;
}

if (this.min === null) {
this.min = value;
Expand Down Expand Up @@ -155,17 +161,18 @@
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
// This must be called after fit has been run so that
// this.left, this.top, this.right, and this.bottom have been defined
var rightValue = this.getRightValue(value);
var pixel;
var range = this.end - this.start;

if (this.isHorizontal()) {

var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
pixel = this.left + (innerWidth / range * (this.getRightValue(value) - this.start));
pixel = this.left + (innerWidth / range * (rightValue - this.start));
return Math.round(pixel + this.paddingLeft);
} else {
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (this.getRightValue(value) - this.start));
pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (rightValue - this.start));
return Math.round(pixel);
}
},
Expand Down
8 changes: 7 additions & 1 deletion src/scales/scale.logarithmic.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));

if (remain === 1 || remain === 2 || remain === 5) {
return value.toExponential()
return value.toExponential();
} else {
return '';
}
Expand All @@ -38,6 +38,9 @@
helpers.each(dataset.data, function(rawValue, index) {

var value = this.getRightValue(rawValue);
if (isNaN(value)) {
return;
}

values[index] = values[index] || 0;

Expand All @@ -59,6 +62,9 @@
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
helpers.each(dataset.data, function(rawValue, index) {
var value = this.getRightValue(rawValue);
if (isNaN(value)) {
return;
}

if (this.min === null) {
this.min = value;
Expand Down
Loading