/*! * smooth scroll - v1.4.10 - 2013-03-02 * https://github.com/kswedberg/jquery-smooth-scroll * copyright (c) 2013 karl swedberg * licensed mit (https://github.com/kswedberg/jquery-smooth-scroll/blob/master/license-mit) */ (function($) { var version = '1.4.10', defaults = { exclude: [], excludewithin:[], offset: 0, // one of 'top' or 'left' direction: 'top', // jquery set of elements you wish to scroll (for $.smoothscroll). // if null (default), $('html, body').firstscrollable() is used. scrollelement: null, // only use if you want to override default behavior scrolltarget: null, // fn(opts) function to be called before scrolling occurs. // `this` is the element(s) being scrolled beforescroll: function() {}, // fn(opts) function to be called after scrolling occurs. // `this` is the triggering element afterscroll: function() {}, easing: 'swing', speed: 400, // coefficient for "auto" speed autocoefficent: 2 }, 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 , // 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({ scrollable: function(dir) { var scrl = getscrollable.call(this, {dir: dir}); return this.pushstack(scrl); }, 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);