
( function( $ ) { 
    $.scrollFollow = function ( box, options ) 
    { 
        // Convert box into a jQuery object 
        box = $( box ); 
        // 'box' is the object to be animated 
        var position = box.css( 'position' ); 
        function ani() 
        {         
            // The script runs on every scroll which really means many times during a scroll. 
            // We don't want multiple slides to queue up. 
            box.queue( [ ] ); 
            // A bunch of values we need to determine where to animate to 
            var viewportHeight = parseInt( $( window ).height() );     
            var pageScroll = parseInt( $( document ).scrollTop() ); 
            var parentTop = parseInt( box.cont.offset().top ); 
            var parentHeight = parseInt( box.cont.attr( 'offsetHeight' ) ); 
            var boxHeight = parseInt( box.attr( 'offsetHeight' ) + ( parseInt( box.css( 'marginTop' ) ) || 0 ) + ( parseInt( box.css( 'marginBottom' ) ) || 0 ) ); 
            var aniTop; 
            // Make sure the user wants the animation to happen 
            if ( isActive ) 
            { 
                // If the box should animate relative to the top of the window 
                if ( options.relativeTo == 'top' ) 
                { 
                    // Don't animate until the top of the window is close enough to the top of the box 
                    if ( box.initialOffsetTop >= ( pageScroll + options.offset ) ) 
                    { 
                        aniTop = box.initialTop; 
                    } 
                    else 
                    { 
                        aniTop = Math.min( ( Math.max( ( -parentTop ), ( pageScroll - box.initialOffsetTop + box.initialTop ) ) + options.offset ), ( parentHeight - boxHeight - box.paddingAdjustment ) ); 
                    } 
                } 
                // If the box should animate relative to the bottom of the window 
                else if ( options.relativeTo == 'bottom' ) 
                { 
                    // Don't animate until the bottom of the window is close enough to the bottom of the box 
                    if ( ( box.initialOffsetTop + boxHeight ) >= ( pageScroll + options.offset + viewportHeight ) ) 
                    { 
                        aniTop = box.initialTop; 
                    } 
                    else 
                    { 
                        aniTop = Math.min( ( pageScroll + viewportHeight - boxHeight - options.offset ), ( parentHeight - boxHeight ) ); 
                    } 
                } 
                // Checks to see if the relevant scroll was the last one 
                // "-20" is to account for inaccuracy in the timeout 
                if ( ( new Date().getTime() - box.lastScroll ) >= ( options.delay - 20 ) ) 
                { 
                    box.animate( 
                        { 
                            top: aniTop 
                        }, options.speed, options.easing 
                    ); 
                } 
            } 
        }; 
        // For user-initiated stopping of the slide 
        var isActive = true; 
        if ( $.cookie != undefined ) 
        { 
            if( $.cookie( 'scrollFollowSetting' + box.attr( 'id' ) ) == 'false' ) 
            { 
                var isActive = false; 
                $( '#' + options.killSwitch ).text( options.offText ) 
                    .toggle( 
                        function () 
                        { 
                            isActive = true; 
                            $( this ).text( options.onText ); 
                            $.cookie( 'scrollFollowSetting' + box.attr( 'id' ), true, { expires: 365, path: '/'} ); 
                            ani(); 
                        }, 
                        function () 
                        { 
                            isActive = false; 
                            $( this ).text( options.offText ); 
                            box.animate( 
                                { 
                                    top: box.initialTop 
                                }, options.speed, options.easing 
                            );     
                            $.cookie( 'scrollFollowSetting' + box.attr( 'id' ), false, { expires: 365, path: '/'} ); 
                        } 
                    ); 
            } 
            else 
            { 
                $( '#' + options.killSwitch ).text( options.onText ) 
                    .toggle( 
                        function () 
                        { 
                            isActive = false; 
                            $( this ).text( options.offText ); 
                            box.animate( 
                                { 
                                    top: box.initialTop 
                                }, 0 
                            );     
                            $.cookie( 'scrollFollowSetting' + box.attr( 'id' ), false, { expires: 365, path: '/'} ); 
                        }, 
                        function () 
                        { 
                            isActive = true; 
                            $( this ).text( options.onText ); 
                            $.cookie( 'scrollFollowSetting' + box.attr( 'id' ), true, { expires: 365, path: '/'} ); 
                            ani(); 
                        } 
                    ); 
            } 
        } 
        // If no parent ID was specified, and the immediate parent does not have an ID 
        // options.container will be undefined. So we need to figure out the parent element. 
        if ( options.container == '') 
        { 
            box.cont = box.parent(); 
        } 
        else 
        { 
            box.cont = $( '#' + options.container ); 
        } 
        // Finds the default positioning of the box. 
        box.initialOffsetTop = parseInt( box.offset().top ); 
        box.initialTop = parseInt( box.css( 'top' ) ) || 0; 
        // Hack to fix different treatment of boxes positioned 'absolute' and 'relative' 
        if ( box.css( 'position' ) == 'relative' ) 
        { 
            box.paddingAdjustment = parseInt( box.cont.css( 'paddingTop' ) ) + parseInt( box.cont.css( 'paddingBottom' ) ); 
        } 
        else 
        { 
            box.paddingAdjustment = 0; 
        } 
        // Animate the box when the page is scrolled 
        $( window ).scroll( function () 
            { 
                // Sets up the delay of the animation 
                $.fn.scrollFollow.interval = setTimeout( function(){ ani();} , options.delay ); 
                // To check against right before setting the animation 
                box.lastScroll = new Date().getTime(); 
            } 
        ); 
        // Animate the box when the page is resized 
        $( window ).resize( function () 
            { 
                // Sets up the delay of the animation 
                $.fn.scrollFollow.interval = setTimeout( function(){ ani();} , options.delay ); 
                // To check against right before setting the animation 
                box.lastScroll = new Date().getTime(); 
            } 
        ); 
        // Run an initial animation on page load 
        box.lastScroll = 0; 
        ani(); 
    }; 
    $.fn.scrollFollow = function ( options ) 
    { 
        options = options || {}; 
        options.relativeTo = options.relativeTo || 'top'; 
        options.speed = options.speed || 200; 
        options.offset = options.offset || 10; 
        options.easing = options.easing || 'swing'; 
        options.container = options.container || this.parent().attr( 'id' ); 
        options.killSwitch = options.killSwitch || 'killSwitch'; 
        options.onText = options.onText || 'Turn Slide Off'; 
        options.offText = options.offText || 'Turn Slide On'; 
        options.delay = options.delay || 100; 
        this.each( function() 
            { 
                new $.scrollFollow( this, options ); 
            } 
        ); 
        return this; 
    }; 
})( jQuery );

