// Stardock Effects Library
// Trimmed down and enhanced version of jQuery's animation functions.
//
// Adapted from jQuery.fx 1.3.1.1 http://jquery.com/
// Copyright (c) 2007 John Resig (jquery.com)
//
// Also adapted from jQuery Cycle plugin
// Version: 1.9 (8/22/2007)
// Copyright (c) 2007 M. Alsup
//
// Uses jQuery Easing v1.1.1 - http://gsgd.co.uk/sandbox/jquery.easing.php
// Copyright (c) 2007 George Smith
//
// These copyright notices must stay in this file according to the MIT License.
// This file requires Stardock.js

// Notes:
// Investigate removing var ref and using Function.createDelegate
// Allow for lookup of elements using $id()


Sd.Effects = Class.create();
Sd.Effects = function(elem, options, prop) {
   var ref = this;
   var style = elem.style;
   
   ref.show = function() {
      options.show = true;
      ref.animate(0, 1);
      style.display = "block";
   };
   
   ref.hide = function() {
      options.hide = true;
      ref.animate(1, 0);
   };
   
   ref.max = function() {
   
      return 0;
     // return parseFloat( Sd.Effects.getCSS(elem, prop) );
   }
   
   // returns the current style prop as an integer
   ref.cur = function() {
   
      var r = parseFloat( Sd.Effects.getCSS(elem, prop) );
      return r;

   }
   
   ref.changeStyle = function() {
      if( options.step ) options.step.apply( elem, [this.now] );
   
      // If it's opacity, let Style handle it so issues with IE can be managed. Otherwise, set the property
      if( prop == "opacity" ) {
        
         Sd.Effects.Style(elem, 'opacity', this.now);
         
      } else {
         style[prop] = parseInt(this.now) + "px";
         if( prop == "height" || prop == "width" ) style.display = "block";
         
      }
   };
   
   ref.animate = function(start, end) {
      ref.startTime = (new Date()).getTime();
      ref.now = start;
      ref.changeStyle();
      
      
      Sd.Effects.timers.push( function() {
        return ref.step(start, end)
      } );
      
      
      if ( Sd.Effects.timers.length == 1 ) {
			var timer = setInterval(function(){
				var timers = Sd.Effects.timers;
				
				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) clearInterval( timer );
				
			}, 13);
		}	
   };
   
   ref.step = function(first, last) {
      var t = (new Date()).getTime();
      
      if( t > options.duration + ref.startTime ) {
         ref.now = last;
         ref.changeStyle();
         var done = true;
         
         if( done ) {
            if( options.hide ) style.display = "none";
         }      
      
         if( done && Sd.Effects.isFunction( options.complete ) ) {
            options.complete.apply(elem);
         }
         return false;
      } else {
        var n = t - ref.startTime;
        var p = n / options.duration;
        
        // Use the easing function.
        ref.now = ref.easing[options.easing]( p, n, first, (last-first), options.duration );
    
        ref.changeStyle();
      }
      
      
      return true;
   };
   
   ref.easing = {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		},
		easein: function(x, t, b, c, d) {
			return c*(t/=d)*t + b; // in
		},
		easeinout: function(x, t, b, c, d) {
			if (t < d/2) return 2*c*t*t/(d*d) + b;
			var ts = t - d/2;
			return -2*c*ts*ts/(d*d) + 2*c*ts/d + c/2 + b;		
		},
		easeout: function(x, t, b, c, d) {
			return -c*t*t/(d*d) + 2*c*t/d + b;
		},
		expoin: function(x, t, b, c, d) {
			var flip = 1;
			if (c < 0) {
				flip *= -1;
				c *= -1;
			}
			return flip * (Math.exp(Math.log(c)/d * t)) + b;		
		},
		expoout: function(x, t, b, c, d) {
			var flip = 1;
			if (c < 0) {
				flip *= -1;
				c *= -1;
			}
			return flip * (-Math.exp(-Math.log(c)/d * (t-d)) + c + 1) + b;
		},
		expoinout: function(x, t, b, c, d) {
			var flip = 1;
			if (c < 0) {
				flip *= -1;
				c *= -1;
			}
			if (t < d/2) return flip * (Math.exp(Math.log(c/2)/(d/2) * t)) + b;
			return flip * (-Math.exp(-2*Math.log(c/2)/d * (t-d)) + c + 1) + b;
		},
		bouncein: function(x, t, b, c, d) {
			return c - ref.easing['bounceout'](x, d-t, 0, c, d) + b;
		},
		bounceout: function(x, t, b, c, d) {
			if ((t/=d) < (1/2.75)) {
				return c*(7.5625*t*t) + b;
			} else if (t < (2/2.75)) {
				return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
			} else if (t < (2.5/2.75)) {
				return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
			} else {
				return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
			}
		},
		bounceinout: function(x, t, b, c, d) {
			if (t < d/2) return ref.easing['bouncein'] (x, t*2, 0, c, d) * .5 + b;
			return ref.easing['bounceout'] (x, t*2-d,0, c, d) * .5 + c*.5 + b;
		},
		elasin: function(x, t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
			if (a < Math.abs(c)) { a=c; var s=p/4; }
			else var s = p/(2*Math.PI) * Math.asin (c/a);
			return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		},
		elasout: function(x, t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
			if (a < Math.abs(c)) { a=c; var s=p/4; }
			else var s = p/(2*Math.PI) * Math.asin (c/a);
			return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
		},
		elasinout: function(x, t, b, c, d) {
			var s=1.70158;var p=0;var a=c;
			if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
			if (a < Math.abs(c)) { a=c; var s=p/4; }
			else var s = p/(2*Math.PI) * Math.asin (c/a);
			if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
			return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
		},
		backin: function(x, t, b, c, d) {
			var s=1.70158;
			return c*(t/=d)*t*((s+1)*t - s) + b;
		},
		backout: function(x, t, b, c, d) {
			var s=1.70158;
			return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
		},
		backinout: function(x, t, b, c, d) {
			var s=1.70158;
			if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
			return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
		}
		
	};
};

