From 57225a3a743ffe682d9960578b7762294755f040 Mon Sep 17 00:00:00 2001 From: Ken Kubiak Date: Mon, 11 Mar 2013 12:35:01 -0700 Subject: [PATCH 1/3] implement `fromCenter`, allowing placement along line between center and boundary point --- src/core.js | 1 + src/csscoordinates.js | 9 ++++++++ src/placementcalculator.js | 46 +++++++++++++++++++++++++++++--------- src/tooltipcontroller.js | 3 ++- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/core.js b/src/core.js index 19cf95fa..ca8acbac 100644 --- a/src/core.js +++ b/src/core.js @@ -179,6 +179,7 @@ $.fn.powerTip.defaults = { placement: 'n', smartPlacement: false, offset: 10, + fromCenter: 1.0, mouseOnToPopup: false, manual: false, openEvents: [ 'mouseenter', 'focus' ], diff --git a/src/csscoordinates.js b/src/csscoordinates.js index fd793078..ac078b7a 100644 --- a/src/csscoordinates.js +++ b/src/csscoordinates.js @@ -32,4 +32,13 @@ function CSSCoordinates() { me[property] = Math.round(value); } }; + + /** + * Check if a property is set + * @private + * @param {string} property The name of the property. + */ + me.isSet = function(property) { + return $.isNumeric(me[property]); + }; } diff --git a/src/placementcalculator.js b/src/placementcalculator.js index a2ce37d7..55b76c55 100644 --- a/src/placementcalculator.js +++ b/src/placementcalculator.js @@ -22,17 +22,19 @@ function PlacementCalculator() { * @param {number} tipWidth Width of the tooltip element in pixels. * @param {number} tipHeight Height of the tooltip element in pixels. * @param {number} offset Distance to offset tooltips in pixels. + * @param {number} fromCenter Distance along line from center (0) to boundary (1). * @return {CSSCoordinates} A CSSCoordinates object with the position. */ - function computePlacementCoords(element, placement, tipWidth, tipHeight, offset) { + function computePlacementCoords(element, placement, tipWidth, tipHeight, + offset, fromCenter) { var placementBase = placement.split('-')[0], // ignore 'alt' for corners coords = new CSSCoordinates(), position; if (isSvgElement(element)) { - position = getSvgPlacement(element, placementBase); + position = getSvgPlacement(element, placementBase, fromCenter); } else { - position = getHtmlPlacement(element, placementBase); + position = getHtmlPlacement(element, placementBase, fromCenter); } // calculate the appropriate x and y position in the document @@ -90,20 +92,36 @@ function PlacementCalculator() { return coords; } + /** + * Finds the weighted average of two values + * @private + * @param {number} a the first value (returned if weight=0) + * @param {number} b the second value (returned if weight=1) + * @param {number} weight the weight (0 <= weight <= 1) + */ + function weightedAvg(a, b, weight) { + return Math.round( b * weight + a * (1.0 - weight) ); + } + /** * Finds the tooltip attachment point in the document for a HTML DOM element * for the specified placement. * @private * @param {jQuery} element The element that the tooltip should target. * @param {string} placement The placement for the tooltip. + * @param {number} fromCenter The relative distance between center and boundary * @return {Object} An object with the top,left position values. */ - function getHtmlPlacement(element, placement) { + function getHtmlPlacement(element, placement, fromCenter) { var objectOffset = element.offset(), objectWidth = element.outerWidth(), objectHeight = element.outerHeight(), left, - top; + top, + objectCenter = { + top: objectOffset.top + objectHeight / 2, + left: objectOffset.left + objectWidth / 2 + }; // calculate the appropriate x and y position in the document switch (placement) { @@ -142,8 +160,8 @@ function PlacementCalculator() { } return { - top: top, - left: left + top: weightedAvg(objectCenter.top, top, fromCenter), + left: weightedAvg(objectCenter.left, left, fromCenter) }; } @@ -153,9 +171,10 @@ function PlacementCalculator() { * @private * @param {jQuery} element The element that the tooltip should target. * @param {string} placement The placement for the tooltip. + * @param {number} fromCenter The relative distance between center and boundary * @return {Object} An object with the top,left position values. */ - function getSvgPlacement(element, placement) { + function getSvgPlacement(element, placement, fromCenter) { var svgElement = element.closest('svg')[0], domElement = element[0], point = svgElement.createSVGPoint(), @@ -166,6 +185,7 @@ function PlacementCalculator() { placements = [], placementKeys = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'], coords, + center = svgElement.createSVGPoint(), rotation, steps, x; @@ -174,9 +194,12 @@ function PlacementCalculator() { placements.push(point.matrixTransform(matrix)); } - // get bounding box corners and midpoints + // Get bounding box corners and midpoints point.x = boundingBox.x; point.y = boundingBox.y; + center.x = point.x + halfWidth; + center.y = point.y + halfHeight; + center = center.matrixTransform(matrix); pushPlacement(); point.x += halfWidth; pushPlacement(); @@ -197,6 +220,7 @@ function PlacementCalculator() { if (placements[0].y !== placements[1].y || placements[0].x !== placements[7].x) { rotation = Math.atan2(matrix.b, matrix.a) * RAD2DEG; steps = Math.ceil(((rotation % 360) - 22.5) / 45); + center = center.matrixTransform(matrix); if (steps < 1) { steps += 8; } @@ -214,8 +238,8 @@ function PlacementCalculator() { } return { - top: coords.y + session.scrollTop, - left: coords.x + session.scrollLeft + top: weightedAvg(center.y, coords.y, fromCenter) + session.scrollTop, + left: weightedAvg(center.x, coords.x, fromCenter) + session.scrollLeft }; } diff --git a/src/tooltipcontroller.js b/src/tooltipcontroller.js index 80ae643b..6685fbb2 100644 --- a/src/tooltipcontroller.js +++ b/src/tooltipcontroller.js @@ -339,7 +339,8 @@ function TooltipController(options) { placement, tipWidth, tipHeight, - options.offset + options.offset, + options.fromCenter ); // place the tooltip From eec5ada316ab78e7fa37220885aad26bd9843337 Mon Sep 17 00:00:00 2001 From: Ken Kubiak Date: Tue, 12 Mar 2013 17:42:09 -0700 Subject: [PATCH 2/3] make 'inset' (distance from corner in ne, nw, se, sw placements) configurable Conflicts: src/placementcalculator.js --- src/core.js | 1 + src/placementcalculator.js | 19 +++++++++++-------- src/tooltipcontroller.js | 3 +-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/core.js b/src/core.js index ca8acbac..0312db85 100644 --- a/src/core.js +++ b/src/core.js @@ -179,6 +179,7 @@ $.fn.powerTip.defaults = { placement: 'n', smartPlacement: false, offset: 10, + inset: 20, fromCenter: 1.0, mouseOnToPopup: false, manual: false, diff --git a/src/placementcalculator.js b/src/placementcalculator.js index 55b76c55..f2b53dde 100644 --- a/src/placementcalculator.js +++ b/src/placementcalculator.js @@ -21,13 +21,16 @@ function PlacementCalculator() { * @param {string} placement The placement for the tooltip. * @param {number} tipWidth Width of the tooltip element in pixels. * @param {number} tipHeight Height of the tooltip element in pixels. - * @param {number} offset Distance to offset tooltips in pixels. - * @param {number} fromCenter Distance along line from center (0) to boundary (1). + * @param {number} options.offset Distance to offset tooltips in pixels. + * @param {number} options.fromCenter Distance along line from center (0) to boundary (1). + * @param {number} options.inset Distance from corner of tooltip to object for ne, nw, se, sw. * @return {CSSCoordinates} A CSSCoordinates object with the position. */ - function computePlacementCoords(element, placement, tipWidth, tipHeight, - offset, fromCenter) { + function computePlacementCoords(element, placement, tipWidth, tipHeight, options ) { var placementBase = placement.split('-')[0], // ignore 'alt' for corners + offset = options.offset, + fromCenter = options.fromCenter, + inset = options.inset, coords = new CSSCoordinates(), position; @@ -57,14 +60,14 @@ function PlacementCalculator() { break; case 'nw': coords.set('bottom', session.windowHeight - position.top + offset); - coords.set('right', session.windowWidth - position.left - 20); + coords.set('right', session.windowWidth - position.left - inset); break; case 'nw-alt': coords.set('left', position.left); coords.set('bottom', session.windowHeight - position.top + offset); break; case 'ne': - coords.set('left', position.left - 20); + coords.set('left', position.left - inset); coords.set('bottom', session.windowHeight - position.top + offset); break; case 'ne-alt': @@ -73,14 +76,14 @@ function PlacementCalculator() { break; case 'sw': coords.set('top', position.top + offset); - coords.set('right', session.windowWidth - position.left - 20); + coords.set('right', session.windowWidth - position.left - inset); break; case 'sw-alt': coords.set('left', position.left); coords.set('top', position.top + offset); break; case 'se': - coords.set('left', position.left - 20); + coords.set('left', position.left - inset); coords.set('top', position.top + offset); break; case 'se-alt': diff --git a/src/tooltipcontroller.js b/src/tooltipcontroller.js index 6685fbb2..19e45d3f 100644 --- a/src/tooltipcontroller.js +++ b/src/tooltipcontroller.js @@ -339,8 +339,7 @@ function TooltipController(options) { placement, tipWidth, tipHeight, - options.offset, - options.fromCenter + options ); // place the tooltip From fef8bef28351a2de0b69eaed5dd82b2d869c36e7 Mon Sep 17 00:00:00 2001 From: Nick Rabinowitz Date: Fri, 12 Jul 2013 17:12:43 -0700 Subject: [PATCH 3/3] JSHint fixes so that the build will run --- src/core.js | 2 +- src/csscoordinates.js | 6 +++--- src/placementcalculator.js | 44 +++++++++++++++++++------------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/core.js b/src/core.js index 0312db85..fa763374 100644 --- a/src/core.js +++ b/src/core.js @@ -179,7 +179,7 @@ $.fn.powerTip.defaults = { placement: 'n', smartPlacement: false, offset: 10, - inset: 20, + inset: 20, fromCenter: 1.0, mouseOnToPopup: false, manual: false, diff --git a/src/csscoordinates.js b/src/csscoordinates.js index ac078b7a..c407f58a 100644 --- a/src/csscoordinates.js +++ b/src/csscoordinates.js @@ -38,7 +38,7 @@ function CSSCoordinates() { * @private * @param {string} property The name of the property. */ - me.isSet = function(property) { - return $.isNumeric(me[property]); - }; + me.isSet = function(property) { + return $.isNumeric(me[property]); + }; } diff --git a/src/placementcalculator.js b/src/placementcalculator.js index f2b53dde..bdeab656 100644 --- a/src/placementcalculator.js +++ b/src/placementcalculator.js @@ -28,9 +28,9 @@ function PlacementCalculator() { */ function computePlacementCoords(element, placement, tipWidth, tipHeight, options ) { var placementBase = placement.split('-')[0], // ignore 'alt' for corners - offset = options.offset, - fromCenter = options.fromCenter, - inset = options.inset, + offset = options.offset, + fromCenter = options.fromCenter, + inset = options.inset, coords = new CSSCoordinates(), position; @@ -95,16 +95,16 @@ function PlacementCalculator() { return coords; } - /** - * Finds the weighted average of two values - * @private - * @param {number} a the first value (returned if weight=0) - * @param {number} b the second value (returned if weight=1) - * @param {number} weight the weight (0 <= weight <= 1) - */ - function weightedAvg(a, b, weight) { - return Math.round( b * weight + a * (1.0 - weight) ); - } + /** + * Finds the weighted average of two values + * @private + * @param {number} a the first value (returned if weight=0) + * @param {number} b the second value (returned if weight=1) + * @param {number} weight the weight (0 <= weight <= 1) + */ + function weightedAvg(a, b, weight) { + return Math.round( b * weight + a * (1.0 - weight) ); + } /** * Finds the tooltip attachment point in the document for a HTML DOM element @@ -121,10 +121,10 @@ function PlacementCalculator() { objectHeight = element.outerHeight(), left, top, - objectCenter = { - top: objectOffset.top + objectHeight / 2, - left: objectOffset.left + objectWidth / 2 - }; + objectCenter = { + top: objectOffset.top + objectHeight / 2, + left: objectOffset.left + objectWidth / 2 + }; // calculate the appropriate x and y position in the document switch (placement) { @@ -188,7 +188,7 @@ function PlacementCalculator() { placements = [], placementKeys = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'], coords, - center = svgElement.createSVGPoint(), + center = svgElement.createSVGPoint(), rotation, steps, x; @@ -200,9 +200,9 @@ function PlacementCalculator() { // Get bounding box corners and midpoints point.x = boundingBox.x; point.y = boundingBox.y; - center.x = point.x + halfWidth; - center.y = point.y + halfHeight; - center = center.matrixTransform(matrix); + center.x = point.x + halfWidth; + center.y = point.y + halfHeight; + center = center.matrixTransform(matrix); pushPlacement(); point.x += halfWidth; pushPlacement(); @@ -223,7 +223,7 @@ function PlacementCalculator() { if (placements[0].y !== placements[1].y || placements[0].x !== placements[7].x) { rotation = Math.atan2(matrix.b, matrix.a) * RAD2DEG; steps = Math.ceil(((rotation % 360) - 22.5) / 45); - center = center.matrixTransform(matrix); + center = center.matrixTransform(matrix); if (steps < 1) { steps += 8; }