/**
 * jQuery Page Slider
 *
 * Allows the pagination to provide a nice sliding effect when transitioning
 * between pages.
 *
 * @package   Visum
 * @author    $LastChangedBy$
 * @copyright Copyright (c) 2009 Titan Interactive (http://www.titaninteractive.com.au/)
 * @version   $Rev$
 *            $URL$
 *            $LastChangedDate$
 */

(function($){
    
    $.fn.nextPage = function ( page_container )
    {
        /// Determine the next page
        var next_page = $.trim( this.find('.current').next().text() );
        var next_url = this.find('.current').next().find('a').attr('href');
        
        return this.page( next_page, next_url, page_container );
    }
    
    $.fn.prevPage = function ( page_container )
    {
        /// Determine the next page
        var prev_page = $.trim( this.find('.current').prev().text() );
        var prev_url = this.find('.current').prev().find('a').attr('href');
        
        return this.page( prev_page, prev_url, page_container );
    }
    
    $.fn.page = function( page_number, page_url, page_container )
    {
        /// Determine the current page
        var current_page = $.trim( this.find('.current').text() );
        
        /// Change the current page to match the selected page
        this.children('.current').removeClass('current');
        this.children(':contains('+ page_number +')').addClass('current');
        
        /// Load the page url using an ajax request and retrive the page
        /// data from the page content
        $.ajax(
            { url: page_url
            , cache: false
            , pagination: this
            , container: page_container
            , current_page: current_page
            , page_number: page_number
            , success: function( html )
                {
					/// Load the new and old elements and prepare to shift them
                    var new_element = $( html ).find( this.container + ' > *' );
					var old_element = $( this.container ).children(':last-child');
					
					/// Shift the elements within the container
					$( this.container ).slideSwitch( old_element, new_element, { direction: ( current_page < page_number ? 'after' : 'before' ) } );
                }
            }
        );
        
        /// Hide the next button if neccisasary
        if( this.children('.current').next().hasClass('next') )
        {
            this.children('.next').hide();
        }
        else
        {
            this.children('.next').show();
            this.children('.next').find('a').attr('href', this.children('.current').next().find('a').attr('href') );
        }
        
        /// Hide the previous button if neccisasary
        if( this.children('.current').prev().hasClass('prev') )
        {
            this.children('.prev').hide();
        }
        else
        {
            this.children('.prev').show();
            this.children('.prev').find('a').attr('prev', this.children('.current').prev().find('a').attr('href') );
        }
        
        /// Implement a fluid interface
        return this;
    }
	
	$.fn.slideSwitch = function( old_element, new_element, options )
	{
		/// Default options
		var defaults = { direction: 'after'
		               , speed: 'slow' };
		
		/// Merge the default options
		options = $.extend( {}, defaults, options );
		
		/// Determine the parent element of the old element
		var parent = $( old_element ).parent();
		
		/// Determine the parent height
		var parent_old_height = parent.height();
		var parent_width = parent.width();
		
		/// Absolutely position the old element
		$( old_element ).css({ position: 'absolute'
							 , width: $( old_element ).width() });
		
		/// Fix the height within the parent while the new element is added
		var x = 0;
		switch( options.direction )
		{
			case 'before':
				$( new_element ).insertBefore( old_element );
				x = 1;
				break;
			
			default:
				$( new_element ).insertAfter( old_element );
				x = -1;
		}
		
		/// Determine the new height of the parent element
		var parent_new_height = parent.height();
		parent.css({ height: parent_old_height });
		
		/// Display the new element outside the parent element
		$( new_element ).css({ left: -x * parent_width });
		
		/// If the parent is increasing in size animate it prior to sliding the
		/// elements
		if( parent_new_height > parent_old_height )
		{
			/// Animate the parent's height, then animate the elements within
			parent.animate({ height: parent_new_height }
						  , options.speed
						  , function()
							{
								$( old_element ).animate({ left: x * parent_width }, options.speed, function(){ $(this).remove(); } );
								$( new_element ).animate({ left: 0 }, options.speed);
								parent.css({ height: 'auto' });
							}
						  );
		}
		
		/// If the parent is decreasing in size, animate it after sliding the
		/// elements
		else if ( parent_new_height < parent_old_height )
		{
			$( old_element ).animate({ left: x * parent_width }, options.speed, function(){ $(this).remove(); } );
			$( new_element ).animate({ left: 0 }, options.speed
									, function()
										{
											parent.animate({ height: parent_new_height }, options.speed, function(){ $(this).css({ height: 'auto' }); } );
										}
									);
		}
		
		/// Otherwise, only animate the internal elements
		else
		{
			$( old_element ).animate({ left: x * parent_width }, options.speed, function(){ $(this).remove(); });
			$( new_element ).animate({ left: 0 }, options.speed, function(){ parent.css({ height: 'auto' }); });
		}
        
        /// Implement a fluid interface
        return this;
	}
    
})(jQuery);