function calculateMenuPositions(scope, element, opts) {
      var
        containerNode = element[0],
        targetNode = opts.target[0].children[0], // target the label
        parentNode = $document[0].body,
        selectNode = opts.selectEl[0],
        contentNode = opts.contentEl[0],
        parentRect = parentNode.getBoundingClientRect(),
        targetRect = targetNode.getBoundingClientRect(),
        shouldOpenAroundTarget = false,
        bounds = {
          left: parentRect.left + SELECT_EDGE_MARGIN,
          top: SELECT_EDGE_MARGIN,
          bottom: parentRect.height - SELECT_EDGE_MARGIN,
          right: parentRect.width - SELECT_EDGE_MARGIN - ($mdUtil.floatingScrollbars() ? 16 : 0)
        },
        spaceAvailable = {
          top: targetRect.top - bounds.top,
          left: targetRect.left - bounds.left,
          right: bounds.right - (targetRect.left + targetRect.width),
          bottom: bounds.bottom - (targetRect.top + targetRect.height)
        },
        maxWidth = parentRect.width - SELECT_EDGE_MARGIN * 2,
        selectedNode = selectNode.querySelector('md-option[selected]'),
        optionNodes = selectNode.getElementsByTagName('md-option'),
        optgroupNodes = selectNode.getElementsByTagName('md-optgroup'),
        isScrollable = calculateScrollable(element, contentNode),
        centeredNode;

      var loading = isPromiseLike(opts.loadingAsync);
      if (!loading) {
        // If a selected node, center around that
        if (selectedNode) {
          centeredNode = selectedNode;
          // If there are option groups, center around the first option group
        } else if (optgroupNodes.length) {
          centeredNode = optgroupNodes[0];
          // Otherwise - if we are not loading async - center around the first optionNode
        } else if (optionNodes.length) {
          centeredNode = optionNodes[0];
          // In case there are no options, center on whatever's in there... (eg progress indicator)
        } else {
          centeredNode = contentNode.firstElementChild || contentNode;
        }
      } else {
        // If loading, center on progress indicator
        centeredNode = contentNode.firstElementChild || contentNode;
      }

      if (contentNode.offsetWidth > maxWidth) {
        contentNode.style['max-width'] = maxWidth + 'px';
      } else {
        contentNode.style.maxWidth = null;
      }
      if (shouldOpenAroundTarget) {
        contentNode.style['min-width'] = targetRect.width + 'px';
      }

      // Remove padding before we compute the position of the menu
      if (isScrollable) {
        selectNode.classList.add('md-overflow');
      }

      var focusedNode = centeredNode;
      if ((focusedNode.tagName || '').toUpperCase() === 'MD-OPTGROUP') {
        focusedNode = optionNodes[0] || contentNode.firstElementChild || contentNode;
        centeredNode = focusedNode;
      }
      // Cache for autoFocus()
      opts.focusedNode = focusedNode;

      // Get the selectMenuRect *after* max-width is possibly set above
      containerNode.style.display = 'block';
      var selectMenuRect = selectNode.getBoundingClientRect();
      var centeredRect = getOffsetRect(centeredNode);

      if (centeredNode) {
        var centeredStyle = $window.getComputedStyle(centeredNode);
        centeredRect.paddingLeft = parseInt(centeredStyle.paddingLeft, 10) || 0;
        centeredRect.paddingRight = parseInt(centeredStyle.paddingRight, 10) || 0;
      }

      if (isScrollable) {
        var scrollBuffer = contentNode.offsetHeight / 2;
        contentNode.scrollTop = centeredRect.top + centeredRect.height / 2 - scrollBuffer;

        if (spaceAvailable.top < scrollBuffer) {
          contentNode.scrollTop = Math.min(
            centeredRect.top,
            contentNode.scrollTop + scrollBuffer - spaceAvailable.top
          );
        } else if (spaceAvailable.bottom < scrollBuffer) {
          contentNode.scrollTop = Math.max(
            centeredRect.top + centeredRect.height - selectMenuRect.height,
            contentNode.scrollTop - scrollBuffer + spaceAvailable.bottom
          );
        }
      }

      var left, top, transformOrigin, minWidth, fontSize;
      if (shouldOpenAroundTarget) {
        left = targetRect.left;
        top = targetRect.top + targetRect.height;
        transformOrigin = '50% 0';
        if (top + selectMenuRect.height > bounds.bottom) {
          top = targetRect.top - selectMenuRect.height;
          transformOrigin = '50% 100%';
        }
      } else {
        left = (targetRect.left + centeredRect.left - centeredRect.paddingLeft) + 2;
        top = Math.floor(targetRect.top + targetRect.height / 2 - centeredRect.height / 2 -
            centeredRect.top + contentNode.scrollTop) + 2;

        transformOrigin = (centeredRect.left + targetRect.width / 2) + 'px ' +
          (centeredRect.top + centeredRect.height / 2 - contentNode.scrollTop) + 'px 0px';

        minWidth = Math.min(targetRect.width + centeredRect.paddingLeft + centeredRect.paddingRight, maxWidth);

        fontSize = window.getComputedStyle(targetNode)['font-size'];
      }

      // Keep left and top within the window
      var containerRect = containerNode.getBoundingClientRect();
      var scaleX = Math.round(100 * Math.min(targetRect.width / selectMenuRect.width, 1.0)) / 100;
      var scaleY = Math.round(100 * Math.min(targetRect.height / selectMenuRect.height, 1.0)) / 100;

      return {
        container: {
          element: angular.element(containerNode),
          styles: {
            left: Math.floor(clamp(bounds.left, left, bounds.right - containerRect.width)),
            top: Math.floor(clamp(bounds.top, top, bounds.bottom - containerRect.height)),
            'min-width': minWidth,
            'font-size': fontSize
          }
        },
        dropDown: {
          element: angular.element(selectNode),
          styles: {
            transformOrigin: transformOrigin,
            transform: !opts.alreadyOpen ? $mdUtil.supplant('scale({0},{1})', [scaleX, scaleY]) : ""
          }
        }
      };

    }
