diff --git a/API.md b/API.md index d6d5879..79edb3f 100644 --- a/API.md +++ b/API.md @@ -542,7 +542,7 @@ You can see a timestamp like this alert((new Date()).getTime()) ``` -There are different schools of thought when it comes to diplay of +There are different schools of thought when it comes to display of timestamps. Many will want the timestamps to be displayed according to a certain time zone, usually the time zone in which the data has been produced. Some want the localized experience, where the timestamps are @@ -572,6 +572,19 @@ In Python you can get it with something like: ```python calendar.timegm(datetime_object.timetuple()) * 1000 ``` +In Ruby you can get it using the `#to_i` method on the +[`Time`](http://apidock.com/ruby/Time/to_i) object. If you're using the +`active_support` gem (default for Ruby on Rails applications) `#to_i` is also +available on the `DateTime` and `ActiveSupport::TimeWithZone` objects. You +simply need to multiply the result by 1000: + +```ruby +Time.now.to_i * 1000 # => 1383582043000 +# ActiveSupport examples: +DateTime.now.to_i * 1000 # => 1383582043000 +ActiveSupport::TimeZone.new('Asia/Shanghai').now.to_i * 1000 +# => 1383582043000 +``` In .NET you can get it with something like: @@ -1497,7 +1510,7 @@ hooks in the plugins bundled with Flot. case a plot is overwritten by a new plot. If you're writing a plugin that adds extra DOM elements or event handlers, you should add a callback to clean up after you. Take a look at the section in - PLUGINS.txt for more info. + the [PLUGINS](PLUGINS.md) document for more info. ## Plugins ## @@ -1519,7 +1532,7 @@ from the "option" attribute of the plugin. The init function gets a reference to the plot object created and uses this to register hooks and add new public methods if needed. -See the PLUGINS.txt file for details on how to write a plugin. As the +See the [PLUGINS](PLUGINS.md) document for details on how to write a plugin. As the above description hints, it's actually pretty easy. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eef971b..3e6e43a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,9 +8,8 @@ work for us, and a faster and better response. Issues are not a way to ask general questions about Flot. If you see unexpected behavior but are not 100% certain that it is a bug, please try posting to the [forum](http://groups.google.com/group/flot-graphs) first, and confirm that -what you see is really a Flot problem before creating a new issue for it. - -When reporting a bug, please include a working demonstration of the problem, if +what you see is really a Flot problem before creating a new issue for it. When +reporting a bug, please include a working demonstration of the problem, if possible, or at least a clear description of the options you're using and the environment (browser and version, jQuery version, other libraries) that you're running under. @@ -21,23 +20,23 @@ love to hear them! Please submit each suggestion as a separate new issue. If you would like to work on an existing issue, please make sure it is not already assigned to someone else. If an issue is assigned to someone, that person has already started working on it. So, pick unassigned issues to prevent -duplicated efforts. +duplicated effort. ### Pull Requests ### To make merging as easy as possible, please keep these rules in mind: - 1. Divide larger changes into a series of small, logical commits with - descriptive messages. - - 2. Format your code according to the style guidelines below. + 1. Submit new features or architectural changes to the *<version>-work* + branch for the next major release. Submit bug fixes to the master branch. - 3. Submit new features or architectural changes to the -work branch - for the next major release. Submit bug fixes to the master branch. + 2. Divide larger changes into a series of small, logical commits with + descriptive messages. - 4. Rebase, if necessary, before submitting your pull request, to reduce the + 3. Rebase, if necessary, before submitting your pull request, to reduce the work we need to do to merge it. + 4. Format your code according to the style guidelines below. + ### Flot Style Guidelines ### Flot follows the [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines), @@ -45,38 +44,38 @@ with the following updates and exceptions: #### Spacing #### -Do not add horizontal space around parameter lists, loop definitions, or -array/object indices. For example: +Use four-space indents, no tabs. Do not add horizontal space around parameter +lists, loop definitions, or array/object indices. For example: ```js - for ( var i = 0; i < data.length; i++ ) { // This block is wrong! - if ( data[ i ] > 1 ) { - data[ i ] = 2; - } - } - - for (var i = 0; i < data.length; i++) { // This block is correct! - if (data[i] > 1) { - data[i] = 2; - } - } + for ( var i = 0; i < data.length; i++ ) { // This block is wrong! + if ( data[ i ] > 1 ) { + data[ i ] = 2; + } + } + + for (var i = 0; i < data.length; i++) { // This block is correct! + if (data[i] > 1) { + data[i] = 2; + } + } ``` #### Comments #### -Use // for all comments except the header at the top of a file or inline -include. +Use [jsDoc](http://usejsdoc.org) comments for all file and function headers. +Use // for all inline and block comments, regardless of length. All // comment blocks should have an empty line above *and* below them. For example: ```js - var a = 5; + var a = 5; - // We're going to loop here - // TODO: Make this loop faster, better, stronger! + // We're going to loop here + // TODO: Make this loop faster, better, stronger! - for (var x = 0; x < 10; x++) {} + for (var x = 0; x < 10; x++) {} ``` #### Wrapping #### @@ -91,9 +90,9 @@ Statements containing complex logic should not be wrapped arbitrarily if they do not exceed 80 characters. For example: ```js - if (a == 1 && // This block is wrong! - b == 2 && - c == 3) {} + if (a == 1 && // This block is wrong! + b == 2 && + c == 3) {} - if (a == 1 && b == 2 && c == 3) {} // This block is correct! + if (a == 1 && b == 2 && c == 3) {} // This block is correct! ``` diff --git a/NEWS.md b/NEWS.md index ffe5e00..8103ffb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,11 +14,32 @@ ### Changes ### - - Added a table of contents to the API documentation. - (patch by Brian Peiris, pull request #1064) + - Added a plot.destroy method as a way to free memory when emptying the plot + placeholder and then re-using it for some other purpose. + (patch by Thodoris Greasidis, issue #1129, pull request #1130) + + - Added a table of contents and PLUGINS link to the API documentation. + (patches by Brian Peiris, pull requests #1064 and #1127) + + - Added Ruby code examples for time conversion. + (patch by Mike Połtyn, pull request #1182) + + - Minor improvements to API.md and README.md. + (patches by Patrik Ragnarsson, pull requests #1085 and #1086) + + - Updated inlined jQuery Resize to the latest version to fix errors. + (reported by Matthew Sabol and sloker, issues #997 ad #1081) ### Bug fixes ### + - Fixed an unexpected change in behavior that resulted in duplicate tick + labels when using a plugin, like flot-tickrotor, that overrode tick labels. + (patch by Mark Cote, pull request #1091) + + - Fixed a regression from 0.7 where axis labels were given the wrong width, + causing them to overlap at certain scales and ignore the labelWidth option. + (patch by Benjamin Gram, pull request #1177) + - Fixed a bug where the second axis in an xaxes/yaxes array incorrectly had its 'innermost' property set to false or undefined, even if it was on the other side of the plot from the first axis. This resulted in the axis bar @@ -26,6 +47,53 @@ when the grid had a left/right border width of zero. (reported by Teq1, fix researched by ryleyb, issue #1056) + - Fixed an error when using a placeholder that has no font-size property. + (patch by Craig Oldford, pull request #1135) + + - Fixed a regression from 0.7 where nulls at the end of a series were ignored + for purposes of determing the range of the x-axis. + (reported by Munsifali Rashid, issue #1095) + + - If a font size is provided, base the default lineHeight on that size rather + that the font size of the plot placeholder, which may be very different. + (reported by Daniel Hoffmann Bernardes, issue #1131, pull request #1199) + + - Fix broken highlighting for right-aligned bars. + (reported by BeWiBu and Mihai Stanciu, issues #975 and #1093, with further + assistance by Eric Byers, pull request #1120) + + - Prevent white circles from sometimes showing up inside of pie charts. + (reported by Pierre Dubois and Jack Klink, issues #1128 and #1073) + + - Label formatting no longer breaks when a page contains multiple pie charts. + (reported by Brend Wanders, issue #1055) + + - When using multiple axes on opposite sides of the plot, the innermost axis + coming later in the list no longer has its bar drawn incorrectly. + (reported by ryleyb, issue #1056) + + - When removing series labels and redrawing the plot, the legend now updates + correctly even when using an external container. + (patch by Luis Silva, issue #1159, pull request #1160) + + - The pie plugin no longer ignores the value of the left offset option. + (reported by melanker, issue #1136) + + - Fixed a regression from 0.7, where extra padding was added unnecessarily to + sides of the plot where there was no last tick label. + (reported by sknob001, issue #1048, pull request #1200) + + - Fixed incorrect tooltip behavior in the interacting example. + (patch by cleroux, issue #686, pull request #1074) + + - Fixed an error in CSS color extraction with elements outside the DOM. + (patch by execjosh, pull request #1084) + + - Fixed :not selector error when using jQuery without Sizzle. + (patch by Anthony Ryan, pull request #1180) + + - Worked around a browser issue that caused bars to appear un-filled. + (reported by irbian, issue #915) ## Flot 0.8.1 ## diff --git a/README.md b/README.md index 4de7bde..a8f7064 100644 --- a/README.md +++ b/README.md @@ -107,4 +107,4 @@ examples/axes-time-zones/index.html. [excanvas]: http://code.google.com/p/explorercanvas/ [flashcanvas]: http://code.google.com/p/flashcanvas/ [timezone-js]: https://github.com/mde/timezone-js -[olson]: ftp://ftp.iana.org/tz/ +[olson]: http://ftp.iana.org/time-zones diff --git a/examples/interacting/index.html b/examples/interacting/index.html index dad0db5..ca70f36 100644 --- a/examples/interacting/index.html +++ b/examples/interacting/index.html @@ -42,20 +42,15 @@ } }); - function showTooltip(x, y, contents) { - $("
" + contents + "
").css({ - position: "absolute", - display: "none", - top: y + 5, - left: x + 5, - border: "1px solid #fdd", - padding: "2px", - "background-color": "#fee", - opacity: 0.80 - }).appendTo("body").fadeIn(200); - } + $("
").css({ + position: "absolute", + display: "none", + border: "1px solid #fdd", + padding: "2px", + "background-color": "#fee", + opacity: 0.80 + }).appendTo("body"); - var previousPoint = null; $("#placeholder").bind("plothover", function (event, pos, item) { if ($("#enablePosition:checked").length > 0) { @@ -65,20 +60,14 @@ if ($("#enableTooltip:checked").length > 0) { if (item) { - if (previousPoint != item.dataIndex) { - - previousPoint = item.dataIndex; - - $("#tooltip").remove(); - var x = item.datapoint[0].toFixed(2), + var x = item.datapoint[0].toFixed(2), y = item.datapoint[1].toFixed(2); - showTooltip(item.pageX, item.pageY, - item.series.label + " of " + x + " = " + y); - } + $("#tooltip").html(item.series.label + " of " + x + " = " + y) + .css({top: item.pageY+5, left: item.pageX+5}) + .fadeIn(200); } else { - $("#tooltip").remove(); - previousPoint = null; + $("#tooltip").hide(); } } }); @@ -98,7 +87,6 @@ - diff --git a/jquery.flot.js b/jquery.flot.js index 674a6c3..5171e6c 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -775,6 +775,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 (width, height) { width = width || placeholder.width(); height = height || placeholder.height(); @@ -860,17 +877,17 @@ 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") }, markings; - fontDefaults.lineHeight = fontDefaults.size * 1.15; - axisCount = options.xaxes.length || 1; for (i = 0; i < axisCount; ++i) { @@ -893,15 +910,34 @@ Licensed under the MIT license. axisOptions = $.extend(true, {}, options.xaxis, axisOptions); options.xaxes[i] = axisOptions; - fontDefaults.color = axisOptions.color; if (axisOptions.font) { axisOptions.font = $.extend({}, fontDefaults, axisOptions.font); } if (axisOptions.tickFont || axisOptions.font) { axisOptions.tickFont = $.extend({}, axisOptions.font || fontDefaults, axisOptions.tickFont); + if (!axisOptions.tickFont.color) { + axisOptions.tickFont.color = axisOptions.color; + } + if (!axisOptions.tickFont.lineHeight) { + axisOptions.tickFont.lineHeight = Math.round(axisOptions.tickFont.size * 1.15); + } } if (axisOptions.label && (axisOptions.labelFont || axisOptions.font)) { axisOptions.labelFont = $.extend({}, axisOptions.font || fontDefaults, axisOptions.labelFont); + if (!axisOptions.labelFont.color) { + axisOptions.labelFont.color = axisOptions.color; + } + if (!axisOptions.labelFont.lineHeight) { + axisOptions.labelFont.lineHeight = Math.round(axisOptions.labelFont.size * 1.15); + } + } + if (axisOptions.font) { + if (!axisOptions.font.color) { + axisOptions.font.color = axisOptions.color; + } + if (!axisOptions.font.lineHeight) { + axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); + } } } @@ -927,15 +963,34 @@ Licensed under the MIT license. axisOptions = $.extend(true, {}, options.yaxis, axisOptions); options.yaxes[i] = axisOptions; - fontDefaults.color = axisOptions.color; if (axisOptions.font) { axisOptions.font = $.extend({}, fontDefaults, axisOptions.font); } if (axisOptions.tickFont || axisOptions.font) { axisOptions.tickFont = $.extend({}, axisOptions.font || fontDefaults, axisOptions.tickFont); + if (!axisOptions.tickFont.color) { + axisOptions.tickFont.color = axisOptions.color; + } + if (!axisOptions.tickFont.lineHeight) { + axisOptions.tickFont.lineHeight = Math.round(axisOptions.tickFont.size * 1.15); + } } if (axisOptions.label && (axisOptions.labelFont || axisOptions.font)) { axisOptions.labelFont = $.extend({}, axisOptions.font || fontDefaults, axisOptions.labelFont); + if (!axisOptions.labelFont.color) { + axisOptions.labelFont.color = axisOptions.color; + } + if (!axisOptions.labelFont.lineHeight) { + axisOptions.labelFont.lineHeight = Math.round(axisOptions.labelFont.size * 1.15); + } + } + if (axisOptions.font) { + if (!axisOptions.font.color) { + axisOptions.font.color = axisOptions.color; + } + if (!axisOptions.font.lineHeight) { + axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15); + } } } @@ -1327,7 +1382,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); } @@ -1401,11 +1456,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) { @@ -1437,7 +1489,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 @@ -1540,7 +1594,8 @@ Licensed under the MIT license. tickWidth = opts.tickWidth || opts.labelWidth || 0, tickHeight = opts.tickHeight || opts.labelHeight || 0, maxWidth = tickWidth || axis.direction === "x" ? Math.floor(surface.width / (ticks.length || 1)) : null, - layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + axis.direction + "Axis " + axis.direction + axis.n + "Axis", + legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", + layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, font = opts.tickFont || "flot-tick-label tickLabel"; for (var i = 0; i < ticks.length; ++i) { @@ -1582,30 +1637,41 @@ Licensed under the MIT license. axisPosition = axisOptions.position, axisMargin = options.grid.axisMargin, padding = options.grid.labelMargin, - all = axis.direction === "x" ? xaxes : yaxes, - innermost; - - // Determine the margin around the axis - - var samePosition = $.grep(all, function(axis) { - return axis && axis.options.position === axisPosition && axis.reserveSpace; + isXAxis = axis.direction === "x", + 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 === axisPosition) { + if (found) { + outermost = false; + } else { + innermost = false; + } + } + if (!found) { + first = false; + } + } }); - if ($.inArray(axis, samePosition) === samePosition.length - 1) { - axisMargin = 0; // outermost - } - // Determine whether the axis is the first (innermost) on its side + // The outermost axis on each side has no margin - innermost = $.inArray(axis, samePosition) === 0; + if (outermost) { + axisMargin = 0; + } - // Determine the length of the tick marks + // The ticks for the first axis in each direction stretch across if (tickLength == null) { - if (innermost) { - tickLength = "full"; - } else { - tickLength = 5; - } + tickLength = first ? "full" : 5; } if (!isNaN(+tickLength)) { @@ -1615,9 +1681,10 @@ Licensed under the MIT license. // Measure the dimensions of the axis label, if it has one if (axisOptions.label) { - var layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + axis.direction + "Axis " + axis.direction + axis.n + "Axis", + var legacyStyles = "Axis " + axis.direction + axis.n + "Axis", + layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + axis.direction + legacyStyles, font = axisOptions.labelFont || "flot-axis-label axisLabels " + axis.direction + axis.n + "axisLabel", - angle = axis.direction === "x" ? 0 : axisOptions.position === "right" ? 90 : -90, + angle = isXAxis ? 0 : axisOptions.position === "right" ? 90 : -90, labelInfo = surface.getTextInfo(layer, axisOptions.label, font, angle); contentWidth += labelInfo.width + axisOptions.labelPadding; contentHeight += labelInfo.height + axisOptions.labelPadding; @@ -1625,7 +1692,7 @@ Licensed under the MIT license. // Compute the axis bounding box and update the plot bounds - if (axis.direction === "x") { + if (isXAxis) { contentHeight += padding; if (axisPosition === "top") { axis.box = { top: plotOffset.top + axisMargin, height: contentHeight }; @@ -1667,35 +1734,49 @@ Licensed under the MIT license. // possibly adjust plot offset to ensure everything stays // inside the canvas and isn't clipped off - var minMargin = options.grid.minBorderMargin, - margins = { x: 0, y: 0 }, i; + var minMargin = options.grid.minBorderMargin; // check stuff from the plot (FIXME: this should just read // a value from the series, otherwise it's impossible to // customize) if (minMargin == null) { minMargin = 0; - for (i = 0; i < series.length; ++i) { + for (var i = 0; i < series.length; ++i) { 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.tickWidth : axis.tickHeight) / 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.tickWidth / 2); + if (lastTick.v <= axis.max) { + margins.right = Math.max(margins.right, axis.tickWidth / 2); + } + } else { + margins.bottom = Math.max(margins.bottom, axis.tickHeight / 2); + if (lastTick.v <= axis.max) { + margins.top = Math.max(margins.top, axis.tickHeight / 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() { @@ -2403,19 +2484,25 @@ Licensed under the MIT license. function drawAxisLabels() { $.each(allAxes(), function (_, axis) { - if (!axis.show || axis.ticks.length === 0) { - return; - } var box = axis.box, axisOptions = axis.options, - layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + axis.direction + "Axis " + axis.direction + axis.n + "Axis", + legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis", + layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles, labelFont = axisOptions.labelFont || "flot-axis-label axisLabels " + axis.direction + axis.n + "axisLabel", tickFont = axisOptions.tickFont || "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; + } + if (axisOptions.label) { if (axis.direction === "x") { if (axisOptions.position === "top") { @@ -2824,7 +2911,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; @@ -2899,13 +2986,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 @@ -2913,40 +2995,36 @@ Licensed under the MIT license. c.beginPath(); // FIXME: inline moveTo is buggy with excanvas - c.moveTo(left, bottom + offset); - if (drawLeft) { - c.lineTo(left, top + offset); - } else { - c.moveTo(left, top + offset); - } - if (drawTop) { - c.lineTo(right, top + offset); - } else { - c.moveTo(right, top + offset); - } - if (drawRight) { - c.lineTo(right, bottom + offset); - } else { - c.moveTo(right, bottom + offset); - } - if (drawBottom) { - c.lineTo(left, bottom + offset); - } else { - c.moveTo(left, bottom + offset); - } + c.moveTo(left, bottom); + if (drawLeft) + c.lineTo(left, top); + else + c.moveTo(left, top); + if (drawTop) + c.lineTo(right, top); + else + c.moveTo(right, top); + if (drawRight) + c.lineTo(right, bottom); + else + c.moveTo(right, bottom); + if (drawBottom) + c.lineTo(left, bottom); + else + 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); } } @@ -2966,15 +3044,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(); } @@ -2996,7 +3071,11 @@ 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) { return; @@ -3198,8 +3277,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) { x = points[j]; @@ -3417,13 +3509,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) { diff --git a/jquery.flot.pie.js b/jquery.flot.pie.js index 3be2b25..a46c365 100644 --- a/jquery.flot.pie.js +++ b/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, @@ -294,16 +295,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; diff --git a/lib/jquery.colorhelpers.js b/lib/jquery.colorhelpers.js index 3b94fb7..f01cd17 100644 --- a/lib/jquery.colorhelpers.js +++ b/lib/jquery.colorhelpers.js @@ -76,15 +76,16 @@ // if it's "transparent" $.color.extract = function (elem, css) { var c; + do { c = elem.css(css).toLowerCase(); // keep going until we find an element that has color, or - // we hit the body + // we hit the body or root (have no parent) if (c !== "" && c !== "transparent") { break; } elem = elem.parent(); - } while (!$.nodeName(elem.get(0), "body")); + } while (elem.length && !$.nodeName(elem.get(0), "body")); // catch Safari's way of signalling transparent if (c === "rgba(0, 0, 0, 0)") {