Sd.Effects.timers = [];

Sd.Effects.perform = function( elem, prop, speed, easing, callback) {

   // setting up the options object
   var options = speed && speed.constructor == Object ? speed: {
      complete: callback,
      duration: speed,
      easing: easing || easing && easing.constructor != Function && easing || "swing"
   };
                   
   // duration can take in a number, "fast", or "slow"            
   options.duration = (options.duration && options.duration.constructor == Number ? options.duration : { slow: 600, fast: 200 }[options.duration]) || 400;

   // Running effects.
   for( action in prop ) {
      var effect = new Sd.Effects(elem, options, action);
      
      if( prop[action].constructor == Number ) {
         effect.animate( effect.cur() || 0, prop[action] );
      } else {
         effect[ prop[action] ]( prop );
      }
   }
};

Sd.Effects.isFunction = function( fn ) {
    return !!fn && typeof fn != "string" && !fn.nodeName &&
            fn.constructor != Array && /function/i.test( fn + "" ); 
};


// changes the css style of 'key' to 'value' on element 'elem'
// stripped down mix of jQuery .css and .attr. ONLY works with styles!! Will not set attributes for all elements.
Sd.Effects.Style = function( elem, key, value ) {

   // Safari fix for selected attr
   if ( value == "selected" && Sd.Common.Browser.safari ) elem.parentNode.selectedIndex;
   
   // Allow for elem to be an ID of an element.
   if( elem && elem.constructor == String ) elem = $id(elem);
   
   // force elements to use style. IE was having issues with this, so it's being forced to use it.
   if( Sd.Common.Browser.ie || elem != elem.style ) elem = elem.style; 
      
   // filter fix for IE opacity
   if( key == "opacity" && Sd.Common.Browser.ie ) {
      if( value != undefined ) {
         elem.zoom = 1;
         elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,"") +
                  (parseFloat(value).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")")

         return elem.filter ? 
               (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : "";
      }
   }

   // set the style. 
   key = key.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});
   if ( value != undefined ) elem[key] = value;
   return elem[key];

};


