MediaWiki:ResponsiveSlider/jcarousel.js

/*! jCarousel - v0.3.0 - 2013-11-22 (function($) {   'use strict';
 * http://sorgalla.com/jcarousel
 * Copyright (c) 2013 Jan Sorgalla; Licensed MIT */

var jCarousel = $.jCarousel = {};

jCarousel.version = '0.3.0';

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.length > 0) { carousel = element.filter('[data-jcarousel]');

if (carousel.length > 0) { return carousel; }

carousel = element.find('[data-jcarousel]');

if (carousel.length > 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, defaultPrevented = false;

data = [this].concat(data || []);

(element || this._element).each(function {                   event = $.Event((pluginName + ':' + type).toLowerCase);

$(this).trigger(event, data);

if (event.isDefaultPrevented) { defaultPrevented = true; }               });

return !defaultPrevented; }       };    };

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 instanceof Plugin) { 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,        relative:    false,

_options: { list: function { return this.element.children.eq(0); },           items: function { return this.list.children; },           animation:   400, transitions: false, 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); };

return this; },       _create: function { this._reload;

$(window).on('resize.jcarousel', this.onWindowResize); },       _destroy: function { $(window).off('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';

// Ensure before closest call this.relative = this.list.css('position') === 'relative';

// Force list and items reload this._list = null; 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;

var props = {'left': 0, 'top': 0};

if (item.length > 0) { this._prepare(item); this.list.find('[data-jcarousel-clone]').remove;

// Force items reload this._items = null;

this.underflow = this._fullyvisible.length >= this.items.length; this.circular = this.circular && !this.underflow;

props[this.lt] = this._position(item) + 'px'; }

this.move(props);

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 && !this.relative ? 'left' : 'right'), width;

if (this.rtl && this.relative && !this.vertical) { pos += this.list.width - this.clipping; }

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.length - 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.length > 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.length - 1, scroll = Math.abs(parsed.target), wrap  = this.options('wrap'), current, first, index, start, curr, isVisible, props, 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 { if ($.isFunction(callback)) { callback.call(this, false); }                           }                        }                    } else { current = this.index(this._target);

if ((this.underflow && current === end && (wrap === 'circular' || wrap === 'both' || wrap === 'last')) ||                           (!this.underflow && last === end && (wrap === 'both' || wrap === 'last'))) { this._scroll(0, animate, callback); } else { index = current + scroll;

if (this.circular && index > end) { i = end; curr = this.items.get(-1);

while (i++ < index) { curr = this.items.eq(0); isVisible = this._visible.index(curr) >= 0;

if (isVisible) { curr.after(curr.clone(true).attr('data-jcarousel-clone', true)); }

this.list.append(curr);

if (!isVisible) { props = {}; props[this.lt] = this.dimension(curr); this.moveBy(props); }

// 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); current = this.index(this._target); start = this.underflow ? current : 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); isVisible = this._visible.index(curr) >= 0;

if (isVisible) { curr.after(curr.clone(true).attr('data-jcarousel-clone', true)); }

this.list.prepend(curr);

// Force items reload this._items = null;

var dim = this.dimension(curr);

props = {}; props[this.lt] = -dim; this.moveBy(props);

}

this._scroll(curr, animate, callback); } else { this._scroll(Math.max(index, 0), animate, callback); }                       }                    }                }            } else { this._scroll(parsed.target, animate, callback); }

this._trigger('scrollend');

