/*

 *  Enhanced Easy Slider

 *

 *  Built off of the Easy Slider - jQuery plugin

 *  written by Alen Grakalic

 *  http://cssglobe.com/post/3783/jquery-plugin-easy-image-or-content-slider

 *

 *  enhancements by Joseph Pecoraro

 *  email: joepeck02@gmail.com

 *  http://blog.bogojoker.com

 *

 *  The Easy Slider Copyrights:

 *  Copyright (c) 2009 Alen Grakalic (http://cssglobe.com)

 *  Dual licensed under the MIT (MIT-LICENSE.txt)

 *  and GPL (GPL-LICENSE.txt) licenses.

 *

 *  Built for jQuery library

 *  http://jquery.com

 *

 */



/*

 *  Quick Documentation of New Features

 *

 *    * Non-Autogenerated Pagination - set the autogeneratePagination

 *      option to false in the easySlide options and be sure to provide

 *      id's in the prevId and nextId options.  Those provided ids will

 *      unobtrusively get the easySlide actions applied to them.

 *

 *    * Looping - just set the loop option to true in the easySlide

 *      options and you will be able to navigate forward/backward around

 *      the ends smoothly.

 *

 *    * Autoplay - just set the autoplayDuration to a non-zero value

 *      in the easySlide options and the content will slide on its own.

 *      The value you provide will only be the value between animations,

 *      so you don't have to compensate for the speed of transitions,

 *      that is handled automatically.  Autoplaying works fine with

 *      looping.

 *

 *      If you have pagination buttons, when the user clicks a button

 *      the autoplay will suspend for a little while.  The restartDuration

 *      value specifies the amount of time since the last user

 *      interruption to wait before restarting the autoplay.

 *

 *    * Hovering - just set hover to true and pagination will trigger

 *      when hovering instead of clicking.  The slides will continue to

 *      transition as long as you hover over the pagination element.

 *      Hovering works fine with looping.

 *

 *      If you want a pause between slides you can set the hoverPause

 *      value to an integer greater than 0.  That specifies the time

 *      to wait between transitions.

 *

 *    * Linear or Swing easing - jQuery offers two different styles

 *      of animations.  Just set the easing option to 'linear' or

 *      'swing' (default)and it will use that easing style.

 *

 *    * Pauseable - Pause autoplay by hovering over an image.  Likewise

 *      you can extend this to pause when hovering the buttons as well.

 *

 *    * Fade Orientation - Not Vertical or Horizontal Slideing, but Fading!

 *      Just provide orientation: 'fade' for fading to happen.

 *

 *    * Callbacks - You are allowed to provide your own functions for

 *      events triggered by the slider.  You can provide a function

 *      for 'beforeTransition' and 'afterTransition'.  Their signature

 *      is as follows:

 *

 *          function callback( slideNumber, jQuery_li, jQuery_ul )

 *                                 ^            ^         ^

 *                                 |            |         |

 *     int of the slide number -----            |         |

 *     jQuery wrapper for the now showing <li> --         |

 *     jQuery wrapper for the entire <ul> of all slides ---

 *

 *       For example, to get the explicit DOM <li> Node you could do

 *

 *          function after(num, $li, $ul) {

 *            dom_li = $li[0];

 *            console.log(dom_li);

 *          }

 *

 */