// curCSS from jQuery
Sd.Effects.getCSS = function( elem, prop, force ) {

	var ret;

   // handle opacity
   if (prop == "opacity" && Sd.Common.Browser.ie) {
   
     return elem.style.filter ? (parseFloat( elem.style.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : "";
    //  ret = jQuery.attr(elem.style, "opacity");
   //   return ret == "" ? "1" : ret;
   }
   
   if (prop.match(/float/i)) 
      prop = Sd.Common.Browser.ie ? "styleFloat" : "cssFloat";
   
   if (!force && elem.style[prop])
      ret = elem.style[prop];

   else if (document.defaultView && document.defaultView.getComputedStyle) {

      if (prop.match(/float/i))
         prop = "float";

      prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();
      var cur = document.defaultView.getComputedStyle(elem, null);

      if ( cur )
         ret = cur.getPropertyValue(prop);
      else if ( prop == "display" )
         ret = "none";
      else {
      
         // swap function.
         elem.style["olddisplay"] = elem.style["display"];
         elem.style["display"] = "block";
         var c = document.defaultView.getComputedStyle(elem, "");
         ret = c && c.getPropertyValue(prop) || "";
         elem.style["display"] = e.style["olddisplay"];
      
      }

   } else if (elem.currentStyle) {
      var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});
      ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
   }

   return ret;

}

Sd.Effects.Hover = Class.create();
Sd.Effects.Hover.prototype = 
{
   activityDelay: 5000,
   delay: 250,

   initialize: function( ele, funcOver, funcOut, delay )  
   {
      if( ele.constructor == String ) ele = $id(ele);
   
      this.ele = ele;
      this.funcOver = funcOver;
      this.funcOut = funcOut;
      if( delay ) this.delay = delay;

      var hoverOverHandler = Function.createDelegate(this, this.show);
      var hoverOutHandler = Function.createDelegate(this, this.hoverOut);
      
      Sd.Common.addEvent( this.ele, 'mouseover', hoverOverHandler, ele.id + 'Hover_MouseOver');
      Sd.Common.addEvent( this.ele, 'mouseout', hoverOutHandler, ele.id + 'Hover_MouseOut');
   },

   // fires hide function again.
   hoverOut: function() 
   {
      this.open = false;
      this.hideMenu();
   },
   /*
   // calls hide menu   
   out: function() 
   {
      this.over = false;
      this.clearTimeout();
      this.hideMenu();
   },*/

   // if not already over, fades in. Fires hide function after actDelay 
   show: function() 
   {
      this.clearTimeout();
      this.over = true;
      var showHandler = Function.createDelegate(this, this.showMenu)
      this.hideTimer = window.setTimeout( showHandler, this.delay);
   },

   showMenu: function() 
   {
      if( this.over ) {
         // fire the in function
         this.funcOver.apply(this.ele);
         
         var timeoutHandler = Function.createDelegate(this, this.hideMenu)
         this.timeoutFunc = window.setTimeout( timeoutHandler, this.activityDelay);
      }
   },

   // clears both timers.
   clearTimeout: function() 
   {
      if( this.hideTimer ) this.hideTimer = window.clearTimeout(this.hideTimer);
      if( this.timeoutFunc ) window.clearTimeout(this.timeoutFunc);
   },

   // clears hideTimer, fires hide() after delay.
   hideMenu: function() 
   {
      if( this.hideTimer ) window.clearTimeout(this.hideTimer);
      var hideHandler = Function.createDelegate(this, this.hide);
      this.hideTimer = window.setTimeout(hideHandler, this.delay);
   },

   // resets flags, clears hideTimer, fires fade out
   hide: function() 
   {
  
      
      //if( !this.over )  {
         if( this.hideTimer ) window.clearTimeout(this.hideTimer);
         this.hideTimer = 0;
         
         // Fire the outgoing function
         this.funcOut.apply(this.ele);
   //   }
   }

}
 















