mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Hide click-triggered tooltips when clicking anywhere outside of tooltip
Signed-off-by: Antonio Scandurra <as-cii@github.com>
This commit is contained in:
@@ -16,23 +16,50 @@ describe "TooltipManager", ->
|
|||||||
hover = (element, fn) ->
|
hover = (element, fn) ->
|
||||||
element.dispatchEvent(new CustomEvent('mouseenter', bubbles: false))
|
element.dispatchEvent(new CustomEvent('mouseenter', bubbles: false))
|
||||||
element.dispatchEvent(new CustomEvent('mouseover', bubbles: true))
|
element.dispatchEvent(new CustomEvent('mouseover', bubbles: true))
|
||||||
advanceClock(manager.defaults.delay.show)
|
advanceClock(manager.hoverDefaults.delay.show)
|
||||||
fn()
|
fn()
|
||||||
element.dispatchEvent(new CustomEvent('mouseleave', bubbles: false))
|
element.dispatchEvent(new CustomEvent('mouseleave', bubbles: false))
|
||||||
element.dispatchEvent(new CustomEvent('mouseout', bubbles: true))
|
element.dispatchEvent(new CustomEvent('mouseout', bubbles: true))
|
||||||
advanceClock(manager.defaults.delay.hide)
|
advanceClock(manager.hoverDefaults.delay.hide)
|
||||||
|
|
||||||
describe "::add(target, options)", ->
|
describe "::add(target, options)", ->
|
||||||
it "creates a tooltip when hovering over the target element if no trigger is specified", ->
|
describe "when the trigger is 'hover' (the default)", ->
|
||||||
manager.add element, title: "Title"
|
it "creates a tooltip when hovering over the target element", ->
|
||||||
hover element, ->
|
manager.add element, title: "Title"
|
||||||
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
hover element, ->
|
||||||
|
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
||||||
|
|
||||||
it "creates a tooltip immediately if the trigger type is manual", ->
|
describe "when the trigger is 'manual'", ->
|
||||||
disposable = manager.add element, title: "Title", trigger: "manual"
|
it "creates a tooltip immediately and only hides it on dispose", ->
|
||||||
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
disposable = manager.add element, title: "Title", trigger: "manual"
|
||||||
disposable.dispose()
|
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
|
||||||
expect(document.body.querySelector(".tooltip")).toBeNull()
|
disposable.dispose()
|
||||||
|
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||||
|
|
||||||
|
describe "when the trigger is 'click'", ->
|
||||||
|
it "shows and hides the tooltip when the target element is clicked", ->
|
||||||
|
disposable = manager.add element, title: "Title", trigger: "click"
|
||||||
|
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||||
|
element.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).not.toBeNull()
|
||||||
|
element.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||||
|
|
||||||
|
# Hide the tooltip when clicking anywhere but inside the tooltip element
|
||||||
|
element.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).not.toBeNull()
|
||||||
|
document.body.querySelector(".tooltip").click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).not.toBeNull()
|
||||||
|
document.body.querySelector(".tooltip").firstChild.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).not.toBeNull()
|
||||||
|
document.body.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||||
|
|
||||||
|
# Tooltip can show again after hiding due to clicking outside of the tooltip
|
||||||
|
element.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).not.toBeNull()
|
||||||
|
element.click()
|
||||||
|
expect(document.body.querySelector(".tooltip")).toBeNull()
|
||||||
|
|
||||||
it "allows a custom item to be specified for the content of the tooltip", ->
|
it "allows a custom item to be specified for the content of the tooltip", ->
|
||||||
tooltipElement = document.createElement('div')
|
tooltipElement = document.createElement('div')
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ class AtomEnvironment extends Model
|
|||||||
|
|
||||||
@keymaps = new KeymapManager({@configDirPath, resourcePath, notificationManager: @notifications})
|
@keymaps = new KeymapManager({@configDirPath, resourcePath, notificationManager: @notifications})
|
||||||
|
|
||||||
@tooltips = new TooltipManager(keymapManager: @keymaps)
|
@tooltips = new TooltipManager(keymapManager: @keymaps, viewRegistry: @views)
|
||||||
|
|
||||||
@commands = new CommandRegistry
|
@commands = new CommandRegistry
|
||||||
@commands.attach(@window)
|
@commands.attach(@window)
|
||||||
|
|||||||
@@ -46,14 +46,15 @@ Tooltip = null
|
|||||||
module.exports =
|
module.exports =
|
||||||
class TooltipManager
|
class TooltipManager
|
||||||
defaults:
|
defaults:
|
||||||
delay:
|
trigger: 'hover'
|
||||||
show: 1000
|
|
||||||
hide: 100
|
|
||||||
container: 'body'
|
container: 'body'
|
||||||
html: true
|
html: true
|
||||||
placement: 'auto top'
|
placement: 'auto top'
|
||||||
viewportPadding: 2
|
viewportPadding: 2
|
||||||
|
|
||||||
|
hoverDefaults:
|
||||||
|
{delay: {show: 1000, hide: 100}}
|
||||||
|
|
||||||
constructor: ({@keymapManager, @viewRegistry}) ->
|
constructor: ({@keymapManager, @viewRegistry}) ->
|
||||||
|
|
||||||
# Essential: Add a tooltip to the given element.
|
# Essential: Add a tooltip to the given element.
|
||||||
@@ -92,7 +93,11 @@ class TooltipManager
|
|||||||
else if keystroke?
|
else if keystroke?
|
||||||
options.title = getKeystroke(bindings)
|
options.title = getKeystroke(bindings)
|
||||||
|
|
||||||
tooltip = new Tooltip(target, _.defaults(options, @defaults), @viewRegistry)
|
options = _.defaults(options, @defaults)
|
||||||
|
if options.trigger is 'hover'
|
||||||
|
options = _.defaults(options, @hoverDefaults)
|
||||||
|
|
||||||
|
tooltip = new Tooltip(target, options, @viewRegistry)
|
||||||
|
|
||||||
hideTooltip = ->
|
hideTooltip = ->
|
||||||
tooltip.leave(currentTarget: target)
|
tooltip.leave(currentTarget: target)
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ Tooltip.prototype.init = function (element, options) {
|
|||||||
|
|
||||||
if (trigger === 'click') {
|
if (trigger === 'click') {
|
||||||
this.disposables.add(listen(this.element, 'click', this.options.selector, this.toggle.bind(this)))
|
this.disposables.add(listen(this.element, 'click', this.options.selector, this.toggle.bind(this)))
|
||||||
|
this.hideOnClickOutsideOfTooltip = (event) => {
|
||||||
|
const tooltipElement = this.getTooltipElement()
|
||||||
|
if (tooltipElement === event.target) return
|
||||||
|
if (tooltipElement.contains(event.target)) return
|
||||||
|
if (this.element === event.target) return
|
||||||
|
if (this.element.contains(event.target)) return
|
||||||
|
this.hide()
|
||||||
|
}
|
||||||
} else if (trigger === 'manual') {
|
} else if (trigger === 'manual') {
|
||||||
this.show()
|
this.show()
|
||||||
} else {
|
} else {
|
||||||
@@ -183,8 +191,11 @@ Tooltip.prototype.leave = function (event) {
|
|||||||
|
|
||||||
Tooltip.prototype.show = function () {
|
Tooltip.prototype.show = function () {
|
||||||
if (this.hasContent() && this.enabled) {
|
if (this.hasContent() && this.enabled) {
|
||||||
var tip = this.getTooltipElement()
|
if (this.hideOnClickOutsideOfTooltip) {
|
||||||
|
window.addEventListener('click', this.hideOnClickOutsideOfTooltip, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tip = this.getTooltipElement()
|
||||||
var tipId = this.getUID('tooltip')
|
var tipId = this.getUID('tooltip')
|
||||||
|
|
||||||
this.setContent()
|
this.setContent()
|
||||||
@@ -316,6 +327,12 @@ Tooltip.prototype.setContent = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tooltip.prototype.hide = function (callback) {
|
Tooltip.prototype.hide = function (callback) {
|
||||||
|
this.inState = {}
|
||||||
|
|
||||||
|
if (this.hideOnClickOutsideOfTooltip) {
|
||||||
|
window.removeEventListener('click', this.hideOnClickOutsideOfTooltip, true)
|
||||||
|
}
|
||||||
|
|
||||||
this.tip && this.tip.classList.remove('in')
|
this.tip && this.tip.classList.remove('in')
|
||||||
|
|
||||||
if (this.hoverState !== 'in') this.tip && this.tip.remove()
|
if (this.hoverState !== 'in') this.tip && this.tip.remove()
|
||||||
@@ -445,7 +462,7 @@ Tooltip.prototype.destroy = function () {
|
|||||||
Tooltip.prototype.getDelegateComponent = function (element) {
|
Tooltip.prototype.getDelegateComponent = function (element) {
|
||||||
var component = tooltipComponentsByElement.get(element)
|
var component = tooltipComponentsByElement.get(element)
|
||||||
if (!component) {
|
if (!component) {
|
||||||
component = new Tooltip(element, this.getDelegateOptions())
|
component = new Tooltip(element, this.getDelegateOptions(), this.viewRegistry)
|
||||||
tooltipComponentsByElement.set(element, component)
|
tooltipComponentsByElement.set(element, component)
|
||||||
}
|
}
|
||||||
return component
|
return component
|
||||||
|
|||||||
Reference in New Issue
Block a user