From 9b52bfaf0c8aa08028e70cfe4cfb09092697bd66 Mon Sep 17 00:00:00 2001 From: Topher Fangio Date: Wed, 23 Sep 2015 10:44:57 -0500 Subject: [PATCH] fix(tooltip): using tooltip inside subheader causes Firefox hang. When a `` was placed inside the ``, an infinite loop was being hit (only in Firefox) which was causing the browser to hang. The infinite loop was caused by the tooltip's `getParentWithPointerEvents()` method which travels up the DOM looking for a parent who has pointer events. In Firefox, the `element.parent()` can apparently return an empty jqLite object that is not null, but whose length is 0. In this case, calling `parent.parent()` again will return the same object. Add a check to the tooltip's loop to ensure that `parent.length` is never 0. Fixes #4777. Closes #4800. --- src/components/tooltip/tooltip.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/components/tooltip/tooltip.js b/src/components/tooltip/tooltip.js index a5aee16d08c..4eeae383462 100644 --- a/src/components/tooltip/tooltip.js +++ b/src/components/tooltip/tooltip.js @@ -106,9 +106,12 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe */ function getParentWithPointerEvents () { var parent = element.parent(); - while (parent && hasComputedStyleValue('pointer-events','none', parent[0])) { + + // jqLite might return a non-null, but still empty, parent; so check for parent and length + while (hasComputedStyleValue('pointer-events','none', parent)) { parent = parent.parent(); } + return parent; } @@ -123,12 +126,17 @@ function MdTooltipDirective($timeout, $window, $$rAF, $document, $mdUtil, $mdThe function hasComputedStyleValue(key, value, target) { - key = attr.$normalize(key); - target = target || element[0]; + var hasValue = false; - var computedStyles = $window.getComputedStyle(target); + if ( target && target.length ) { + key = attr.$normalize(key); + target = target[0] || element[0]; + + var computedStyles = $window.getComputedStyle(target); + hasValue = angular.isDefined(computedStyles[key]) && (computedStyles[key] == value); + } - return angular.isDefined(computedStyles[key]) && (computedStyles[key] == value); + return hasValue; } function bindEvents () {