279 lines
8.5 KiB
JavaScript
279 lines
8.5 KiB
JavaScript
/**
|
|
* UpSolution Element: Page Scroller
|
|
*/
|
|
( function( $ ) {
|
|
"use strict";
|
|
|
|
$us.PageScroller = function( container, options ) {
|
|
this.init( container, options );
|
|
};
|
|
|
|
$us.PageScroller.prototype = {
|
|
init: function( container, options ) {
|
|
var defaults = {
|
|
coolDown: 100,
|
|
animationDuration: 1000,
|
|
animationEasing: 'easeInOutExpo'
|
|
},
|
|
scrollTop = parseInt( $us.$window.scrollTop() );
|
|
|
|
this.options = $.extend( {}, defaults, options );
|
|
|
|
this.$container = $( container );
|
|
this._canvasTopOffset = $us.$canvas.offset().top;
|
|
this.activeSection = 0;
|
|
this.sections = [];
|
|
this.dots = [];
|
|
this.scrolls = [];
|
|
this.usingDots = false;
|
|
this.isTouch = ( ( 'ontouchstart' in window ) || ( navigator.msMaxTouchPoints > 0 ) || ( navigator.maxTouchPoints ) );
|
|
this.disableWidth = ( this.$container.data( 'disablewidth' ) !== undefined ) ? this.$container.data( 'disablewidth' ) : 768;
|
|
|
|
if ( this.$container.data( 'speed' ) !== undefined ) {
|
|
this.options.animationDuration = this.$container.data( 'speed' );
|
|
}
|
|
|
|
// Adding header if isn't sticky
|
|
if ( $us.canvas.headerPos == 'static' && $us.header.orientation == 'hor' ) {
|
|
$us.canvas.$header.each( function() {
|
|
var $section = $us.canvas.$header,
|
|
section = {
|
|
$section: $section
|
|
};
|
|
this._countPosition( section );
|
|
this.sections.push( section );
|
|
}.bind( this ) );
|
|
}
|
|
|
|
// Adding canvas sections
|
|
$us.$canvas.find( '.l-section' ).each( function( key, elm ) {
|
|
var $section = $( elm ),
|
|
section = {
|
|
$section: $section
|
|
};
|
|
this._countPosition( section );
|
|
this.sections.push( section );
|
|
}.bind( this ) );
|
|
|
|
// Adding dots for canvas sections
|
|
this.$dotsContainer = this.$container.find( '.w-scroller-dots' );
|
|
if ( this.$dotsContainer.length ) {
|
|
this.usingDots = true;
|
|
|
|
this.$firstDot = this.$dotsContainer.find( '.w-scroller-dot' ).first();
|
|
for ( var i = 1; i < this.sections.length; i ++ ) {
|
|
this.$firstDot.clone().appendTo( this.$dotsContainer );
|
|
}
|
|
|
|
this.$dots = this.$dotsContainer.find( '.w-scroller-dot' );
|
|
this.$dots.each( function( key, elm ) {
|
|
var $dot = $( elm );
|
|
this.dots[ key ] = $dot;
|
|
$dot.click( function() {
|
|
this.scrollTo( key );
|
|
this.$dots.removeClass( 'active' );
|
|
$dot.addClass( 'active' );
|
|
}.bind( this ) );
|
|
}.bind( this ) );
|
|
|
|
this.dots[ this.activeSection ].addClass( 'active' );
|
|
|
|
this.$dotsContainer.addClass( 'show' );
|
|
}
|
|
|
|
// Adding footer sections
|
|
$( '.l-footer > .l-section' ).each( function( key, elm ) {
|
|
var $section = $( elm ),
|
|
section = {
|
|
$section: $section
|
|
};
|
|
this._countPosition( section );
|
|
this.sections.push( section );
|
|
}.bind( this ) );
|
|
|
|
this._attachEvents();
|
|
|
|
// Boundable events
|
|
this._events = {
|
|
scroll: this.scroll.bind( this ),
|
|
resize: this.resize.bind( this )
|
|
};
|
|
|
|
$us.$canvas.on( 'contentChange', this._events.resize );
|
|
$us.$window.on( 'resize load', this._events.resize );
|
|
$us.$window.on( 'resize load scroll', this._events.scroll );
|
|
setTimeout( this._events.resize, 100 );
|
|
},
|
|
getScrollSpeed: function( number ) {
|
|
var sum = 0;
|
|
var lastElements = this.scrolls.slice( Math.max( this.scrolls.length - number, 1 ) );
|
|
|
|
for ( var i = 0; i < lastElements.length; i ++ ) {
|
|
sum = sum + lastElements[ i ];
|
|
}
|
|
|
|
return Math.ceil( sum / number );
|
|
},
|
|
_attachEvents: function() {
|
|
|
|
$us.$document.off( 'mousewheel DOMMouseScroll MozMousePixelScroll' );
|
|
$us.$canvas.off( 'touchstart touchmove' );
|
|
|
|
if ( $us.$window.width() > this.disableWidth && $us.mobileNavOpened <= 0 && ( ! $us.$html.hasClass( 'cloverlay_fixed' ) ) ) {
|
|
$us.$document.on( 'mousewheel DOMMouseScroll MozMousePixelScroll', function( e ) {
|
|
e.preventDefault();
|
|
var currentTime = new Date().getTime(),
|
|
target = this.activeSection,
|
|
direction = e.originalEvent.wheelDelta || - e.originalEvent.detail,
|
|
speedEnd, speedMiddle, isAccelerating;
|
|
|
|
|
|
if ( this.scrolls.length > 149 ) {
|
|
this.scrolls.shift();
|
|
}
|
|
this.scrolls.push( Math.abs( direction ) );
|
|
|
|
if ( ( currentTime - this.previousMouseWheelTime ) > this.options.coolDown ) {
|
|
this.scrolls = [];
|
|
}
|
|
this.previousMouseWheelTime = currentTime;
|
|
|
|
speedEnd = this.getScrollSpeed( 10 );
|
|
speedMiddle = this.getScrollSpeed( 70 );
|
|
isAccelerating = speedEnd >= speedMiddle;
|
|
|
|
if ( isAccelerating ) {
|
|
if ( direction < 0 ) {
|
|
target ++;
|
|
} else if ( direction > 0 ) {
|
|
target --;
|
|
}
|
|
if ( this.sections[ target ] == undefined ) {
|
|
return;
|
|
}
|
|
this.scrollTo( target );
|
|
this.lastScroll = currentTime;
|
|
}
|
|
|
|
}.bind( this ) );
|
|
|
|
if ( $.isMobile || this.isTouch ) {
|
|
$us.$canvas.on( 'touchstart', function( event ) {
|
|
var e = event.originalEvent;
|
|
if ( typeof e.pointerType === 'undefined' || e.pointerType != 'mouse' ) {
|
|
this.touchStartY = e.touches[ 0 ].pageY;
|
|
}
|
|
}.bind( this ) );
|
|
|
|
$us.$canvas.on( 'touchmove', function( event ) {
|
|
event.preventDefault();
|
|
|
|
var currentTime = new Date().getTime(),
|
|
e = event.originalEvent,
|
|
target = this.activeSection;
|
|
this.touchEndY = e.touches[ 0 ].pageY;
|
|
|
|
if ( Math.abs( this.touchStartY - this.touchEndY ) > ( $us.$window.height() / 50 ) ) {
|
|
if ( this.touchStartY > this.touchEndY ) {
|
|
target ++;
|
|
} else if ( this.touchEndY > this.touchStartY ) {
|
|
target --;
|
|
}
|
|
|
|
if ( this.sections[ target ] == undefined ) {
|
|
return;
|
|
}
|
|
this.scrollTo( target );
|
|
this.lastScroll = currentTime;
|
|
}
|
|
}.bind( this ) );
|
|
}
|
|
}
|
|
|
|
},
|
|
_countPosition: function( section ) {
|
|
section.top = section.$section.offset().top - this._canvasTopOffset;
|
|
if ( $us.header.headerTop === undefined || ( $us.header.headerTop > 0 && section.top > $us.header.headerTop ) ) {
|
|
section.top = section.top - $us.header.scrolledOccupiedHeight;
|
|
}
|
|
section.bottom = section.top + section.$section.outerHeight( false );
|
|
},
|
|
_countAllPositions: function() {
|
|
for ( var section in this.sections ) {
|
|
if ( this.sections[ section ].$section.length ) {
|
|
this._countPosition( this.sections[ section ] );
|
|
}
|
|
}
|
|
},
|
|
scrollTo: function( target ) {
|
|
var currentTime = new Date().getTime();
|
|
if ( this.previousScrollTime !== undefined && ( currentTime - this.previousScrollTime < this.options.animationDuration ) ) {
|
|
return;
|
|
}
|
|
this.previousScrollTime = currentTime;
|
|
|
|
if ( this.usingDots ) {
|
|
this.$dots.removeClass( 'active' );
|
|
if ( this.dots[ target ] !== undefined ) {
|
|
this.dots[ target ].addClass( 'active' );
|
|
}
|
|
}
|
|
|
|
$us.$htmlBody.stop( true, false ).animate( {
|
|
scrollTop: this.sections[ target ][ 'top' ] + 'px'
|
|
}, {
|
|
duration: this.options.animationDuration,
|
|
easing: this.options.animationEasing,
|
|
always: function() {
|
|
this.activeSection = target;
|
|
}.bind( this )
|
|
} );
|
|
},
|
|
resize: function() {
|
|
this._attachEvents();
|
|
|
|
// Delaying the resize event to prevent glitches
|
|
setTimeout( function() {
|
|
this._countAllPositions();
|
|
// this.scrollTo(this.activeSection);
|
|
}.bind( this ), 150 );
|
|
this._countAllPositions();
|
|
// this.scrollTo(this.activeSection);
|
|
},
|
|
scroll: function() {
|
|
var currentTime = new Date().getTime();
|
|
if ( ( currentTime - this.lastScroll ) < ( this.options.coolDown + this.options.animationDuration ) ) {
|
|
return;
|
|
}
|
|
if ( this.scrollTimeout ) {
|
|
clearTimeout( this.scrollTimeout );
|
|
}
|
|
this.scrollTimeout = setTimeout( function() {
|
|
var scrollTop = parseInt( $us.$window.scrollTop() );
|
|
|
|
for ( var section in this.sections ) {
|
|
if ( scrollTop >= ( this.sections[ section ].top - 1 ) && scrollTop < ( this.sections[ section ].bottom - 1 ) ) {
|
|
this.activeSection = section;
|
|
break;
|
|
}
|
|
}
|
|
if ( this.usingDots ) {
|
|
this.$dots.removeClass( 'active' );
|
|
if ( this.dots[ this.activeSection ] !== undefined ) {
|
|
this.dots[ this.activeSection ].addClass( 'active' );
|
|
}
|
|
}
|
|
}.bind( this ), 500 );
|
|
}
|
|
};
|
|
|
|
$.fn.usPageScroller = function( options ) {
|
|
return this.each( function() {
|
|
$( this ).data( 'usPageScroller', new $us.PageScroller( this, options ) );
|
|
} );
|
|
};
|
|
|
|
$( function() {
|
|
$( '.w-scroller' ).usPageScroller();
|
|
} );
|
|
} )( jQuery ); |