diff --git a/docs/00-Getting-Started.md b/docs/00-Getting-Started.md
index 74287a94c..7cb1097aa 100644
--- a/docs/00-Getting-Started.md
+++ b/docs/00-Getting-Started.md
@@ -132,6 +132,9 @@ Chart.defaults.global = {
// Boolean - Determines whether to draw tooltips on the canvas or not
showTooltips: true,
+ // Function - Determines whether to execute the externalTooltips function instead of drawing the built in tooltips (See [Advanced - External Tooltips](#advanced-usage-external-tooltips))
+ externalTooltips: false,
+
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove"],
diff --git a/docs/06-Advanced.md b/docs/06-Advanced.md
index f9d696da2..d6cbf3a03 100644
--- a/docs/06-Advanced.md
+++ b/docs/06-Advanced.md
@@ -70,6 +70,39 @@ myLineChart.generateLegend();
// => returns HTML string of a legend for this chart
```
+### External Tooltips
+
+You can enable external tooltips in the global or chart configuration like so:
+
+```javascript
+var myPieChart = new Chart(ctx).Pie(data, {
+ externalTooltips: function(tooltip) {
+
+ // tooltip will be false if tooltip is not visible or should be hidden
+ if (!tooltip) {
+ return;
+ }
+
+ // Otherwise, tooltip will be an object with all tooltip properties like:
+
+ // tooltip.caretHeight
+ // tooltip.caretPadding
+ // tooltip.chart
+ // tooltip.cornerRadius
+ // tooltip.fillColor
+ // tooltip.font...
+ // tooltip.text
+ // tooltip.x
+ // tooltip.y
+ // etc...
+
+ };
+});
+```
+
+See files `sample/pie-externalTooltips.html` and `sample/line-externalTooltips.html` for examples on how to get started.
+
+
### Writing new chart types
Chart.js 1.0 has been rewritten to provide a platform for developers to create their own custom chart types, and be able to share and utilise them through the Chart.js API.
diff --git a/samples/line-externalTooltips.html b/samples/line-externalTooltips.html
new file mode 100644
index 000000000..67eab85ee
--- /dev/null
+++ b/samples/line-externalTooltips.html
@@ -0,0 +1,129 @@
+
+
+
+
+ Line Chart with Custom Tooltips
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/pie-externalTooltips.html b/samples/pie-externalTooltips.html
new file mode 100644
index 000000000..c126c640f
--- /dev/null
+++ b/samples/pie-externalTooltips.html
@@ -0,0 +1,156 @@
+
+
+
+
+ Pie Chart with Custom Tooltips
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Chart.Core.js b/src/Chart.Core.js
index 03b99b45a..07c63c4d5 100755
--- a/src/Chart.Core.js
+++ b/src/Chart.Core.js
@@ -98,6 +98,9 @@
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
showTooltips: true,
+ // Boolean - Determines whether to draw built-in tooltip or call custom tooltip function
+ externalTooltips: false,
+
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
@@ -895,6 +898,9 @@
this.activeElements = ChartElements;
}
this.draw();
+ if(this.options.externalTooltips){
+ this.options.externalTooltips(false);
+ }
if (ChartElements.length > 0){
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
@@ -975,7 +981,8 @@
legendColorBackground : this.options.multiTooltipKeyBackground,
title: ChartElements[0].label,
chart: this.chart,
- ctx: this.chart.ctx
+ ctx: this.chart.ctx,
+ external: this.options.externalTooltips
}).draw();
} else {
@@ -994,7 +1001,8 @@
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: template(this.options.tooltipTemplate, Element),
- chart: this.chart
+ chart: this.chart,
+ external: this.options.externalTooltips
}).draw();
}, this);
}
@@ -1250,7 +1258,7 @@
this.yAlign = "above";
//Distance between the actual element.y position and the start of the tooltip caret
- var caretPadding = 2;
+ var caretPadding = this.caretPadding = 2;
var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
tooltipRectHeight = this.fontSize + 2*this.yPadding,
@@ -1272,47 +1280,53 @@
ctx.fillStyle = this.fillColor;
- switch(this.yAlign)
- {
- case "above":
- //Draw a caret above the x/y
- ctx.beginPath();
- ctx.moveTo(this.x,this.y - caretPadding);
- ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
- ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
- ctx.closePath();
- ctx.fill();
- break;
- case "below":
- tooltipY = this.y + caretPadding + this.caretHeight;
- //Draw a caret below the x/y
- ctx.beginPath();
- ctx.moveTo(this.x, this.y + caretPadding);
- ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
- ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
- ctx.closePath();
- ctx.fill();
- break;
+ // Custom Tooltips
+ if(this.external){
+ this.external(this);
}
+ else{
+ switch(this.yAlign)
+ {
+ case "above":
+ //Draw a caret above the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x,this.y - caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
+ ctx.closePath();
+ ctx.fill();
+ break;
+ case "below":
+ tooltipY = this.y + caretPadding + this.caretHeight;
+ //Draw a caret below the x/y
+ ctx.beginPath();
+ ctx.moveTo(this.x, this.y + caretPadding);
+ ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
+ ctx.closePath();
+ ctx.fill();
+ break;
+ }
- switch(this.xAlign)
- {
- case "left":
- tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
- break;
- case "right":
- tooltipX = this.x - (this.cornerRadius + this.caretHeight);
- break;
+ switch(this.xAlign)
+ {
+ case "left":
+ tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
+ break;
+ case "right":
+ tooltipX = this.x - (this.cornerRadius + this.caretHeight);
+ break;
+ }
+
+ drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
+
+ ctx.fill();
+
+ ctx.fillStyle = this.textColor;
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
}
-
- drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
-
- ctx.fill();
-
- ctx.fillStyle = this.textColor;
- ctx.textAlign = "center";
- ctx.textBaseline = "middle";
- ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
}
});
@@ -1366,36 +1380,42 @@
},
draw : function(){
- drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
- var ctx = this.ctx;
- ctx.fillStyle = this.fillColor;
- ctx.fill();
- ctx.closePath();
+ // Custom Tooltips
+ if(this.external){
+ this.external(this);
+ }
+ else{
+ drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
+ var ctx = this.ctx;
+ ctx.fillStyle = this.fillColor;
+ ctx.fill();
+ ctx.closePath();
- ctx.textAlign = "left";
- ctx.textBaseline = "middle";
- ctx.fillStyle = this.titleTextColor;
- ctx.font = this.titleFont;
+ ctx.textAlign = "left";
+ ctx.textBaseline = "middle";
+ ctx.fillStyle = this.titleTextColor;
+ ctx.font = this.titleFont;
- ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
+ ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
- ctx.font = this.font;
- helpers.each(this.labels,function(label,index){
- ctx.fillStyle = this.textColor;
- ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
+ ctx.font = this.font;
+ helpers.each(this.labels,function(label,index){
+ ctx.fillStyle = this.textColor;
+ ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
- //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
- //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- //Instead we'll make a white filled block to put the legendColour palette over.
+ //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
+ //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ //Instead we'll make a white filled block to put the legendColour palette over.
- ctx.fillStyle = this.legendColorBackground;
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ ctx.fillStyle = this.legendColorBackground;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- ctx.fillStyle = this.legendColors[index].fill;
- ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
+ ctx.fillStyle = this.legendColors[index].fill;
+ ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
- },this);
+ },this);
+ }
}
});