function calculateMenuPositions(scope, element, opts) {
      var
        containerNode = element[0],
        targetNode = opts.target[0].children[0], // target the label
        parentNode = $document[0].body,
        selectNode = opts.selectEl[0],
        contentNode = opts.contentEl[0],
        parentRect = parentNode.getBoundingClientRect(),
        targetRect = targetNode.getBoundingClientRect(),
        shouldOpenAroundTarget = false,
        bounds = {
          left: parentRect.left + SELECT_EDGE_MARGIN,
          top: SELECT_EDGE_MARGIN,
          bottom: parentRect.height - SELECT_EDGE_MARGIN,
          right: parentRect.width - SELECT_EDGE_MARGIN - ($mdUtil.floatingScrollbars() ? 16 : 0)
        },
        spaceAvailable = {
          top: targetRect.top - bounds.top,
          left: targetRect.left - bounds.left,
          right: bounds.right - (targetRect.left + targetRect.width),
          bottom: bounds.bottom - (targetRect.top + targetRect.height)
        },
        maxWidth = parentRect.width - SELECT_EDGE_MARGIN * 2,
        selectedNode = selectNode.querySelector('md-option[selected]'),
        optionNodes = selectNode.getElementsByTagName('md-option'),
        optgroupNodes = selectNode.getElementsByTagName('md-optgroup'),
        isScrollable = calculateScrollable(element, contentNode),
        centeredNode;

      var loading = isPromiseLike(opts.loadingAsync);
      if (!loading) {
        // If a selected node, center around that
        if (selectedNode) {
          centeredNode = selectedNode;
          // If there are option groups, center around the first option group
        } else if (optgroupNodes.length) {
          centeredNode = optgroupNodes[0];
          // Otherwise - if we are not loading async - center around the first optionNode
        } else if (optionNodes.length) {
          centeredNode = optionNodes[0];
          // In case there are no options, center on whatever's in there... (eg progress indicator)
        } else {
          centeredNode = contentNode.firstElementChild || contentNode;
        }
      } else {
        // If loading, center on progress indicator
        centeredNode = contentNode.firstElementChild || contentNode;
      }

      if (contentNode.offsetWidth > maxWidth) {
        contentNode.style['max-width'] = maxWidth + 'px';
      } else {
        contentNode.style.maxWidth = null;
      }
      if (shouldOpenAroundTarget) {
        contentNode.style['min-width'] = targetRect.width + 'px';
      }

      // Remove padding before we compute the position of the menu
      if (isScrollable) {
        selectNode.classList.add('md-overflow');
      }

      var focusedNode = centeredNode;
      if ((focusedNode.tagName || '').toUpperCase() === 'MD-OPTGROUP') {
        focusedNode = optionNodes[0] || contentNode.firstElementChild || contentNode;
        centeredNode = focusedNode;
      }
      // Cache for autoFocus()
      opts.focusedNode = focusedNode;

      // Get the selectMenuRect *after* max-width is possibly set above
      containerNode.style.display = 'block';
      var selectMenuRect = selectNode.getBoundingClientRect();
      var centeredRect = getOffsetRect(centeredNode);

      if (centeredNode) {
        var centeredStyle = $window.getComputedStyle(centeredNode);
        centeredRect.paddingLeft = parseInt(centeredStyle.paddingLeft, 10) || 0;
        centeredRect.paddingRight = parseInt(centeredStyle.paddingRight, 10) || 0;
      }

      if (isScrollable) {
        var scrollBuffer = contentNode.offsetHeight / 2;
        contentNode.scrollTop = centeredRect.top + centeredRect.height / 2 - scrollBuffer;

        if (spaceAvailable.top < scrollBuffer) {
          contentNode.scrollTop = Math.min(
            centeredRect.top,
            contentNode.scrollTop + scrollBuffer - spaceAvailable.top
          );
        } else if (spaceAvailable.bottom < scrollBuffer) {
          contentNode.scrollTop = Math.max(
            centeredRect.top + centeredRect.height - selectMenuRect.height,
            contentNode.scrollTop - scrollBuffer + spaceAvailable.bottom
          );
        }
      }

      var left, top, transformOrigin, minWidth, fontSize;
      if (shouldOpenAroundTarget) {
        left = targetRect.left;
        top = targetRect.top + targetRect.height;
        transformOrigin = '50% 0';
        if (top + selectMenuRect.height > bounds.bottom) {
          top = targetRect.top - selectMenuRect.height;
          transformOrigin = '50% 100%';
        }
      } else {
        left = (targetRect.left + centeredRect.left - centeredRect.paddingLeft) + 2;
        top = Math.floor(targetRect.top + targetRect.height / 2 - centeredRect.height / 2 -
            centeredRect.top + contentNode.scrollTop) + 2;

        transformOrigin = (centeredRect.left + targetRect.width / 2) + 'px ' +
          (centeredRect.top + centeredRect.height / 2 - contentNode.scrollTop) + 'px 0px';

        minWidth = Math.min(targetRect.width + centeredRect.paddingLeft + centeredRect.paddingRight, maxWidth);

        fontSize = window.getComputedStyle(targetNode)['font-size'];
      }

      // Keep left and top within the window
      var containerRect = containerNode.getBoundingClientRect();
      var scaleX = Math.round(100 * Math.min(targetRect.width / selectMenuRect.width, 1.0)) / 100;
      var scaleY = Math.round(100 * Math.min(targetRect.height / selectMenuRect.height, 1.0)) / 100;

      return {
        container: {
          element: angular.element(containerNode),
          styles: {
            left: Math.floor(clamp(bounds.left, left, bounds.right - containerRect.width)),
            top: Math.floor(clamp(bounds.top, top, bounds.bottom - containerRect.height)),
            'min-width': minWidth,
            'font-size': fontSize
          }
        },
        dropDown: {
          element: angular.element(selectNode),
          styles: {
            transformOrigin: transformOrigin,
            transform: !opts.alreadyOpen ? $mdUtil.supplant('scale({0},{1})', [scaleX, scaleY]) : ""
          }
        }
      };

    }
