Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

hide tooltips and popovers when a user clicks away (corrected) #4871

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/tooltip/docs/readme.md
Original file line number Diff line number Diff line change
@@ -41,9 +41,12 @@ provided hide triggers:

- `mouseenter`: `mouseleave`
- `click`: `click`
- `outsideClick`: `outsideClick`
- `focus`: `blur`
- `none`: ``

The `outsideClick` trigger will cause the tooltip to toggle on click, and hide when anything else is clicked.

For any non-supported value, the trigger will be used to both show and hide the
tooltip. Using the 'none' trigger will disable the internal trigger(s), one can
then use the `tooltip-is-open` attribute exclusively to show and hide the tooltip.
25 changes: 25 additions & 0 deletions src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
@@ -573,6 +573,31 @@ describe('tooltip', function() {
elm.trigger('mouseenter');
expect(tooltipScope.isOpen).toBeFalsy();
}));

it('should toggle on click and hide when anything else is clicked when trigger is set to "outsideClick"', inject(function($compile, $document) {
elm = $compile(angular.element(
'<span uib-tooltip="tooltip text" tooltip-trigger="outsideClick">Selector Text</span>'
))(scope);
scope.$apply();
elmScope = elm.scope();
tooltipScope = elmScope.$$childTail;

// start off
expect(tooltipScope.isOpen).toBeFalsy();

// toggle
trigger(elm, 'click');
expect(tooltipScope.isOpen).toBeTruthy();
trigger(elm, 'click');
expect(tooltipScope.isOpen).toBeFalsy();

// click on, outsideClick off
trigger(elm, 'click');
expect(tooltipScope.isOpen).toBeTruthy();
angular.element($document[0].body).trigger('click');
tooltipScope.$digest();
expect(tooltipScope.isOpen).toBeFalsy();
}));
});

describe('with an append-to-body attribute', function() {
35 changes: 32 additions & 3 deletions src/tooltip/tooltip.js
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
var triggerMap = {
'mouseenter': 'mouseleave',
'click': 'click',
'outsideClick': 'outsideClick',
'focus': 'blur',
'none': ''
};
@@ -422,13 +423,37 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
}
}

// hide tooltips/popovers for outsideClick trigger
function bodyHideTooltipBind(e) {
if (ttScope === null || !ttScope.isOpen || tooltip === null) {
return;
}
// make sure the tooltip/popover link or tool tooltip/popover itself were not clicked
if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {
hideTooltipBind();
}
}

var unregisterTriggers = function() {
triggers.show.forEach(function(trigger) {
element.unbind(trigger, showTooltipBind);
if (trigger === 'outsideClick') {
element[0].removeEventListener('click', toggleTooltipBind);
}
else
{
element[0].removeEventListener(trigger, showTooltipBind);
element[0].removeEventListener(trigger, toggleTooltipBind);
}
});
triggers.hide.forEach(function(trigger) {
trigger.split(' ').forEach(function(hideTrigger) {
element[0].removeEventListener(hideTrigger, hideTooltipBind);
if (trigger === 'outsideClick') {
$document[0].body.removeEventListener('click', bodyHideTooltipBind);
}
else
{
element[0].removeEventListener(hideTrigger, hideTooltipBind);
}
});
});
};
@@ -442,7 +467,11 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
if (triggers.show !== 'none') {
triggers.show.forEach(function(trigger, idx) {
// Using raw addEventListener due to jqLite/jQuery bug - #4060
if (trigger === triggers.hide[idx]) {
if (trigger === 'outsideClick') {
element[0].addEventListener('click', toggleTooltipBind);
$document[0].body.addEventListener('click', bodyHideTooltipBind);
}
else if (trigger === triggers.hide[idx]) {
element[0].addEventListener(trigger, toggleTooltipBind);
} else if (trigger) {
element[0].addEventListener(trigger, showTooltipBind);