// Effects
Sd.Effects.fadeOut = function(elem, speed, callback) {
   return Sd.Effects.perform(elem, {opacity: "hide"}, speed, "linear", callback);
};

Sd.Effects.fadeIn = function(elem, speed, callback) {
   return Sd.Effects.perform(elem, {opacity: "show"}, speed, "linear", callback);
};

Sd.Effects.slideShow = function( elem, options ) {

   // Allow for elem to be an ID of an element.
   if( elem && elem.constructor == String ) elem = $id(elem);
   
   $slides = [];
   opts = options;
   
   // Using prototype's object.extend to copy properties over
   for (var property in Sd.Effects.slideShow.defaults) {

      // Prevent overwriting of properties! Might be a bad idea.
      if( opts[property] == null ) opts[property] = Sd.Effects.slideShow.defaults[property];
     
   }

   // Get all child elements from .children()
   var slide = elem.firstChild;
   for( ; slide; slide = slide.nextSibling ) {
    if( slide.nodeType == 1 && (!elem || slide != elem) ) $slides.push( slide );
   }

   // Hover pausing function 
   
   if (opts.pause) new Sd.Effects.Hover(elem, 
   
      // pause on mouseover
      function(){ 
         opts.paused = 1; 
         clearTimeout(elem.cycleTimeout); 
         elem.cycleTimeout = 0;
      }, 
      
      // unpause, reset timer on mouse out
      function(){ 
         opts.paused = 0; 
         
         clearTimeout(elem.cycleTimeout);
         elem.cycleTimeout = 0;
         if (opts.timeout) elem.cycleTimeout = setTimeout(function() {Sd.Effects.slideShow.perform($slides, opts, 0) }, opts.timeout);

      });
   
   opts.before = opts.before ? [opts.before] : [];
   opts.after = opts.after ? [opts.after] : [];
   
   // This is NECESSARY. Sets the width, height, and position of the container.
   elem.style.position = 'relative';
   if (opts.width) elem.style.width = opts.width;
   if (opts.height && opts.height != 'auto') elem.style.height = opts.height;

   // We're going to assume that all slides fit within elem. Otherwise, resize here.
   
   // Modify z-index so each slide is on a different 'layer', hide all slides, set position
   for( i=0; i<$slides.length; i++ ) {
      Sd.Effects.Style($slides[i], 'z-index', $slides.length - i);
      Sd.Effects.Style($slides[i], 'position', 'absolute');
      Sd.Effects.Style($slides[i], 'display', 'none');
   }
   
   // Show the first slide.
   Sd.Effects.Style($slides[0], 'display', 'block');

   // Test here if we have diff fx functions
   var init;
   if( opts.fxNext != null && opts.fxPrev != null ) {
      opts.fxDiff = true;
      
      init = Sd.Effects.slideShow.transitions[opts.fxNext];
   } else {
   
      init = Sd.Effects.slideShow.transitions[opts.fx];
   }
   
   if (Sd.Effects.isFunction(init)) init(elem, $slides, opts);

   // Making sure these options have objects at least
   opts.cssBefore = opts.cssBefore || {};
   opts.animIn = opts.animIn || {};
   opts.animOut = opts.animOut || {};
   
   // applying cssBefore and cssFirst to the first slide
   for( prop in opts.cssBefore ) {
      if( prop != null ) Sd.Effects.Style($slides[0], prop, opts.cssBefore[prop] );
   }
   for( prop in opts.cssFirst ) {
      if( prop != null ) Sd.Effects.Style($slides[0], prop, opts.cssFirst[prop] );
   }
   
   // Set other options
   if (opts.timeout) {
      // ensure that timeout and speed settings are sane
      if (opts.speed.constructor == String)
          opts.speed = {slow: 600, fast: 200}[opts.speed] || 400;
      if (!opts.sync)
          opts.speed = opts.speed / 2;
      while((opts.timeout - opts.speed) < 250)
          opts.timeout += opts.speed;
   }
   
   if (opts.easing) opts.easeIn = opts.easeOut = opts.easing;
   if (!opts.speedIn) opts.speedIn = opts.speed;
   if (!opts.speedOut) opts.speedOut = opts.speed;

   // Randomize next slide or choose 1 for the next slide
   opts.nextSlide = opts.random ? (Math.floor(Math.random() * ($slides.length-1)))+1 : 1;
   opts.currSlide = 0;   
      
   // Set click events 
   if (opts.click && !opts.next) opts.next = opts.click;
   if (opts.next)
      Sd.Common.addEvent( $id(opts.next), 'mousedown', function(){return Sd.Effects.slideShow.advance($slides,opts,1)}, 'slideShowNext');
   if (opts.prev)
     Sd.Common.addEvent( $id(opts.prev), 'mousedown', function(){return Sd.Effects.slideShow.advance($slides,opts,-1)}, 'slideShowPrev');
    
  // if (opts.pager)
     // buildPager(els,opts);
   if (opts.timeout) this.cycleTimeout = setTimeout(function(){Sd.Effects.slideShow.perform($slides,opts,0)}, opts.timeout + (opts.delay||0));
      
};
// advance slide forward or back
Sd.Effects.slideShow.advance = function(els, opts, val) {
   
   if( !opts.isAnim && !opts.paused ) {
      opts.isAnim = true;

      var p = els[0].parentNode, timeout = p.cycleTimeout;

      if (timeout) {
        clearTimeout(timeout);
        p.cycleTimeout = 0;
      }

      opts.nextSlide = opts.currSlide + val;

      if (opts.nextSlide < 0)
        opts.nextSlide = els.length - 1;
      else if (opts.nextSlide >= els.length)
        opts.nextSlide = 0;
        
      // Check for diff fx functions. If there are, fire the init of that transition. 
      // We probably need to clear variables here, in case the transitions are REALLY different...i.e., shuffle and scroll
      if( opts.fxDiff ) {
        
         if( val == 1 ) 
            init = Sd.Effects.slideShow.transitions[opts.fxNext];
         else
            init = Sd.Effects.slideShow.transitions[opts.fxPrev];
    
      
         if (Sd.Effects.isFunction(init)) init(p, $slides, opts);
      } 
        
      Sd.Effects.slideShow.perform(els, opts, 1, function() { opts.isAnim = false; } );
      return false;
   }
};