function calculateMenuPositions ( scope , element , opts ) { var containerNode = element [ 0 ] , targetNode = opts . target [ 0 ] . children [ 0 ] , // target the label parentNode = $document [ 0 ] . body , selectNode = opts . selectEl [ 0 ] , contentNode = opts . contentEl [ 0 ] , parentRect = parentNode . getBoundingClientRect ( ) , targetRect = targetNode . getBoundingClientRect ( ) , shouldOpenAroundTarget = false , bounds = { left : parentRect . left + SELECT_EDGE_MARGIN , top : SELECT_EDGE_MARGIN , bottom : parentRect . height - SELECT_EDGE_MARGIN , right : parentRect . width - SELECT_EDGE_MARGIN - ( $mdUtil . floatingScrollbars ( ) ? 16 : 0 ) } , spaceAvailable = { top : targetRect . top - bounds . top , left : targetRect . left - bounds . left , right : bounds . right - ( targetRect . left + targetRect . width ) , bottom : bounds . bottom - ( targetRect . top + targetRect . height ) } , maxWidth = parentRect . width - SELECT_EDGE_MARGIN * 2 , selectedNode = selectNode . querySelector ( 'md-option[selected]' ) , optionNodes = selectNode . getElementsByTagName ( 'md-option' ) , optgroupNodes = selectNode . getElementsByTagName ( 'md-optgroup' ) , isScrollable = calculateScrollable ( element , contentNode ) , centeredNode ; var loading = isPromiseLike ( opts . loadingAsync ) ; if ( ! loading ) { // If a selected node, center around that if ( selectedNode ) { centeredNode = selectedNode ; // If there are option groups, center around the first option group } else if ( optgroupNodes . length ) { centeredNode = optgroupNodes [ 0 ] ; // Otherwise - if we are not loading async - center around the first optionNode } else if ( optionNodes . length ) { centeredNode = optionNodes [ 0 ] ; // In case there are no options, center on whatever's in there... (eg progress indicator) } else { centeredNode = contentNode . firstElementChild || contentNode ; } } else { // If loading, center on progress indicator centeredNode = contentNode . firstElementChild || contentNode ; } if ( contentNode . offsetWidth > maxWidth ) { contentNode . style [ 'max-width' ] = maxWidth + 'px' ; } else { contentNode . style . maxWidth = null ; } if ( shouldOpenAroundTarget ) { contentNode . style [ 'min-width' ] = targetRect . width + 'px' ; } // Remove padding before we compute the position of the menu if ( isScrollable ) { selectNode . classList . add ( 'md-overflow' ) ; } var focusedNode = centeredNode ; if ( ( focusedNode . tagName || '' ) . toUpperCase ( ) === 'MD-OPTGROUP' ) { focusedNode = optionNodes [ 0 ] || contentNode . firstElementChild || contentNode ; centeredNode = focusedNode ; } // Cache for autoFocus() opts . focusedNode = focusedNode ; // Get the selectMenuRect *after* max-width is possibly set above containerNode . style . display = 'block' ; var selectMenuRect = selectNode . getBoundingClientRect ( ) ; var centeredRect = getOffsetRect ( centeredNode ) ; if ( centeredNode ) { var centeredStyle = $window . getComputedStyle ( centeredNode ) ; centeredRect . paddingLeft = parseInt ( centeredStyle . paddingLeft , 10 ) || 0 ; centeredRect . paddingRight = parseInt ( centeredStyle . paddingRight , 10 ) || 0 ; } if ( isScrollable ) { var scrollBuffer = contentNode . offsetHeight / 2 ; contentNode . scrollTop = centeredRect . top + centeredRect . height / 2 - scrollBuffer ; if ( spaceAvailable . top < scrollBuffer ) { contentNode . scrollTop = Math . min ( centeredRect . top , contentNode . scrollTop + scrollBuffer - spaceAvailable . top ) ; } else if ( spaceAvailable . bottom < scrollBuffer ) { contentNode . scrollTop = Math . max ( centeredRect . top + centeredRect . height - selectMenuRect . height , contentNode . scrollTop - scrollBuffer + spaceAvailable . bottom ) ; } } var left , top , transformOrigin , minWidth , fontSize ; if ( shouldOpenAroundTarget ) { left = targetRect . left ; top = targetRect . top + targetRect . height ; transformOrigin = '50% 0' ; if ( top + selectMenuRect . height > bounds . bottom ) { top = targetRect . top - selectMenuRect . height ; transformOrigin = '50% 100%' ; } } else { left = ( targetRect . left + centeredRect . left - centeredRect . paddingLeft ) + 2 ; top = Math . floor ( targetRect . top + targetRect . height / 2 - centeredRect . height / 2 - centeredRect . top + contentNode . scrollTop ) + 2 ; transformOrigin = ( centeredRect . left + targetRect . width / 2 ) + 'px ' + ( centeredRect . top + centeredRect . height / 2 - contentNode . scrollTop ) + 'px 0px' ; minWidth = Math . min ( targetRect . width + centeredRect . paddingLeft + centeredRect . paddingRight , maxWidth ) ; fontSize = window . getComputedStyle ( targetNode ) [ 'font-size' ] ; } // Keep left and top within the window var containerRect = containerNode . getBoundingClientRect ( ) ; var scaleX = Math . round ( 100 * Math . min ( targetRect . width / selectMenuRect . width , 1.0 ) ) / 100 ; var scaleY = Math . round ( 100 * Math . min ( targetRect . height / selectMenuRect . height , 1.0 ) ) / 100 ; return { container : { element : angular . element ( containerNode ) , styles : { left : Math . floor ( clamp ( bounds . left , left , bounds . right - containerRect . width ) ) , top : Math . floor ( clamp ( bounds . top , top , bounds . bottom - containerRect . height ) ) , 'min-width' : minWidth , 'font-size' : fontSize } } , dropDown : { element : angular . element ( selectNode ) , styles : { transformOrigin : transformOrigin , transform : ! opts . alreadyOpen ? $mdUtil . supplant ( 'scale({0},{1})' , [ scaleX , scaleY ] ) : "" } } } ; }
Calculate the
Calculate the
Calculate the position of the menu