Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed bug #313; Tooltip goes beyond graph in 2.1.6

  • Loading branch information...
commit f0748c927d4cb9db29bc9bb1ef60e0a7884025ba 1 parent 6eeb8cc
Erik Olsson eolsson authored
64 js/highcharts.src.js
View
@@ -2,7 +2,7 @@
// @compilation_level SIMPLE_OPTIMIZATIONS
/**
- * @license @product.name@ JS v@product.version@ (@product.date@)
+ * @license Highcharts JS v2.1.6 (2011-07-08)
*
* (c) 2009-2011 Torstein Hønsi
*
@@ -477,6 +477,37 @@ ChartCounters.prototype = {
};
/**
+ * Utility method extracted from Tooltip code that places a tooltip in a chart without spilling over
+ * and not covering the point it self.
+ */
+function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point) {
+ // keep the box within the chart area
+ var x = point.x - boxWidth + outerLeft - 25,
+ y = point.y - boxHeight + outerTop + 10;
+
+ // it is too far to the left, adjust it
+ if (x < 7) {
+ x = outerLeft + point.x + 15;
+ }
+
+ // Test to see if the tooltip is to far to the right,
+ // if it is, move it back to be inside and then up to not cover the point.
+ if ((x + boxWidth) > (outerLeft + outerWidth)) {
+ x -= (x + boxWidth) - (outerLeft + outerWidth);
+ y -= boxHeight;
+ }
+
+ if (y < 5) {
+ y = 5; // above
+ } else if (y + boxHeight > outerHeight) {
+ y = outerHeight - boxHeight - 5; // below
+ y = outerHeight - boxHeight - 5; // below
+ }
+
+ return {x: x, y: y};
+}
+
+/**
* Set the global animation to either a given value, or fall back to the
* given chart's animation option
* @param {Object} animation
@@ -5911,7 +5942,8 @@ function Chart(options, callback) {
pointConfig = [],
tooltipPos = point.tooltipPos,
formatter = options.formatter || defaultFormatter,
- hoverPoints = chart.hoverPoints;
+ hoverPoints = chart.hoverPoints,
+ placedTooltipPoint;
// shared tooltip, array is sent over
if (shared) {
@@ -5992,27 +6024,11 @@ function Chart(options, callback) {
height: boxHeight,
stroke: options.borderColor || point.color || currentSeries.color || '#606060'
});
-
- // keep the box within the chart area
- boxX = x - boxWidth + plotLeft - 25;
- boxY = y - boxHeight + plotTop + 10;
-
- // it is too far to the left, adjust it
- if (boxX < 7) {
- boxX = plotLeft + x + 15;
- }
-
-
- if (boxY < 5) {
- boxY = 5; // above
- } else if (boxY + boxHeight > chartHeight) {
- boxY = chartHeight - boxHeight - 5; // below
- }
-
+
+ placedTooltipPoint = placeBox(boxWidth, boxHeight, plotLeft, plotTop, plotWidth, plotHeight, {x: x, y: y});
+
// do the move
- move(mathRound(boxX - boxOffLeft), mathRound(boxY - boxOffLeft));
-
-
+ move(mathRound(placedTooltipPoint.x - boxOffLeft), mathRound(placedTooltipPoint.y - boxOffLeft));
}
@@ -11068,7 +11084,7 @@ win.Highcharts = {
merge: merge,
pick: pick,
extendClass: extendClass,
- product: '@product.name@',
- version: '@product.version@'
+ product: 'Highcharts',
+ version: '2.1.6'
};
}());
27 js/parts/Chart.js
View
@@ -2009,7 +2009,8 @@ function Chart(options, callback) {
pointConfig = [],
tooltipPos = point.tooltipPos,
formatter = options.formatter || defaultFormatter,
- hoverPoints = chart.hoverPoints;
+ hoverPoints = chart.hoverPoints,
+ placedTooltipPoint;
// shared tooltip, array is sent over
if (shared) {
@@ -2090,27 +2091,11 @@ function Chart(options, callback) {
height: boxHeight,
stroke: options.borderColor || point.color || currentSeries.color || '#606060'
});
-
- // keep the box within the chart area
- boxX = x - boxWidth + plotLeft - 25;
- boxY = y - boxHeight + plotTop + 10;
-
- // it is too far to the left, adjust it
- if (boxX < 7) {
- boxX = plotLeft + x + 15;
- }
-
-
- if (boxY < 5) {
- boxY = 5; // above
- } else if (boxY + boxHeight > chartHeight) {
- boxY = chartHeight - boxHeight - 5; // below
- }
-
+
+ placedTooltipPoint = placeBox(boxWidth, boxHeight, plotLeft, plotTop, plotWidth, plotHeight, {x: x, y: y});
+
// do the move
- move(mathRound(boxX - boxOffLeft), mathRound(boxY - boxOffLeft));
-
-
+ move(mathRound(placedTooltipPoint.x - boxOffLeft), mathRound(placedTooltipPoint.y - boxOffLeft));
}
31 js/parts/Utilities.js
View
@@ -360,3 +360,34 @@ ChartCounters.prototype = {
}
}
};
+
+/**
+ * Utility method extracted from Tooltip code that places a tooltip in a chart without spilling over
+ * and not covering the point it self.
+ */
+function placeBox(boxWidth, boxHeight, outerLeft, outerTop, outerWidth, outerHeight, point) {
+ // keep the box within the chart area
+ var x = point.x - boxWidth + outerLeft - 25,
+ y = point.y - boxHeight + outerTop + 10;
+
+ // it is too far to the left, adjust it
+ if (x < 7) {
+ x = outerLeft + point.x + 15;
+ }
+
+ // Test to see if the tooltip is to far to the right,
+ // if it is, move it back to be inside and then up to not cover the point.
+ if ((x + boxWidth) > (outerLeft + outerWidth)) {
+ x -= (x + boxWidth) - (outerLeft + outerWidth);
+ y -= boxHeight;
+ }
+
+ if (y < 5) {
+ y = 5; // above
+ } else if (y + boxHeight > outerHeight) {
+ y = outerHeight - boxHeight - 5; // below
+ y = outerHeight - boxHeight - 5; // below
+ }
+
+ return {x: x, y: y};
+}
81 test/unit/UtilitiesTest.js
View
@@ -1,4 +1,4 @@
-UtilTest = TestCase("UtilitiesTest");
+var UtilTest = TestCase("UtilitiesTest");
UtilTest.prototype.testExtend = function () {
var empty = {};
@@ -25,7 +25,7 @@ UtilTest.prototype.testExtend = function () {
// test extend of another object
result = extend(extra, extra2);
assertEquals("Extended object with object2", 4, this.countMembers(result));
-}
+};
UtilTest.prototype.countMembers = function (obj) {
var count = 0;
@@ -34,9 +34,9 @@ UtilTest.prototype.countMembers = function (obj) {
}
return count;
-}
+};
-UtilTest.prototype.testPInt = function() {
+UtilTest.prototype.testPInt = function () {
// test without a base defined
assertEquals("base not defined", 15, pInt("15"));
@@ -45,9 +45,9 @@ UtilTest.prototype.testPInt = function() {
// test with base 16
assertEquals("base 16", 15, pInt("F", 16));
-}
+};
-UtilTest.prototype.testIsString = function() {
+UtilTest.prototype.testIsString = function () {
// test with undefined
assertEquals("IsString undefined", false, isString(undefined));
@@ -65,9 +65,9 @@ UtilTest.prototype.testIsString = function() {
// test with string
assertEquals("IsString string", true, isString("this is a string"));
-}
+};
-UtilTest.prototype.testIsObject = function() {
+UtilTest.prototype.testIsObject = function () {
// test with undefined
assertEquals("IsObject undefined", false, isObject(undefined));
@@ -82,9 +82,9 @@ UtilTest.prototype.testIsObject = function() {
// test with object
assertEquals("IsObject object", true, isObject({}));
-}
+};
-UtilTest.prototype.testIsNumber = function() {
+UtilTest.prototype.testIsNumber = function () {
// test with undefined
assertEquals("IsNumber undefined", false, isNumber(undefined));
@@ -99,12 +99,63 @@ UtilTest.prototype.testIsNumber = function() {
// test with object
assertEquals("IsNumber object", false, isNumber({}));
-}
+};
-UtilTest.prototype.testLog2Lin = function() {
+UtilTest.prototype.testLog2Lin = function () {
// TODO: implement
-}
+};
-UtilTest.prototype.testLin2Log = function() {
+UtilTest.prototype.testLin2Log = function () {
// TODO: implement
-}
+};
+
+/**
+ * Tests if a point is inside a rectangle
+ */
+UtilTest.prototype.pointInRect = function (x, y, rect) {
+ var inside = x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height)
+ return inside;
+};
+
+/**
+ * Tests if a small rectangle is inside a bigger rectangle by testing each corner.
+ */
+UtilTest.prototype.rectInRect = function (smallRect, largeRect) {
+ // (Maybe only two corners need to be tested)
+ var inside = this.pointInRect(smallRect.x, smallRect.y, largeRect); // left top
+ inside = inside && this.pointInRect(smallRect.x + smallRect.width, smallRect.y, largeRect); // right top
+ inside = inside && this.pointInRect(smallRect.x + smallRect.width, smallRect.y + smallRect.height, largeRect); // right bottom
+ inside = inside && this.pointInRect(smallRect.x, smallRect.y + smallRect.height, largeRect); // left bottom
+ return inside;
+};
+
+/**
+ * Test the placeBox utility function. It should adjust a tooltip rectangle to be inside the chart but not cover the point itself.
+ */
+UtilTest.prototype.testPlaceBox = function () {
+ var chartRect = {x: 0, y: 0, width: 100, height: 100 },
+ tooltipSize = {width: 50, height: 20},
+ dataPoint = {x: 0, y: 50},
+ tooltipPoint,
+ boxPoint;
+
+ boxPoint = placeBox(tooltipSize.width, tooltipSize.height, chartRect.x, chartRect.y, chartRect.width, chartRect.height, dataPoint);
+ extend(boxPoint, tooltipSize);
+ jstestdriver.console.log(boxPoint.x, boxPoint.y, boxPoint.width, boxPoint.height);
+ assertTrue('Left rectInRect chart', this.rectInRect(boxPoint, chartRect));
+ assertFalse('Left tooltip cover point', this.pointInRect(dataPoint.x, dataPoint.y, boxPoint));
+
+ dataPoint.x = 100;
+ boxPoint = placeBox(tooltipSize.width, tooltipSize.height, chartRect.x, chartRect.y, chartRect.width, chartRect.height, dataPoint);
+ extend(boxPoint, tooltipSize);
+ jstestdriver.console.log(boxPoint.x, boxPoint.y, boxPoint.width, boxPoint.height);
+ assertTrue('Right rectInRect chart', this.rectInRect(boxPoint, chartRect));
+ assertFalse('Right tooltip cover point', this.pointInRect(dataPoint.x, dataPoint.y, boxPoint));
+
+ dataPoint.x = 50;
+ boxPoint = placeBox(tooltipSize.width, tooltipSize.height, chartRect.x, chartRect.y, chartRect.width, chartRect.height, dataPoint);
+ extend(boxPoint, tooltipSize);
+ jstestdriver.console.log(boxPoint.x, boxPoint.y, boxPoint.width, boxPoint.height);
+ assertTrue('Mid rectInRect chart', this.rectInRect(boxPoint, chartRect));
+ assertFalse('Mid tooltip cover point', this.pointInRect(dataPoint.x, dataPoint.y, boxPoint));
+};
Please sign in to comment.
Something went wrong with that request. Please try again.