Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

fix(sidenav): update position of sidenav and backdrop if scrolled. #8184

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 57 additions & 10 deletions src/components/sidenav/sidenav.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
var lastParentOverFlow;
var backdrop;
var triggeringElement = null;
var previousContainerStyles;
var promise = $q.when(true);
var isLockedOpenParsed = $parse(attr.mdIsLockedOpen);
var isLocked = function() {
Expand Down Expand Up @@ -315,6 +316,8 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
parent[isOpen ? 'on' : 'off']('keydown', onKeyDown);
if (backdrop) backdrop[isOpen ? 'on' : 'off']('click', close);

var restorePositioning = updateContainerPositions(parent, isOpen);

if ( isOpen ) {
// Capture upon opening..
triggeringElement = $document[0].activeElement;
Expand All @@ -323,16 +326,60 @@ function SidenavDirective($mdMedia, $mdUtil, $mdConstant, $mdTheming, $animate,
disableParentScroll(isOpen);

return promise = $q.all([
isOpen && backdrop ? $animate.enter(backdrop, parent) :
backdrop ? $animate.leave(backdrop) : $q.when(true),
$animate[isOpen ? 'removeClass' : 'addClass'](element, '_md-closed')
])
.then(function() {
// Perform focus when animations are ALL done...
if (scope.isOpen) {
focusEl && focusEl.focus();
}
});
isOpen && backdrop ? $animate.enter(backdrop, parent) : backdrop ?
$animate.leave(backdrop) : $q.when(true),
$animate[isOpen ? 'removeClass' : 'addClass'](element, '_md-closed')
]).then(function() {
// Perform focus when animations are ALL done...
if (scope.isOpen) {
focusEl && focusEl.focus();
}

// Restores the positioning on the sidenav and backdrop.
restorePositioning && restorePositioning();
});
}

function updateContainerPositions(parent, willOpen) {
var drawerEl = element[0];
var scrollTop = parent[0].scrollTop;

if (willOpen && scrollTop) {
previousContainerStyles = {
top: drawerEl.style.top,
bottom: drawerEl.style.bottom,
height: drawerEl.style.height
};

// When the parent is scrolled down, then we want to be able to show the sidenav at the current scroll
// position. We're moving the sidenav down to the correct scroll position and apply the height of the
// parent, to increase the performance. Using 100% as height, will impact the performance heavily.
var positionStyle = {
top: scrollTop + 'px',
bottom: 'initial',
height: parent[0].clientHeight + 'px'
};

// Apply the new position styles to the sidenav and backdrop.
element.css(positionStyle);
backdrop.css(positionStyle);
}

// When the sidenav is closing and we have previous defined container styles,
// then we return a restore function, which resets the sidenav and backdrop.
if (!willOpen && previousContainerStyles) {
return function() {
drawerEl.style.top = previousContainerStyles.top;
drawerEl.style.bottom = previousContainerStyles.bottom;
drawerEl.style.height = previousContainerStyles.height;

backdrop[0].style.top = null;
backdrop[0].style.bottom = null;
backdrop[0].style.height = null;

previousContainerStyles = null;
}
}
}

/**
Expand Down