text: /*! jCarousel - v0.3.0-beta - 2013-01-18
  * http://sorgalla.com/jcarousel/
  * Copyright 2013 Jan Sorgalla
  * Released under the MIT license */
  
  (function($) {
      'use strict';
  
      var jCarousel = $.jCarousel = {};
  
      jCarousel.version = '0.3.0-beta';
  
      var rRelativeTarget = /^([+\-]=)?(.+)$/;
  
      jCarousel.parseTarget = function(target) {
          var relative = false,
              parts    = typeof target !== 'object' ?
                             rRelativeTarget.exec(target) :
                             null;
  
          if (parts) {
              target = parseInt(parts[2], 10) || 0;
  
              if (parts[1]) {
                  relative = true;
                  if (parts[1] === '-=') {
                      target *= -1;
                  }
              }
          } else if (typeof target !== 'object') {
              target = parseInt(target, 10) || 0;
          }
  
          return {
              target: target,
              relative: relative
          };
      };
  
      jCarousel.detectCarousel = function(element) {
          var carousel;
  
          while (element.size() > 0) {
              carousel = element.filter('[data-jcarousel]');
  
              if (carousel.size() > 0) {
                  return carousel;
              }
  
              carousel = element.find('[data-jcarousel]');
  
              if (carousel.size() > 0) {
                  return carousel;
              }
  
              element = element.parent();
          }
  
          return null;
      };
  
      jCarousel.base = function(pluginName) {
          return {
              version:  jCarousel.version,
              _options:  {},
              _element:  null,
              _carousel: null,
              _init:     $.noop,
              _create:   $.noop,
              _destroy:  $.noop,
              _reload:   $.noop,
              create: function() {
                  this._element
                      .attr('data-' + pluginName.toLowerCase(), true)
                      .data(pluginName, this);
  
                  if (false === this._trigger('create')) {
                      return this;
                  }
  
                  this._create();
  
                  this._trigger('createend');
  
                  return this;
              },
              destroy: function() {
                  if (false === this._trigger('destroy')) {
                      return this;
                  }
  
                  this._destroy();
  
                  this._trigger('destroyend');
  
                  this._element
                      .removeData(pluginName)
                      .removeAttr('data-' + pluginName.toLowerCase());
  
                  return this;
              },
              reload: function(options) {
                  if (false === this._trigger('reload')) {
                      return this;
                  }
  
                  if (options) {
                      this.options(options);
                  }
  
                  this._reload();
  
                  this._trigger('reloadend');
  
                  return this;
              },
              element: function() {
                  return this._element;
              },
              options: function(key, value) {
                  if (arguments.length === 0) {
                      return $.extend({}, this._options);
                  }
  
                  if (typeof key === 'string') {
                      if (typeof value === 'undefined') {
                          return typeof this._options[key] === 'undefined' ?
                                  null :
                                  this._options[key];
                      }
  
                      this._options[key] = value;
                  } else {
                      this._options = $.extend({}, this._options, key);
                  }
  
                  return this;
              },
              carousel: function() {
                  if (!this._carousel) {
                      this._carousel = jCarousel.detectCarousel(this.options('carousel') || this._element);
  
                      if (!this._carousel) {
                          $.error('Could not detect carousel for plugin "' + pluginName + '"');
                      }
                  }
  
                  return this._carousel;
              },
              _trigger: function(type, element, data) {
                  var event = $.Event((type + '.' + pluginName).toLowerCase());
  
                  (element || this._element)
                      .trigger(event, [this].concat(data || []));
  
                  return !event.isDefaultPrevented();
              }
          };
      };
  
      jCarousel.plugin = function(pluginName, pluginPrototype) {
          var Plugin = $[pluginName] = function(element, options) {
              this._element = $(element);
              this.options(options);
  
              this._init();
              this.create();
          };
  
          Plugin.fn = Plugin.prototype = $.extend(
              {},
              jCarousel.base(pluginName),
              pluginPrototype
          );
  
          $.fn[pluginName] = function(options) {
              var args        = Array.prototype.slice.call(arguments, 1),
                  returnValue = this;
  
              if (typeof options === 'string') {
                  this.each(function() {
                      var instance = $(this).data(pluginName);
  
                      if (!instance) {
                          return $.error(
                              'Cannot call methods on ' + pluginName + ' prior to initialization; ' +
                              'attempted to call method "' + options + '"'
                          );
                      }
  
                      if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
                          return $.error(
                              'No such method "' + options + '" for ' + pluginName + ' instance'
                          );
                      }
  
                      var methodValue = instance[options].apply(instance, args);
  
                      if (methodValue !== instance && typeof methodValue !== 'undefined') {
                          returnValue = methodValue;
                          return false;
                      }
                  });
              } else {
                  this.each(function() {
                      var instance = $(this).data(pluginName);
  
                      if (instance) {
                          instance.reload(options);
                      } else {
                          new Plugin(this, options);
                      }
                  });
              }
  
              return returnValue;
          };
  
          return Plugin;
      };
  }(jQuery));
  
  (function($, window) {
      'use strict';
  
      var toFloat = function(val) {
          return parseFloat(val) || 0;
      };
  
      $.jCarousel.plugin('jcarousel', {
          animating:   false,
          tail:        0,
          inTail:      false,
          resizeTimer: null,
          lt:          null,
          vertical:    false,
          rtl:         false,
          circular:    false,
          underflow:   false,
  
          _options: {
              list: function() {
                  return this.element().children().eq(0);
              },
              items: function() {
                  return this.list().children();
              },
              animation: 400,
              wrap:      null,
              vertical:  null,
              rtl:       null,
              center:    false
          },
  
          // Protected, don't access directly
          _list:         null,
          _items:        null,
          _target:       null,
          _first:        null,
          _last:         null,
          _visible:      null,
          _fullyvisible: null,
          _init: function() {
              var self = this;
  
              this.onWindowResize = function() {
                  if (self.resizeTimer) {
                      clearTimeout(self.resizeTimer);
                  }
  
                  self.resizeTimer = setTimeout(function() {
                      self.reload();
                  }, 100);
              };
  
              this.onAnimationComplete = function(callback) {
                  self.animating = false;
  
                  var c = self.list().find('[data-jcarousel-clone]');
  
                  if (c.size() > 0) {
                      c.remove();
                      self._reload();
                  }
  
                  self._trigger('animateend');
  
                  if ($.isFunction(callback)) {
                      callback.call(self, true);
                  }
              };
  
              return this;
          },
          _create: function() {
              this._reload();
  
              $(window)
                  .bind('resize.jcarousel', this.onWindowResize);
          },
          _destroy: function() {
              $(window)
                  .unbind('resize.jcarousel', this.onWindowResize);
          },
          _reload: function() {
              this.vertical = this.options('vertical');
  
              if (this.vertical == null) {
                  this.vertical = this.list().height() > this.list().width();
              }
  
              this.rtl = this.options('rtl');
  
              if (this.rtl == null) {
                  this.rtl = (function(element) {
                      if (('' + element.attr('dir')).toLowerCase() === 'rtl') {
                          return true;
                      }
  
                      var found = false;
  
                      element.parents('[dir]').each(function() {
                          if ((/rtl/i).test($(this).attr('dir'))) {
                              found = true;
                              return false;
                          }
                      });
  
                      return found;
                  }(this._element));
              }
  
              this.lt = this.vertical ? 'top' : 'left';
  
              // Force items reload
              this._items = null;
  
              var item = this._target && this.index(this._target) >= 0 ?
                             this._target :
                             this.closest();
  
              // _prepare() needs this here
              this.circular  = this.options('wrap') === 'circular';
              this.underflow = false;
  
              if (item.size() > 0) {
                  this._prepare(item);
                  this.list().find('[data-jcarousel-clone]').remove();
  
                  // Force items reload
                  this._items = null;
  
                  this.underflow = this._fullyvisible.size() >= this.items().size();
                  this.circular  = this.circular && !this.underflow;
  
                  this.list().css(this.lt, this._position(item) + 'px');
              } else {
                  this.list().css({'left': 0, 'top': 0});
              }
  
              return this;
          },
          list: function() {
              if (this._list === null) {
                  var option = this.options('list');
                  this._list = $.isFunction(option) ? option.call(this) : this._element.find(option);
              }
  
              return this._list;
          },
          items: function() {
              if (this._items === null) {
                  var option = this.options('items');
                  this._items = ($.isFunction(option) ? option.call(this) : this.list().find(option)).not('[data-jcarousel-clone]');
              }
  
              return this._items;
          },
          index: function(item) {
              return this.items().index(item);
          },
          closest: function() {
              var self    = this,
                  pos     = this.list().position()[this.lt],
                  closest = $(), // Ensure we're returning a jQuery instance
                  stop    = false,
                  lrb     = this.vertical ? 'bottom' : (this.rtl ? 'left' : 'right'),
                  width;
  
              if (this.rtl && !this.vertical) {
                  pos = (pos + this.list().width() - this.clipping()) * -1;
              }
  
              this.items().each(function() {
                  closest = $(this);
  
                  if (stop) {
                      return false;
                  }
  
                  var dim = self.dimension(closest);
  
                  pos += dim;
  
                  if (pos >= 0) {
                      width = dim - toFloat(closest.css('margin-' + lrb));
  
                      if ((Math.abs(pos) - dim + (width / 2)) <= 0) {
                          stop = true;
                      } else {
                          return false;
                      }
                  }
              });
  
              return closest;
          },
          target: function() {
              return this._target;
          },
          first: function() {
              return this._first;
          },
          last: function() {
              return this._last;
          },
          visible: function() {
              return this._visible;
          },
          fullyvisible: function() {
              return this._fullyvisible;
          },
          hasNext: function() {
              if (false === this._trigger('hasnext')) {
                  return true;
              }
  
              var wrap = this.options('wrap'),
                  end = this.items().size() - 1;
  
              return end >= 0 &&
                  ((wrap && wrap !== 'first') ||
                      (this.index(this._last) < end) ||
                      (this.tail && !this.inTail)) ? true : false;
          },
          hasPrev: function() {
              if (false === this._trigger('hasprev')) {
                  return true;
              }
  
              var wrap = this.options('wrap');
  
              return this.items().size() > 0 &&
                  ((wrap && wrap !== 'last') ||
                      (this.index(this._first) > 0) ||
                      (this.tail && this.inTail)) ? true : false;
          },
          clipping: function() {
              return this._element['inner' + (this.vertical ? 'Height' : 'Width')]();
          },
          dimension: function(element) {
              return element['outer' + (this.vertical ? 'Height' : 'Width')](true);
          },
          scroll: function(target, animate, callback) {
              if (this.animating) {
                  return this;
              }
  
              if (false === this._trigger('scroll', null, [target, animate])) {
                  return this;
              }
  
              if ($.isFunction(animate)) {
                  callback = animate;
                  animate  = true;
              }
  
              var parsed = $.jCarousel.parseTarget(target);
  
              if (parsed.relative) {
                  var end    = this.items().size() - 1,
                      scroll = Math.abs(parsed.target),
                      wrap   = this.options('wrap'),
                      target,
                      first,
                      index,
                      curr,
                      i;
  
                  if (parsed.target > 0) {
                      var last = this.index(this._last);
  
                      if (last >= end && this.tail) {
                          if (!this.inTail) {
                              this._scrollTail(animate, callback);
                          } else {
                              if (wrap === 'both' || wrap === 'last') {
                                  this._scroll(0, animate, callback);
                              } else {
                                  this._scroll(Math.min(this.index(this._target) + scroll, end), animate, callback);
                              }
                          }
                      } else {
                          target = this.index(this._target);
  
                          if ((this.underflow && target === end && (wrap === 'circular' || wrap === 'both' || wrap === 'last')) ||
                              (!this.underflow && last === end && (wrap === 'both' || wrap === 'last'))) {
                              this._scroll(0, animate, callback);
                          } else {
                              index = target + scroll;
  
                              if (this.circular && index > end) {
                                  i = end;
                                  curr = this.items().get(-1);
  
                                  while (i++ < index) {
                                      curr = this.items().eq(0);
                                      curr.after(curr.clone(true).attr('data-jcarousel-clone', true));
                                      this.list().append(curr);
                                      // Force items reload
                                      this._items = null;
                                  }
  
                                  this._scroll(curr, animate, callback);
                              } else {
                                  this._scroll(Math.min(index, end), animate, callback);
                              }
                          }
                      }
                  } else {
                      if (this.inTail) {
                          this._scroll(Math.max((this.index(this._first) - scroll) + 1, 0), animate, callback);
                      } else {
                          first  = this.index(this._first);
                          target = this.index(this._target);
                          start  = this.underflow ? target : first;
                          index  = start - scroll;
  
                          if (start <= 0 && ((this.underflow && wrap === 'circular') || wrap === 'both' || wrap === 'first')) {
                              this._scroll(end, animate, callback);
                          } else {
                              if (this.circular && index < 0) {
                                  i    = index;
                                  curr = this.items().get(0);
  
                                  while (i++ < 0) {
                                      curr = this.items().eq(-1);
                                      curr.after(curr.clone(true).attr('data-jcarousel-clone', true));
                                      this.list().prepend(curr);
                                      // Force items reload
                                      this._items = null;
  
                                      var lt  = toFloat(this.list().css(this.lt)),
                                          dim = this.dimension(curr);
  
                                      if (this.rtl && !this.vertical) {
                                          lt += dim;
                                      } else {
                                          lt -= dim;
                                      }
  
                                      this.list().css(this.lt, lt + 'px');
                                  }
  
                                  this._scroll(curr, animate, callback);
                              } else {
                                  var start = this.underflow ? this.index(this._target) : first;
                                  this._scroll(Math.max(index, 0), animate, callback);
                              }
                          }
                      }
                  }
              } else {
                  this._scroll(parsed.target, animate, callback);
              }
  
              this._trigger('scrollend');
  
              return this;
          },
          _scroll: function(item, animate, callback) {
              if (this.animating) {
                  if ($.isFunction(callback)) {
                      callback.call(this, false);
                  }
  
                  return this;
              }
  
              if (typeof item !== 'object') {
                  item = this.items().eq(item);
              } else if (typeof item.jquery === 'undefined') {
                  item = $(item);
              }
  
              if (item.size() === 0) {
                  if ($.isFunction(callback)) {
                      callback.call(this, false);
                  }
  
                  return this;
              }
  
              this.inTail = false;
  
              this._prepare(item);
  
              var pos     = this._position(item),
                  currPos = toFloat(this.list().css(this.lt));
  
              if (pos === currPos) {
                  if ($.isFunction(callback)) {
                      callback.call(this, false);
                  }
  
                  return this;
              }
  
              var properties = {};
              properties[this.lt] = pos + 'px';
  
              this._animate(properties, animate, callback);
  
              return this;
          },
          _scrollTail: function(animate, callback) {
              if (this.animating || !this.tail) {
                  if ($.isFunction(callback)) {
                      callback.call(this, false);
                  }
  
                  return this;
              }
  
              var pos = this.list().position()[this.lt];
  
              if (this.rtl) {
                  pos += this.tail;
              } else {
                  pos -= this.tail;
              }
  
              this.inTail = true;
  
              var properties = {};
              properties[this.lt] = pos + 'px';
  
              this._update({
                  target:       this._target.next(),
                  fullyvisible: this._fullyvisible.slice(1).add(this._visible.last())
              });
  
              this._animate(properties, animate, callback);
  
              return this;
          },
          _animate: function(properties, animate, callback) {
              if (false === this._trigger('animate')) {
                  if ($.isFunction(callback)) {
                      callback.call(this, false);
                  }
  
                  return this;
              }
  
              this.animating = true;
  
              var animation = this.options('animation');
  
              if (!animation || animate === false) {
                  this.list().css(properties);
                  this.onAnimationComplete(callback);
              } else {
                  var self = this;
  
                  if ($.isFunction(animation)) {
                      animation.call(this, properties, function() {
                          self.onAnimationComplete(callback);
                      });
                  } else {
                      var opts = typeof animation === 'object' ?
                                     $.extend({}, animation) :
                                     {duration: animation},
                          oldComplete = opts.complete;
  
                      opts.complete = function() {
                          self.onAnimationComplete(callback);
  
                          if ($.isFunction(oldComplete)) {
                              oldComplete.call(this);
                          }
                      };
  
                      this.list().animate(properties, opts);
                  }
              }
  
              return this;
          },
          _prepare: function(item) {
              var index  = this.index(item),
                  idx    = index,
                  wh     = this.dimension(item),
                  clip   = this.clipping(),
                  lrb    = this.vertical ? 'bottom' : (this.rtl ? 'left'  : 'right'),
                  update = {
                      target:       item,
                      first:        item,
                      last:         item,
                      visible:      item,
                      fullyvisible: wh <= clip ? item : $()
                  },
                  curr,
                  margin;
  
              if (this.options('center')) {
                  wh /= 2;
                  clip /= 2;
              }
  
              if (wh < clip) {
                  while (true) {
                      curr = this.items().eq(++idx);
  
                      if (curr.size() === 0) {
                          if (this.circular) {
                              curr = this.items().eq(0);
  
                              if (item.get(0) === curr.get(0)) {
                                  break;
                              }
  
                              curr.after(curr.clone(true).attr('data-jcarousel-clone', true));
  
                              this.list().append(curr);
  
                              // Force items reload
                              this._items = null;
                          } else {
                              break;
                          }
                      }
  
                      wh += this.dimension(curr);
  
                      update.last    = curr;
                      update.visible = update.visible.add(curr);
  
                      // Remove right/bottom margin from total width
                      margin = toFloat(curr.css('margin-' + lrb));
  
                      if ((wh - margin) <= clip) {
                          update.fullyvisible = update.fullyvisible.add(curr);
                      }
  
                      if (wh >= clip) {
                          break;
                      }
                  }
              }
  
              if (!this.circular && wh < clip) {
                  idx = index;
  
                  while (true) {
                      if (--idx < 0) {
                          break;
                      }
  
                      curr = this.items().eq(idx);
  
                      if (curr.size() === 0) {
                          break;
                      }
  
                      wh += this.dimension(curr);
  
                      update.first   = curr;
                      update.visible = update.visible.add(curr);
  
                      // Remove right/bottom margin from total width
                      margin = toFloat(curr.css('margin-' + lrb));
  
                      if ((wh - margin) <= clip) {
                          update.fullyvisible = update.fullyvisible.add(curr);
                      }
  
                      if (wh >= clip) {
                          break;
                      }
                  }
              }
  
              this._update(update);
  
              this.tail = 0;
  
              if (this.options('wrap') !== 'circular' &&
                  this.options('wrap') !== 'custom' &&
                  this.index(update.last) === (this.items().size() - 1)) {
  
                  // Remove right/bottom margin from total width
                  wh -= toFloat(update.last.css('margin-' + lrb));
  
                  if (wh > clip) {
                      this.tail = wh - clip;
                  }
              }
  
              return this;
          },
          _position: function(item) {
              var first = this._first,
                  pos   = first.position()[this.lt];
  
              if (this.rtl && !this.vertical) {
                  pos -= this.clipping() - this.dimension(first);
              }
  
              if (this.options('center')) {
                  pos -= (this.clipping() / 2) - (this.dimension(first) / 2);
              }
  
              if ((this.index(item) > this.index(first) || this.inTail) && this.tail) {
                  pos = this.rtl ? pos - this.tail : pos + this.tail;
                  this.inTail = true;
              } else {
                  this.inTail = false;
              }
  
              return -pos;
          },
          _update: function(update) {
              var self = this,
                  current = {
                      target:       this._target || $(),
                      first:        this._first || $(),
                      last:         this._last || $(),
                      visible:      this._visible || $(),
                      fullyvisible: this._fullyvisible || $()
                  },
                  back = this.index(update.first || current.first) < this.index(current.first),
                  key,
                  doUpdate = function(key) {
                      var elIn  = [],
                          elOut = [];
  
                      update[key].each(function() {
                          if (current[key].index(this) < 0) {
                              elIn.push(this);
                          }
                      });
  
                      current[key].each(function() {
                          if (update[key].index(this) < 0) {
                              elOut.push(this);
                          }
                      });
  
                      if (back) {
                          elIn = elIn.reverse();
                      } else {
                          elOut = elOut.reverse();
                      }
  
                      self._trigger('item' + key + 'in', $(elIn));
                      self._trigger('item' + key + 'out', $(elOut));
  
                      self['_' + key] = update[key];
                  };
  
              for (key in update) {
                  doUpdate(key);
              }
  
              return this;
          }
      });
  }(jQuery, window));
  
  (function($) {
      'use strict';
  
      $.jcarousel.fn.scrollIntoView = function(target, animate, callback) {
          var index = typeof target !== 'object' ? parseInt(target, 10) : this.index(target),
              first = this.index(this._fullyvisible.first());
  
          if (index < first) {
              return this.scroll(index, animate, callback);
          }
  
          if (index >= first && index <= this.index(this._fullyvisible.last())) {
              if ($.isFunction(callback)) {
                  callback.call(this, false);
              }
  
              return this;
          }
  
          var items = this.items(),
              clip = this.clipping(),
              lrb  = this.vertical ? 'bottom' : (this.rtl ? 'left'  : 'right'),
              wh   = 0,
              curr;
  
          while (true) {
              curr = items.eq(index);
  
              if (curr.size() === 0) {
                  break;
              }
  
              wh += this.dimension(curr);
  
              if (wh >= clip) {
                  var margin = parseFloat(curr.css('margin-' + lrb)) || 0;
                  if ((wh - margin) !== clip) {
                      index++;
                  }
                  break;
              }
  
              if (index <= 0) {
                  break;
              }
  
              index--;
          }
  
          return this.scroll(index, animate, callback);
      };
  }(jQuery));
  
  (function($) {
      'use strict';
  
      $.jCarousel.plugin('jcarouselControl', {
          _options: {
              target: '+=1',
              event:  'click'
          },
          _active: null,
          _init: function() {
              this.onDestroy = $.proxy(function() {
                  this._destroy();
                  this.carousel()
                      .one('createend.jcarousel', $.proxy(this._create, this));
              }, this);
              this.onReload = $.proxy(this._reload, this);
              this.onEvent = $.proxy(function(e) {
                  e.preventDefault();
                  this.carousel()
                      .jcarousel('scroll', this.options('target'));
              }, this);
          },
          _create: function() {
              this.carousel()
                  .one('destroy.jcarousel', this.onDestroy)
                  .bind('reloadend.jcarousel scrollend.jcarousel', this.onReload);
  
              this._element
                  .bind(this.options('event') + '.jcarouselcontrol', this.onEvent);
  
              this._reload();
          },
          _destroy: function() {
              this._element
                  .unbind('.jcarouselcontrol', this.onEvent);
  
              this.carousel()
                  .unbind('destroy.jcarousel', this.onDestroy)
                  .unbind('reloadend.jcarousel scrollend.jcarousel', this.onReload);
          },
          _reload: function() {
              var parsed   = $.jCarousel.parseTarget(this.options('target')),
                  carousel = this.carousel(),
                  active;
  
              if (parsed.relative) {
                  active = carousel
                      .jcarousel(parsed.target > 0 ? 'hasNext' : 'hasPrev');
              } else {
                  var target = typeof parsed.target !== 'object' ?
                                  carousel.jcarousel('items').eq(parsed.target) :
                                  parsed.target;
  
                  active = carousel.jcarousel('target').index(target) >= 0;
              }
  
              if (this._active !== active) {
                  this._trigger(active ? 'active' : 'inactive');
                  this._active = active;
              }
  
              return this;
          }
      });
  }(jQuery));
  
  (function($) {
      'use strict';
  
      $.jCarousel.plugin('jcarouselPagination', {
          _options: {
              perPage: null,
              item: function(page) {
                  return '<a href="#' + page + '">' + page + '</a>';
              }
          },
          _pages: {},
          _items: {},
          _init: function() {
              this.onDestroy = $.proxy(function() {
                  this._destroy();
                  this.carousel()
                      .one('createend.jcarousel', $.proxy(this._create, this));
              }, this);
              this.onReload = $.proxy(this._reload, this);
          },
          _create: function() {
              this.carousel()
                  .one('destroy.jcarousel', this.onDestroy)
                  .bind('reloadend.jcarousel', this.onReload);
  
              this._reload();
          },
          _destroy: function() {
              if ($.fn.jcarouselControl) {
                  $.each(this._items, function(page, item) {
                      item.jcarouselControl('destroy');
                  });
              }
  
              this._element.empty();
  
              this.carousel()
                  .unbind('destroy.jcarousel', this.onDestroy)
                  .unbind('reloadend.jcarousel', this.onReload);
          },
          _reload: function() {
              var perPage = this.options('perPage');
  
              this._pages = {};
              this._items = {};
  
              // Calculate pages
              if ($.isFunction(perPage)) {
                  perPage = perPage.call(this);
              }
  
              if (perPage == null) {
                  this._pages = this._calculatePages();
              } else {
                  var pp    = parseInt(perPage, 10) || 0,
                      items = this.carousel().jcarousel('items'),
                      page  = 1,
                      i     = 0,
                      curr;
  
                  while (true) {
                      curr = items.eq(i++);
  
                      if (curr.size() === 0) {
                          break;
                      }
  
                      if (!this._pages[page]) {
                          this._pages[page] = curr;
                      } else {
                          this._pages[page] = this._pages[page].add(curr);
                      }
  
                      if (i % pp === 0) {
                          page++;
                      }
                  }
              }
  
              var self    = this,
                  element = this._element.empty(),
                  item    = this.options('item');
  
              $.each(this._pages, function(page, carouselItems) {
                  var currItem = self._items[page] = $(item.call(self, page, carouselItems));
  
                  element.append(currItem);
  
                  if ($.fn.jcarouselControl) {
                      currItem.jcarouselControl({
                          carousel: self.carousel(),
                          target:   carouselItems.eq(0)
                      });
                  }
              });
          },
          items: function() {
              return this._items;
          },
          _calculatePages: function() {
              var carousel = this.carousel().data('jcarousel'),
                  items    = carousel.items(),
                  clip     = carousel.clipping(),
                  wh       = 0,
                  idx      = 0,
                  page     = 1,
                  pages    = {},
                  curr;
  
              while (true) {
                  curr = items.eq(idx++);
  
                  if (curr.size() === 0) {
                      break;
                  }
  
                  if (!pages[page]) {
                      pages[page] = curr;
                  } else {
                      pages[page] = pages[page].add(curr);
                  }
  
                  wh += carousel.dimension(curr);
  
                  if (wh >= clip) {
                      page++;
                      wh = 0;
                  }
              }
  
              return pages;
          }
      });
  }(jQuery));
  
  (function($) {
      'use strict';
  
      $.jCarousel.plugin('jcarouselAutoscroll', {
          _options: {
              target:    '+=1',
              interval:  3000,
              autostart: true
          },
          _timer: null,
          _init: function () {
              this.onDestroy = $.proxy(function() {
                  this._destroy();
                  this.carousel()
                      .one('createend.jcarousel', $.proxy(this._create, this));
              }, this);
  
              this.onAnimateEnd = $.proxy(this.start, this);
          },
          _create: function() {
              this.carousel()
                  .one('destroy.jcarousel', this.onDestroy);
  
              if (this.options('autostart')) {
                  this.start();
              }
          },
          _destroy: function() {
              this.stop();
              this.carousel()
                  .unbind('destroy.jcarousel', this.onDestroy);
          },
          start: function() {
              this.stop();
  
              this.carousel()
                  .one('animateend.jcarousel', this.onAnimateEnd);
  
              this._timer = setTimeout($.proxy(function() {
                  this.carousel().jcarousel('scroll', this.options('target'));
              }, this), this.options('interval'));
  
              return this;
          },
          stop: function() {
              if (this._timer) {
                  this._timer = clearTimeout(this._timer);
              }
  
              this.carousel()
                  .unbind('animateend.jcarousel', this.onAnimateEnd);
  
              return this;
          }
      });
  }(jQuery));
  