From aa90dd835f67faccc88b7945f4402a4709e42347 Mon Sep 17 00:00:00 2001 From: Darrin Holst Date: Mon, 9 May 2016 09:10:32 -0500 Subject: [PATCH 1/2] fix(positioning): wait for animation to complete When calculating the dropdown position the height of the dropdown needs to be known. When using ngAnimate the animation has not finished by the time the height calculation is needed. This fix extracts the positioning calculation out to a function that is called after animation is done (or immediately when animation is not in use). Fixes #1593. --- src/uiSelectDirective.js | 86 +++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/src/uiSelectDirective.js b/src/uiSelectDirective.js index 3032d8168..88a602a62 100644 --- a/src/uiSelectDirective.js +++ b/src/uiSelectDirective.js @@ -323,10 +323,41 @@ uis.directive('uiSelect', }; - scope.calculateDropdownPos = function(){ + var calculateDropdownPosAfterAnimation = function() { + // Delay positioning the dropdown until all choices have been added so its height is correct. + $timeout(function() { + if ($select.dropdownPosition === 'up') { + //Go UP + setDropdownPosUp(); + } else { + //AUTO + element.removeClass(directionUpClassName); + + var offset = uisOffset(element); + var offsetDropdown = uisOffset(dropdown); + + //https://code.google.com/p/chromium/issues/detail?id=342307#c4 + var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox). + + // Determine if the direction of the dropdown needs to be changed. + if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) { + //Go UP + setDropdownPosUp(offset, offsetDropdown); + }else{ + //Go DOWN + setDropdownPosDown(offset, offsetDropdown); + } + } + // Display the dropdown once it has been positioned. + dropdown[0].style.opacity = 1; + }); + }; + + scope.calculateDropdownPos = function() { if ($select.open) { dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown'); + if (dropdown.length === 0) { return; } @@ -334,46 +365,27 @@ uis.directive('uiSelect', // Hide the dropdown so there is no flicker until $timeout is done executing. dropdown[0].style.opacity = 0; - // Delay positioning the dropdown until all choices have been added so its height is correct. - $timeout(function(){ - - if ($select.dropdownPosition === 'up'){ - //Go UP - setDropdownPosUp(); - - }else{ //AUTO + if (!uisOffset(dropdown).height && $select.$animate && $select.$animate.on && $select.$animate.enabled(dropdown)) { + var needsCalculated = true; - element.removeClass(directionUpClassName); - - var offset = uisOffset(element); - var offsetDropdown = uisOffset(dropdown); - - //https://code.google.com/p/chromium/issues/detail?id=342307#c4 - var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox). - - // Determine if the direction of the dropdown needs to be changed. - if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) { - //Go UP - setDropdownPosUp(offset, offsetDropdown); - }else{ - //Go DOWN - setDropdownPosDown(offset, offsetDropdown); + $select.$animate.on('enter', dropdown, function (elem, phase) { + if (phase === 'close' && needsCalculated) { + calculateDropdownPosAfterAnimation(); + needsCalculated = false; } - - } - - // Display the dropdown once it has been positioned. - dropdown[0].style.opacity = 1; - }); + }); + } else { + calculateDropdownPosAfterAnimation(); + } } else { - if (dropdown === null || dropdown.length === 0) { - return; - } + if (dropdown === null || dropdown.length === 0) { + return; + } - // Reset the position of the dropdown. - dropdown[0].style.position = ''; - dropdown[0].style.top = ''; - element.removeClass(directionUpClassName); + // Reset the position of the dropdown. + dropdown[0].style.position = ''; + dropdown[0].style.top = ''; + element.removeClass(directionUpClassName); } }; }; From ca4d09e8e1e591cb337c62180ae7ee912f96d6da Mon Sep 17 00:00:00 2001 From: Darrin Holst Date: Mon, 16 May 2016 13:07:43 -0500 Subject: [PATCH 2/2] fix(positioning): stop flicker when closed When the dropdown is in an up position and it is closed we were removing the positioning before hiding it which caused a flicker while it moved down to it's natural bottom position. This change sets the opacity to 0 before resetting the positioning style attributes. --- src/uiSelectDirective.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uiSelectDirective.js b/src/uiSelectDirective.js index 88a602a62..781c1d193 100644 --- a/src/uiSelectDirective.js +++ b/src/uiSelectDirective.js @@ -383,6 +383,7 @@ uis.directive('uiSelect', } // Reset the position of the dropdown. + dropdown[0].style.opacity = 0; dropdown[0].style.position = ''; dropdown[0].style.top = ''; element.removeClass(directionUpClassName);