return this; },       moveBy: function(properties, opts) { var position = this.list.position, multiplier = 1, correction = 0;

if (this.rtl && !this.vertical) { multiplier = -1;

if (this.relative) { correction = this.list.width - this.clipping; }           }

if (properties.left) { properties.left = (position.left + correction + toFloat(properties.left) * multiplier) + 'px'; }

if (properties.top) { properties.top = (position.top + correction + toFloat(properties.top) * multiplier) + 'px'; }

return this.move(properties, opts); },       move: function(properties, opts) { opts = opts || {};

var option      = this.options('transitions'), transitions = !!option, transforms  = !!option.transforms, transforms3d = !!option.transforms3d, duration    = opts.duration || 0, list        = this.list;

if (!transitions && duration > 0) { list.animate(properties, opts); return; }

var complete = opts.complete || $.noop, css = {};

if (transitions) { var backup = list.css(['transitionDuration', 'transitionTimingFunction', 'transitionProperty']), oldComplete = complete;

complete = function { $(this).css(backup); oldComplete.call(this); };               css = { transitionDuration: (duration > 0 ? duration / 1000 : 0) + 's', transitionTimingFunction: option.easing || opts.easing, transitionProperty: duration > 0 ? (function {                       if (transforms || transforms3d) {                            // We have to use 'all' because jQuery doesn't prefix                            // css values, like transition-property: transform;                            return 'all';                        }

return properties.left ? 'left' : 'top'; }) : 'none',                   transform: 'none'                };            }

if (transforms3d) { css.transform = 'translate3d(' + (properties.left || 0) + ',' + (properties.top || 0) + ',0)'; } else if (transforms) { css.transform = 'translate(' + (properties.left || 0) + ',' + (properties.top || 0) + ')'; } else { $.extend(css, properties); }

if (transitions && duration > 0) { list.one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', complete); }

list.css(css);

if (duration <= 0) { list.each(function {                   complete.call(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.length === 0) { if ($.isFunction(callback)) { callback.call(this, false); }

return this; }

this.inTail = false;

this._prepare(item);

var pos    = this._position(item), currPos = this.list.position[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 && this.relative && !this.vertical) { pos += this.list.width - this.clipping; }

if (this.rtl && !this.vertical) { 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) { callback = callback || $.noop;

if (false === this._trigger('animate')) { callback.call(this, false); return this; }

this.animating = true;

var animation = this.options('animation'), complete = $.proxy(function {                    this.animating = false;

var c = this.list.find('[data-jcarousel-clone]');

if (c.length > 0) { c.remove; this._reload; }

this._trigger('animateend');

callback.call(this, true); }, this);

var opts = typeof animation === 'object' ? $.extend({}, animation) : {duration: animation}, oldComplete = opts.complete || $.noop;

if (animate === false) { opts.duration = 0; } else if (typeof $.fx.speeds[opts.duration] !== 'undefined') { opts.duration = $.fx.speeds[opts.duration]; }

opts.complete = function { complete; oldComplete.call(this); };

this.move(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'), center = this.options('center'), update = { target:      item, first:       item, last:        item, visible:     item, fullyvisible: wh <= clip ? item : $ },               curr, isVisible, margin, dim;

if (center) { wh /= 2; clip /= 2; }

if (wh < clip) { while (true) { curr = this.items.eq(++idx);

if (curr.length === 0) { if (!this.circular) { break; }

curr = this.items.eq(0);

if (item.get(0) === curr.get(0)) { break; }

isVisible = this._visible.index(curr) >= 0;

if (isVisible) { curr.after(curr.clone(true).attr('data-jcarousel-clone', true)); }

this.list.append(curr);

if (!isVisible) { var props = {}; props[this.lt] = this.dimension(curr); this.moveBy(props); }

// Force items reload this._items = null; }

dim = this.dimension(curr);

if (dim === 0) { break; }

wh += dim;

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 && !center && wh < clip) { idx = index;

while (true) { if (--idx < 0) { break; }

curr = this.items.eq(idx);

if (curr.length === 0) { break; }

dim = this.dimension(curr);

if (dim === 0) { break; }

wh += dim;

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 (!center &&               this.options('wrap') !== 'circular' &&                this.options('wrap') !== 'custom' &&                this.index(update.last) === (this.items.length - 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], center = this.options('center'), centerOffset = center ? (this.clipping / 2) - (this.dimension(first) / 2) : 0;

if (this.rtl && !this.vertical) { if (this.relative) { pos -= this.list.width - this.dimension(first); } else { pos -= this.clipping - this.dimension(first); }

pos += centerOffset; } else { pos -= centerOffset; }

if (!center &&               (this.index(item) > this.index(first) || this.inTail) &&                this.tail) { pos = this.rtl && !this.vertical ? 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(key + 'in', $(elIn)); self._trigger(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 parsed = $.jCarousel.parseTarget(target), first = this.index(this._fullyvisible.first), last  = this.index(this._fullyvisible.last), index;

if (parsed.relative) { index = parsed.target < 0 ? Math.max(0, first + parsed.target) : last + parsed.target; } else { index = typeof parsed.target !== 'object' ? parsed.target : this.index(parsed.target); }

if (index < first) { return this.scroll(index, animate, callback); }

if (index >= first && index <= 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.length === 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',            method: 'scroll'        },        _active: null,        _init: function {            this.onDestroy = $.proxy(function { this._destroy; this.carousel .one('jcarousel:createend', $.proxy(this._create, this)); }, this);           this.onReload = $.proxy(this._reload, this);            this.onEvent = $.proxy(function(e) { e.preventDefault;

var method = this.options('method');

if ($.isFunction(method)) { method.call(this); } else { this.carousel .jcarousel(this.options('method'), this.options('target')); }           }, this);        },        _create: function {            this.carousel                .one('jcarousel:destroy', this.onDestroy)                .on('jcarousel:reloadend jcarousel:scrollend', this.onReload);

this._element .on(this.options('event') + '.jcarouselcontrol', this.onEvent);

this._reload; },       _destroy: function { this._element .off('.jcarouselcontrol', this.onEvent);

this.carousel .off('jcarousel:destroy', this.onDestroy) .off('jcarousel:reloadend jcarousel:scrollend', 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 '' + page + '';            },            event:  'click',            method: 'scroll'        },        _pages: {},        _items: {},        _currentPage: null,        _init: function {            this.onDestroy = $.proxy(function { this._destroy; this.carousel .one('jcarousel:createend', $.proxy(this._create, this)); }, this);           this.onReload = $.proxy(this._reload, this);            this.onScroll = $.proxy(this._update, this);        },        _create: function {            this.carousel                .one('jcarousel:destroy', this.onDestroy)                .on('jcarousel:reloadend', this.onReload)                .on('jcarousel:scrollend', this.onScroll);

this._reload; },       _destroy: function { this._clear;

this.carousel .off('jcarousel:destroy', this.onDestroy) .off('jcarousel:reloadend', this.onReload) .off('jcarousel:scrollend', this.onScroll); },       _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.length === 0) { break; }

if (!this._pages[page]) { this._pages[page] = curr; } else { this._pages[page] = this._pages[page].add(curr); }

if (i % pp === 0) { page++; }               }            }

this._clear;

var self    = this, carousel = this.carousel.data('jcarousel'), element = this._element, item    = this.options('item');

$.each(this._pages, function(page, carouselItems) {               var currItem = self._items[page] = $(item.call(self, page, carouselItems));

currItem.on(self.options('event') + '.jcarouselpagination', $.proxy(function { var target = carouselItems.eq(0);

// If circular wrapping enabled, ensure correct scrolling direction if (carousel.circular) { var currentIndex = carousel.index(carousel.target), newIndex    = carousel.index(target);

if (parseFloat(page) > parseFloat(self._currentPage)) { if (newIndex < currentIndex) { target = '+=' + (carousel.items.length - currentIndex + newIndex); }                       } else { if (newIndex > currentIndex) { target = '-=' + (currentIndex + (carousel.items.length - newIndex)); }                       }                    }

carousel[this.options('method')](target); }, self));

element.append(currItem); });

this._update; },       _update: function { var target = this.carousel.jcarousel('target'), currentPage;

$.each(this._pages, function(page, carouselItems) {               carouselItems.each(function { if (target.is(this)) { currentPage = page; return false; }               });

if (currentPage) { return false; }           });

if (this._currentPage !== currentPage) { this._trigger('inactive', this._items[this._currentPage]); this._trigger('active', this._items[currentPage]); }

this._currentPage = currentPage; },       items: function { return this._items; },       _clear: function { this._element.empty; this._currentPage = null; },       _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.length === 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('jcarousel:createend', $.proxy(this._create, this)); }, this);

this.onAnimateEnd = $.proxy(this.start, this); },       _create: function { this.carousel .one('jcarousel:destroy', this.onDestroy);

if (this.options('autostart')) { this.start; }       },        _destroy: function { this.stop; this.carousel .off('jcarousel:destroy', this.onDestroy); },       start: function { this.stop;

this.carousel .one('jcarousel:animateend', 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 .off('jcarousel:animateend', this.onAnimateEnd);

return this; }   }); }(jQuery));