Sd.Effects.slideShow.perform = function($slides, opts, manual, callback) {
   var parentElem = $slides[0].parentNode;
   var curr = $slides[opts.currSlide];
   var next = $slides[opts.nextSlide];
   
   // Fire the before functions
   if( opts.before.length ) {
      for( var func in opts.before ) {
         opts.before[func](curr, next, opts);
      }
   }
   
   
   if (manual || !opts.paused) {
      if (opts.autostop && (--opts.countdown == 0)) return;
      if (opts.nextSlide != opts.currSlide) {

         // set CSS for the next slide
         for( prop in opts.cssBefore ) {
            if( prop != null ) Sd.Effects.Style(next, prop, opts.cssBefore[prop] );
         }
   
         // Save the next slide animation function as a variable.
         var nextFunc = function() {  Sd.Effects.perform( next, opts.animIn, opts.speedIn, opts.easeIn, callback ); };

         // Fire the current slide out animation. If animation is not synced, fire when done
         Sd.Effects.perform( curr, opts.animOut, opts.speedOut, opts.easeOut, function() {
            if (!opts.sync) nextFunc();
         } );   
         
         // Otherwise, fire the next slide animation at the same time
         if( opts.sync ) nextFunc();
      }
      
      // Finding the next slide...
      if (opts.random) {
         opts.currSlide = opts.nextSlide;
         while (opts.nextSlide == opts.currSlide)
             opts.nextSlide = Math.floor(Math.random() * $slides.length);
      }
      else { // sequence
         var roll = (opts.nextSlide + 1) == $slides.length;
         opts.nextSlide = roll ? 0 : opts.nextSlide+1;
         opts.currSlide = roll ? $slides.length-1 : opts.nextSlide-1;
      }
   } 
  
   // clear timeout first so we dont have more than one running
   if (opts.timeout) {
      clearTimeout( parentElem.cycleTimeout );
      parentElem.cycleTimeout = setTimeout(function() {Sd.Effects.slideShow.perform($slides, opts, 0) }, opts.timeout);
   }
}


