Skip to content

Commit

Permalink
Merge pull request atom#13095 from atom/fb-vj-follow-through
Browse files Browse the repository at this point in the history
Introduce follow through behavior for tooltips
  • Loading branch information
Nathan Sobo authored Nov 2, 2016
2 parents f293b80 + 00b6122 commit 4ce0f5c
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"one-light-syntax": "1.6.0",
"solarized-dark-syntax": "1.1.1",
"solarized-light-syntax": "1.1.1",
"about": "1.7.0",
"about": "1.7.1",
"archive-view": "0.62.0",
"autocomplete-atom-api": "0.10.0",
"autocomplete-css": "0.14.1",
Expand Down
52 changes: 45 additions & 7 deletions spec/tooltip-manager-spec.coffee
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{CompositeDisposable} = require 'atom'
TooltipManager = require '../src/tooltip-manager'
Tooltip = require '../src/tooltip'
_ = require 'underscore-plus'

describe "TooltipManager", ->
Expand All @@ -9,17 +11,27 @@ describe "TooltipManager", ->

beforeEach ->
manager = new TooltipManager(keymapManager: atom.keymaps, viewRegistry: atom.views)
element = document.createElement('div')
element.classList.add('foo')
jasmine.attachToDOM(element)
element = createElement 'foo'

hover = (element, fn) ->
createElement = (className) ->
el = document.createElement('div')
el.classList.add(className)
jasmine.attachToDOM(el)
el

mouseEnter = (element) ->
element.dispatchEvent(new CustomEvent('mouseenter', bubbles: false))
element.dispatchEvent(new CustomEvent('mouseover', bubbles: true))
advanceClock(manager.hoverDefaults.delay.show)
fn()

mouseLeave = (element) ->
element.dispatchEvent(new CustomEvent('mouseleave', bubbles: false))
element.dispatchEvent(new CustomEvent('mouseout', bubbles: true))

hover = (element, fn) ->
mouseEnter(element)
advanceClock(manager.hoverDefaults.delay.show)
fn()
mouseLeave(element)
advanceClock(manager.hoverDefaults.delay.hide)

describe "::add(target, options)", ->
Expand All @@ -29,6 +41,32 @@ describe "TooltipManager", ->
hover element, ->
expect(document.body.querySelector(".tooltip")).toHaveText("Title")

it "displays tooltips immediately when hovering over new elements once a tooltip has been displayed once", ->
disposables = new CompositeDisposable
element1 = createElement('foo')
disposables.add(manager.add element1, title: 'Title')
element2 = createElement('bar')
disposables.add(manager.add element2, title: 'Title')
element3 = createElement('baz')
disposables.add(manager.add element3, title: 'Title')

hover element1, ->
expect(document.body.querySelector(".tooltip")).toBeNull()

mouseEnter(element2)
expect(document.body.querySelector(".tooltip")).not.toBeNull()
mouseLeave(element2)
advanceClock(manager.hoverDefaults.delay.hide)
expect(document.body.querySelector(".tooltip")).toBeNull()

advanceClock(Tooltip.FOLLOW_THROUGH_DURATION)
mouseEnter(element3)
expect(document.body.querySelector(".tooltip")).toBeNull()
advanceClock(manager.hoverDefaults.delay.show)
expect(document.body.querySelector(".tooltip")).not.toBeNull()

disposables.dispose()

describe "when the trigger is 'manual'", ->
it "creates a tooltip immediately and only hides it on dispose", ->
disposable = manager.add element, title: "Title", trigger: "manual"
Expand Down Expand Up @@ -149,6 +187,6 @@ describe "TooltipManager", ->
it "hides the tooltips", ->
manager.add element, title: "Title"
hover element, ->
expect(document.body.querySelector(".tooltip")).toBeDefined()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
window.dispatchEvent(new CustomEvent('resize'))
expect(document.body.querySelector(".tooltip")).toBeNull()
18 changes: 16 additions & 2 deletions src/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const listen = require('./delegated-listener')
// This tooltip class is derived from Bootstrap 3, but modified to not require
// jQuery, which is an expensive dependency we want to eliminate.

var followThroughTimer = null

var Tooltip = function (element, options, viewRegistry) {
this.options = null
this.enabled = null
Expand All @@ -21,7 +23,7 @@ var Tooltip = function (element, options, viewRegistry) {

Tooltip.VERSION = '3.3.5'

Tooltip.TRANSITION_DURATION = 150
Tooltip.FOLLOW_THROUGH_DURATION = 300

Tooltip.DEFAULTS = {
animation: true,
Expand Down Expand Up @@ -151,7 +153,11 @@ Tooltip.prototype.enter = function (event) {

this.hoverState = 'in'

if (!this.options.delay || !this.options.delay.show) return this.show()
if (!this.options.delay ||
!this.options.delay.show ||
followThroughTimer) {
return this.show()
}

this.timeout = setTimeout(function () {
if (this.hoverState === 'in') this.show()
Expand Down Expand Up @@ -343,6 +349,14 @@ Tooltip.prototype.hide = function (callback) {

this.hoverState = null

clearTimeout(followThroughTimer)
followThroughTimer = setTimeout(
function () {
followThroughTimer = null
},
Tooltip.FOLLOW_THROUGH_DURATION
)

return this
}

Expand Down

0 comments on commit 4ce0f5c

Please sign in to comment.