diff --git a/src/vendor/jquery/jquery.flot.js b/src/vendor/jquery/jquery.flot.js index 5505c76d11362..965e78efe7c17 100644 --- a/src/vendor/jquery/jquery.flot.js +++ b/src/vendor/jquery/jquery.flot.js @@ -1,4 +1,4 @@ -/* Javascript plotting library for jQuery, version 0.8.1. +/* Javascript plotting library for jQuery, version 0.8.2. Copyright (c) 2007-2013 IOLA and Ole Laursen. Licensed under the MIT license. @@ -29,7 +29,7 @@ Licensed under the MIT license. * V. 1.1: Fix error handling so e.g. parsing an empty string does * produce a color rather than just crashing. */ -(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return KI?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); +(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return valuemax?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); // the actual Flot code (function($) { @@ -425,7 +425,7 @@ Licensed under the MIT license. element: positions.length ? info.element.clone() : info.element, x: x, y: y - } + }; positions.push(position); @@ -567,6 +567,7 @@ Licensed under the MIT license. fillColor: null, align: "left", // "left", "right", or "center" horizontal: false, + zero: true }, shadowSize: 3, highlightColor: null @@ -657,6 +658,23 @@ Licensed under the MIT license. }; }; plot.shutdown = shutdown; + plot.destroy = function () { + shutdown(); + placeholder.removeData("plot").empty(); + + series = []; + options = null; + surface = null; + overlay = null; + eventHolder = null; + ctx = null; + octx = null; + xaxes = []; + yaxes = []; + hooks = null; + highlights = []; + plot = null; + }; plot.resize = function () { var width = placeholder.width(), height = placeholder.height(); @@ -734,16 +752,16 @@ Licensed under the MIT license. // since the rest of the code assumes that they exist. var i, axisOptions, axisCount, + fontSize = placeholder.css("font-size"), + fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13, fontDefaults = { style: placeholder.css("font-style"), - size: Math.round(0.8 * (+placeholder.css("font-size").replace("px", "") || 13)), + size: Math.round(0.8 * fontSizeDefault), variant: placeholder.css("font-variant"), weight: placeholder.css("font-weight"), family: placeholder.css("font-family") }; - fontDefaults.lineHeight = fontDefaults.size * 1.15; - axisCount = options.xaxes.length || 1; for (i = 0; i < axisCount; ++i) { @@ -760,6 +778,9 @@ Licensed under the MIT license. if (!axisOptions.font.color) { axisOptions.font.color = axisOptions.color; } + if (!axisOptions.font.lineHeight) { + axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); + } } } @@ -779,6 +800,9 @@ Licensed under the MIT license. if (!axisOptions.font.color) { axisOptions.font.color = axisOptions.color; } + if (!axisOptions.font.lineHeight) { + axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); + } } } @@ -1130,7 +1154,7 @@ Licensed under the MIT license. if (val != null) { f = format[m]; // extract min/max info - if (f.autoscale) { + if (f.autoscale !== false) { if (f.x) { updateAxis(s.xaxis, val, val); } @@ -1217,11 +1241,8 @@ Licensed under the MIT license. case "right": delta = -s.bars.barWidth; break; - case "center": - delta = -s.bars.barWidth / 2; - break; default: - throw new Error("Invalid bar alignment: " + s.bars.align); + delta = -s.bars.barWidth / 2; } if (s.bars.horizontal) { @@ -1252,7 +1273,9 @@ Licensed under the MIT license. // from a previous plot in this container that we'll try to re-use. placeholder.css("padding", 0) // padding messes up the positioning - .children(":not(.flot-base,.flot-overlay)").remove(); + .children().filter(function(){ + return !$(this).hasClass("flot-overlay") && !$(this).hasClass('flot-base'); + }).remove(); if (placeholder.css("position") == 'static') placeholder.css("position", "relative"); // for positioning labels and overlay @@ -1349,7 +1372,7 @@ Licensed under the MIT license. ticks = axis.ticks || [], labelWidth = opts.labelWidth || 0, labelHeight = opts.labelHeight || 0, - maxWidth = labelWidth || axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null; + maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null), legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, font = opts.font || "flot-tick-label tickLabel"; @@ -1381,37 +1404,50 @@ Licensed under the MIT license. var lw = axis.labelWidth, lh = axis.labelHeight, pos = axis.options.position, + isXAxis = axis.direction === "x", tickLength = axis.options.tickLength, axisMargin = options.grid.axisMargin, padding = options.grid.labelMargin, - all = axis.direction == "x" ? xaxes : yaxes, - index, innermost; - - // determine axis margin - var samePosition = $.grep(all, function (a) { - return a && a.options.position == pos && a.reserveSpace; + innermost = true, + outermost = true, + first = true, + found = false; + + // Determine the axis's position in its direction and on its side + + $.each(isXAxis ? xaxes : yaxes, function(i, a) { + if (a && a.reserveSpace) { + if (a === axis) { + found = true; + } else if (a.options.position === pos) { + if (found) { + outermost = false; + } else { + innermost = false; + } + } + if (!found) { + first = false; + } + } }); - if ($.inArray(axis, samePosition) == samePosition.length - 1) - axisMargin = 0; // outermost - // determine tick length - if we're innermost, we can use "full" - if (tickLength == null) { - var sameDirection = $.grep(all, function (a) { - return a && a.reserveSpace; - }); + // The outermost axis on each side has no margin - innermost = $.inArray(axis, sameDirection) == 0; - if (innermost) - tickLength = "full"; - else - tickLength = 5; + if (outermost) { + axisMargin = 0; + } + + // The ticks for the first axis in each direction stretch across + + if (tickLength == null) { + tickLength = first ? "full" : 5; } if (!isNaN(+tickLength)) padding += +tickLength; - // compute box - if (axis.direction == "x") { + if (isXAxis) { lh += padding; if (pos == "bottom") { @@ -1461,7 +1497,7 @@ Licensed under the MIT license. // inside the canvas and isn't clipped off var minMargin = options.grid.minBorderMargin, - margins = { x: 0, y: 0 }, i, axis; + axis, i; // check stuff from the plot (FIXME: this should just read // a value from the series, otherwise it's impossible to @@ -1472,21 +1508,37 @@ Licensed under the MIT license. minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2)); } - margins.x = margins.y = Math.ceil(minMargin); + var margins = { + left: minMargin, + right: minMargin, + top: minMargin, + bottom: minMargin + }; // check axis labels, note we don't check the actual // labels but instead use the overall width/height to not // jump as much around with replots $.each(allAxes(), function (_, axis) { - var dir = axis.direction; - if (axis.reserveSpace) - margins[dir] = Math.ceil(Math.max(margins[dir], (dir == "x" ? axis.labelWidth : axis.labelHeight) / 2)); + if (axis.reserveSpace && axis.ticks && axis.ticks.length) { + var lastTick = axis.ticks[axis.ticks.length - 1]; + if (axis.direction === "x") { + margins.left = Math.max(margins.left, axis.labelWidth / 2); + if (lastTick.v <= axis.max) { + margins.right = Math.max(margins.right, axis.labelWidth / 2); + } + } else { + margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2); + if (lastTick.v <= axis.max) { + margins.top = Math.max(margins.top, axis.labelHeight / 2); + } + } + } }); - plotOffset.left = Math.max(margins.x, plotOffset.left); - plotOffset.right = Math.max(margins.x, plotOffset.right); - plotOffset.top = Math.max(margins.y, plotOffset.top); - plotOffset.bottom = Math.max(margins.y, plotOffset.bottom); + plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left)); + plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right)); + plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top)); + plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom)); } function setupGrid() { @@ -2099,17 +2151,21 @@ Licensed under the MIT license. function drawAxisLabels() { $.each(allAxes(), function (_, axis) { - if (!axis.show || axis.ticks.length == 0) - return; - var box = axis.box, legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, font = axis.options.font || "flot-tick-label tickLabel", tick, x, y, halign, valign; + // Remove text before checking for axis.show and ticks.length; + // otherwise plugins, like flot-tickrotor, that draw their own + // tick labels will end up with both theirs and the defaults. + surface.removeText(layer); + if (!axis.show || axis.ticks.length == 0) + return; + for (var i = 0; i < axis.ticks.length; ++i) { tick = axis.ticks[i]; @@ -2438,9 +2494,9 @@ Licensed under the MIT license. radius = series.points.radius, symbol = series.points.symbol; - // If the user sets the line width to 0, we change it to a very + // If the user sets the line width to 0, we change it to a very // small value. A line width of 0 seems to force the default of 1. - // Doing the conditional here allows the shadow setting to still be + // Doing the conditional here allows the shadow setting to still be // optional even with a lineWidth of 0. if( lw == 0 ) @@ -2467,7 +2523,7 @@ Licensed under the MIT license. ctx.restore(); } - function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) { + function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) { var left, right, bottom, top, drawLeft, drawRight, drawTop, drawBottom, tmp; @@ -2542,13 +2598,8 @@ Licensed under the MIT license. // fill the bar if (fillStyleCallback) { - c.beginPath(); - c.moveTo(left, bottom); - c.lineTo(left, top); - c.lineTo(right, top); - c.lineTo(right, bottom); c.fillStyle = fillStyleCallback(bottom, top); - c.fill(); + c.fillRect(left, top, right - left, bottom - top) } // draw outline @@ -2556,35 +2607,35 @@ Licensed under the MIT license. c.beginPath(); // FIXME: inline moveTo is buggy with excanvas - c.moveTo(left, bottom + offset); + c.moveTo(left, bottom); if (drawLeft) - c.lineTo(left, top + offset); + c.lineTo(left, top); else - c.moveTo(left, top + offset); + c.moveTo(left, top); if (drawTop) - c.lineTo(right, top + offset); + c.lineTo(right, top); else - c.moveTo(right, top + offset); + c.moveTo(right, top); if (drawRight) - c.lineTo(right, bottom + offset); + c.lineTo(right, bottom); else - c.moveTo(right, bottom + offset); + c.moveTo(right, bottom); if (drawBottom) - c.lineTo(left, bottom + offset); + c.lineTo(left, bottom); else - c.moveTo(left, bottom + offset); + c.moveTo(left, bottom); c.stroke(); } } function drawSeriesBars(series) { - function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { + function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) { var points = datapoints.points, ps = datapoints.pointsize; for (var i = 0; i < points.length; i += ps) { if (points[i] == null) continue; - drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth); + drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth); } } @@ -2604,15 +2655,12 @@ Licensed under the MIT license. case "right": barLeft = -series.bars.barWidth; break; - case "center": - barLeft = -series.bars.barWidth / 2; - break; default: - throw new Error("Invalid bar alignment: " + series.bars.align); + barLeft = -series.bars.barWidth / 2; } var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; - plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); + plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis); ctx.restore(); } @@ -2632,10 +2680,15 @@ Licensed under the MIT license. function insertLegend() { - placeholder.find(".legend").remove(); + if (options.legend.container != null) { + $(options.legend.container).html(""); + } else { + placeholder.find(".legend").remove(); + } - if (!options.legend.show) + if (!options.legend.show) { return; + } var fragments = [], entries = [], rowStarted = false, lf = options.legend.labelFormatter, s, label; @@ -2796,8 +2849,21 @@ Licensed under the MIT license. } if (s.bars.show && !item) { // no other point can be nearby - var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, - barRight = barLeft + s.bars.barWidth; + + var barLeft, barRight; + + switch (s.bars.align) { + case "left": + barLeft = 0; + break; + case "right": + barLeft = -s.bars.barWidth; + break; + default: + barLeft = -s.bars.barWidth / 2; + } + + barRight = barLeft + s.bars.barWidth; for (j = 0; j < points.length; j += ps) { var x = points[j], y = points[j + 1], b = points[j + 2]; @@ -2995,13 +3061,24 @@ Licensed under the MIT license. function drawBarHighlight(series, point) { var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale('a', 0.5).toString(), fillStyle = highlightColor, - barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + barLeft; + + switch (series.bars.align) { + case "left": + barLeft = 0; + break; + case "right": + barLeft = -series.bars.barWidth; + break; + default: + barLeft = -series.bars.barWidth / 2; + } octx.lineWidth = series.bars.lineWidth; octx.strokeStyle = highlightColor; drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, - 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth); + function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth); } function getColorOrGradient(spec, bottom, top, defaultColor) { @@ -3040,7 +3117,7 @@ Licensed under the MIT license. return plot; }; - $.plot.version = "0.8.1"; + $.plot.version = "0.8.2"; $.plot.plugins = []; diff --git a/src/vendor/jquery/jquery.flot.pie.js b/src/vendor/jquery/jquery.flot.pie.js index 6553c8ea3a812..9915863082025 100644 --- a/src/vendor/jquery/jquery.flot.pie.js +++ b/src/vendor/jquery/jquery.flot.pie.js @@ -69,6 +69,7 @@ More detail and specific examples can be found in the included HTML file. var canvas = null, target = null, + options = null, maxRadius = null, centerLeft = null, centerTop = null, @@ -293,16 +294,15 @@ More detail and specific examples can be found in the included HTML file. } else { centerLeft -= legendWidth / 2; } + if (centerLeft < maxRadius) { + centerLeft = maxRadius; + } else if (centerLeft > canvasWidth - maxRadius) { + centerLeft = canvasWidth - maxRadius; + } } else { centerLeft += options.series.pie.offset.left; } - if (centerLeft < maxRadius) { - centerLeft = maxRadius; - } else if (centerLeft > canvasWidth - maxRadius) { - centerLeft = canvasWidth - maxRadius; - } - var slices = plot.getData(), attempts = 0;