From b8e92d78183d38ab67a6d63abedf8da2e157d706 Mon Sep 17 00:00:00 2001 From: Topher Fangio Date: Wed, 16 Dec 2015 16:55:02 -0600 Subject: [PATCH] fix(select): Position incorrect if selection scrolled. If the currently selected object scrolled into view because it was further down in the list, the position of the menu was incorrect upon opening because the `scrollTop` of the `contentNode` was always `0` due to the ARIA changes which set it to `display: none` upon closing. Fix by modifying the display to `block` when we run the `isScrollable` check and back afterward (usually `display: none` but we account for other options). Also fixes a slight `2px` positioning issue which made the menu not perfectly line up with the underlying selection. Fixes #6190. --- src/components/select/select.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/components/select/select.js b/src/components/select/select.js index c6c2a5e6912..6116120c17e 100755 --- a/src/components/select/select.js +++ b/src/components/select/select.js @@ -1276,7 +1276,7 @@ function SelectProvider($$interimElementProvider) { * Calculate the */ function calculateMenuPositions(scope, element, opts) { - var + var containerNode = element[0], targetNode = opts.target[0].children[0], // target the label parentNode = $document[0].body, @@ -1298,11 +1298,12 @@ function SelectProvider($$interimElementProvider) { bottom: bounds.bottom - (targetRect.top + targetRect.height) }, maxWidth = parentRect.width - SELECT_EDGE_MARGIN * 2, - isScrollable = contentNode.scrollHeight > contentNode.offsetHeight, selectedNode = selectNode.querySelector('md-option[selected]'), optionNodes = selectNode.getElementsByTagName('md-option'), optgroupNodes = selectNode.getElementsByTagName('md-optgroup'); + var isScrollable = calculateScrollable(element, contentNode); + var loading = isPromiseLike(opts.loadingAsync); var centeredNode; if (!loading) { @@ -1386,7 +1387,7 @@ function SelectProvider($$interimElementProvider) { } else { left = (targetRect.left + centeredRect.left - centeredRect.paddingLeft) + 2; top = Math.floor(targetRect.top + targetRect.height / 2 - centeredRect.height / 2 - - centeredRect.top + contentNode.scrollTop) + 4; + centeredRect.top + contentNode.scrollTop) + 2; transformOrigin = (centeredRect.left + targetRect.width / 2) + 'px ' + (centeredRect.top + centeredRect.height / 2 - contentNode.scrollTop) + 'px 0px'; @@ -1437,5 +1438,24 @@ function SelectProvider($$interimElementProvider) { height: node.offsetHeight } : {left: 0, top: 0, width: 0, height: 0}; } + + function calculateScrollable(element, contentNode) { + var isScrollable = false; + + try { + var oldDisplay = element[0].style.display; + + // Set the element's display to block so that this calculation is correct + element[0].style.display = 'block'; + + isScrollable = contentNode.scrollHeight > contentNode.offsetHeight; + + // Reset it back afterwards + element[0].style.display = oldDisplay; + } finally { + // Nothing to do + } + return isScrollable; + } }