// Transition functions
Sd.Effects.slideShow.transitions = {

   scrollRight: function(elem, $slides, opts) {
      Sd.Effects.Style(elem, 'overflow', 'hidden');

      // Move the slide to the left of the current slide and show it.
      opts.before.push(function(curr, next, opts) {
        opts.cssBefore.left = 0-curr.offsetWidth + "px";
        opts.cssBefore.display = "block";
        opts.animOut.left = curr.offsetWidth;
      });

      opts.cssFirst = { left: "0px" };
      opts.animIn   = { left:  0 };
   },
   
   scrollLeft: function(elem, $slides, opts) {
      Sd.Effects.Style(elem, 'overflow', 'hidden');
      opts.before.push(function(curr, next, opts) {
         opts.cssBefore.left = curr.offsetWidth + "px";
         opts.cssBefore.display = "block";
         opts.animOut.left = 0-curr.offsetWidth;
      });
      opts.cssFirst = { left: "0px" };
      opts.animIn   = { left: 0 };
   }

}


Sd.Effects.slideShow.defaults = {
    fx:         'scrollRight', // one of: fade, shuffle, zoom, slideX, slideY, scrollUp/Down/Left/Right
    timeout:     4000,  // milliseconds between slide transitions (0 to disable auto advance)
    speed:       1000,  // speed of the transition (any valid fx speed value)
    speedIn:     null,  // speed of the 'in' transition
    speedOut:    null,  // speed of the 'out' transition
    next:        null,  // id of element to use as click trigger for next slide
    prev:        null,  // id of element to use as click trigger for previous slide
    pager:       null,  // id of element to use as pager container
    before:      null,  // transition callback (scope set to element to be shown)
    after:       null,  // transition callback (scope set to element that was shown)
    easing:      null,  // easing method for both in and out transitions
    easeIn:      null,  // easing for "in" transition
    easeOut:     null,  // easing for "out" transition
    shuffle:     null,  // coords for shuffle animation, ex: { top:15, left: 200 }
    animIn:      null,  // properties that define how the slide animates in
    animOut:     null,  // properties that define how the slide animates out
    cssBefore:   null,  // properties that define the initial state of the slide before transitioning in
    cssAfter:    null,  // properties that defined the state of the slide after transitioning out
    height:     'auto', // container height
    sync:        1,     // true if in/out transitions should occur simultaneously
    random:      0,     // true for random, false for sequence (not applicable to shuffle fx)
    fit:         0,     // force slides to fit container
    pause:       0,     // true to enable "pause on hover"
    autostop:    0,     // true to end slideshow after X transitions (where X == slide count)
    delay:       0,     // additional delay (in ms) for first transition (hint: can be negative)
    isAnim:      0,     // Flag to prevent abuse of advancing the slides
    fxNext:       null, // next animation
    fxPrev:       null, // prev animation
    fxDiff:       0     // boolean to see if Next and Prev animations exist, and if so, perform different ones.
};