(function($) {



  $.fn.easySlider = function(options){



    // default configuration properties

    var defaults = {

      prevId: 'prevBtn',             // id of the element to apply prev rules to

      nextId: 'nextBtn',             // id of the element to apply next rules to

      prevText: 'Previous',          // text for autogenerated prev link

      nextText: 'Next',              // text for autogenerated next link

      autogeneratePagination: false, // will automatically generate pagination links

      orientation: '',               // 'vertical', 'fade', or anything else will assume horizontal

      speed: 800,                    // duration of a transition

      autoplayDuration: 0,           // auto-play if non-zero, this is the time between transitions

      restartDuration: 2500,         // time to restart autoplay after a user interupts and autoplay

      loop: false,                   // loop around the content

      hoverPause: 0,                 // when hovering, the time between transitions

      hover: false,                  // on hover instead of onclick

      easing: null,                  // jQuery animation settings 'linear' or 'swing' (default)

      pauseable: false,              // pause autoplay when hovering the image

      pauseButtons: false,           // hovering over the cuttons will pause as well

      beforeTransition: null,        // callback before transitioning

      afterTransition: null          // callback after transitioning

    };



    var options = $.extend(defaults, options);



    return this.each(function() {



      // Setup Measurements and Options

      var obj = $(this),

          totalSlides  = $("li", obj).length,

          slideWidth   = obj.width(),

          slideHeight  = obj.height(),

          lastSlide    = totalSlides-1,

          current      = 0;



      // States

      var vertical         = (options.orientation == 'vertical'),

          fade             = (options.orientation == 'fade'),

          horizontal       = (!vertical && !fade),

          autogen          = options.autogeneratePagination,

          pauseable        = options.pauseable,

          loop             = options.loop,

          speed            = options.speed,

          easing           = options.easing,

          hover            = options.hover,

          hoverPause       = options.hoverPause,

          buttonsPause     = options.pauseButtons,

          restartDuration  = options.restartDuration,

          autoplayDuration = Math.max(options.autoplayDuration,25)+speed,

          autoplay         = (options.autoplayDuration > 0),

          beforeTransition = options.beforeTransition,

          afterTransition  = options.afterTransition;

          interval         = null,

          restart          = null;



      // Autogenerate Pagination

      if (autogen) {

        $(obj).after( '<div id="navBar"><ul><li class="arrLeft" id="'+options.prevId+'"><a href=\"javascript:void(0);\"><span>'+options.prevText+'</span></a></li> '+
'<li class="allV"><a href="/pareri"><span>Vall</span></a></li>'+
                      '<li class="arrRight" id="'+options.nextId+'"><a href=\"javascript:void(0);\"><span>'+options.nextText+'</span></a></ul></div>');

      }



      // Important Elements

      var $ul   = $("ul", obj),

          $next = $("#"+options.nextId),

          $prev = $("#"+options.prevId);



      // Loop - Duplicate the First Slide onto the end

      if (loop) {

        $ul.append( $("li:first", obj).clone() );

        totalSlides += 1;

        lastSlide += 1;

      }



      // Horizontal - Make them float left and set the width of the ul (for all slides)

      if (horizontal) {

        $("li", obj).css('float','left');

        $ul.css('width', totalSlides * slideWidth);

      }



      // Fade - Hide all but the first slide so they can fadeIn from nothing

      if (fade) {

        $ul.find("li:not(:first)").hide();

      }



      // Reusable Closure to pause the autoplay timer

      var pauseFunc = function() {

        clearInterval(interval);

        clearTimeout(restart);

      }



      // Reusable Closure to restart the autoplay timers using the restartDuration

      var restartFunc = function() {

        restart = setTimeout(function() {

          interval = setInterval(auto, autoplayDuration);

        }, restartDuration);

      };



      // Pauseable (should be autoplay only, but would have no effect otherwise)

      // On Hover: cancel the autoplay timers

      // On Leave: restart the autoplay timers

      if ( pauseable && autoplay ) {

        $(obj).hover(pauseFunc, restartFunc);

        if ( buttonsPause ) {

          $next.hover(pauseFunc, restartFunc);

          $prev.hover(pauseFunc, restartFunc);

        }

      }



      // Add Actions to Next and Prev Buttons

      // If Not Hover Mode made it click(), if it is Hover Mode, make it hover()

      // When in autoplay mode make next/prev reset the autoplay timers

      if ( !hover ) {



        $next.click(function(){

          if (autoplay) {

            pauseFunc();

            if ( !buttonsPause ) {

              restartFunc();

            }

          };

          animate("next");

        });



        $prev.click(function(){

          if (autoplay) {

            pauseFunc();

            if ( !buttonsPause ) {

              restartFunc();

            }

          };

          animate("prev");

        });



      } else {



        var hoverNext = false,

            hoverPrev = false,

            isAnimating = false;



        $next.hover(

          function() {

            var tfunc = arguments.callee;

            hoverNext = true;

            if ( !isAnimating ) {

              isAnimating = true;

              animate("next", function() {

                isAnimating = false;

                if ( hoverNext ) { tfunc(); }

              });

            }

          },

          function() {

            hoverNext = false;

          }

        );



        $prev.hover(

          function() {

            var tfunc = arguments.callee;

            hoverPrev = true;

            if ( !isAnimating ) {

              isAnimating = true;

              animate("prev", function() {

                isAnimating = false;

                if ( hoverPrev ) { tfunc(); }

              });

            }

          },

          function() {

            hoverPrev = false;

          }

        );



      }





      //

      // Enclosed Slide Animation

      //

      // This handles all of the sliding/faiding animation

      // @param dir the direction "next" or "prev"

      // @param cb the callback function

      //

      function animate(dir, cb) {



        // Before Transition, Guarantee

        if ( beforeTransition ) {

          beforeTransition( current, $ul.find('li:eq('+current+')'), $ul );

        }





        // After Transition, Guarantee

        // Setup the next have

        // NOTE: That current will be the new value when this is called

        // due to it being a closure!

        var newcb = function() {

          if ( cb != null ) {

            ( hoverPause == 0 ) ? cb() : setTimeout(cb, hoverPause);

          }

          if ( afterTransition ) {

            afterTransition( current, $ul.find('li:eq('+current+')'), $ul );

          }

        }





        // cur, nex, and update "current"

        // cur is the old current slide, the slide we are currently on

        // nex is the new current slide, the slide we are transitioning too

        // current is a global value that gets updated right here

        var cur = current;

        if ( loop ) {

          if ( dir == 'next' ) {

            current = (current==lastSlide) ? 1 : current+1;

          } else {

            current = (current==0) ? lastSlide-1 : current-1;

          }

        } else {

          if (dir == "next") {

            current = (current>=lastSlide) ? lastSlide : current+1;

          } else {

            current = (current<=0) ? 0 : current-1;

          }

        }

        var nex = current;





        // Special Case for looping

        // If at the end and going forward, instantaneous jump to the first slide

        // If at the start and going backward, instantaneous jump to the last slide

        // NOTE: The instantaneous jump is an animate() so jQuery handles it in tune

        // with the rest of the animations, and is -1 (not 0) time so its instant.

        if ( loop ) {

          if ( (dir == "next") && (cur == lastSlide) ) {

            (vertical) ?

              $ul.animate({marginTop:0}, -1) :

              $ul.animate({marginLeft:0}, -1);

          } else if ( (dir == "prev") && (cur == 0) ) {

            (vertical) ?

              $ul.animate({marginTop:(totalSlides-1)*slideHeight*-1}, -1) :

              $ul.animate({marginLeft:(totalSlides-1)*slideWidth*-1}, -1);

          }

        }





        // Dispatch jQuery Animation for the transition

        // Slide horizontally, vertically, or fade

        if ( horizontal ) {

          $ul.animate( { marginLeft: (nex*slideWidth*-1)  }, speed, easing, newcb );

        } else if ( vertical ) {

          $ul.animate( { marginTop:  (nex*slideHeight*-1) }, speed, easing, newcb );

        } else {

          var curli = 'li:eq(' + cur + ')';

          var nexli = 'li:eq(' + nex + ')';

          $ul.find(curli).fadeOut("slow", function() {

            $ul.find(nexli).fadeIn("slow", newcb);

          });

        }





        // Correctly show the Next/Prev links

        // When looping they always show, so we can ignore that

        // If at the end, hide the next link

        // If at the start, hide the previous link

        // Any other case we can show both links

        if ( !loop ) {

          if ( nex <= 0 ) {

            $prev.fadeOut();

          } else if ( nex >= lastSlide ) {

            $next.fadeOut();

          } else {

            $next.fadeIn();

            $prev.fadeIn();

          }

        }



      };





      //

      // Autoplay

      //

      // Note that autoplayDuration already has the transitionDuration

      // added to it (to prevent doing the addition over and over).

      // However that means that the first invokation would take

      // autoplayDuration+transitionDuration.  We remove that extra

      // wait by first doing a single setTimeout with the correct

      // time, followed by the correct setInterval.

      //

      if ( autoplay ) {

        var auto = function() {

          animate('next');

          if ( !loop && current>=lastSlide ) {

            clearInterval(interval);

          }

        }

        restart = setTimeout(function() {

          auto();

          interval = setInterval(auto, autoplayDuration);

        }, autoplayDuration-speed);

      }





      // Initially Hide both buttons

      $next.hide();

      $prev.hide();



      // Finally, Display the Next Link if more then one slide

      if (totalSlides>1) {

        $next.fadeIn();

        if(loop) { $prev.fadeIn(); }

      }



    });



  };



})(jQuery);
