/*
 * jQuery RefineSlide plugin v0.4.1
 * http://github.com/alexdunphy/refineslide
 * Requires: jQuery v1.8+
 * MIT License (http://www.opensource.org/licenses/mit-license.php)
 *
 * global Modernizr 
*/

;(function ($, window, document) {
  'use strict';

  // Baked-in settings for extension
  var defaults = {
    maxWidth              : 800,      // Max slider width - should be set to image width
    // Transition type:
    // ('custom', random', 'cubeH', 'cubeV', 'fade', 'sliceH', 'sliceV', 'slideH', 'slideV', 
    // 'scale', 'blockScale', 'kaleidoscope', 'fan', 'blindH', 'blindV')
    transition            : 'cubeV',
    customTransitions     : [],
    // 3d fallback: (default 'sliceV'): 
    // Fallback for browsers that support transitions, but not 3d transforms 
    // (used if primary transition uses 3d-transforms)
    fallback3d            : 'sliceV',
    perspective           : 1000,     // Perspective (used for 3d transforms)
    useThumbs             : true,     // Bool (default true): Navigation type thumbnails
    useArrows             : false,    // Bool (default false): Navigation type previous and next arrows
    thumbMargin           : 3,        // Int (default 3): Percentage width of thumb margin
    autoPlay              : false,    // Int (default false): Auto-cycle slider
    delay                 : 5000,     // Int (default 5000) Time between slides in ms
    transitionDuration    : 800,      // Int (default 800): Transition length in ms
    startSlide            : 0,        // Int (default 0): First slide
    keyNav                : true,     // Bool (default true): Use left/right arrow keys to switch slide
    captionWidth          : 50,       // Int (default 50): Percentage of slide taken by caption
    // String: The markup used for arrow controls (if arrows are used). Must use classes '.rs-next' & '.rs-prev'
    controlsTemplate      : '<div class="rs-controls"><button class="rs-prev" title="Previous">◅</button>'+
                            '<button class="rs-next" title="Next">▻</button>'+
                            '<span class="rs-counter"><span class="rs-current-index"></span>'+
                            ' of <span class="rs-count"></span></span>' +
                            '<button class="fullscreen-toggle" title="full-screen">⤄</button></div>',
    onInit                : function () {}, // Func: User-defined, fires with slider initialisation
    onChange              : function () {}, // Func: User-defined, fires with transition start
    afterChange           : function () {}  // Func: User-defined, fires after transition end
  };

  // RS (RefineSlide) object constructor
  function RS(elem, settings) {
    this.$slider            = $(elem).addClass('rs-slider');       // Elem: Slider element
    this.settings           = $.extend({}, defaults, settings);    // Obj: Merged user settings/defaults
    this.$slides            = this.$slider.find('> *');            // Elem Arr: Slide elements
    this.totalSlides        = this.$slides.length;                 // Int: Number of slides
    this.cssTransitions     = testBrowser.cssTransitions();        // Bool: Test for CSS transition support
    this.cssTransforms3d    = testBrowser.cssTransforms3d();       // Bool: Test for 3D transform support
    this.currentPlace       = this.settings.startSlide;         // Int: Index of current slide (starts at 0)
    this.$currentSlide      = this.$slides.eq(this.currentPlace);  // Elem: Starting slide
    this.inProgress         = false;                               // Bool: Prevents overlapping transitions
    this.$sliderWrap        = this.$slider.wrap('<div class="rs-wrap" />').parent();      // Elem: Slider wrapper div
    // Elem: Slider background (useful for styling & essential for cube transitions)
    this.$sliderBG          = this.$slider.wrap('<div class="rs-slide-bg" />').parent();
    // Make slider object accessible to client call code with 'this.slider' (there's probably a better way to do this)
    this.settings.slider = this;
    this.$currentIndexWrapper = $('.rs-current-index');
    this.init();
  }

  RS.prototype = {
    cycling: null,
    $slideImages: null,

    init: function () {
      // User-defined function to fire on slider initialisation
      this.settings.onInit();

      // Setup captions
      this.captions();

      if(this.settings.transition === 'custom') {
        this.nextAnimIndex = -1; // Set animation index for custom animation
      }

      if (this.settings.keyNav) {
        this.setKeys(); // Setup keyboard navigation
      }

      for (var i = 0; i < this.totalSlides; i++) { // Add slide identifying classes
        this.$slides.eq(i).addClass('rs-slide-' + i);
      }

      if (this.settings.autoPlay) {
        this.setAutoPlay();

        // Listen for slider mouseover
        this.$slider.on({
          mouseenter: $.proxy(function () {
            if (this.cycling !== null) {
              clearTimeout(this.cycling);
            }
          }, this),
          mouseleave: $.proxy(this.setAutoPlay, this) // Resume slideshow
        });
      }

      // Get the first image in each slide <li>
      this.$slideImages = this.$slides.find('img:eq(0)');

      this.setup();
    },
    setup: function () {

      if (this.settings.useThumbs) {
        this.setThumbs();
      }

      if (this.settings.useArrows) {
        this.setArrows(); // Setup arrow navigation
      }
      $('.rs-current-index').html(this.settings.startSlide + 1);
      $('.rs-count').html(this.totalSlides);

      // Display first slide
      this.$currentSlide.css({'opacity' : 1, 'z-index' : 2});
    },
    setArrows:function () {
      var that = this;

      // Append user-defined arrow template (elems) to '.rs-wrap' elem
      this.$sliderWrap.prepend(this.settings.controlsTemplate);

      // Fire next() method when clicked
      $('.rs-next', this.$sliderWrap).on('click', function (e) {
        e.preventDefault();
        that.next();
      });

      // Fire prev() method when clicked
      $('.rs-prev', this.$sliderWrap).on('click', function (e) {
        e.preventDefault();
        that.prev();
      });
    },
    next: function () {
      if (this.settings.transition === 'custom') {
        this.nextAnimIndex++;
      }
      // If on final slide, loop back to first slide
      if (this.currentPlace === this.totalSlides - 1) {
        this.transition(0, true); // Call transition
      } else {
        this.transition(this.currentPlace + 1, true); // Call transition
      }
    },
    prev: function () {
      if (this.settings.transition === 'custom') {
        this.nextAnimIndex--;
      }
      // If on first slide, loop round to final slide
      if (this.currentPlace === 0) {
        this.transition(this.totalSlides - 1, false); // Call transition
      } else {
        this.transition(this.currentPlace - 1, false); // Call transition
      }
    },
    setKeys: function () {
      var that = this;

      // Bind keyboard left/right arrows to next/prev methods
      $(document).on('keydown', function (e) {
        if (e.keyCode === 39) { // Right arrow key
          that.next();
        } else if (e.keyCode === 37) { // Left arrow key
          that.prev();
        }
      });
    },
    setAutoPlay: function () {
      var that = this;

      // Set timeout to object property so it can be accessed/cleared externally
      this.cycling = setTimeout(function () {
        that.next();
      }, this.settings.delay);
    },
    setThumbs: function () {
      var that = this,
        // Set percentage width (minus user-defined margin) to span width of slider
        width = (100 - ((this.totalSlides) * this.settings.thumbMargin)) / this.totalSlides + '%';

      //<Wrapper to contain thumbnails
      this.$thumbWrap = $('<div class="rs-thumb-wrap" />').prependTo(this.$sliderWrap);

      // Loop to apply thumbnail widths/margins to <a> wraps, appending an image clone to each
      for (var i = 0; i < this.totalSlides; i++) {
        var $thumb = $('<a />')
          .css({
            width : width,
            marginLeft : this.settings.thumbMargin + '%'
          })
          .attr('href', '#')
          .data('rs-num', i);
        this.$thumbWrap.append($thumb);
      }
      this.$thumbWrapLinks = this.$thumbWrap.find('a');

      this.$slides.each(function(index) {
        var $thumb = $('.rs-thumb-wrap a').eq(index),
            $this = $(this),
            $img = $this.find('img');

        if ($img.length > 0) {
          $thumb.html($img.clone());
        }
        else {
          $thumb.html('<span>' + $this.data('slide-type') + '</span>')
          .attr('data-slide-type', $this.data('slide-type'));
        }
      });

      // Safety margin to stop IE7 wrapping the thumbnails (no visual effect in other browsers)
      //this.$thumbWrap.children().last().css('margin-right', -10);

      // Add active class to starting slide's respective thumb
      this.$thumbWrapLinks.eq(this.settings.startSlide).addClass('active');

      // Listen for click events on thumnails
      this.$thumbWrap.on('click', 'a', function (e) {
        e.preventDefault();

        that.transition(parseInt($(this).data('rs-num'), 10)); // Call transition using identifier from thumb class
      });
    },
    captions: function() {
      var that = this,
          $captions = this.$slides.find('.rs-caption');

      // User-defined caption width
      $captions.css({
        width: that.settings.captionWidth + '%',
        opacity: 0
      });

      // Display starting slide's caption
      this.$currentSlide.find('.rs-caption').css('opacity', 1);

      $captions.each(function() {
        $(this).css({
          transition: 'opacity ' + that.settings.transitionDuration + 'ms linear',
          backfaceVisibility: 'hidden'
        });
      });
    },
    transition: function (slideNum, forward) {
      // If inProgress flag is not set (i.e. if not mid-transition)
      if (!this.inProgress) {
        // If not already on requested slide
        if (slideNum !== this.currentPlace) {
          // Check whether the requested slide index is ahead or behind in the array (if not passed in as param)
          if (typeof forward === 'undefined') {
            forward = slideNum > this.currentPlace ? true : false;
          }

          // If thumbnails exist, revise active class states
          if (this.settings.useThumbs) {
            this.$thumbWrapLinks.eq(this.currentPlace).removeClass('active');
            this.$thumbWrapLinks.eq(slideNum).addClass('active');
          }

          // Assign next slide prop (elem)
          this.$nextSlide = this.$slides.eq(slideNum);

          // Assign next slide index prop (int)
          this.currentPlace = slideNum;

          // User-defined function, fires with transition
          $('.rs-current-index').html(this.currentPlace + 1);
          //$('.rs-current-index').html('foo');
          this.settings.onChange();

          // Instantiate new Transition object, passing in self (RS obj), transition type (string), direction (bool)
          new Transition(this, this.settings.transition, forward);
        }
      }
    }
  };

  // Transition object constructor
  function Transition(RS, transition, forward) {
    this.RS = RS; // RS (RefineSlide) object
    // Set RS inProgress flag to prevent additional Transition objects being instantiated until transition end
    this.RS.inProgress = true;
    this.forward = forward; // Bool: true for forward, false for backward
    this.transition = transition; // String: name of transition requested

    if (this.transition === 'custom') {
      this.customAnims = this.RS.settings.customTransitions;
      this.isCustomTransition = true;
    }

    // Remove incorrect specified elements from customAnims array.
    if (this.transition === 'custom') {
      var that = this;
      $.each(this.customAnims, function (i, obj) {
        if ($.inArray(obj, that.anims) === -1) {
          that.customAnims.splice(i, 1);
        }
      });
    }

    this.fallback3d = this.RS.settings.fallback3d; // String: fallback to use when 3D transforms aren't supported

    this.init(); // Call Transition initialisation method
  }

  // Transition object Prototype
  Transition.prototype = {
    // Fallback to use if CSS transitions are unsupported
    fallback: 'fade',

    anims: [ // Array of possible animations
      'cubeH', 'cubeV', 'fade', 'sliceH', 'sliceV', 'slideH', 'slideV', 'scale', 'blockScale',
      'kaleidoscope', 'fan', 'blindH', 'blindV'
    ],
    customAnims: [],
    init: function () {
      // Call requested transition method
      this[this.transition]();
    },
    before: function (callback) {
      var that = this;

      // Prepare slide opacity & z-index
      this.RS.$currentSlide.css('z-index', 2);
      this.RS.$nextSlide.css({'opacity' : 1, 'z-index' : 1});

      // Fade out/in captions with CSS/JS depending on browser capability
      if (this.RS.cssTransitions) {
        this.RS.$currentSlide.find('.rs-caption').css('opacity', 0);
        this.RS.$nextSlide.find('.rs-caption').css('opacity', 1);
      } else {
        this.RS.$currentSlide.find('.rs-caption').animate({'opacity' : 0}, that.RS.settings.transitionDuration);
        this.RS.$nextSlide.find('.rs-caption').animate({'opacity' : 1}, that.RS.settings.transitionDuration);
      }

      // Check if transition describes a setup method
      if (typeof this.setup === 'function') {
        // Setup required by transition
        var transition = this.setup();

        setTimeout(function () {
          callback(transition);
        }, 20);
      } else {
        // Transition execution
        this.execute();
      }

      // Listen for CSS transition end on elem (set by transition)
      if (this.RS.cssTransitions) {
        $(this.listenTo).one('webkitTransitionEnd transitionend otransitionend oTransitionEnd mstransitionend',
          $.proxy(this.after, this)
        );
      }
    },
    after: function () {
      // Reset transition CSS
      this.RS.$sliderBG.removeAttr('style');
      this.RS.$slider.removeAttr('style');
      this.RS.$currentSlide.removeAttr('style');
      this.RS.$nextSlide.removeAttr('style');
      this.RS.$currentSlide.css({
        zIndex: 1,
        opacity: 0
      });
      this.RS.$nextSlide.css({
        zIndex: 2,
        opacity : 1
      });

      // Additional reset steps required by transition (if any exist)
      if (typeof this.reset === 'function') {
        this.reset();
      }

      // If slideshow is active, reset the timeout
      if (this.RS.settings.autoPlay) {
        clearTimeout(this.RS.cycling);
        this.RS.setAutoPlay();
      }

      // Assign new slide position
      this.RS.$currentSlide = this.RS.$nextSlide;

      // Remove RS obj inProgress flag (i.e. allow new Transition to be instantiated)
      this.RS.inProgress = false;

      // User-defined function, fires after transition has ended
      this.RS.settings.afterChange();
    },
    fade: function () {
      var that = this;

      // If CSS transitions are supported by browser
      if (this.RS.cssTransitions) {
        // Setup steps
        this.setup = function () {
          // Set event listener to next slide elem
          that.listenTo = that.RS.$currentSlide;
          that.RS.$currentSlide.css('transition', 'opacity ' + that.RS.settings.transitionDuration + 'ms linear');
        };

        // Execution steps
        this.execute = function () {
          // Display next slide over current slide
          that.RS.$currentSlide.css('opacity', 0);
        };
      } else { // JS animation fallback
        this.execute = function () {
          that.RS.$currentSlide.animate({'opacity' : 0}, that.RS.settings.transitionDuration, function () {
            // Reset steps
            that.after();
          });
        };
      }

      this.before($.proxy(this.execute, this));
    },
    // Args: translateZ, (next slide) translateX, (next slide) translateY, (next slide) rotateX, (next slide) rotateY, 
    // (wrap) rotateX, (wrap) rotateY
    cube: function (tz, ntx, nty, nrx, nry, wrx, wry) {
      // Fallback if browser does not support 3d transforms/CSS transitions
      if (!this.RS.cssTransitions || !this.RS.cssTransforms3d) {
        return this[this.fallback3d](); // User-defined transition
      }

      var that = this;

      // Setup steps
      this.setup = function () {
        // Set event listener to '.rs-slider' <ul>
        that.listenTo = that.RS.$slider;

        this.RS.$sliderBG.css('perspective', 1000);

        // props for slide <li>s
        that.RS.$currentSlide.css({
          transform : 'translateZ(' + tz + 'px)',
          backfaceVisibility : 'hidden'
        });

        // props for next slide <li>
        that.RS.$nextSlide.css({
          opacity : 1,
          backfaceVisibility : 'hidden',
          transform : 'translateY(' + nty + 'px) translateX(' + ntx + 'px) rotateY('+ nry +'deg) rotateX('+ nrx +'deg)'
        });

        // props for slider <ul>
        that.RS.$slider.css({
          transform: 'translateZ(-' + tz + 'px)',
          transformStyle: 'preserve-3d'
        });
      };

      // Execution steps
      this.execute = function () {
        that.RS.$slider.css({
          transition: 'all ' + that.RS.settings.transitionDuration + 'ms ease-in-out',
          transform: 'translateZ(-' + tz + 'px) rotateX('+ wrx +'deg) rotateY('+ wry +'deg)'
        });
      };

      this.before($.proxy(this.execute, this));
    },
    cubeH: function () {
      // Set to half of slide width
      var dimension = $(this.RS.$slides).width() / 2;

      // If next slide is ahead in array
      if (this.forward) {
        this.cube(dimension, dimension, 0, 0, 90, 0, -90);
      } else {
        this.cube(dimension, -dimension, 0, 0, -90, 0, 90);
      }
    },
    cubeV: function () {
      // Set to half of slide height
      var dimension = $(this.RS.$slides).height() / 2;

      // If next slide is ahead in array
      if (this.forward) {
        this.cube(dimension, 0, -dimension, 90, 0, -90, 0);
      } else {
        this.cube(dimension, 0, dimension, -90, 0, 90, 0);
      }
    },
    grid: function (cols, rows, ro, tx, ty, sc, op) {
      // grid() method is used by many transitions - not for calling directly
      // Grid calculations are based on those in the awesome flux slider (joelambert.co.uk/flux)
      // Args: columns, rows, rotate, translateX, translateY, scale, opacity
      // Fallback if browser does not support CSS transitions
      if (!this.RS.cssTransitions) {
        return this[this.fallback]();
      }

      var that = this;

      // Setup steps
      this.setup = function () {
        // The time (in ms) added to/subtracted from the delay total for each new gridlet
        var count = (that.RS.settings.transitionDuration) / (cols + rows);

        // Gridlet creator (divisions of the image grid, positioned with background-images 
        // to replicate the look of an entire slide image when assembled)
        function gridlet(width, height, top, left, src, imgWidth, imgHeight, c, r) {
          var delay = (c + r) * count;

          // Return a gridlet elem with styles for specific transition
          return $('<div class="rs-gridlet" />').css({
            width : width,
            height : height,
            top : top,
            left : left,
            backgroundImage : 'url(' + src + ')',
            backgroundPosition : '-' + left + 'px -' + top + 'px',
            backgroundSize : imgWidth + 'px ' + imgHeight + 'px',
            transition : 'all ' + that.RS.settings.transitionDuration + 'ms ease-in-out ' + delay + 'ms',
            transform : 'none'
          });
        }

        // Get the next slide's image
        that.$img = that.RS.$currentSlide.find('img.rs-slide-image');

        // Create a grid to hold the gridlets
        that.$grid = $('<div />').addClass('rs-grid');

        // Prepend the grid to the next slide (i.e. so it's above the slide image)
        that.RS.$currentSlide.prepend(that.$grid);

        // vars to calculate positioning/size of gridlets
        var imgWidth = that.$img.width(),
            imgHeight = that.$img.height(),
            imgSrc = that.$img.attr('src'),
            colWidth = Math.floor(imgWidth / cols),
            rowHeight = Math.floor(imgHeight / rows),
            colRemainder = imgWidth - (cols * colWidth),
            colAdd = Math.ceil(colRemainder / cols),
            rowRemainder = imgHeight - (rows * rowHeight),
            rowAdd = Math.ceil(rowRemainder / rows),
            leftDist = 0;

        // tx/ty args can be passed as 'auto'/'min-auto' (meaning use slide width/height or negative slide width/height)
        tx = tx === 'auto' ? imgWidth : tx;
        tx = tx === 'min-auto' ? - imgWidth : tx;
        ty = ty === 'auto' ? imgHeight : ty;
        ty = ty === 'min-auto' ? - imgHeight : ty;

        // Loop through cols
        for (var i = 0; i < cols; i++) {
          var topDist = 0,
            newColWidth = colWidth;

          // If imgWidth (px) does not divide cleanly into the specified number of cols, 
          // adjust individual col widths to create correct total
          if (colRemainder > 0) {
            var add = colRemainder >= colAdd ? colAdd : colRemainder;
            newColWidth += add;
            colRemainder -= add;
          }

          // Nested loop to create row gridlets for each col
          for (var j = 0; j < rows; j++)  {
            var newRowHeight = rowHeight,
              newRowRemainder = rowRemainder;

            // If imgHeight (px) does not divide cleanly into the specified number of rows, 
            // adjust individual row heights to create correct total
            if (newRowRemainder > 0) {
              var addRowRemainder = newRowRemainder >= rowAdd ? rowAdd : rowRemainder;
              newRowHeight += addRowRemainder;
              newRowRemainder -= addRowRemainder;
            }

            // Create & append gridlet to grid
            that.$grid.append(gridlet(newColWidth, newRowHeight, topDist, leftDist, imgSrc, imgWidth, imgHeight, i, j));

            topDist += newRowHeight;
          }

          leftDist += newColWidth;
        }

        // Set event listener on last gridlet to finish transitioning
        that.listenTo = that.$grid.children().last();

        // Show grid & hide the image it replaces
        that.$grid.show();
        that.$img.css('opacity', 0);

        // Add identifying classes to corner gridlets (useful if applying border radius)
        that.$grid.children().first().addClass('rs-top-left');
        that.$grid.children().last().addClass('rs-bottom-right');
        that.$grid.children().eq(rows - 1).addClass('rs-bottom-left');
        that.$grid.children().eq(- rows).addClass('rs-top-right');
      };

      // Execution steps
      this.execute = function () {
        that.$grid.children().css({
          opacity: op,
          transform: 'rotate('+ ro +'deg) translateX('+ tx +'px) translateY('+ ty +'px) scale('+ sc +')'
        });
      };

      this.before($.proxy(this.execute, this));

      // Reset steps
      this.reset = function () {
        that.$img.css('opacity', 1);
        that.$grid.remove();
      };
    },
    sliceH: function () {
      this.grid(1, 8, 0, 'min-auto', 0, 1, 0);
    },
    sliceV: function () {
      this.grid(10, 1, 0, 0, 'auto', 1, 0);
    },
    slideV: function () {
      var dir = this.forward ?
          'min-auto' :
          'auto';

      this.grid(1, 1, 0, 0, dir, 1, 1);
    },
    slideH: function () {
      var dir = this.forward ?
          'min-auto' :
          'auto';

      this.grid(1, 1, 0, dir, 0, 1, 1);
    },
    scale: function () {
      this.grid(1, 1, 0, 0, 0, 1.5, 0);
    },
    blockScale: function () {
      this.grid(8, 6, 0, 0, 0, 0.6, 0);
    },
    kaleidoscope: function () {
      this.grid(10, 8, 0, 0, 0, 1, 0);
    },
    fan: function () {
      this.grid(1, 10, 45, 100, 0, 1, 0);
    },
    blindV: function () {
      this.grid(1, 8, 0, 0, 0, 0.7, 0);
    },
    blindH: function () {
      this.grid(10, 1, 0, 0, 0, 0.7, 0);
    },
    random: function () {
      // Pick a random transition from the anims array (obj prop)
      this[this.anims[Math.floor(Math.random() * this.anims.length)]]();
    },
    custom: function() {
      if (this.RS.nextAnimIndex < 0) {
        this.RS.nextAnimIndex = this.customAnims.length - 1;
      }
      if (this.RS.nextAnimIndex === this.customAnims.length) {
        this.RS.nextAnimIndex = 0;
      }
      // Pick the next item in the list of transitions provided by user.
      this[this.customAnims[this.RS.nextAnimIndex]]();
    }
  };

  // Obj to check browser capabilities
  var testBrowser = {
    // Browser vendor CSS prefixes
    browserVendors: [
      '', '-webkit-', '-moz-', '-ms-', '-o-', '-khtml-'
    ],
    domPrefixes: [
      '', 'Webkit', 'Moz', 'ms', 'O', 'Khtml'
    ],

    // Method to iterate over a property (using all DOM prefixes)
    // Returns true if prop is recognised by browser (else returns false)
    testDom: function (prop) {
      var i = this.domPrefixes.length;

      while (i--) {
        if (typeof document.body.style[this.domPrefixes[i] + prop] !== 'undefined') {
          return true;
        }
      }

      return false;
    },
    cssTransitions: function () {
      // Use Modernizr if available & implements csstransitions test
      if (typeof window.Modernizr !== 'undefined' && Modernizr.csstransitions !== 'undefined') {
        return Modernizr.csstransitions;
      }

      // Use testDom method to check prop (returns bool)
      return this.testDom('Transition');
    },
    cssTransforms3d: function () {
      // Use Modernizr if available & implements csstransforms3d test
      if (typeof window.Modernizr !== 'undefined' && window.Modernizr.csstransforms3d !== 'undefined') {
        return window.Modernizr.csstransforms3d;
      }

      // Check for vendor-less prop
      if (typeof document.body.style.perspectiveProperty !== 'undefined') {
        return true;
      }

      // Use testDom method to check prop (returns bool)
      return this.testDom('Perspective');
    }
  };

  // jQuery plugin wrapper
  $.fn.refineSlide = function (settings) {
    return this.each(function () {
      // Check if already instantiated on this elem
      if (!$.data(this, 'refineSlide')) {
        // Instantiate & store elem + string
        $.data(this, 'refineSlide', new RS(this, settings));
      }
    });
  };
})(window.jQuery, window, window.document);


