/**
* Form Slide
*
* Element slider with optional form post
* © 2011 Nick Sutton ( nrsutton@gmail.com ) 
* 
* To create a default form slider on a specific element use $( "#elementID" ).formSlide();
* To create a default form slider on a group of elements with the same class use $( ".className" ).formSlide();
* 
* To customise the slider simply send through the relevant options
* $( "#element" ).formSlide({
*     pageWidth: 500,
*     transitionSpeed: 200
* });
* and so on.
*
* Read below for the descriptions for each option.  Don't forget to leave out the comma after the last option.  If you 
* put one in it will work in all browsers but IE
*
* If you activate a slideshow or set the slider to wrap the submit form functionality will be automatically disabled
*
* If you want to use the form slider with a form simply wrap the element you are sliding in a for e.g.
*
* <form>
*   <div id='elementForSlider'>
*       <div class='pages-container'>
*
*           <div class='form-slide-page'>
*               Page Content
*           </div>
*
*           <div class='form-slide-page'>
*               Page Content
*           </div>
*      </div>
*   </div>
* </form>
* 
* As long as the wrap option is false (which is default) and the showSubmit option is true (which is default) the form
* will be posted when the last page is reached and the submit button is clicked
*/

var shiteBrowser = $.browser.msie || false;
(function($){
    $.fn.formSlide = function( options )
    {
        var defaults = {
            explorerReductionPercentage: 20,    // Reduce the size of the box for explorer so it's the same size as the other browsers
            pageWidth: 265,                     // Width in pixels of the page
            pageHeight: 220,                    // Height in pixels of the page
            pagePadding: 8,                    // Padding in pixels of the page
            transitionSpeed: 300,               // Speed in milliseconds the transition should complete
            previousButtonText: "<Previous",  // Text for the previous button
            nextButtonText: "Next>",          // Text for the next button
            submitButtonText: "Finish",         // Text for the submit button
            pageBorderWidth: 0,                 // Border width for the page
            pageBorderColour: "#6599FF",               // Border colour for the page
            pageBorderStyle: "solid",           // Border style for the page
            showSubmit: true,                   // If set to false the submit button will not show on the last page
            allowPageScrolling: false,          // If set to true the pages will allow scrolling content.
            slideShow: false,                   // If set to true the pages will automatically slide
            slideShowInterval: 5000,            // The time in milliseconds between automatic page scrolling
            wrap: false,                        // When set to true the pages start at the begining when the end if reached ( if show submit is false )
            hideButtons: false,                 // Usefull for when slideShow is set to true
            easing: "swing"                     // Possible values "Linear", "swing"
                                                // These are how the pages ease into view.  This value has no effect
                                                // when the transitionSpeed is set to 0 making a marquee
                                                // If the easing plugin is available the installed transitions are
                                                // also available, which could be
                                                // easeOutBounce
                                                // easeOutElastic
                                                // easeOutQuad
                                                // easeOutCubic
                                                // easeOutQuart
                                                // easeOutQuint
                                                // easeOutSine
                                                // easeOutExpo
                                                // easeOutCirc
                                                // easeOutElastic (my favourite)
                                                // easeOutBack
                                                // easeOutBounce
                                                // easeIn and easeInOut versions of the above are also availale
                                                
        };

        var options = $.extend( defaults, options );
        var currentPage = 1;
        var containerWidth = options.pageWidth;
        var containerHeight = options.pageHeight;

        return this.each(function()
        {
            var dontSetTimer = false;
            var slideShowHandle;
            var obj = $( this );
            var pagesSlider = obj.children( ".pages-container")
            var pageCount = pagesSlider.children( ".form-slide-page" ).length;

            // If slideshow or wrapping is enabled the submit button will be disabled
            if ( options.slideShow || options.wrap )
                options.showSubmit = false;

            if( shiteBrowser )
            {
                // IE seems to disagree with the other browsers on how big a pixel is so
                // reduce the size of the box here
                options.pageHeight = options.pageHeight -( options.pageHeight * options.explorerReductionPercentage / 100 );
                options.pageWidth = options.pageWidth -( options.pageWidth * options.explorerReductionPercentage / 100 );
                containerWidth = options.pageWidth;
                containerHeight = options.pageHeight;
            } else {
                // Everything else other than IE puts the padding and borders on the outside of an
                // element so if it's not IE make changes to the page width here so the pages fit nicely
                // in the visible area of the container
                options.pageWidth = containerWidth - ( options.pageBorderWidth * 2 ) - ( options.pagePadding * 2 );
                options.pageHeight = containerHeight - ( options.pageBorderWidth * 2 ) - ( options.pagePadding * 2 );
            }

            // Main container CSS Properties
                obj.css( "width", containerWidth );
                obj.css( "height", containerHeight + 30); // + 30 to incorporate the buttons
                obj.css( "overflow", "hidden" );
                obj.css( "position", "relative" );

            // Page container CSS Properties
                pagesSlider.css( "height", containerHeight );
                pagesSlider.css( "width", pageCount * containerWidth );
                pagesSlider.css( "position", "relative" );

            // Page CSS Properties
                pagesSlider.children( ".form-slide-page" ).css( "padding", options.pagePadding );
                pagesSlider.children( ".form-slide-page" ).css( "width", options.pageWidth );
                pagesSlider.children( ".form-slide-page" ).css( "height", options.pageHeight );
                pagesSlider.children( ".form-slide-page" ).css( "border", options.pageBorderStyle + " " + options.pageBorderColour + " " + options.pageBorderWidth + "px" );
                pagesSlider.children( ".form-slide-page" ).css( "float", "left" );
                pagesSlider.children( ".form-slide-page" ).css( "overflow", options.allowPageScrolling ? "auto" : "hidden" );

            // Create the buttons
                var prevButton = $( "<input type=\"button\">" );
                var nextButton = $( "<input type=\"button\">" );
                var prevButtonContainer = $( "<div></div>" );
                var nextButtonContainer = $( "<div></div>" );

            // Button and button container CSS Properties
                prevButton.css( "float", "left" );
                nextButton.css( "float", "right" );
                prevButtonContainer.css( "overflow", "hidden" );
                prevButtonContainer.css( "z-index", "10" );
                prevButtonContainer.css( "position", "absolute" );
                prevButtonContainer.css( "bottom", "0" );
                nextButtonContainer.css( "overflow", "hidden" );
                nextButtonContainer.css( "position", "absolute" );
                nextButtonContainer.css( "bottom", "0" );
                nextButtonContainer.css( "text-align", "right" );
                nextButtonContainer.css( "width", containerWidth );
                //if ( ! options.wrap )
                    prevButton.css( "display", "none" );

                if ( options.hideButtons )
                {
                    nextButton.css( "display", "none" );
                    prevButton.css( "display", "none" );
                }

            // Button Values
                nextButton.val( options.nextButtonText );
                prevButton.val( options.previousButtonText );

            // Attach the buttons to the DOM
                prevButtonContainer.append( prevButton );
                nextButtonContainer.append( nextButton );
                obj.append( prevButtonContainer );
                obj.append( nextButtonContainer );

            // Previous Button functionality
                prevButton.click( function()
                {
                    if ( currentPage == 1 ) return;

                    currentPage--;
                    pagesSlider.animate({ left: '+=' + containerWidth }, options.transitionSpeed );

                    if ( currentPage == 1 )
                        prevButton.hide();

                    if ( currentPage < pageCount )
                    {
                        nextButton.val( options.nextButtonText );
                        if ( ! options.hideButtons ) nextButton.show();
                    }
                });

            // Next Button functionality
                nextButton.click( function()
                {
                    var doneSlide = false; // Used for the wrapping effect on the last page

                    if ( currentPage == pageCount )
                    {
                        if ( options.wrap )
                        {
                            // Duplicate page slider
                                var tmpHTML = pagesSlider.html();
                                var tmpWrapSlider = $( "<div>" + tmpHTML + "</div>" );
                                tmpWrapSlider.attr( "id", pagesSlider.attr( "id" ) );
                                tmpWrapSlider.attr( "rel", pagesSlider.attr( "rel" ) );
                                tmpWrapSlider.attr( "class", pagesSlider.attr( "class" ) );
                                tmpWrapSlider.css( "height", containerHeight );
                                tmpWrapSlider.css( "width", pageCount * containerWidth );
                                tmpWrapSlider.css( "position", "relative" );
                                tmpWrapSlider.css( "left", containerWidth);
                                tmpWrapSlider.css( "margin-left", "-1" );
                                tmpWrapSlider.css( "top", ( containerHeight * - 1 ) );
                                tmpWrapSlider.css( "float", "left" );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "padding", options.pagePadding );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "width", options.pageWidth );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "height", options.pageHeight );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "border", options.pageBorderStyle + " " + options.pageBorderColour + " " + options.pageBorderWidth + "px" );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "float", "left" );
                                tmpWrapSlider.children( ".form-slide-page" ).css( "overflow", options.allowPageScrolling ? "auto" : "hidden" );

                            // Add it to the container
                                obj.append( tmpWrapSlider );

                            // Animate the slider but when done, remove the current slider and replace it with the duplicate
                                var easing = options.slideShowInterval > 0 ? options.easing : "linear";
                                pagesSlider.animate({ left: [ '-=' + containerWidth, easing ] }, options.transitionSpeed, function()
                                {
                                    pagesSlider.remove();
                                    tmpWrapSlider.css( "top", 0 );
                                    pagesSlider = tmpWrapSlider;
                                } );

                            // Animate the duplicated slider (should happen at the same time as the above animation)
                                var easing = options.slideShowInterval > 0 ? options.easing : "linear";
                                tmpWrapSlider.animate({ left: [ '-=' + containerWidth, easing ] }, options.transitionSpeed, function()
                                {
                                     // This if makes the transition smoother if the interval is 0
                                     if ( options.slideShow && options.slideShowInterval > 0 && ! dontSetTimer )
                                     {
                                        slideShowHandle = setTimeout( function()
                                        {
                                            if ( ( currentPage < pageCount ) || options.wrap )
                                                nextButton.click();
                                        }, options.slideShowInterval );
                                    } else if( options.slideShow && options.slideShowInterval == 0 && ! dontSetTimer)
                                    {
                                        if ( ( currentPage < pageCount ) || options.wrap )
                                            nextButton.click();
                                    }
                                });

                            currentPage = 1;
                            prevButton.hide();
                            doneSlide = true;
                        } else {
                            obj.parent( "form" ).submit();
                            return;
                        }
                    }

                    // Sort out the sliding animation
                        if ( ! doneSlide )
                        {
                            currentPage++;
                            var easing = options.slideShowInterval > 0 ? options.easing : "linear";
                            pagesSlider.animate({ left: [ '-=' + containerWidth, easing ] }, options.transitionSpeed, function()
                            {
                                 // This if, makes the transition smoother if the interval is 0
                                 if ( options.slideShow && options.slideShowInterval > 0 && ! dontSetTimer )
                                 {
                                    slideShowHandle = setTimeout( function()
                                    {
                                        if ( ( currentPage < pageCount ) || options.wrap )
                                            nextButton.click();
                                    }, options.slideShowInterval );
                                } else if( options.slideShow && options.slideShowInterval == 0 && ! dontSetTimer )
                                {
                                    if ( ( currentPage < pageCount ) || options.wrap )
                                        nextButton.click();
                                }
                            } );
                        }

                    // Take care of the buttons
                        if ( currentPage == pageCount )
                        {
                            if ( options.showSubmit )
                                nextButton.val( options.submitButtonText );
                            else
                                if ( ! options.wrap )
                                    nextButton.hide();
                        }
    
                        if ( currentPage > 1 )
                            if ( ! options.hideButtons ) prevButton.show();
                });

            // If this is a slideshow set it off
                if ( options.slideShow )
                    slideShowHandle = setTimeout( function()
                    {
                        if ( ( currentPage < pageCount ) || options.wrap )
                            nextButton.click();
                    }, options.slideShowInterval );

            obj.mouseenter( function()
            {
                if ( options.slideShow )
                {
                    dontSetTimer = true;
                    clearTimeout( slideShowHandle );
                }
            }).mouseleave( function()
            {
                if ( options.slideShow )
                {
                    dontSetTimer = false;
                    slideShowHandle = setTimeout( function()
                    {
                        if ( ( currentPage < pageCount ) || options.wrap )
                            nextButton.click();
                    }, options.slideShowInterval );
                }
            });
        });
    };
})(jQuery);
