
    function ArtboxSlideshow( slides, loadedSlides, options )
    {
        this.defaults = {
                            playback: 'auto',
                            loop: false,
                            replay: false,
                            displayTime: 4000,
                            transitionTime: 1000,
                            transition: 'crossFade',
                            transitionFirst: false,
                            captionEffect: 'none',
                            prev: '#slideshow_prev_button',
                            next: '#slideshow_next_button',
                            nextButtonImage: '/static/img/button_next.png',
                            nextButtonOverImage: '/static/img/button_next_over.png',
                            prevButtonImage: '/static/img/button_prev.png',
                            prevButtonOverImage: '/static/img/button_prev_over.png',
                            endButtonImage: '/static/img/button_end.png'
                       };

        this.settings = $.extend( {}, this.defaults, options );

        // TODO: for now, if manual, don't allow looping because there are issues with displaying the previous image when you are on the first image
        if ( this.settings.playback == 'manual' )
        {
            this.settings.loop = false;
        }

        this.slides = slides;
        this.loadedSlides = loadedSlides;

        // Initialize prev and next buttons
        this.initializeButtons();
    }

    ArtboxSlideshow.prototype.display = function()
    {

        // Set up cycle
        var obj = this;  // for use in callback
        var timeout = ( this.settings.playback == 'manual' ) ? 0 : parseInt( this.settings.displayTime );
        var speed = parseInt( this.settings.transitionTime );
        var nowrap = ! (this.settings.loop === 'true');
        var next = this.settings.next;
        var prev = this.settings.prev;
        
        // Set up transitions
        var fx = '';
        var sync = true;

        switch( this.settings.transition )
        {
            case 'scrollHorz':
            case 'scrollVert':
            case 'toss':
            case 'cover':
            case 'uncover':
			case 'none':
                fx = this.settings.transition;
                break;

            case 'fadeBg':
                fx = 'fade';
                sync = false;
                break;

            case 'crossFade':
            default:
                fx = 'fade';
                break;
        }


		// Center first slide
        var firstImage = $('#slide img:first');
        var marginTop = ( this.settings.height - firstImage.attr('height') ) / 2;
        var marginLeft = ( this.settings.width - firstImage.attr('width') ) / 2;
		firstImage.css( { 'marginTop': marginTop, 'marginLeft': marginLeft, 'display':'inline' } );


        // Start up slideshow
        $('#slide').cycle( {
                                fx: fx,
                                sync: sync,
                                prev: prev, 
                                next: next, 
                                timeout: timeout,
                                speed: speed,
                                nowrap: nowrap,
                                before: function( curSlideElement, nextSlideElement, options, forwardFlag ){ obj.beforeSlide( curSlideElement, nextSlideElement, options, forwardFlag ); },
                                end: function( options ) { obj.endSlide( options ); }
                            }
                         );
    };

    ArtboxSlideshow.prototype.beforeSlide = function( curSlideElement, nextSlideElement, options, forwardFlag )
    {
        var slideIndex;


        //
        // Enable and disable buttons
        //

        // If this is the first slide
        if ( options.nextSlide == 0 || curSlideElement == nextSlideElement && options.currSlide == 0 )
        {
            slideIndex = 0;
            if ( this.settings.playback != 'auto' )
            {
                this.disablePrevButton();
                this.enableNextButton();
            }
        }

        // If this is the last slide
        else if ( options.nextSlide == this.slides.length - 1 )
        {
            slideIndex = options.nextSlide;
            if ( this.settings.playback != 'auto' )
            {
                this.enablePrevButton();
                if ( this.settings.loop == false )
                  this.disableNextButton();
            }
        }
        else
        {
            slideIndex = options.nextSlide;
            if ( this.settings.playback != 'auto' )
            {
                this.enablePrevButton();
                this.enableNextButton();
            }
        }


		// Center next slide
		var $slide = $(nextSlideElement);
		var w = $slide.outerWidth();
		var h = $slide.outerHeight();
		$slide.css({
		    marginTop: (this.settings.height - h) / 2,
		    marginLeft: (this.settings.width - w) / 2
	    });


        // Update alt, title, link
        $slide.attr( 'alt', this.slides[slideIndex].alt );
        $slide.attr( 'title', this.slides[slideIndex].alt );
        if ( this.slides[slideIndex].link != '' )
        {
            var target = '';
            if ( this.slides[slideIndex].target )
            {
                target = ' target="_blank"';
            }

            $slide.wrap( '<a href="' + this.slides[slideIndex].link + '"' + target + '>' );
        }

        // Update caption
        var obj = this;
        obj.slideIndex = slideIndex;
        switch ( this.settings.captionEffect )
        {
            case 'fade':
                $('#slideshow_caption').fadeOut( this.settings.transitionTime/2,
                                                 function() { $(this).html( obj.slides[obj.slideIndex].caption ) } ).fadeIn(  this.settings.transitionTime/2 );
                break;

            case 'slide':
                $('#slideshow_caption').slideUp( function() { $(this).html( obj.slides[obj.slideIndex].caption ) } ).slideDown();
                break;

            case 'none':
            default:
                $('#slideshow_caption').html( this.slides[slideIndex].caption );
                break;
        }


        //
        // Load slide if needed
        //

        // The first time through the addSlide function doesn't exist
        if ( options.addSlide )
		{
            var loadSlideIndex = slideIndex + 1;

            if ( (loadSlideIndex < this.slides.length) && ( ! this.loadedSlides[loadSlideIndex] )  )
            {
                // Load slide
                var s = this.slides[loadSlideIndex];
                this.loadedSlides[loadSlideIndex] = s;
                var nextImage = $('<img />').attr( 'src', s.src );

                // Add it to the slideshow
                options.addSlide( '<img src="' + s.src + '" />' );
                this.enableNextButton();
            }
        }


    };


    ArtboxSlideshow.prototype.initializeButtons = function()
    {
        // If automatic playback mode, hide the prev/next controls
        if ( this.settings.playback == 'auto' || this.settings.next != this.defaults.next )
        {
            $('#slideshow_prev_button').hide();
            $('#slideshow_next_button').hide();
        }
        else if ( this.settings.playback == 'manual' )
        {
            if ( this.slides.length == 1 )
            {
                $('#slideshow_prev_button').hide();
                $('#slideshow_next_button').hide();
            }
            else if ( this.settings.loop )
            {
                this.enablePrevButton();
                this.enableNextButton();
            }
            else
            {
                this.prevButtonEnabled = true;
                this.disablePrevButton();
                this.enableNextButton();
            }

            // Preload images
            var image = $('<img />').attr( 'src', this.settings.nextButtonImage );
            image = $('<img />').attr( 'src', this.settings.nextButtonOverImage );
            image = $('<img />').attr( 'src', this.settings.prevButtonImage );
            image = $('<img />').attr( 'src', this.settings.prevButtonOverImage );
            image = $('<img />').attr( 'src', this.settings.endButtonImage );
            
            // Move the next and prev button
            $('#slideshow_prev_button').append( '#slideshow_nav' );
            $('#slideshow_next_button').append( '#slideshow_nav' );
    
        }
    };


    ArtboxSlideshow.prototype.enableNextButton = function()
    {
        if ( this.nextButtonEnabled )
          return;

        $('#slideshow_next_button').attr( 'src', this.settings.nextButtonImage );
        $('#slideshow_next_button').bind( 'mouseenter.ab', { settings: this.settings }, function(e) {
                                                          $(this).attr( 'src', e.data.settings.nextButtonOverImage );
                                                          $(this).css( 'cursor', 'pointer' );
                                                      } );
        $('#slideshow_next_button').bind( 'mouseleave.ab', { settings: this.settings },  function(e) {
                                                          $(this).attr( 'src', e.data.settings.nextButtonImage );
                                                          $(this).css( 'cursor', 'auto' );
                                                      } );
        this.nextButtonEnabled = true;
    };


    ArtboxSlideshow.prototype.enablePrevButton = function()
    {
        if ( this.prevButtonEnabled )
          return;

        $('#slideshow_prev_button').attr( 'src', this.settings.prevButtonImage );
        $('#slideshow_prev_button').bind( 'mouseenter.ab', { settings: this.settings}, function(e) {
                                                          $(this).attr( 'src', e.data.settings.prevButtonOverImage );
                                                          $(this).css( 'cursor', 'pointer' );
                                                      } );
        $('#slideshow_prev_button').bind( 'mouseleave.ab', { settings: this.settings}, function(e) {
                                                          $(this).attr( 'src', e.data.settings.prevButtonImage );
                                                          $(this).css( 'cursor', 'auto' );
                                                      } );
        this.prevButtonEnabled = true;
    };


    ArtboxSlideshow.prototype.disableNextButton = function()
    {
        if ( ! this.nextButtonEnabled )
          return;

        $('#slideshow_next_button').attr( 'src', this.settings.endButtonImage );
        $('#slideshow_next_button').unbind( 'click.ab' ).unbind( 'mouseenter.ab' ).unbind( 'mouseleave.ab' );
        this.nextButtonEnabled = false;
    };


    ArtboxSlideshow.prototype.disablePrevButton = function()
    {
        if ( ! this.prevButtonEnabled )
          return;

        $('#slideshow_prev_button').attr( 'src', this.settings.endButtonImage );
        $('#slideshow_prev_button').unbind( 'click.ab' ).unbind( 'mouseenter.ab' ).unbind( 'mouseleave.ab' );
        this.prevButtonEnabled = false;
    };


    ArtboxSlideshow.prototype.endSlide = function( options )
    {
    };
