'),s.x.options.title&&s.x.used&&t.push('
',s.x.options.title,"
"),s.x2.options.title&&s.x2.used&&t.push('
',s.x2.options.title,"
"),s.y.options.title&&s.y.used&&t.push('
',s.y.options.title,"
"),s.y2.options.title&&s.y2.used&&t.push('
',s.y2.options.title,"
"),t=t.join("");var u=e.create("div");e.setStyles({color:n.grid.color}),u.className="flotr-titles",e.insert(this.el,u),e.insert(u,t)}}})}(),function(){var e=Flotr.DOM;Flotr.addPlugin("statusGraphTitle",{callbacks:{"flotr:afterdraw":function(){this.statusGraphTitle.drawStatusTitle()}},drawStatusTitle:function(){var e=this.options,t=e.grid.labelMargin,n=this.ctx,r=this.axes,i={size:e.statusGraphTitle.fontSize,color:e.statusGraphTitle.color,textAlign:"center",weight:1.5,textBaseline:"middle"};e.statusGraphTitle.text&&Flotr.drawText(n,e.statusGraphTitle.text,this.plotOffset.left+this.plotWidth/2,this.plotHeight/2,i)}})}();
diff --git a/flotr2.nolibs.js b/flotr2.nolibs.js
index 303b18cf..dd275814 100644
--- a/flotr2.nolibs.js
+++ b/flotr2.nolibs.js
@@ -1267,6 +1267,7 @@ Graph.prototype = {
textEnabled : this.textEnabled,
htmlText : this.options.HtmlText,
text : this._text, // TODO Is this necessary?
+ labelText : series.label,
element : this.el,
data : series.data,
color : series.color,
@@ -1280,10 +1281,21 @@ Graph.prototype = {
options = flotr.merge(type, options);
// Fill
- options.fillStyle = this.processColor(
- type.fillColor || series.color,
- {opacity: type.fillOpacity}
- );
+ var color = type.fillColor || series.color;
+ var colorType = color.substring( 0, color.indexOf('('));
+ if (colorType == 'rgba') {
+ // Color already has alpha, use it
+ var colorAlpha = color.substring( color.lastIndexOf(',')+1, color.lastIndexOf(')')).replace(/ /g,''); // Get the alpha value (if it exists), and remove whitespace
+ options.fillStyle = this.processColor(
+ color,
+ {opacity: colorAlpha}
+ );
+ } else {
+ options.fillStyle = this.processColor(
+ color,
+ {opacity: type.fillOpacity}
+ );
+ }
return options;
},
@@ -3423,7 +3435,7 @@ function isImage (i) {
var
_ = Flotr._;
-Flotr.defaultPieLabelFormatter = function (total, value) {
+Flotr.defaultPieLabelFormatter = function (total, value, labelText) {
return (100 * value / total).toFixed(2)+'%';
};
@@ -3467,7 +3479,8 @@ Flotr.addType('pie', {
startAngle = this.startAngle || (2 * Math.PI * options.startAngle), // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
endAngle = startAngle + measure,
bisection = startAngle + measure / 2,
- label = options.labelFormatter(this.total, value),
+ //label = options.labelFormatter(this.total, value),
+ label = options.labelFormatter(this.total, value, options.labelText),
//plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale;
explodeCoeff = explode + radius + 4,
distX = Math.cos(bisection) * explodeCoeff,
@@ -3626,6 +3639,262 @@ Flotr.addType('pie', {
});
})();
+/**
+ * Donut
+ *
+ * Formats the donuts labels.
+ * @param {Object} slice - Slice object
+ * @return {String} Formatted donut label string
+ */
+(function () {
+
+var
+ _ = Flotr._;
+
+Flotr.defaultDonutLabelFormatter = function (total, value, labelText) {
+ return (100 * value / total).toFixed(2)+'%';
+};
+
+Flotr.addType('donut', {
+ options: {
+ show: false, // => setting to true will show bars, false will hide
+ lineWidth: 1, // => in pixels
+ fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill
+ fillColor: null, // => fill color
+ fillOpacity: 0.6, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
+ explode: 6, // => the number of pixels the splices will be far from the center
+ sizeRatio: 0.6, // => the size ratio of the donut relative to the plot
+ startAngle: Math.PI/4, // => the first slice start angle
+ labelFormatter: Flotr.defaultDonutLabelFormatter,
+ epsilon: 0.1, // => how close do you have to get to hit empty slice
+ sliceThickness: 20 // => thickness of each slice in the donut
+ },
+
+ startAngle: [],
+ total: [],
+
+ draw : function (options) {
+
+ var startAngle = [];
+ var endAngle = [];
+
+ var
+ data = options.data,
+ context = options.context,
+ lineWidth = options.lineWidth,
+ shadowSize = options.shadowSize,
+ sizeRatio = options.sizeRatio,
+ height = options.height,
+ width = options.width,
+ explode = options.explode,
+ color = options.color,
+ fill = options.fill,
+ fillStyle = options.fillStyle,
+ radius = Math.min(width, height) * sizeRatio / 2,
+ thickness = options.sliceThickness,
+ value = data[0][1],
+ layer = data[0][0],
+ html = [],
+ vScale = 1,
+ measure = Math.PI * 2 * value / this.total[layer];
+ startAngle[layer] = this.startAngle[layer] || (2 * Math.PI * options.startAngle); // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
+ endAngle[layer] = startAngle[layer] + measure;
+ var
+ bisection = startAngle[layer] + measure / 2,
+ label = options.labelFormatter(this.total[layer], value, options.labelText),
+ explodeCoeff = explode + radius + 4,
+ distX = Math.cos(bisection) * explodeCoeff,
+ distY = Math.sin(bisection) * explodeCoeff,
+ textAlign = distX < 0 ? 'right' : 'left',
+ textBaseline = distY > 0 ? 'top' : 'bottom',
+ style,
+ x, y;
+
+ context.save();
+ context.translate(width / 2, height / 2);
+ context.scale(1, vScale);
+
+ x = Math.cos(bisection) * explode;
+ y = Math.sin(bisection) * explode;
+
+ // Shadows
+ if (shadowSize > 0) {
+ this.plotSlice(x + shadowSize, y + shadowSize, radius, thickness, layer, startAngle[layer], endAngle[layer], context);
+ if (fill) {
+ context.fillStyle = 'rgba(0,0,0,0.1)';
+ context.fill();
+ }
+ }
+
+ if (value > 0) {
+ this.plotSlice(x, y, radius, thickness, layer, startAngle[layer], endAngle[layer], context);
+ if (fill) {
+ context.fillStyle = fillStyle;
+ context.fill();
+ }
+ context.lineWidth = lineWidth;
+ context.strokeStyle = color;
+ context.stroke();
+ }
+
+ style = {
+ size : options.fontSize * 1.2,
+ color : options.fontColor,
+ weight : 1.5
+ };
+
+ if (label) {
+ if (options.htmlText || !options.textEnabled) {
+ // iterate through slices and check for overlap
+ _.each(this.slices, function (slice){
+ // Get old bisection
+ sliceBisect = slice.start + (slice.end-slice.start) / 2;
+ // Check if close
+ if (sliceBisect-bisection < 0 && sliceBisect-bisection > -0.3) {
+ // Values close, move bisection up
+ bisection += 0.3;
+ adjustValues();
+ } else if (sliceBisect-bisection < 0.3 && sliceBisect-bisection >= 0) {
+ // Values close, move bisection down
+ bisection -= 0.3;
+ adjustValues();
+ }
+
+ function adjustValues() {
+ // Adjust new values
+ distX = Math.cos(bisection) * explodeCoeff;
+ distY = Math.sin(bisection) * explodeCoeff;
+ textAlign = distX < 0 ? 'right' : 'left';
+ textBaseline = distY > 0 ? 'top' : 'bottom';
+ }
+ });
+
+ divStyle = 'position:absolute;' + textBaseline + ':' + (height / 2 + (textBaseline === 'top' ? distY : -distY)) + 'px;';
+ divStyle += textAlign + ':' + (width / 2 + (textAlign === 'right' ? -distX : distX)) + 'px;';
+ html.push('
', label, '
');
+ }
+ else {
+ style.textAlign = textAlign;
+ style.textBaseline = textBaseline;
+ Flotr.drawText(context, label, distX, distY, style);
+ }
+ }
+
+ if (options.htmlText || !options.textEnabled) {
+ var div = Flotr.DOM.node('
');
+ Flotr.DOM.insert(div, html.join(''));
+ Flotr.DOM.insert(options.element, div);
+ }
+
+ context.restore();
+
+ // New start angle
+ this.startAngle[layer] = endAngle[layer];
+ this.slices = this.slices || [];
+ this.slices.push({
+ radius : radius,
+ x : x,
+ y : y,
+ explode : explode,
+ start : startAngle[layer],
+ end : endAngle[layer]
+ });
+ },
+ plotSlice : function (x, y, radius, thickness, layer, startAngle, endAngle, context) {
+ // Start path
+ context.beginPath();
+ // Move to inside arc start pt
+ context.moveTo(x+Math.cos(startAngle)*(radius-thickness*(layer+1)), y+Math.sin(startAngle)*(radius-thickness*(layer+1)));
+ // Line to outside arc start pt
+ context.lineTo(x+Math.cos(startAngle)*(radius-thickness*(layer)), y+Math.sin(startAngle)*(radius-thickness*(layer)));
+ // Outside arc
+ context.arc(x, y, radius-thickness*(layer), startAngle, endAngle, false);
+ // Line to inside arc end pt
+ context.lineTo(x+Math.cos(endAngle)*(radius-thickness*(layer+1)), y+Math.sin(endAngle)*(radius-thickness*(layer+1)));
+ // Inside arc
+ context.arc(x, y, radius-thickness*(layer+1), endAngle, startAngle, true);
+ // Close
+ context.closePath();
+ },
+ hit : function (options) {
+
+ var
+ data = options.data[0],
+ args = options.args,
+ index = options.index,
+ mouse = args[0],
+ n = args[1],
+ slice = this.slices[index],
+ x = mouse.relX - options.width / 2,
+ y = mouse.relY - options.height / 2,
+ r = Math.sqrt(x * x + y * y),
+ theta = Math.atan(y / x),
+ circle = Math.PI * 2,
+ explode = slice.explode || options.explode,
+ start = slice.start % circle,
+ end = slice.end % circle,
+ epsilon = options.epsilon;
+
+ if (x < 0) {
+ theta += Math.PI;
+ } else if (x > 0 && y < 0) {
+ theta += circle;
+ }
+
+ if (r < slice.radius + explode && r > explode) {
+ if (
+ (theta > start && theta < end) || // Normal Slice
+ (start > end && (theta < end || theta > start)) || // First slice
+ // TODO: Document the two cases at the end:
+ (start === end && ((slice.start === slice.end && Math.abs(theta - start) < epsilon) || (slice.start !== slice.end && Math.abs(theta-start) > epsilon)))
+ ) {
+
+ // TODO Decouple this from hit plugin (chart shouldn't know what n means)
+ n.x = data[0];
+ n.y = data[1];
+ n.sAngle = start;
+ n.eAngle = end;
+ n.index = 0;
+ n.seriesIndex = index;
+ n.fraction = data[1] / this.total[layer];
+ }
+ }
+ },
+ drawHit: function (options) {
+ var
+ context = options.context,
+ slice = this.slices[options.args.seriesIndex];
+
+ context.save();
+ context.translate(options.width / 2, options.height / 2);
+ this.plotSlice(slice.x, slice.y, slice.radius, thickness, layer, slice.start, slice.end, context);
+ context.stroke();
+ context.restore();
+ },
+ clearHit : function (options) {
+ var
+ context = options.context,
+ slice = this.slices[options.args.seriesIndex],
+ padding = 2 * options.lineWidth,
+ radius = slice.radius + padding;
+
+ context.save();
+ context.translate(options.width / 2, options.height / 2);
+ context.clearRect(
+ slice.x - radius,
+ slice.y - radius,
+ 2 * radius + padding,
+ 2 * radius + padding
+ );
+ context.restore();
+ },
+ extendYRange : function (axis, data) {
+ var layer = data[0][0];
+ this.total[layer] = (this.total[layer] || 0) + data[0][1];
+ }
+});
+})();
+
/** Points **/
Flotr.addType('points', {
options: {
@@ -5863,3 +6132,44 @@ Flotr.addPlugin('titles', {
}
});
})();
+
+(function () {
+
+var D = Flotr.DOM;
+
+Flotr.addPlugin('statusGraphTitle', {
+ callbacks: {
+ 'flotr:afterdraw': function() {
+ this.statusGraphTitle.drawStatusTitle();
+ }
+ },
+ /**
+ * Draws the title
+ */
+ drawStatusTitle : function () {
+ var
+ options = this.options,
+ margin = options.grid.labelMargin,
+ ctx = this.ctx,
+ a = this.axes;
+
+ var style = {
+ size: options.statusGraphTitle.fontSize,
+ color: options.statusGraphTitle.color,
+ textAlign: 'center',
+ weight: 1.5,
+ textBaseline: 'middle'
+ };
+
+ // Draw text
+ if (options.statusGraphTitle.text) {
+ Flotr.drawText(
+ ctx, options.statusGraphTitle.text,
+ this.plotOffset.left + this.plotWidth/2,
+ this.plotHeight/2,
+ style
+ );
+ }
+}
+});
+})();
\ No newline at end of file
diff --git a/js/Graph.js b/js/Graph.js
index 5a88f9f1..841ac174 100644
--- a/js/Graph.js
+++ b/js/Graph.js
@@ -293,6 +293,7 @@ Graph.prototype = {
textEnabled : this.textEnabled,
htmlText : this.options.HtmlText,
text : this._text, // TODO Is this necessary?
+ labelText : series.label,
element : this.el,
data : series.data,
color : series.color,
@@ -306,10 +307,21 @@ Graph.prototype = {
options = flotr.merge(type, options);
// Fill
- options.fillStyle = this.processColor(
- type.fillColor || series.color,
- {opacity: type.fillOpacity}
- );
+ var color = type.fillColor || series.color;
+ var colorType = color.substring( 0, color.indexOf('('));
+ if (colorType == 'rgba') {
+ // Color already has alpha, use it
+ var colorAlpha = color.substring( color.lastIndexOf(',')+1, color.lastIndexOf(')')).replace(/ /g,''); // Get the alpha value (if it exists), and remove whitespace
+ options.fillStyle = this.processColor(
+ color,
+ {opacity: colorAlpha}
+ );
+ } else {
+ options.fillStyle = this.processColor(
+ color,
+ {opacity: type.fillOpacity}
+ );
+ }
return options;
},
diff --git a/js/plugins/statusGraphTitle.js b/js/plugins/statusGraphTitle.js
new file mode 100644
index 00000000..921ff264
--- /dev/null
+++ b/js/plugins/statusGraphTitle.js
@@ -0,0 +1,40 @@
+(function () {
+
+var D = Flotr.DOM;
+
+Flotr.addPlugin('statusGraphTitle', {
+ callbacks: {
+ 'flotr:afterdraw': function() {
+ this.statusGraphTitle.drawStatusTitle();
+ }
+ },
+ /**
+ * Draws the title
+ */
+ drawStatusTitle : function () {
+ var
+ options = this.options,
+ margin = options.grid.labelMargin,
+ ctx = this.ctx,
+ a = this.axes;
+
+ var style = {
+ size: options.statusGraphTitle.fontSize,
+ color: options.statusGraphTitle.color,
+ textAlign: 'center',
+ weight: 1.5,
+ textBaseline: 'middle'
+ };
+
+ // Draw text
+ if (options.statusGraphTitle.text) {
+ Flotr.drawText(
+ ctx, options.statusGraphTitle.text,
+ this.plotOffset.left + this.plotWidth/2,
+ this.plotHeight/2,
+ style
+ );
+ }
+}
+});
+})();
\ No newline at end of file
diff --git a/js/types/donut.js b/js/types/donut.js
new file mode 100644
index 00000000..73f67ba6
--- /dev/null
+++ b/js/types/donut.js
@@ -0,0 +1,255 @@
+/**
+ * Donut
+ *
+ * Formats the donuts labels.
+ * @param {Object} slice - Slice object
+ * @return {String} Formatted donut label string
+ */
+(function () {
+
+var
+ _ = Flotr._;
+
+Flotr.defaultDonutLabelFormatter = function (total, value, labelText) {
+ return (100 * value / total).toFixed(2)+'%';
+};
+
+Flotr.addType('donut', {
+ options: {
+ show: false, // => setting to true will show bars, false will hide
+ lineWidth: 1, // => in pixels
+ fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill
+ fillColor: null, // => fill color
+ fillOpacity: 0.6, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill
+ explode: 6, // => the number of pixels the splices will be far from the center
+ sizeRatio: 0.6, // => the size ratio of the donut relative to the plot
+ startAngle: Math.PI/4, // => the first slice start angle
+ labelFormatter: Flotr.defaultDonutLabelFormatter,
+ epsilon: 0.1, // => how close do you have to get to hit empty slice
+ sliceThickness: 20 // => thickness of each slice in the donut
+ },
+
+ startAngle: [],
+ total: [],
+
+ draw : function (options) {
+
+ var startAngle = [];
+ var endAngle = [];
+
+ var
+ data = options.data,
+ context = options.context,
+ lineWidth = options.lineWidth,
+ shadowSize = options.shadowSize,
+ sizeRatio = options.sizeRatio,
+ height = options.height,
+ width = options.width,
+ explode = options.explode,
+ color = options.color,
+ fill = options.fill,
+ fillStyle = options.fillStyle,
+ radius = Math.min(width, height) * sizeRatio / 2,
+ thickness = options.sliceThickness,
+ value = data[0][1],
+ layer = data[0][0],
+ html = [],
+ vScale = 1,
+ measure = Math.PI * 2 * value / this.total[layer];
+ startAngle[layer] = this.startAngle[layer] || (2 * Math.PI * options.startAngle); // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
+ endAngle[layer] = startAngle[layer] + measure;
+ var
+ bisection = startAngle[layer] + measure / 2,
+ label = options.labelFormatter(this.total[layer], value, options.labelText),
+ explodeCoeff = explode + radius + 4,
+ distX = Math.cos(bisection) * explodeCoeff,
+ distY = Math.sin(bisection) * explodeCoeff,
+ textAlign = distX < 0 ? 'right' : 'left',
+ textBaseline = distY > 0 ? 'top' : 'bottom',
+ style,
+ x, y;
+
+ context.save();
+ context.translate(width / 2, height / 2);
+ context.scale(1, vScale);
+
+ x = Math.cos(bisection) * explode;
+ y = Math.sin(bisection) * explode;
+
+ // Shadows
+ if (shadowSize > 0) {
+ this.plotSlice(x + shadowSize, y + shadowSize, radius, thickness, layer, startAngle[layer], endAngle[layer], context);
+ if (fill) {
+ context.fillStyle = 'rgba(0,0,0,0.1)';
+ context.fill();
+ }
+ }
+
+ if (value > 0) {
+ this.plotSlice(x, y, radius, thickness, layer, startAngle[layer], endAngle[layer], context);
+ if (fill) {
+ context.fillStyle = fillStyle;
+ context.fill();
+ }
+ context.lineWidth = lineWidth;
+ context.strokeStyle = color;
+ context.stroke();
+ }
+
+ style = {
+ size : options.fontSize * 1.2,
+ color : options.fontColor,
+ weight : 1.5
+ };
+
+ if (label) {
+ if (options.htmlText || !options.textEnabled) {
+ // iterate through slices and check for overlap
+ _.each(this.slices, function (slice){
+ // Get old bisection
+ sliceBisect = slice.start + (slice.end-slice.start) / 2;
+ // Check if close
+ if (sliceBisect-bisection < 0 && sliceBisect-bisection > -0.3) {
+ // Values close, move bisection up
+ bisection += 0.3;
+ adjustValues();
+ } else if (sliceBisect-bisection < 0.3 && sliceBisect-bisection >= 0) {
+ // Values close, move bisection down
+ bisection -= 0.3;
+ adjustValues();
+ }
+
+ function adjustValues() {
+ // Adjust new values
+ distX = Math.cos(bisection) * explodeCoeff;
+ distY = Math.sin(bisection) * explodeCoeff;
+ textAlign = distX < 0 ? 'right' : 'left';
+ textBaseline = distY > 0 ? 'top' : 'bottom';
+ }
+ });
+
+ divStyle = 'position:absolute;' + textBaseline + ':' + (height / 2 + (textBaseline === 'top' ? distY : -distY)) + 'px;';
+ divStyle += textAlign + ':' + (width / 2 + (textAlign === 'right' ? -distX : distX)) + 'px;';
+ html.push('
', label, '
');
+ }
+ else {
+ style.textAlign = textAlign;
+ style.textBaseline = textBaseline;
+ Flotr.drawText(context, label, distX, distY, style);
+ }
+ }
+
+ if (options.htmlText || !options.textEnabled) {
+ var div = Flotr.DOM.node('
');
+ Flotr.DOM.insert(div, html.join(''));
+ Flotr.DOM.insert(options.element, div);
+ }
+
+ context.restore();
+
+ // New start angle
+ this.startAngle[layer] = endAngle[layer];
+ this.slices = this.slices || [];
+ this.slices.push({
+ radius : radius,
+ x : x,
+ y : y,
+ explode : explode,
+ start : startAngle[layer],
+ end : endAngle[layer]
+ });
+ },
+ plotSlice : function (x, y, radius, thickness, layer, startAngle, endAngle, context) {
+ // Start path
+ context.beginPath();
+ // Move to inside arc start pt
+ context.moveTo(x+Math.cos(startAngle)*(radius-thickness*(layer+1)), y+Math.sin(startAngle)*(radius-thickness*(layer+1)));
+ // Line to outside arc start pt
+ context.lineTo(x+Math.cos(startAngle)*(radius-thickness*(layer)), y+Math.sin(startAngle)*(radius-thickness*(layer)));
+ // Outside arc
+ context.arc(x, y, radius-thickness*(layer), startAngle, endAngle, false);
+ // Line to inside arc end pt
+ context.lineTo(x+Math.cos(endAngle)*(radius-thickness*(layer+1)), y+Math.sin(endAngle)*(radius-thickness*(layer+1)));
+ // Inside arc
+ context.arc(x, y, radius-thickness*(layer+1), endAngle, startAngle, true);
+ // Close
+ context.closePath();
+ },
+ hit : function (options) {
+
+ var
+ data = options.data[0],
+ args = options.args,
+ index = options.index,
+ mouse = args[0],
+ n = args[1],
+ slice = this.slices[index],
+ x = mouse.relX - options.width / 2,
+ y = mouse.relY - options.height / 2,
+ r = Math.sqrt(x * x + y * y),
+ theta = Math.atan(y / x),
+ circle = Math.PI * 2,
+ explode = slice.explode || options.explode,
+ start = slice.start % circle,
+ end = slice.end % circle,
+ epsilon = options.epsilon;
+
+ if (x < 0) {
+ theta += Math.PI;
+ } else if (x > 0 && y < 0) {
+ theta += circle;
+ }
+
+ if (r < slice.radius + explode && r > explode) {
+ if (
+ (theta > start && theta < end) || // Normal Slice
+ (start > end && (theta < end || theta > start)) || // First slice
+ // TODO: Document the two cases at the end:
+ (start === end && ((slice.start === slice.end && Math.abs(theta - start) < epsilon) || (slice.start !== slice.end && Math.abs(theta-start) > epsilon)))
+ ) {
+
+ // TODO Decouple this from hit plugin (chart shouldn't know what n means)
+ n.x = data[0];
+ n.y = data[1];
+ n.sAngle = start;
+ n.eAngle = end;
+ n.index = 0;
+ n.seriesIndex = index;
+ n.fraction = data[1] / this.total[layer];
+ }
+ }
+ },
+ drawHit: function (options) {
+ var
+ context = options.context,
+ slice = this.slices[options.args.seriesIndex];
+
+ context.save();
+ context.translate(options.width / 2, options.height / 2);
+ this.plotSlice(slice.x, slice.y, slice.radius, thickness, layer, slice.start, slice.end, context);
+ context.stroke();
+ context.restore();
+ },
+ clearHit : function (options) {
+ var
+ context = options.context,
+ slice = this.slices[options.args.seriesIndex],
+ padding = 2 * options.lineWidth,
+ radius = slice.radius + padding;
+
+ context.save();
+ context.translate(options.width / 2, options.height / 2);
+ context.clearRect(
+ slice.x - radius,
+ slice.y - radius,
+ 2 * radius + padding,
+ 2 * radius + padding
+ );
+ context.restore();
+ },
+ extendYRange : function (axis, data) {
+ var layer = data[0][0];
+ this.total[layer] = (this.total[layer] || 0) + data[0][1];
+ }
+});
+})();
diff --git a/js/types/pie.js b/js/types/pie.js
index dd4bea73..0208a2a1 100644
--- a/js/types/pie.js
+++ b/js/types/pie.js
@@ -10,7 +10,7 @@
var
_ = Flotr._;
-Flotr.defaultPieLabelFormatter = function (total, value) {
+Flotr.defaultPieLabelFormatter = function (total, value, labelText) {
return (100 * value / total).toFixed(2)+'%';
};
@@ -54,7 +54,8 @@ Flotr.addType('pie', {
startAngle = this.startAngle || (2 * Math.PI * options.startAngle), // TODO: this initial startAngle is already in radians (fixing will be test-unstable)
endAngle = startAngle + measure,
bisection = startAngle + measure / 2,
- label = options.labelFormatter(this.total, value),
+ //label = options.labelFormatter(this.total, value),
+ label = options.labelFormatter(this.total, value, options.labelText),
//plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale;
explodeCoeff = explode + radius + 4,
distX = Math.cos(bisection) * explodeCoeff,
diff --git a/make/flotr2.json b/make/flotr2.json
index fc945cc4..4e322012 100644
--- a/make/flotr2.json
+++ b/make/flotr2.json
@@ -19,6 +19,7 @@
"./js/types/gantt.js",
"./js/types/markers.js",
"./js/types/pie.js",
+ "./js/types/donut.js",
"./js/types/points.js",
"./js/types/radar.js",
"./js/types/timeline.js",
@@ -30,7 +31,8 @@
"./js/plugins/labels.js",
"./js/plugins/legend.js",
"./js/plugins/spreadsheet.js",
- "./js/plugins/titles.js"
+ "./js/plugins/titles.js",
+ "./js/plugins/statusGraphTitle.js"
]
}
}