Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (function($) {
- var version = '@VERSION',
- defaults = {
- exclude: [],
- excludeWithin:[],
- offset: 0,
- direction: 'top', // one of 'top' or 'left'
- scrollElement: null, // jQuery set of elements you wish to scroll (for $.smoothScroll).
- // if null (default), $('html, body').firstScrollable() is used.
- scrollTarget: null, // only use if you want to override default behavior
- beforeScroll: function() {}, // fn(opts) function to be called before scrolling occurs. "this" is the element(s) being scrolled
- afterScroll: function() {}, // fn(opts) function to be called after scrolling occurs. "this" is the triggering element
- easing: 'swing',
- speed: 400,
- autoCoefficent: 2 // coefficient for "auto" speed
- },
- getScrollable = function(opts) {
- var scrollable = [],
- scrolled = false,
- dir = opts.dir && opts.dir == 'left' ? 'scrollLeft' : 'scrollTop';
- this.each(function() {
- if (this == document || this == window) { return; }
- var el = $(this);
- if ( el[dir]() > 0 ) {
- scrollable.push(this);
- } else {
- // if scroll(Top|Left) === 0, nudge the element 1px and see if it moves
- el[dir](1);
- scrolled = el[dir]() > 0;
- if ( scrolled ) {
- scrollable.push(this);
- }
- // then put it back, of course
- el[dir](0);
- }
- });
- // If no scrollable elements, fall back to <body>,
- // if it's in the jQuery collection
- // (doing this because Safari sets scrollTop async,
- // so can't set it to 1 and immediately get the value.)
- if (!scrollable.length) {
- this.each(function(index) {
- if (this.nodeName === 'BODY') {
- scrollable = [this];
- }
- });
- }
- // Use the first scrollable element if we're calling firstScrollable()
- if ( opts.el === 'first' && scrollable.length > 1 ) {
- scrollable = [ scrollable[0] ];
- }
- return scrollable;
- },
- isTouch = 'ontouchend' in document;
- $.fn.extend({
- firstScrollable: function(dir) {
- var scrl = getScrollable.call(this, {el: 'first', dir: dir});
- return this.pushStack(scrl);
- },
- smoothScroll: function(options) {
- options = options || {};
- var opts = $.extend({}, $.fn.smoothScroll.defaults, options),
- locationPath = $.smoothScroll.filterPath(location.pathname);
- this
- .unbind('click.smoothscroll')
- .bind('click.smoothscroll', function(event) {
- var link = this,
- $link = $(this),
- exclude = opts.exclude,
- excludeWithin = opts.excludeWithin,
- elCounter = 0, ewlCounter = 0,
- include = true,
- clickOpts = {},
- hostMatch = ((location.hostname === link.hostname) || !link.hostname),
- pathMatch = opts.scrollTarget || ( $.smoothScroll.filterPath(link.pathname) || locationPath ) === locationPath,
- thisHash = escapeSelector(link.hash);
- if ( !opts.scrollTarget && (!hostMatch || !pathMatch || !thisHash) ) {
- include = false;
- } else {
- while (include && elCounter < exclude.length) {
- if ($link.is(escapeSelector(exclude[elCounter++]))) {
- include = false;
- }
- }
- while ( include && ewlCounter < excludeWithin.length ) {
- if ($link.closest(excludeWithin[ewlCounter++]).length) {
- include = false;
- }
- }
- }
- if ( include ) {
- event.preventDefault();
- $.extend( clickOpts, opts, {
- scrollTarget: opts.scrollTarget || thisHash,
- link: link
- });
- $.smoothScroll( clickOpts );
- }
- });
- return this;
- }
- });
- $.smoothScroll = function(options, px) {
- var opts, $scroller, scrollTargetOffset, speed,
- scrollerOffset = 0,
- offPos = 'offset',
- scrollDir = 'scrollTop',
- aniProps = {},
- aniOpts = {},
- scrollprops = [];
- if (typeof options === 'number') {
- opts = $.fn.smoothScroll.defaults;
- scrollTargetOffset = options;
- } else {
- opts = $.extend({}, $.fn.smoothScroll.defaults, options || {});
- if (opts.scrollElement) {
- offPos = 'position';
- if (opts.scrollElement.css('position') == 'static') {
- opts.scrollElement.css('position', 'relative');
- }
- }
- }
- opts = $.extend({link: null}, opts);
- scrollDir = opts.direction == 'left' ? 'scrollLeft' : scrollDir;
- if ( opts.scrollElement ) {
- $scroller = opts.scrollElement;
- scrollerOffset = $scroller[scrollDir]();
- } else {
- $scroller = $('html, body').firstScrollable();
- }
- // beforeScroll callback function must fire before calculating offset
- opts.beforeScroll.call($scroller, opts);
- scrollTargetOffset = (typeof options === 'number') ? options :
- px ||
- ( $(opts.scrollTarget)[offPos]() &&
- $(opts.scrollTarget)[offPos]()[opts.direction] ) ||
- 0;
- aniProps[scrollDir] = scrollTargetOffset + scrollerOffset + opts.offset;
- speed = opts.speed;
- // automatically calculate the speed of the scroll based on distance / coefficient
- if (speed === 'auto') {
- // if aniProps[scrollDir] == 0 then we'll use scrollTop() value instead
- speed = aniProps[scrollDir] || $scroller.scrollTop();
- // divide the speed by the coefficient
- speed = speed / opts.autoCoefficent;
- }
- aniOpts = {
- duration: speed,
- easing: opts.easing,
- complete: function() {
- opts.afterScroll.call(opts.link, opts);
- }
- };
- if (opts.step) {
- aniOpts.step = opts.step;
- }
- if ($scroller.length) {
- $scroller.stop().animate(aniProps, aniOpts);
- } else {
- opts.afterScroll.call(opts.link, opts);
- }
- };
- $.smoothScroll.version = version;
- $.smoothScroll.filterPath = function(string) {
- return string
- .replace(/^\//,'')
- .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
- .replace(/\/$/,'');
- };
- // default options
- $.fn.smoothScroll.defaults = defaults;
- function escapeSelector (str) {
- return str.replace(/(:|\.)/g,'\\$1');
- }
- })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment