diff --git a/jquery.flot.pie.js b/jquery.flot.pie.js index c1751e9..5e4b698 100644 --- a/jquery.flot.pie.js +++ b/jquery.flot.pie.js @@ -1,10 +1,14 @@ /* -Flot plugin for rendering pie charts. The plugin assumes the data is -coming is as a single data value for each series, and each of those -values is a positive value or zero (negative numbers don't make -any sense and will cause strange effects). The data values do -NOT need to be passed in as percentage values because it -internally calculates the total and percentages. +Flot plugin for rendering pie charts. + +Copyright (c) 2007-2012 IOLA and Ole Laursen. +Licensed under the MIT license. + +The plugin assumes that each series has a single data value, and that +each value is a positive integer or zero. Negative numbers don't make +sense for a pie chart, and have unpredictable results. The values do +NOT need to be passed in as percentages; the plugin will calculate the +total and per-slice percentages internally. * Created by Brian Medendorp, June 2009 * Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars @@ -15,7 +19,6 @@ internally calculates the total and percentages. 2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera 2009-11-17: Added IE hover capability submitted by Anthony Aragues 2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well) - Available options are: series: { @@ -58,10 +61,10 @@ More detail and specific examples can be found in the included HTML file. */ -(function ($) -{ - function init(plot) // this is the "body" of the plugin - { +(function ($) { + + function init(plot) { + var canvas = null; var canvasWidth = 0; var canvasHeight = 0; @@ -76,301 +79,313 @@ More detail and specific examples can be found in the included HTML file. var legendWidth = 0; var processed = false; var raw = false; - - // interactive variables - var highlights = []; - + + // interactive variables + + var highlights = []; + // add hook to determine if pie plugin in enabled, and then perform necessary operations + plot.hooks.processOptions.push(checkPieEnabled); - plot.hooks.bindEvents.push(bindEvents); + plot.hooks.bindEvents.push(bindEvents); // check to see if the pie plugin is enabled - function checkPieEnabled(plot, options) - { - if (options.series.pie.show) - { + + function checkPieEnabled(plot, options) { + if (options.series.pie.show) { + //disable grid + options.grid.show = false; - + // set labels.show - if (options.series.pie.label.show=='auto') - if (options.legend.show) + + if (options.series.pie.label.show == "auto") { + if (options.legend.show) { options.series.pie.label.show = false; - else + } else { options.series.pie.label.show = true; - + } + } + // set radius - if (options.series.pie.radius=='auto') - if (options.series.pie.label.show) + + if (options.series.pie.radius == "auto") { + if (options.series.pie.label.show) { options.series.pie.radius = 3/4; - else + } else { options.series.pie.radius = 1; - + } + } + // ensure sane tilt - if (options.series.pie.tilt>1) - options.series.pie.tilt=1; - if (options.series.pie.tilt<0) - options.series.pie.tilt=0; - + + if (options.series.pie.tilt > 1) { + options.series.pie.tilt = 1; + } else if (options.series.pie.tilt < 0) { + options.series.pie.tilt = 0; + } + // add processData hook to do transformations on the data + plot.hooks.processDatapoints.push(processDatapoints); - plot.hooks.drawOverlay.push(drawOverlay); - - // add draw hook + plot.hooks.drawOverlay.push(drawOverlay); + + // draw hook + plot.hooks.draw.push(draw); } } - + // bind hoverable events - function bindEvents(plot, eventHolder) - { + + function bindEvents(plot, eventHolder) { var options = plot.getOptions(); - - if (options.series.pie.show && options.grid.hoverable) - eventHolder.unbind('mousemove').mousemove(onMouseMove); - - if (options.series.pie.show && options.grid.clickable) - eventHolder.unbind('click').click(onClick); - } - + if (options.series.pie.show) { + if (options.grid.hoverable) { + eventHolder.unbind("mousemove").mousemove(onMouseMove); + } + if (options.grid.clickable) { + eventHolder.unbind("click").click(onClick); + } + } + } // debugging function that prints out an object - function alertObject(obj) - { - var msg = ''; - function traverse(obj, depth) - { - if (!depth) + + function alertObject(obj) { + + var msg = ""; + + function traverse(obj, depth) { + + if (!depth) { depth = 0; + } + for (var i = 0; i < obj.length; ++i) { - for (var j=0; jcanvasWidth-maxRadius) - centerLeft = canvasWidth-maxRadius; + } else if (centerLeft > canvasWidth - maxRadius) { + centerLeft = canvasWidth - maxRadius; + } } - - function fixData(data) - { - for (var i = 0; i < data.length; ++i) - { - if (typeof(data[i].data)=='number') - data[i].data = [[1,data[i].data]]; - else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined') - { - if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined') + + function fixData(data) { + for (var i = 0; i < data.length; ++i) { + if (typeof(data[i].data) == "number") { + data[i].data = [[1, data[i].data]]; + } else if (typeof(data[i].data) == "undefined" || typeof(data[i].data[0]) == "undefined") { + if (typeof(data[i].data) != "undefined" && typeof(data[i].data.label) != "undefined") { data[i].label = data[i].data.label; // fix weirdness coming from flot - data[i].data = [[1,0]]; - + } + data[i].data = [[1, 0]]; } } return data; } - - function combine(data) - { + + function combine(data) { + data = fixData(data); calcTotal(data); + var combined = 0; var numCombined = 0; var color = options.series.pie.combine.color; - var newdata = []; - for (var i = 0; i < data.length; ++i) - { + + for (var i = 0; i < data.length; ++i) { + // make sure its a number + data[i].data[0][1] = parseFloat(data[i].data[0][1]); - if (!data[i].data[0][1]) + + if (!data[i].data[0][1]) { data[i].data[0][1] = 0; - - if (data[i].data[0][1]/total<=options.series.pie.combine.threshold) - { + } + + if (data[i].data[0][1] / total <= options.series.pie.combine.threshold) { combined += data[i].data[0][1]; numCombined++; - if (!color) + if (!color) { color = data[i].color; - } - else - { + } + } else { newdata.push({ - data: [[1,data[i].data[0][1]]], - color: data[i].color, + data: [[1, data[i].data[0][1]]], + color: data[i].color, label: data[i].label, - angle: (data[i].data[0][1]*(Math.PI*2))/total, - percent: (data[i].data[0][1]/total*100) + angle: data[i].data[0][1] * Math.PI * 2 / total, + percent: data[i].data[0][1] / total * 100 }); } } - if (numCombined>0) + + if (numCombined > 0) { newdata.push({ - data: [[1,combined]], - color: color, + data: [[1, combined]], + color: color, label: options.series.pie.combine.label, - angle: (combined*(Math.PI*2))/total, - percent: (combined/total*100) + angle: combined * Math.PI * 2 / total, + percent: combined / total * 100 }); + return newdata; - } - - function draw(plot, newCtx) - { - if (!target) return; // if no series were passed + } + + function draw(plot, newCtx) { + + if (!target) { + return; // if no series were passed + } + ctx = newCtx; - setupPie(); + var slices = plot.getData(); - var attempts = 0; - while (redraw && attempts0) + if (attempts > 0) { maxRadius *= shrink; + } attempts += 1; clear(); - if (options.series.pie.tilt<=0.8) + if (options.series.pie.tilt <= 0.8) { drawShadow(); + } drawPie(); } + if (attempts >= redrawAttempts) { clear(); - target.prepend('
Could not draw pie with labels contained inside canvas
'); + target.prepend("
Could not draw pie with labels contained inside canvas
"); } - - if ( plot.setSeries && plot.insertLegend ) - { + + if (plot.setSeries && plot.insertLegend) { plot.setSeries(slices); plot.insertLegend(); } - + // we're actually done at this point, just defining internal functions at this point - - function clear() - { - ctx.clearRect(0,0,canvasWidth,canvasHeight); - target.children().filter('.pieLabel, .pieLabelBackground').remove(); + + function clear() { + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + target.children().filter(".pieLabel, .pieLabelBackground").remove(); } - - function drawShadow() - { + + function drawShadow() { + var shadowLeft = options.series.pie.shadow.left; var shadowTop = options.series.pie.shadow.top; var edge = 10; var alpha = options.series.pie.shadow.alpha; - - // set radius - if (options.series.pie.radius>1) - var radius = options.series.pie.radius; - else - var radius = maxRadius * options.series.pie.radius; - - if (radius>=(canvasWidth/2)-shadowLeft || radius*options.series.pie.tilt>=(canvasHeight/2)-shadowTop || radius<=edge) + var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; + + if (radius >= canvasWidth / 2 - shadowLeft || radius * options.series.pie.tilt >= canvasHeight / 2 - shadowTop || radius <= edge) { return; // shadow would be outside canvas, so don't draw it - + } + ctx.save(); ctx.translate(shadowLeft,shadowTop); ctx.globalAlpha = alpha; - ctx.fillStyle = '#000'; + ctx.fillStyle = "#000"; // center and rotate to starting position + ctx.translate(centerLeft,centerTop); ctx.scale(1, options.series.pie.tilt); - + //radius -= edge; - for (var i=1; i<=edge; i++) - { + + for (var i = 1; i <= edge; i++) { ctx.beginPath(); - ctx.arc(0,0,radius,0,Math.PI*2,false); + ctx.arc(0, 0, radius, 0, Math.PI * 2, false); ctx.fill(); radius -= i; - } - + } + ctx.restore(); } - - function drawPie() - { - var startAngle = Math.PI * options.series.pie.startAngle; - var radius; - // set radius - if (options.series.pie.radius > 1) - radius = options.series.pie.radius; - else radius = maxRadius * options.series.pie.radius; + function drawPie() { + + var startAngle = Math.PI * options.series.pie.startAngle; + var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; // center and rotate to starting position + ctx.save(); ctx.translate(centerLeft,centerTop); ctx.scale(1, options.series.pie.tilt); //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera // draw slices + ctx.save(); var currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) - { + for (var i = 0; i < slices.length; ++i) { slices[i].startAngle = currentAngle; drawSlice(slices[i].angle, slices[i].color, true); } @@ -382,286 +397,313 @@ More detail and specific examples can be found in the included HTML file. ctx.save(); ctx.lineWidth = options.series.pie.stroke.width; currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) + for (var i = 0; i < slices.length; ++i) { drawSlice(slices[i].angle, options.series.pie.stroke.color, false); + } ctx.restore(); } // draw donut hole + drawDonutHole(ctx); // draw labels - if (options.series.pie.label.show) + + if (options.series.pie.label.show) { drawLabels(); + } // restore to original state ctx.restore(); - function drawSlice(angle, color, fill) - { - if (angle <= 0 || isNaN(angle)) + function drawSlice(angle, color, fill) { + + if (angle <= 0 || isNaN(angle)) { return; - - if (fill) + } + + if (fill) { ctx.fillStyle = color; - else - { + } else { ctx.strokeStyle = color; - ctx.lineJoin = 'round'; + ctx.lineJoin = "round"; } - + ctx.beginPath(); - if (Math.abs(angle - Math.PI*2) > 0.000000001) - ctx.moveTo(0,0); // Center of the pie - else if ($.browser.msie) + if (Math.abs(angle - Math.PI * 2) > 0.000000001) { + ctx.moveTo(0, 0); // Center of the pie + } else if ($.browser.msie) { angle -= 0.0001; - //ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera - ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false); + } + + //ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera + ctx.arc(0, 0, radius,currentAngle, currentAngle + angle, false); ctx.closePath(); //ctx.rotate(angle); // This doesn't work properly in Opera currentAngle += angle; - - if (fill) + + if (fill) { ctx.fill(); - else + } else { ctx.stroke(); + } } - - function drawLabels() - { + + function drawLabels() { + var currentAngle = startAngle; - - // set radius - if (options.series.pie.label.radius>1) - var radius = options.series.pie.label.radius; - else - var radius = maxRadius * options.series.pie.label.radius; - - for (var i = 0; i < slices.length; ++i) - { - if (slices[i].percent >= options.series.pie.label.threshold*100) + var radius = options.series.pie.label.radius > 1 ? options.series.pie.label.radius : maxRadius * options.series.pie.label.radius; + + for (var i = 0; i < slices.length; ++i) { + if (slices[i].percent >= options.series.pie.label.threshold * 100) { drawLabel(slices[i], currentAngle, i); + } currentAngle += slices[i].angle; } - - function drawLabel(slice, startAngle, index) - { - if (slice.data[0][1]==0) + + function drawLabel(slice, startAngle, index) { + if (slice.data[0][1] == 0) { return; - + } + // format label text + var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter; - if (lf) + + if (lf) { text = lf(slice.label, slice); - else + } else { text = slice.label; - if (plf) + } + + if (plf) { text = plf(text, slice); - - var halfAngle = ((startAngle+slice.angle) + startAngle)/2; + } + + var halfAngle = ((startAngle + slice.angle) + startAngle) / 2; var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt; - - var html = '' + text + ""; + + var html = "" + text + ""; target.append(html); - var label = target.children('#pieLabel'+index); - var labelTop = (y - label.height()/2); - var labelLeft = (x - label.width()/2); - label.css('top', labelTop); - label.css('left', labelLeft); - + + var label = target.children("#pieLabel" + index); + var labelTop = (y - label.height() / 2); + var labelLeft = (x - label.width() / 2); + + label.css("top", labelTop); + label.css("left", labelLeft); + // check to make sure that the label is not outside the canvas - if (0-labelTop>0 || 0-labelLeft>0 || canvasHeight-(labelTop+label.height())<0 || canvasWidth-(labelLeft+label.width())<0) + + if (0 - labelTop > 0 || 0 - labelLeft > 0 || canvasHeight - (labelTop + label.height()) < 0 || canvasWidth - (labelLeft + label.width()) < 0) { redraw = true; - + } + if (options.series.pie.label.background.opacity != 0) { + // put in the transparent background separately to avoid blended labels and label boxes + var c = options.series.pie.label.background.color; + if (c == null) { c = slice.color; } - var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;'; - $('
').insertBefore(label).css('opacity', options.series.pie.label.background.opacity); + + var pos = "top:" + labelTop + "px;left:" + labelLeft + "px;"; + $("
") + .css("opacity", options.series.pie.label.background.opacity) + .insertBefore(label); } } // end individual label function } // end drawLabels function } // end drawPie function } // end draw function - - // Placed here because it needs to be accessed from multiple locations - function drawDonutHole(layer) - { - // draw donut hole - if(options.series.pie.innerRadius > 0) - { + + // Placed here because it needs to be accessed from multiple locations + + function drawDonutHole(layer) { + if (options.series.pie.innerRadius > 0) { + // subtract the center + layer.save(); innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius; - layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color + layer.globalCompositeOperation = "destination-out"; // this does not work with excanvas, but it will fall back to using the stroke color layer.beginPath(); layer.fillStyle = options.series.pie.stroke.color; - layer.arc(0,0,innerRadius,0,Math.PI*2,false); + layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); layer.fill(); layer.closePath(); layer.restore(); - + // add inner stroke + layer.save(); layer.beginPath(); layer.strokeStyle = options.series.pie.stroke.color; - layer.arc(0,0,innerRadius,0,Math.PI*2,false); + layer.arc(0, 0, innerRadius, 0, Math.PI * 2, false); layer.stroke(); layer.closePath(); layer.restore(); + // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. } } - + //-- Additional Interactive related functions -- - - function isPointInPoly(poly, pt) - { + + function isPointInPoly(poly, pt) { for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1])) && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) && (c = !c); return c; } - - function findNearbySlice(mouseX, mouseY) - { - var slices = plot.getData(), - options = plot.getOptions(), - radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - for (var i = 0; i < slices.length; ++i) - { - var s = slices[i]; - - if(s.pie.show) - { + + function findNearbySlice(mouseX, mouseY) { + + var slices = plot.getData(); + var options = plot.getOptions(); + var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; + + for (var i = 0; i < slices.length; ++i) { + + var s = slices[i]; + + if (s.pie.show) { + ctx.save(); ctx.beginPath(); - ctx.moveTo(0,0); // Center of the pie + ctx.moveTo(0, 0); // Center of the pie //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. - ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false); + ctx.arc(0, 0, radius, s.startAngle, s.startAngle + s.angle, false); ctx.closePath(); - x = mouseX-centerLeft; - y = mouseY-centerTop; - if(ctx.isPointInPath) - { - if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop)) - { - //alert('found slice!'); + x = mouseX - centerLeft; + y = mouseY - centerTop; + + if (ctx.isPointInPath) { + if (ctx.isPointInPath(mouseX - centerLeft, mouseY - centerTop)) { ctx.restore(); - return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; + return { + datapoint: [s.percent, s.data], + dataIndex: 0, + series: s, + seriesIndex: i + }; } - } - else - { - // excanvas for IE doesn;t support isPointInPath, this is a workaround. - p1X = (radius * Math.cos(s.startAngle)); - p1Y = (radius * Math.sin(s.startAngle)); - p2X = (radius * Math.cos(s.startAngle+(s.angle/4))); - p2Y = (radius * Math.sin(s.startAngle+(s.angle/4))); - p3X = (radius * Math.cos(s.startAngle+(s.angle/2))); - p3Y = (radius * Math.sin(s.startAngle+(s.angle/2))); - p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5))); - p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5))); - p5X = (radius * Math.cos(s.startAngle+s.angle)); - p5Y = (radius * Math.sin(s.startAngle+s.angle)); - arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]]; - arrPoint = [x,y]; + } else { + + // excanvas for IE doesn;t support isPointInPath, this is a workaround. + + p1X = radius * Math.cos(s.startAngle); + p1Y = radius * Math.sin(s.startAngle); + p2X = radius * Math.cos(s.startAngle + s.angle / 4); + p2Y = radius * Math.sin(s.startAngle + s.angle / 4); + p3X = radius * Math.cos(s.startAngle + s.angle / 2); + p3Y = radius * Math.sin(s.startAngle + s.angle / 2); + p4X = radius * Math.cos(s.startAngle + s.angle / 1.5); + p4Y = radius * Math.sin(s.startAngle + s.angle / 1.5); + p5X = radius * Math.cos(s.startAngle + s.angle); + p5Y = radius * Math.sin(s.startAngle + s.angle); + arrPoly = [[0, 0], [p1X, p1Y], [p2X, p2Y], [p3X, p3Y], [p4X, p4Y], [p5X, p5Y]]; + arrPoint = [x, y]; + // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? - if(isPointInPoly(arrPoly, arrPoint)) - { + + if (isPointInPoly(arrPoly, arrPoint)) { ctx.restore(); - return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; - } + return { + datapoint: [s.percent, s.data], + dataIndex: 0, + series: s, + seriesIndex: i + }; + } } + ctx.restore(); } } - + return null; } - function onMouseMove(e) - { - triggerClickHoverEvent('plothover', e); + function onMouseMove(e) { + triggerClickHoverEvent("plothover", e); } - - function onClick(e) - { - triggerClickHoverEvent('plotclick', e); + + function onClick(e) { + triggerClickHoverEvent("plotclick", e); } // trigger click or hover event (they send the same parameters so we share their code) - function triggerClickHoverEvent(eventname, e) - { - var offset = plot.offset(), - canvasX = parseInt(e.pageX - offset.left), - canvasY = parseInt(e.pageY - offset.top), - item = findNearbySlice(canvasX, canvasY); - - if (options.grid.autoHighlight) - { + + function triggerClickHoverEvent(eventname, e) { + var offset = plot.offset(); + var canvasX = parseInt(e.pageX - offset.left); + var canvasY = parseInt(e.pageY - offset.top); + var item = findNearbySlice(canvasX, canvasY); + + if (options.grid.autoHighlight) { + // clear auto-highlights - for (var i = 0; i < highlights.length; ++i) - { + + for (var i = 0; i < highlights.length; ++i) { var h = highlights[i]; - if (h.auto == eventname && !(item && h.series == item.series)) + if (h.auto == eventname && !(item && h.series == item.series)) { unhighlight(h.series); + } } } - + // highlight the slice - if (item) + + if (item) { highlight(item.series, eventname); - + } + // trigger any hover bind events + var pos = { pageX: e.pageX, pageY: e.pageY }; - target.trigger(eventname, [ pos, item ]); + target.trigger(eventname, [pos, item]); } - function highlight(s, auto) - { - if (typeof s == "number") + function highlight(s, auto) { + if (typeof s == "number") { s = series[s]; + } var i = indexOfHighlight(s); - if (i == -1) - { + + if (i == -1) { highlights.push({ series: s, auto: auto }); plot.triggerRedrawOverlay(); - } - else if (!auto) + } else if (!auto) { highlights[i].auto = false; + } } - function unhighlight(s) - { - if (s == null) - { + function unhighlight(s) { + if (s == null) { highlights = []; plot.triggerRedrawOverlay(); } - - if (typeof s == "number") + + if (typeof s == "number") { s = series[s]; + } var i = indexOfHighlight(s); - if (i != -1) - { + + if (i != -1) { highlights.splice(i, 1); plot.triggerRedrawOverlay(); } } - function indexOfHighlight(s) - { - for (var i = 0; i < highlights.length; ++i) - { + function indexOfHighlight(s) { + for (var i = 0; i < highlights.length; ++i) { var h = highlights[i]; if (h.series == s) return i; @@ -669,52 +711,50 @@ More detail and specific examples can be found in the included HTML file. return -1; } - function drawOverlay(plot, octx) - { - //alert(options.series.pie.radius); + function drawOverlay(plot, octx) { + var options = plot.getOptions(); - //alert(options.series.pie.radius); - + var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; octx.save(); octx.translate(centerLeft, centerTop); octx.scale(1, options.series.pie.tilt); - - for (i = 0; i < highlights.length; ++i) + + for (i = 0; i < highlights.length; ++i) { drawHighlight(highlights[i].series); - + } + drawDonutHole(octx); octx.restore(); - function drawHighlight(series) - { - if (series.angle <= 0 || isNaN(series.angle)) + function drawHighlight(series) { + + if (series.angle <= 0 || isNaN(series.angle)) { return; - + } + //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); - octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor - + octx.fillStyle = "rgba(255, 255, 255, " + options.series.pie.highlight.opacity + ")"; // this is temporary until we have access to parseColor octx.beginPath(); - if (Math.abs(series.angle - Math.PI*2) > 0.000000001) - octx.moveTo(0,0); // Center of the pie - octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false); + if (Math.abs(series.angle - Math.PI * 2) > 0.000000001) { + octx.moveTo(0, 0); // Center of the pie + } + octx.arc(0, 0, radius, series.startAngle, series.startAngle + series.angle, false); octx.closePath(); octx.fill(); } - - } - + } } // end init (plugin body) - + // define pie specific options and their default values var options = { series: { pie: { show: false, - radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) - innerRadius:0, /* for donut */ + radius: "auto", // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) + innerRadius: 0, /* for donut */ startAngle: 3/2, tilt: 1, shadow: { @@ -724,16 +764,16 @@ More detail and specific examples can be found in the included HTML file. }, offset: { top: 0, - left: 'auto' + left: "auto" }, stroke: { - color: '#FFF', + color: "#fff", width: 1 }, label: { - show: 'auto', - formatter: function(label, slice){ - return '
'+label+'
'+Math.round(slice.percent)+'%
'; + show: "auto", + formatter: function(label, slice) { + return "
" + label + "
" + Math.round(slice.percent) + "%
"; }, // formatter function radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) background: { @@ -745,20 +785,21 @@ More detail and specific examples can be found in the included HTML file. combine: { threshold: -1, // percentage at which to combine little slices into one larger slice color: null, // color to give the new slice (auto-generated if null) - label: 'Other' // label to give the new slice + label: "Other" // label to give the new slice }, highlight: { - //color: '#FFF', // will add this functionality once parseColor is available + //color: "#fff", // will add this functionality once parseColor is available opacity: 0.5 } } } }; - + $.plot.plugins.push({ init: init, options: options, name: "pie", - version: "1.0" + version: "1.1" }); + })(jQuery);