From e985896e6d43913b2f12999ecf8a13fb267fea72 Mon Sep 17 00:00:00 2001 From: Joel Steres Date: Wed, 2 Nov 2016 12:13:01 -0700 Subject: [PATCH] Patch for powertip offset bug when zoomed on Blink render Reference getBoundingClientRect behavior in https://bugs.chromium.org/p/chromium/issues/detail?id=489206 --- src/core.js | 8 ++++++-- src/placementcalculator.js | 2 +- src/utility.js | 31 ++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/core.js b/src/core.js index cc11d8c5..45ae16f5 100644 --- a/src/core.js +++ b/src/core.js @@ -35,7 +35,8 @@ var DATA_DISPLAYCONTROLLER = 'displayController', 'mouseenter', 'mouseleave', 'contextmenu' - ]; + ], + PATCH_DUMMY_ELEMENT_ID = 'chromeBugOffsetRef'; /** * Session data @@ -60,7 +61,8 @@ var session = { windowWidth: 0, windowHeight: 0, scrollTop: 0, - scrollLeft: 0 + scrollLeft: 0, + chromePatchRefElement: null }; /** @@ -97,6 +99,8 @@ $.fn.powerTip = function(opts, arg) { return $.powerTip[opts].call(targetElements, targetElements, arg); } + injectChromePatchReferenceElement(); + // extend options options = $.extend({}, $.fn.powerTip.defaults, opts); diff --git a/src/placementcalculator.js b/src/placementcalculator.js index 1ec10ed6..8af20baf 100644 --- a/src/placementcalculator.js +++ b/src/placementcalculator.js @@ -99,7 +99,7 @@ function PlacementCalculator() { * @return {Object} An object with the top,left position values. */ function getHtmlPlacement(element, placement) { - var objectOffset = element.offset(), + var objectOffset = getCompensatedOffset(element), objectWidth = element.outerWidth(), objectHeight = element.outerHeight(), left, diff --git a/src/utility.js b/src/utility.js index b1b5455f..ef395cf4 100644 --- a/src/utility.js +++ b/src/utility.js @@ -109,7 +109,7 @@ function isMouseOver(element) { // methods do not work with SVG elements // compute width/height because those properties do not exist on the object // returned by getBoundingClientRect() in older versions of IE - var elementPosition = element.offset(), + var elementPosition = getCompensatedOffset(element), elementBox = element[0].getBoundingClientRect(), elementWidth = elementBox.right - elementBox.left, elementHeight = elementBox.bottom - elementBox.top; @@ -201,3 +201,32 @@ function countFlags(value) { } return count; } + +/** + * Conditionally insert reference element for use in Chrome zoomed offset patch + * Reference https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + */ +function injectChromePatchReferenceElement() { + if (/Chrome\/[.0-9]*/.test(navigator.userAgent) && !document.getElementById(PATCH_DUMMY_ELEMENT_ID)) { + session.chromePatchRefElement = $('').prependTo(document.body); + } +} + +/** + * Compensate for the Chrome getBoundingClientRect bug when zoomed. + * Reference https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + * @param {jQuery} element The element that the tooltip should target. + * @return {Offsets} The top, left offsets relative to the document. + */ +function getCompensatedOffset(element) { + if (session.chromePatchRefElement) { + var offset = element.offset(); + var rd = session.chromePatchRefElement[0].getBoundingClientRect(); + return { + left: offset.left - (rd.left + window.pageXOffset), + top: offset.top - (rd.top + window.pageYOffset) + }; + } + return element.offset(); +}