Skip to content
This repository has been archived by the owner on May 22, 2023. It is now read-only.

Commit

Permalink
(#19) implemented alternative background scrolling prevention
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Wilden committed Mar 22, 2016
1 parent ef593c8 commit f8fd284
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 28 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,7 +2,8 @@

## Last Changes

- [#19](https://github.com/LaxarJS/ax-details-layer-widget/issues/19): prevent that an element in the background can get the focus by tabbing
- [#19](https://github.com/LaxarJS/ax-details-layer-widget/issues/19): implemented alternative background scrolling prevention
- [#17](https://github.com/LaxarJS/ax-details-layer-widget/issues/17): prevent that an element in the background can get the focus by tabbing


## v1.1.0
Expand Down
81 changes: 54 additions & 27 deletions ax-details-layer-widget.js
Expand Up @@ -301,6 +301,13 @@ define( [
else {
completeOpening();
}
// Issue (#8):
// For iOS Safari: we need to make the body fixed in order to prevent background scrolling.
// To maintain the scroll position, we translate the entire page upwards, and move the layer down.
// Thus we only execute the additional code when the user agent might use the apple webkit engine.
if( isWebKit() ) {
preventBodyScrolling();
}

///////////////////////////////////////////////////////////////////////////////////////////////

Expand All @@ -311,14 +318,6 @@ define( [
backdropElement.addClass( 'ax-details-layer-open' );
element.removeClass( 'ax-details-layer-with-source-animation' );
scope.whenVisibilityChanged( true );

// Issue (#8):
// For iOS Safari: we need to make the body fixed in order to prevent background scrolling.
// To maintain the scroll position, we translate the entire page upwards, and move the layer down.
// Thus we only execute the additional code when the user agent might use the apple webkit engine.
if( isWebKit() ) {
preventBodyScrolling();
}
}
}

Expand Down Expand Up @@ -361,34 +360,62 @@ define( [
//////////////////////////////////////////////////////////////////////////////////////////////////

function preventBodyScrolling() {
previousPageYOffset = window.pageYOffset;

element.parent().children().each( function( _, child ) {
var ch = ng.element( child );
ch.css( 'top', parseFloat( ch.css( 'top' ) ) + previousPageYOffset + 'px' );
} );
// Following body scroll prevention taken from here:
// https://github.com/luster-io/prevent-overscroll
ng.element( '.ax-details-layer-content', element )
.on( 'touchstart', handleContentTouchStart )
.on( 'touchmove', handleContentTouchMove );

ng.element( document.body )
.css( 'position', 'fixed' )
.css( 'transform', 'translateY( -' + previousPageYOffset + 'px )' );
ng.element( document.body ).on( 'touchmove', handleBodyTouchMove );
}

//////////////////////////////////////////////////////////////////////////////////////////////////

function restoreBodyScrolling() {
if( previousPageYOffset !== undefined ) {
element.parent().children().each( function( _, child ) {
var ch = ng.element( child );
ch.css( 'top', parseFloat( ch.css( 'top' ) ) - previousPageYOffset + 'px' );
} );
ng.element( '.ax-details-layer-content', element )
.off( 'touchstart', handleContentTouchStart )
.off( 'touchmove', handleContentTouchMove );

ng.element( document.body ).off( 'touchmove', handleBodyTouchMove );
}

//////////////////////////////////////////////////////////////////////////////////////////////////

function handleContentTouchStart() {
var contentElement = ng.element( '.ax-details-layer-content', element )[0];
var top = contentElement.scrollTop;
var totalScroll = contentElement.scrollHeight;
var currentScroll = top + contentElement.offsetHeight;

// If we're at the top or the bottom of the containers scroll, push up or down one pixel.
// This prevents the scroll from "passing through" to the body.
if( top === 0 ) {
contentElement.scrollTop = 1;
}
else if( currentScroll === totalScroll ) {
contentElement.scrollTop = top - 1;
}
}

ng.element( document.body )
.css( 'position', '' )
.css( 'transform', '' );
//////////////////////////////////////////////////////////////////////////////////////////////////

function handleContentTouchMove( event ) {
var contentElement = ng.element( '.ax-details-layer-content', element )[0];
// If the content is actually scrollable, i.e. the content is long enough
// that scrolling can occur
if( contentElement.offsetHeight < contentElement.scrollHeight ) {
event.originalEvent._isDetailsLayer = true;
}
}

//////////////////////////////////////////////////////////////////////////////////////////////////

if( previousPageYOffset !== undefined ) {
window.scrollTo( window.pageXOffset, previousPageYOffset );
function handleBodyTouchMove( event ) {
// console.log( event.target, event.originalEvent._isDetailsLayer );
// In this case, the default behavior is scrolling the body, which
// would result in an overflow. Since we don't want that, we preventDefault.
if( !event.originalEvent._isDetailsLayer ) {
event.preventDefault();
}
}

Expand Down

0 comments on commit f8fd284

Please sign in to comment.