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

feat(tooltip): hide tooltip when esc is hit #4367

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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
57 changes: 1 addition & 56 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,4 @@
angular.module('ui.bootstrap.modal', [])

/**
* A helper, internal data structure that acts as a map but also allows getting / removing
* elements in the LIFO order
*/
.factory('$$stackedMap', function() {
return {
createNew: function() {
var stack = [];

return {
add: function(key, value) {
stack.push({
key: key,
value: value
});
},
get: function(key) {
for (var i = 0; i < stack.length; i++) {
if (key == stack[i].key) {
return stack[i];
}
}
},
keys: function() {
var keys = [];
for (var i = 0; i < stack.length; i++) {
keys.push(stack[i].key);
}
return keys;
},
top: function() {
return stack[stack.length - 1];
},
remove: function(key) {
var idx = -1;
for (var i = 0; i < stack.length; i++) {
if (key == stack[i].key) {
idx = i;
break;
}
}
return stack.splice(idx, 1)[0];
},
removeTop: function() {
return stack.splice(stack.length - 1, 1)[0];
},
length: function() {
return stack.length;
}
};
}
};
})

angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
/**
* A helper, internal data structure that stores all references attached to key
*/
Expand Down
54 changes: 54 additions & 0 deletions src/stackedMap/stackedMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
angular.module('ui.bootstrap.stackedMap', [])
/**
* A helper, internal data structure that acts as a map but also allows getting / removing
* elements in the LIFO order
*/
.factory('$$stackedMap', function() {
return {
createNew: function() {
var stack = [];

return {
add: function(key, value) {
stack.push({
key: key,
value: value
});
},
get: function(key) {
for (var i = 0; i < stack.length; i++) {
if (key == stack[i].key) {
return stack[i];
}
}
},
keys: function() {
var keys = [];
for (var i = 0; i < stack.length; i++) {
keys.push(stack[i].key);
}
return keys;
},
top: function() {
return stack[stack.length - 1];
},
remove: function(key) {
var idx = -1;
for (var i = 0; i < stack.length; i++) {
if (key == stack[i].key) {
idx = i;
break;
}
}
return stack.splice(idx, 1)[0];
},
removeTop: function() {
return stack.splice(stack.length - 1, 1)[0];
},
length: function() {
return stack.length;
}
};
}
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ describe('stacked map', function() {
it('should ignore removal of non-existing elements', function() {
expect(stackedMap.remove('non-existing')).toBeUndefined();
});
});
});
41 changes: 39 additions & 2 deletions src/tooltip/test/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ describe('tooltip', function() {
elmBody,
scope,
elmScope,
tooltipScope;
tooltipScope,
$document;

// load the tooltip code
beforeEach(module('ui.bootstrap.tooltip'));

// load the template
beforeEach(module('template/tooltip/tooltip-popup.html'));

beforeEach(inject(function($rootScope, $compile) {
beforeEach(inject(function($rootScope, $compile, _$document_) {
elmBody = angular.element(
'<div><span tooltip="tooltip text" tooltip-animation="false">Selector Text</span></div>'
);

$document = _$document_;
scope = $rootScope;
$compile(elmBody)(scope);
scope.$digest();
Expand Down Expand Up @@ -319,6 +321,41 @@ describe('tooltip', function() {

expect(tooltipScope.isOpen).toBe(true);
});

it('should close the tooltips in order', inject(function($compile) {
var elm2 = $compile('<div><span tooltip="tooltip #2" tooltip-is-open="isOpen2">Selector Text</span></div>')(scope);
scope.$digest();
elm2 = elm2.find('span');
var tooltipScope2 = elm2.scope().$$childTail;
tooltipScope2.isOpen = false;
scope.$digest();

trigger(elm, 'mouseenter');
$timeout.flush();
expect(tooltipScope.isOpen).toBe(true);
expect(tooltipScope2.isOpen).toBe(false);

trigger(elm2, 'mouseenter');
$timeout.flush();
expect(tooltipScope.isOpen).toBe(true);
expect(tooltipScope2.isOpen).toBe(true);

var evt = $.Event('keypress');
evt.which = 27;

$document.trigger(evt);

expect(tooltipScope.isOpen).toBe(true);
expect(tooltipScope2.isOpen).toBe(false);

var evt2 = $.Event('keypress');
evt2.which = 27;

$document.trigger(evt2);

expect(tooltipScope.isOpen).toBe(false);
expect(tooltipScope2.isOpen).toBe(false);
}));
});

describe('with an is-open attribute', function() {
Expand Down
25 changes: 23 additions & 2 deletions src/tooltip/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* function, placement as a function, inside, support for more triggers than
* just mouse enter/leave, html tooltips, and selector delegation.
*/
angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position'])
angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])

/**
* The $tooltip service creates tooltip- and popover-like directives as well as
Expand Down Expand Up @@ -66,7 +66,19 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position'])
* Returns the actual instance of the $tooltip service.
* TODO support multiple triggers
*/
this.$get = ['$window', '$compile', '$timeout', '$document', '$position', '$interpolate', '$rootScope', '$parse', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse) {
this.$get = ['$window', '$compile', '$timeout', '$document', '$position', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {
var openedTooltips = $$stackedMap.createNew();
$document.on('keypress', function(e) {
if (e.which === 27) {
var last = openedTooltips.top();
if (last) {
last.value.close();
openedTooltips.removeTop();
last = null;
}
}
});

return function $tooltip(type, prefix, defaultTriggerShow, options) {
options = angular.extend({}, defaultOptions, globalOptions, options);

Expand Down Expand Up @@ -164,6 +176,9 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position'])
// By default, the tooltip is not open.
// TODO add ability to start tooltip opened
ttScope.isOpen = false;
openedTooltips.add(ttScope, {
close: hideTooltipBind
});

function toggleTooltipBind() {
if (!ttScope.isOpen) {
Expand Down Expand Up @@ -406,6 +421,12 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position'])
element[0].addEventListener(trigger, showTooltipBind);
element[0].addEventListener(triggers.hide[idx], hideTooltipBind);
}

element.on('keypress', function(e) {
if (e.which === 27) {
hideTooltipBind();
}
});
});
}
}
Expand Down