diff --git a/samples/bar.html b/samples/bar.html
index 004e0738f..d12765700 100644
--- a/samples/bar.html
+++ b/samples/bar.html
@@ -72,11 +72,11 @@
responsive: true,
legend: {
position: 'top',
- title: {
- display: true,
- text: 'Our 3 Favorite Datasets'
- }
},
+ title: {
+ display: true,
+ text: 'Our 3 Favorite Datasets'
+ }
}
});
diff --git a/samples/doughnut.html b/samples/doughnut.html
index 0a6be617a..f0ebd5129 100644
--- a/samples/doughnut.html
+++ b/samples/doughnut.html
@@ -107,11 +107,11 @@
responsive: true,
legend: {
position: 'top',
- title: {
- display: true,
- text: 'Our Favorite Datasets'
- }
},
+ title: {
+ display: true,
+ text: 'Our Favorite Datasets'
+ }
}
};
diff --git a/samples/line-legend.html b/samples/line-legend.html
index 98ffc18f3..ea345c21b 100644
--- a/samples/line-legend.html
+++ b/samples/line-legend.html
@@ -61,11 +61,7 @@
options: {
responsive: true,
legend: {
- position: 'top',
- title: {
- display: true,
- text: 'Our 4 Favorite Datasets'
- }
+ position: 'bottom',
},
hover: {
mode: 'label'
@@ -85,6 +81,10 @@
labelString: 'Value'
}
}]
+ },
+ title: {
+ display: true,
+ text: 'Our 4 Favorite Datasets'
}
}
};
diff --git a/samples/polar-area.html b/samples/polar-area.html
index 58f9d57f1..8d9bc9c64 100644
--- a/samples/polar-area.html
+++ b/samples/polar-area.html
@@ -62,10 +62,10 @@
responsive: true,
legend: {
position: 'top',
- title: {
- display: true,
- text: 'Our Favorite Dataset'
- }
+ },
+ title: {
+ display: true,
+ text: 'Our Favorite Dataset'
},
scale: {
ticks: {
diff --git a/samples/radar.html b/samples/radar.html
index 867605275..e294cee18 100644
--- a/samples/radar.html
+++ b/samples/radar.html
@@ -58,13 +58,13 @@
options: {
legend: {
position: 'top',
- title: {
- display: true,
- text: 'Our 3 Favorite Datasets'
- }
+ },
+ title: {
+ display: true,
+ text: 'Our 3 Favorite Datasets'
},
scale: {
- reverse: true,
+ reverse: false,
ticks: {
beginAtZero: true
}
diff --git a/src/core/core.controller.js b/src/core/core.controller.js
index 47884b732..88bf11a83 100644
--- a/src/core/core.controller.js
+++ b/src/core/core.controller.js
@@ -59,7 +59,7 @@
this.ensureScalesHaveIDs();
this.buildOrUpdateControllers();
this.buildScales();
- this.buildLegends();
+ this.buildSurroundingItems();
this.updateLayout();
this.resetElements();
this.initToolTip();
@@ -170,18 +170,26 @@
Chart.scaleService.addScalesToLayout(this);
},
- buildLegends: function() {
- if (!this.options.legend) {
- return;
+ buildSurroundingItems: function() {
+ if (this.options.title) {
+ this.titleBlock = new Chart.Title({
+ ctx: this.chart.ctx,
+ options: this.options.title,
+ chart: this
+ });
+
+ Chart.layoutService.addBox(this, this.titleBlock);
}
- this.legend = new Chart.Legend({
- ctx: this.chart.ctx,
- options: this.options.legend,
- chart: this,
- });
+ if (this.options.legend) {
+ this.legend = new Chart.Legend({
+ ctx: this.chart.ctx,
+ options: this.options.legend,
+ chart: this,
+ });
- Chart.layoutService.addBox(this, this.legend);
+ Chart.layoutService.addBox(this, this.legend);
+ }
},
updateLayout: function() {
diff --git a/src/core/core.legend.js b/src/core/core.legend.js
index fb3776d27..14e1c6b4e 100644
--- a/src/core/core.legend.js
+++ b/src/core/core.legend.js
@@ -12,21 +12,6 @@
fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
onClick: false, // a callback will override the default behavior of toggling the datasets
- title: {
- position: 'top',
- fontColor: '#666',
- fontFamily: 'Helvetica Neue',
- fontSize: 12,
- fontStyle: 'bold',
- padding: 10,
-
- // actual title
- text: '',
-
- // display property
- display: false,
- },
-
labels: {
boxWidth: 40,
fontSize: 12,
@@ -136,7 +121,6 @@
fit: function() {
var ctx = this.ctx;
- var titleFont = helpers.fontString(this.options.title.fontSize, this.options.title.fontStyle, this.options.title.fontFamily);
var labelFont = helpers.fontString(this.options.labels.fontSize, this.options.labels.fontStyle, this.options.labels.fontFamily);
// Reset hit boxes
@@ -158,12 +142,6 @@
// Increase sizes here
if (this.isHorizontal()) {
-
- // Title
- if (this.options.title.display) {
- this.minSize.height += this.options.title.fontSize + (this.options.title.padding * 2);
- }
-
// Labels
// Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
@@ -215,7 +193,7 @@
var ctx = this.ctx;
var cursor = {
x: this.left + ((this.width - this.lineWidths[0]) / 2),
- y: this.top,
+ y: this.top + this.options.labels.padding,
line: 0,
};
@@ -223,17 +201,6 @@
// Horizontal
if (this.isHorizontal()) {
-
- // Title Spacing if on top
- if (this.options.title.display) {
- if (this.options.title.position === 'top') {
- cursor.y += this.options.title.fontSize + (this.options.title.padding * 2);
- } else {
- // bottom
- cursor.y += this.options.labels.padding;
- }
- }
-
// Labels
ctx.textAlign = "left";
ctx.textBaseline = 'top';
@@ -299,49 +266,8 @@
cursor.x += width + (this.options.labels.padding);
}, this);
-
- // Title Spacing if on bottom
- if (this.options.title.display && this.options.title.position === 'bottom') {
- cursor.y += this.options.title.fontSize + (this.options.title.padding * 2);
- }
-
- // Title
- if (this.options.title.display) {
-
- ctx.textAlign = "center";
- ctx.textBaseline = 'middle';
- ctx.fillStyle = this.options.title.fontColor; // render in correct colour
- ctx.font = helpers.fontString(this.options.title.fontSize, this.options.title.fontStyle, this.options.title.fontFamily);
-
- var titleX = this.left + ((this.right - this.left) / 2); // midpoint of the width
- var titleY = this.options.title.position == 'bottom' ? this.bottom - (this.options.title.fontSize / 2) - this.options.title.padding : this.top + (this.options.title.fontSize / 2) + this.options.title.padding;
-
- ctx.fillText(this.options.title.text, titleX, titleY);
- }
-
-
} else {
- // Title
- if (this.options.title.display) {
-
- // Draw the legend label
- titleX = this.options.position == 'left' ? this.left + (this.options.title.fontSize / 2) : this.right - (this.options.title.fontSize / 2);
- titleY = this.top + ((this.bottom - this.top) / 2);
- var rotation = this.options.position == 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
-
- ctx.save();
- ctx.translate(titleX, titleY);
- ctx.rotate(rotation);
- ctx.textAlign = "center";
- ctx.fillStyle = this.options.title.fontColor; // render in correct colour
- ctx.font = helpers.fontString(this.options.title.fontSize, this.options.title.fontStyle, this.options.title.fontFamily);
- ctx.textBaseline = 'middle';
- ctx.fillText(this.options.title.text, 0, 0);
- ctx.restore();
-
- }
-
}
}
},
@@ -363,7 +289,6 @@
this.chart.data.datasets[i].hidden = !this.chart.data.datasets[i].hidden;
// We hid a dataset ... rerender the chart
- //this.chart.render();
this.chart.update();
break;
}
diff --git a/src/core/core.title.js b/src/core/core.title.js
new file mode 100644
index 000000000..7758fd337
--- /dev/null
+++ b/src/core/core.title.js
@@ -0,0 +1,196 @@
+(function() {
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+ Chart.defaults.title = {
+
+ display: true,
+ position: 'top',
+ fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
+
+ fontColor: '#666',
+ fontFamily: 'Helvetica Neue',
+ fontSize: 12,
+ fontStyle: 'bold',
+ padding: 10,
+
+ // actual title
+ text: '',
+ };
+
+ Chart.Title = Chart.Element.extend({
+
+ initialize: function(config) {
+ helpers.extend(this, config);
+ this.options = helpers.configMerge(Chart.defaults.title, config.options);
+
+ // Contains hit boxes for each dataset (in dataset order)
+ this.legendHitBoxes = [];
+ },
+
+ // These methods are ordered by lifecyle. Utilities then follow.
+
+ beforeUpdate: helpers.noop,
+ update: function(maxWidth, maxHeight, margins) {
+
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
+ this.beforeUpdate();
+
+ // Absorb the master measurements
+ this.maxWidth = maxWidth;
+ this.maxHeight = maxHeight;
+ this.margins = margins;
+
+ // Dimensions
+ this.beforeSetDimensions();
+ this.setDimensions();
+ this.afterSetDimensions();
+ // Labels
+ this.beforeBuildLabels();
+ this.buildLabels();
+ this.afterBuildLabels();
+
+ // Fit
+ this.beforeFit();
+ this.fit();
+ this.afterFit();
+ //
+ this.afterUpdate();
+
+ return this.minSize;
+
+ },
+ afterUpdate: helpers.noop,
+
+ //
+
+ beforeSetDimensions: helpers.noop,
+ setDimensions: function() {
+ // Set the unconstrained dimension before label rotation
+ if (this.isHorizontal()) {
+ // Reset position before calculating rotation
+ this.width = this.maxWidth;
+ this.left = 0;
+ this.right = this.width;
+ } else {
+ this.height = this.maxHeight;
+
+ // Reset position before calculating rotation
+ this.top = 0;
+ this.bottom = this.height;
+ }
+
+ // Reset padding
+ this.paddingLeft = 0;
+ this.paddingTop = 0;
+ this.paddingRight = 0;
+ this.paddingBottom = 0;
+
+ // Reset minSize
+ this.minSize = {
+ width: 0,
+ height: 0,
+ };
+ },
+ afterSetDimensions: helpers.noop,
+
+ //
+
+ beforeBuildLabels: helpers.noop,
+ buildLabels: helpers.noop,
+ afterBuildLabels: helpers.noop,
+
+ //
+
+ beforeFit: helpers.noop,
+ fit: function() {
+
+ var ctx = this.ctx;
+ var titleFont = helpers.fontString(this.options.fontSize, this.options.fontStyle, this.options.fontFamily);
+
+ // Width
+ if (this.isHorizontal()) {
+ this.minSize.width = this.maxWidth; // fill all the width
+ } else {
+ this.minSize.width = 0;
+ }
+
+ // height
+ if (this.isHorizontal()) {
+ this.minSize.height = 0;
+ } else {
+ this.minSize.height = this.maxHeight; // fill all the height
+ }
+
+ // Increase sizes here
+ if (this.isHorizontal()) {
+
+ // Title
+ if (this.options.display) {
+ this.minSize.height += this.options.fontSize + (this.options.padding * 2);
+ }
+ } else {
+ // TODO vertical
+ }
+
+ this.width = this.minSize.width;
+ this.height = this.minSize.height;
+
+ },
+ afterFit: helpers.noop,
+
+ // Shared Methods
+ isHorizontal: function() {
+ return this.options.position == "top" || this.options.position == "bottom";
+ },
+
+ // Actualy draw the title block on the canvas
+ draw: function() {
+ if (this.options.display) {
+ var ctx = this.ctx;
+ var titleX, titleY;
+
+ // Horizontal
+ if (this.isHorizontal()) {
+ // Title
+ if (this.options.display) {
+
+ ctx.textAlign = "center";
+ ctx.textBaseline = 'middle';
+ ctx.fillStyle = this.options.fontColor; // render in correct colour
+ ctx.font = helpers.fontString(this.options.fontSize, this.options.fontStyle, this.options.fontFamily);
+
+ titleX = this.left + ((this.right - this.left) / 2); // midpoint of the width
+ titleY = this.top + ((this.bottom - this.top) / 2); // midpoint of the height
+
+ ctx.fillText(this.options.text, titleX, titleY);
+ }
+ } else {
+
+ // Title
+ if (this.options.display) {
+ titleX = this.options.position == 'left' ? this.left + (this.options.fontSize / 2) : this.right - (this.options.fontSize / 2);
+ titleY = this.top + ((this.bottom - this.top) / 2);
+ var rotation = this.options.position == 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
+
+ ctx.save();
+ ctx.translate(titleX, titleY);
+ ctx.rotate(rotation);
+ ctx.textAlign = "center";
+ ctx.fillStyle = this.options.fontColor; // render in correct colour
+ ctx.font = helpers.fontString(this.options.fontSize, this.options.fontStyle, this.options.fontFamily);
+ ctx.textBaseline = 'middle';
+ ctx.fillText(this.options.text, 0, 0);
+ ctx.restore();
+
+ }
+
+ }
+ }
+ }
+ });
+
+}).call(this);