/**
 * this class uses jQuery
 *
 * pass in an element selected by jQuery and the Scroller does the rest
 * optionally add some options
 *
 * options:
 *    - direction: vertical, horizontal
 *
 * $Id: scroller.js,v 1.9 2009/12/05 03:40:02 jmuller Exp $
 */

function Scroller (el, options)
{
    var self = this;

    self.el = el;

    // pull in options
    self.options = options || {};

    var default_options = {
        'animation_length':       1500,
        'animation_pause_length': 3000,
        'direction':              'vertical'
    };

    for( var opt in default_options )
    {
        if( typeof(self.options[opt]) == "undefined" )
        {
            self.options[opt] = default_options[opt];
        }
    }

    self.scrolling = true;
    self.scroll_scheduled = false;

    self.start_scrolling = function ()
    {
        self.scrolling = true;

        self.schedule_a_scroll(true);
    }

    self.stop_scrolling = function ()
    {
        self.scrolling = false;
    }

    self.schedule_a_scroll = function (immediately)
    {
        if( !self.scroll_scheduled )
        {
            self.scroll_scheduled = true;

            if( immediately )
            {
                if( self.scrolling )
                {
                    self.scroll();
                }
                else
                {
                    self.scroll_scheduled = false;
                }
            }
            else
            {
                setTimeout(
                    function() {
                        if( self.scrolling )
                        {
                            self.scroll();
                        }
                        else
                        {
                            self.scroll_scheduled = false;
                        }
                    },
                    self.options.animation_pause_length
                );
            }
        }
    }

    // set scroll function
    if (self.options.direction == 'vertical')
    {
        self.scroll = function ()
        {
            $(self.inner).animate(
                {top: '-'+this.item_height+'px'},
                self.options.animation_length,
                'swing',
                function() {
                    self.scroll_scheduled = false;
                    self.schedule_a_scroll();

                    // pop child off top and put it on the bottom
                    $(self.inner).children().eq(0).remove().appendTo(self.inner);
                    $(self.inner).css('top', '0px');
                }
            );
        }

        self.next = function ()
        {
            self.stop_scrolling();
            $(self.inner).animate(
                {top: '-'+this.item_height+'px'},
                self.options.animation_length / 2,
                'swing',
                function() {
                    // pop child off top and put it on the bottom
                    $(self.inner).children().eq(0).remove().appendTo(self.inner);
                    $(self.inner).css('top', '0px');
                }
            );
        }

        self.prev = function ()
        {
            self.stop_scrolling();
            $(self.inner).children().eq($(self.inner).children().size() - 1).remove().prependTo(self.inner);
            $(self.inner).css('top', '-' + this.item_height + 'px');
            $(self.inner).animate(
                {
                    top: 0
                },
                self.options.animation_length / 2,
                'swing'
            );
        }
    }
    else
    {
        self.scroll = function ()
        {
            $(self.inner).animate(
                {left: '-'+this.item_width+'px'},
                self.options.animation_length,
                'swing',
                function() {
                    self.scroll_scheduled = false;
                    self.schedule_a_scroll();

                    // pop child off top and put it on the bottom
                    $(self.inner).children().eq(0).remove().appendTo(self.inner);
                    $(self.inner).css('left', '0px');
                }
            );
        }

        self.next = function ()
        {
            self.stop_scrolling();
            $(self.inner).animate(
                {left: '-'+this.item_width+'px'},
                self.options.animation_length / 2,
                'swing',
                function() {
                    // pop child off top and put it on the bottom
                    $(self.inner).children().eq(0).remove().appendTo(self.inner);
                    $(self.inner).css('left', '0px');
                }
            );
        }

        self.prev = function ()
        {
            self.stop_scrolling();
            $(self.inner).children().eq($(self.inner).children().size() - 1).remove().prependTo(self.inner);
            $(self.inner).css('left', '-' + this.item_width + 'px');
            $(self.inner).animate(
                {
                    left: 0
                },
                self.options.animation_length / 2,
                'swing'
            );
        }
    }

    // "constructor"
        self.items       = $(self.el).children();
        self.item_height = self.items.eq(0).outerHeight(true);
        self.item_width  = self.items.eq(0).outerWidth(true);
        self.num_items   = self.items.size();

        $(self.el).css({
            'position': 'relative',
            'overflow': 'hidden'
        });

        // make an inner div and move all scrollables in there
        self.inner = $('<div></div>').appendTo(self.el).get(0);
        self.items.each(function () {
            $(this).remove().appendTo(self.inner);
        });

        if (self.options.direction == 'vertical')
        {
            $(self.inner).css(
                {
                    'height': self.item_height * self.num_items,
                    'width':  self.item_width
                }
            );
        }
        else
        {
            $(self.inner).css(
                {
                    'width':  self.item_width * self.num_items,
                    'height': self.item_height
                }
            );
        }

        $(self.inner).css({
            'position': 'absolute'
        });

        self.scroll();
}

/*
 * $Log: scroller.js,v $
 * Revision 1.9  2009/12/05 03:40:02  jmuller
 * Add initial support for next and previous slide.
 *
 * Revision 1.8  2009/12/02 21:42:54  gschwart
 * fixed some bugs
 *
 * Revision 1.7  2009/12/02 20:57:03  gschwart
 * added the ability to stop and start the scroller
 *
 * Revision 1.6  2009/12/02 19:51:28  gschwart
 * inverted how we did the scroller
 * now it keeps the original scroller element as the outer-most element (so css rules can still apply)
 * also removed the items_displayed feature which allowed you to control how many items show at once.  this will now have to be controlled manually by setting the size of the outer element yourself
 * i think its a good idea to leave as much power as possible to the script user
 *
 * Revision 1.5  2009/05/28 21:10:32  gschwart
 * re-spaced things
 *
 * Revision 1.4  2009/04/30 18:20:06  jmuller
 * Add log lines.
 *
 */

