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

Commit

Permalink
feat(tooltip): hide tooltip when esc is hit
Browse files Browse the repository at this point in the history
- Hide tooltip when `esc` is hit for accessibility

Closes #4367
Resolves #4248
  • Loading branch information
wesleycho committed Sep 10, 2015
1 parent f269983 commit c08509a
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 61 deletions.
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 @@ -166,6 +178,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 @@ -413,6 +428,12 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position'])
element[0].addEventListener(trigger, hideTooltipBind);
});
}

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

0 comments on commit c08509a

Please sign in to comment.