From d56c1e292eee96d77c34a05617c79398949e86d3 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 26 Apr 2017 15:48:22 -0700 Subject: [PATCH 1/4] Add Tooltip#recalculatePosition which resets the tooltip's position --- src/tooltip.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/tooltip.js b/src/tooltip.js index 2573b1fb9..7c1b3950e 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -482,6 +482,40 @@ Tooltip.prototype.getDelegateComponent = function (element) { return component } +Tooltip.prototype.recalculatePosition = function() { + var tip = this.getTooltipElement(); + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, tip, this.element) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + tip.classList.add(placement) + + var pos = this.element.getBoundingClientRect() + var actualWidth = tip.offsetWidth + var actualHeight = tip.offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.viewport.getBoundingClientRect() + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + tip.classList.remove(orgPlacement) + tip.classList.add(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + this.applyPlacement(calculatedOffset, placement) +} + function extend () { var args = Array.prototype.slice.apply(arguments) var target = args.shift() From dc6988c94517b5b7f54b979ad6fa3f8440a67986 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 26 Apr 2017 15:49:01 -0700 Subject: [PATCH 2/4] Reposition Tooltips when they mutate --- src/tooltip.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/tooltip.js b/src/tooltip.js index 7c1b3950e..6c911cd68 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -46,6 +46,7 @@ Tooltip.prototype.init = function (element, options) { this.element = element this.options = this.getOptions(options) this.disposables = new EventKit.CompositeDisposable() + this.mutationObserver = new MutationObserver(this.handleMutations.bind(this)); if (this.options.viewport) { if (typeof this.options.viewport === 'function') { @@ -103,6 +104,24 @@ Tooltip.prototype.init = function (element, options) { : this.fixTitle() } +Tooltip.prototype.startObservingMutations = function() { + this.mutationObserver.observe(this.getTooltipElement(), { + attributes: true, childList: true, characterData: true, subtree: true + }) +} + +Tooltip.prototype.stopObservingMutations = function() { + this.mutationObserver.disconnect(); +} + +Tooltip.prototype.handleMutations = function(mutations) { + this.stopObservingMutations(); + requestAnimationFrame(function() { + this.recalculatePosition(); + this.startObservingMutations(); + }.bind(this)) +} + Tooltip.prototype.getDefaults = function () { return Tooltip.DEFAULTS } @@ -202,6 +221,7 @@ Tooltip.prototype.show = function () { } var tip = this.getTooltipElement() + this.startObservingMutations(); var tipId = this.getUID('tooltip') this.setContent() @@ -340,6 +360,7 @@ Tooltip.prototype.hide = function (callback) { } this.tip && this.tip.classList.remove('in') + this.stopObservingMutations(); if (this.hoverState !== 'in') this.tip && this.tip.remove() From ca9054a4f811f1371307c108a89839f6df2f0805 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 26 Apr 2017 16:01:43 -0700 Subject: [PATCH 3/4] :shirt: Fix linting errors --- src/tooltip.js | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/tooltip.js b/src/tooltip.js index 6c911cd68..eb547c286 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -1,3 +1,5 @@ +/* global MutationObserver */ + 'use strict' const EventKit = require('event-kit') @@ -46,7 +48,7 @@ Tooltip.prototype.init = function (element, options) { this.element = element this.options = this.getOptions(options) this.disposables = new EventKit.CompositeDisposable() - this.mutationObserver = new MutationObserver(this.handleMutations.bind(this)); + this.mutationObserver = new MutationObserver(this.handleMutations.bind(this)) if (this.options.viewport) { if (typeof this.options.viewport === 'function') { @@ -104,21 +106,21 @@ Tooltip.prototype.init = function (element, options) { : this.fixTitle() } -Tooltip.prototype.startObservingMutations = function() { +Tooltip.prototype.startObservingMutations = function () { this.mutationObserver.observe(this.getTooltipElement(), { attributes: true, childList: true, characterData: true, subtree: true }) } -Tooltip.prototype.stopObservingMutations = function() { - this.mutationObserver.disconnect(); +Tooltip.prototype.stopObservingMutations = function () { + this.mutationObserver.disconnect() } -Tooltip.prototype.handleMutations = function(mutations) { - this.stopObservingMutations(); - requestAnimationFrame(function() { - this.recalculatePosition(); - this.startObservingMutations(); +Tooltip.prototype.handleMutations = function (mutations) { + this.stopObservingMutations() + window.requestAnimationFrame(function () { + this.recalculatePosition() + this.startObservingMutations() }.bind(this)) } @@ -221,7 +223,7 @@ Tooltip.prototype.show = function () { } var tip = this.getTooltipElement() - this.startObservingMutations(); + this.startObservingMutations() var tipId = this.getUID('tooltip') this.setContent() @@ -360,7 +362,7 @@ Tooltip.prototype.hide = function (callback) { } this.tip && this.tip.classList.remove('in') - this.stopObservingMutations(); + this.stopObservingMutations() if (this.hoverState !== 'in') this.tip && this.tip.remove() @@ -503,11 +505,12 @@ Tooltip.prototype.getDelegateComponent = function (element) { return component } -Tooltip.prototype.recalculatePosition = function() { - var tip = this.getTooltipElement(); - var placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, tip, this.element) : - this.options.placement +Tooltip.prototype.recalculatePosition = function () { + var tip = this.getTooltipElement() + + var placement = typeof this.options.placement === 'function' + ? this.options.placement.call(this, tip, this.element) + : this.options.placement var autoToken = /\s?auto?\s?/i var autoPlace = autoToken.test(placement) @@ -515,19 +518,19 @@ Tooltip.prototype.recalculatePosition = function() { tip.classList.add(placement) - var pos = this.element.getBoundingClientRect() - var actualWidth = tip.offsetWidth + var pos = this.element.getBoundingClientRect() + var actualWidth = tip.offsetWidth var actualHeight = tip.offsetHeight if (autoPlace) { var orgPlacement = placement var viewportDim = this.viewport.getBoundingClientRect() - placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : - placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : - placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : - placement + placement = placement === 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' + : placement === 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' + : placement === 'right' && pos.right + actualWidth > viewportDim.width ? 'left' + : placement === 'left' && pos.left - actualWidth < viewportDim.left ? 'right' + : placement tip.classList.remove(orgPlacement) tip.classList.add(placement) From 63920c2a78a4ea7c22e595ab65fdccc6a3c38f5d Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Wed, 26 Apr 2017 19:27:23 -0700 Subject: [PATCH 4/4] :art: --- src/tooltip.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tooltip.js b/src/tooltip.js index eb547c286..0cd1d86e1 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -116,9 +116,9 @@ Tooltip.prototype.stopObservingMutations = function () { this.mutationObserver.disconnect() } -Tooltip.prototype.handleMutations = function (mutations) { - this.stopObservingMutations() +Tooltip.prototype.handleMutations = function () { window.requestAnimationFrame(function () { + this.stopObservingMutations() this.recalculatePosition() this.startObservingMutations() }.bind(this))