/*!
* 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 <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({
        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);