Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 7920dba

Browse files
SanderEliasThomasBurleson
authored andcommitted
fix(tooltip): tooltip sometimes not hidden after element is disabled.
use an mutationobserver to make sure the tooltip is hidden after an element becomes disabled. fixes: #2602. closes #5912.
1 parent d14e2c5 commit 7920dba

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/components/tooltip/tooltip.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,23 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe
122122

123123
var ngWindow = angular.element($window);
124124

125+
// add an mutationObserver when there is support for it
126+
// and the need for it in the form of viable host(parent[0])
127+
if (parent[0] && 'MutationObserver' in $window) {
128+
// use an mutationObserver to tackle #2602
129+
var attributeObserver = new MutationObserver(function(mutations) {
130+
mutations
131+
.forEach(function (mutation) {
132+
if (mutation.attributeName === 'disabled' && parent[0].disabled) {
133+
setVisible(false);
134+
scope.$digest(); // make sure the elements gets updated
135+
}
136+
});
137+
});
138+
139+
attributeObserver.observe(parent[0], { attributes: true});
140+
};
141+
125142
// Store whether the element was focused when the window loses focus.
126143
var windowBlurHandler = function() {
127144
elementFocusedOnWindowBlur = document.activeElement === parent[0];
@@ -133,6 +150,7 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe
133150
scope.$on('$destroy', function() {
134151
ngWindow.off('blur', windowBlurHandler);
135152
ngWindow.off('resize', debouncedOnResize);
153+
attributeObserver && attributeObserver.disconnect();
136154
});
137155

138156
var enterHandler = function(e) {

src/components/tooltip/tooltip.spec.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,63 @@ describe('<md-tooltip> directive', function() {
224224
triggerEvent('focus');
225225
expect($rootScope.testModel.isVisible).toBe(false);
226226
}));
227+
228+
ddescribe('<md-tooltip> attributeObserver', function() {
229+
if (window.MutationObserver === undefined) {
230+
// PhantomJS doesn't support mo
231+
it(' does not work without support for mutationObservers', function () {
232+
expect(true).toBe(true);
233+
})
234+
return ;
235+
}
236+
var obs
237+
beforeEach(function (mutationDone){
238+
obs = new MutationObserver(function(mutations) {
239+
mutations
240+
.forEach(function (mutation) {
241+
if (mutation.attributeName === 'disabled' && mutation.target.disabled) {
242+
// allow a little time for the observer on the tooltip to finish
243+
setTimeout(function() {
244+
$timeout.flush();
245+
$material.flushOutstandingAnimations();
246+
mutationDone();
247+
},50);
248+
}
249+
})
250+
});
251+
252+
var el = buildTooltip(
253+
'<md-button>' +
254+
'Hello' +
255+
'<md-tooltip md-visible="testModel.isVisible">' +
256+
'Tooltip' +
257+
'</md-tooltip>' +
258+
'</md-button>'
259+
);
260+
261+
showTooltip(true);
262+
// check if the testsetup is ok
263+
expect($rootScope.testModel.isVisible).toBe(true)
264+
expect(findTooltip().length).toBe(1);
265+
// attach the observer
266+
obs.observe(el[0], { attributes: true});
267+
// trigger the mutationObserver(s).
268+
el.attr('disabled',true)
269+
})
270+
271+
afterEach(function () {
272+
// remove observer from dom.
273+
obs.disconnect();
274+
obs = null;
275+
})
276+
277+
it('should be hidden after element gets disabled', function() {
278+
expect($rootScope.testModel.isVisible).toBe(false)
279+
expect(findTooltip().length).toBe(0);
280+
})
281+
});
282+
283+
227284
});
228285

229286
// ******************************************************

0 commit comments

Comments
 (0)