// initialize slideshows
if ($('.slideshow').length > 0) {
  $('.slideshow').refineSlide({
    transition : 'cubeH',
    thumbMargin: 0,
    useArrows: true,
    transitionDuration: 500,
  });

  // set thumb heights
  // should redo this to get shortest child and size by that.
  var $thumbs = $('.rs-thumb-wrap a'),
      thumbHeight = $thumbs.eq(0).outerWidth() * 0.65;
  $thumbs.css('height', thumbHeight);

  // if thumbs are very small, show thumb-viewer
  if ($thumbs.outerWidth() < 80 || thumbHeight < 40) {
    var $previewer = $('<span class="rs-thumb-viewer"></span>');
    $('.rs-thumb-wrap').prepend($previewer);
      
    $thumbs.hover(function() {
      var $this = $(this);
      if ($this.find('map-canvas').length > 0) {
        $previewer.html('map');
      }
      else {
        $previewer.html($this.html());
      }
      $previewer.css('left', (this.offsetLeft + this.offsetWidth/2)).toggle();
    });
  }

  //trigger previous click on swipe left
  $('.rs-slider').hammer().on('swipeleft', function() {
    $('.rs-prev').click();
  });

  // trigger next click on swipe right
  $('.rs-slider').hammer().on('swiperight', function() {
    $('.rs-next').click();
  });

  // toggle full-screen view
  $('.fullscreen-toggle').on('click', function() {
    $('.rs-wrap').toggleClass('rs-fullscreen');
    $('.rs-thumb-wrap a').css('height', 50);
  });
}