diff --git a/API.txt b/API.txt index e3e3324..2d7e5cf 100644 --- a/API.txt +++ b/API.txt @@ -549,9 +549,6 @@ specified, "dataIndex" will be 1, "series" is a normalized series object with among other things the "Foo" label in series.label and the color in series.color, and "seriesIndex" is 0. -Note that the detection of nearby points is limited to points (bars -aren't working) at the moment. - If you use the above events to update some other information and want to clear out that info in case the mouse goes away, you'll probably also need to listen to "mouseout" events on the placeholder div. diff --git a/NEWS.txt b/NEWS.txt index e532792..07af8cd 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -9,8 +9,8 @@ compatibility hooks are in place). Interactivity: added a new "plothover" event and this and the "plotclick" event now returns the closest data item (based on patch by -/david). See the revamped "interacting with the data" example for -some hints on what you can do. +/david, patch by Mark Byers for bar support). See the revamped +"interacting with the data" example for some hints on what you can do. Highlighting: you can now highlight points and points are autohighlighted when you hover over them (if hovering is turned on). diff --git a/jquery.flot.js b/jquery.flot.js index f2371fd..27ad493 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -1484,41 +1484,64 @@ // Returns the data item the mouse is over, or null if none is found function findNearbyItem(mouseX, mouseY) { - var maxDistance = options.grid.mouseActiveRadius; - var lowestDistance = maxDistance * maxDistance + 1, - item = null; + var maxDistance = options.grid.mouseActiveRadius, + lowestDistance = maxDistance * maxDistance + 1, + item = null, foundPoint = false; + function result(i, j) { + return { datapoint: series[i].data[j], + dataIndex: j, + series: series[i], + seriesIndex: i } + } + for (var i = 0; i < series.length; ++i) { var data = series[i].data, axisx = series[i].xaxis, - axisy = series[i].yaxis; - - // precompute some stuff to make the loop faster - var mx = axisx.c2p(mouseX), my = axisy.c2p(mouseY), + axisy = series[i].yaxis, + + // precompute some stuff to make the loop faster + mx = axisx.c2p(mouseX), + my = axisy.c2p(mouseY), maxx = maxDistance / axisx.scale, - maxy = maxDistance / axisy.scale; + maxy = maxDistance / axisy.scale, + checkbar = series[i].bars.show, + checkpoint = !(series[i].bars.show && !(series[i].lines.show || series[i].points.show)), + barLeft = series[i].bars.align == "left" ? 0 : -series[i].bars.barWidth/2, + barRight = barLeft + series[i].bars.barWidth; for (var j = 0; j < data.length; ++j) { if (data[j] == null) continue; - // first check whether we're too far away var x = data[j][0], y = data[j][1]; - if (x - mx > maxx || x - mx < -maxx) - continue; - if (y - my > maxy || y - my < -maxy) - continue; + + if (checkbar) { + // For a bar graph, the cursor must be inside the bar + // and no other point can be nearby + if (!foundPoint && mx >= x + barLeft && + mx <= x + barRight && my <= y) + item = result(i, j); + } + + if (checkpoint) { + // For points and lines, the cursor must be within a + // certain distance to the data point + + // check bounding box first + if ((x - mx > maxx || x - mx < -maxx) || + (y - my > maxy || y - my < -maxy)) + continue; - // We have to calculate distances in pixels, not in - // data units, because the scale of the axes may be different - var dx = Math.abs(axisx.p2c(x) - mouseX), - dy = Math.abs(axisy.p2c(y) - mouseY); - var dist = dx * dx + dy * dy; - if (dist < lowestDistance) { - lowestDistance = dist; - item = { datapoint: data[j], - dataIndex: j, - series: series[i], - seriesIndex: i }; + // We have to calculate distances in pixels, not in + // data units, because the scale of the axes may be different + var dx = Math.abs(axisx.p2c(x) - mouseX), + dy = Math.abs(axisy.p2c(y) - mouseY), + dist = dx * dx + dy * dy; + if (dist < lowestDistance) { + lowestDistance = dist; + foundPoint = true; + item = result(i, j); + } } } }