Skip to content

Instantly share code, notes, and snippets.

@sjd78
Created February 13, 2017 17:02
Show Gist options
  • Save sjd78/7a8d56fad969f3a7448ea10a94c0f552 to your computer and use it in GitHub Desktop.
Save sjd78/7a8d56fad969f3a7448ea10a94c0f552 to your computer and use it in GitHub Desktop.
Override bootstrap 3.3.7 tooltip position code so it works with SVG elements
import jQuery from 'jquery/dist/jquery'
/*
* Override the bootstrap 3.3.7 Tooltip.getPosition() function to fix
* position issues with SVG elements when the page/viewport is scrolled.
*/
;(function ($) {
// const original = $.extend(true, {}, $.fn.tooltip.Constructor.prototype)
const extension = {
getPosition ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName === 'BODY'
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
/*
* Avoid using $.offset() since it gives incorrect results on SVG elements. Directly compute scroll
* adjusted position like $.offset() and angular-ui-bootstrap's $position.offset() does.
*
* See issues: https://github.com/twbs/bootstrap/issues/20280
* https://github.com/twbs/bootstrap/issues/20381
* https://github.com/twbs/bootstrap/issues/21855
*/
var elOffset = isBody
? { top: 0, left: 0 }
: { top: elRect.top + (window.pageYOffset || document.documentElement.scrollTop),
left: elRect.left + (window.pageXOffset || document.documentElement.scrollLeft) }
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
}
$.extend(true, $.fn.tooltip.Constructor.prototype, extension)
}(jQuery))
@sjd78
Copy link
Author

sjd78 commented Feb 13, 2017

This JS does use a few ES6 code features. I use it in a webpack built project so babel converts it to browser compatible JS for me.

@gabel
Copy link

gabel commented Jun 28, 2017

Extend version in EcmaScript5 (converted with https://babeljs.io/repl/) that fixes popovers as well (just applied extension to $.fn.popover.Constructor.prototype too)

/*
 * Override the bootstrap 3.3.7 Tooltip.getPosition() function to fix
 * position issues with SVG elements when the page/viewport is scrolled.
 */
;(function ($) {
  // const original = $.extend(true, {}, $.fn.tooltip.Constructor.prototype)

  var extension = {
    getPosition: function getPosition($element) {
      $element = $element || this.$element;

      var el = $element[0];
      var isBody = el.tagName === 'BODY';

      var elRect = el.getBoundingClientRect();
      if (elRect.width == null) {
        // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
        elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });
      }

      var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() };
      var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null;

      /*
       * Avoid using $.offset() since it gives incorrect results on SVG elements. Directly compute scroll
       * adjusted position like $.offset() and angular-ui-bootstrap's $position.offset() does.
       *
       * See issues: https://github.com/twbs/bootstrap/issues/20280
       *             https://github.com/twbs/bootstrap/issues/20381
       *             https://github.com/twbs/bootstrap/issues/21855
       */
      var elOffset = isBody ? { top: 0, left: 0 } : { top: elRect.top + (window.pageYOffset || document.documentElement.scrollTop),
        left: elRect.left + (window.pageXOffset || document.documentElement.scrollLeft) };

      return $.extend({}, elRect, scroll, outerDims, elOffset);
    }
  };

  $.extend(true, $.fn.tooltip.Constructor.prototype, extension);
  $.extend(true, $.fn.popover.Constructor.prototype, extension);
})(jQuery);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment