-
Notifications
You must be signed in to change notification settings - Fork 3.4k
perf(md-tooltip) use MutationObserver instead of watcher if available #7822
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,19 +92,42 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe | |
content.css('transform-origin', origin); | ||
} | ||
|
||
function onVisibleChanged (isVisible) { | ||
if (isVisible) showTooltip(); | ||
else hideTooltip(); | ||
} | ||
|
||
function configureWatchers () { | ||
scope.$on('$destroy', function() { | ||
scope.visible = false; | ||
element.remove(); | ||
angular.element($window).off('resize', debouncedOnResize); | ||
}); | ||
|
||
scope.$watch('visible', function (isVisible) { | ||
if (isVisible) showTooltip(); | ||
else hideTooltip(); | ||
}); | ||
if (element[0] && 'MutationObserver' in $window) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While $observe is technically faster than $watch since it's a string comparison vs an object/expression evaluation, both are checked synchronously every $digest. MutationObserver is handled by the browser and signaled asynchronously. |
||
var attributeObserver = new MutationObserver(function(mutations) { | ||
mutations | ||
.forEach(function (mutation) { | ||
if (mutation.attributeName === 'md-visible') { | ||
if (!scope.visibleWatcher) | ||
scope.visibleWatcher = scope.$watch('visible', onVisibleChanged ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you end up adding multiple watchers for the same thing here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use the variable 'visibleWatcher' for this reason. If the value is undefined/null, then there is no watcher. If it isn't null, then it means the object already has a watcher and a second shouldn't be created. |
||
} | ||
if (mutation.attributeName === 'md-direction') { | ||
updatePosition(scope.direction); | ||
} | ||
}); | ||
}); | ||
|
||
attributeObserver.observe(element[0], { attributes: true}); | ||
|
||
if (attr.hasOwnProperty('mdVisible')) // build watcher only if mdVisible is being used | ||
scope.visibleWatcher = scope.$watch('visible', onVisibleChanged ); | ||
|
||
scope.$watch('direction', updatePosition ); | ||
} | ||
else { // MutationObserver not supported | ||
scope.visibleWatcher = scope.$watch('visible', onVisibleChanged ); | ||
scope.$watch('direction', updatePosition ); | ||
} | ||
} | ||
|
||
function addAriaLabel () { | ||
|
@@ -194,9 +217,15 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe | |
$timeout(function() { | ||
scope.visible = setVisible.value; | ||
setVisible.queued = false; | ||
if (!scope.visibleWatcher) | ||
onVisibleChanged(scope.visible); | ||
}, scope.delay); | ||
} else { | ||
$mdUtil.nextTick(function() { scope.visible = false; }); | ||
$mdUtil.nextTick(function() { | ||
scope.visible = false; | ||
if (!scope.visibleWatcher) | ||
onVisibleChanged(false); | ||
}); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing braces
(here and elsewhere)