HEX
Server: Apache
System: Linux server1.myinter.net 4.18.0-553.147.1.el8_10.x86_64 #1 SMP Fri Jul 24 08:29:05 EDT 2026 x86_64
User: internet (1005)
PHP: 8.4.23
Disabled: passthru,system
Upload Files
File: /home/internet/public_html/ebookstuff.com/js/jquery.jcarousel.min.js
/*!
 * jCarousel v@VERSION - Riding carousels with jQuery
 * http://sorgalla.com/jcarousel/
 *
 * Copyright 2011, Jan Sorgalla
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * or GPL Version 2 (http://www.opensource.org/licenses/gpl-2.0.php) licenses.
 *
 * Date: @DATE
 */
(function (window) {
    'use strict';

    (function (factory) {
        if (typeof define === 'function' && define.amd) {
            define('jquery.jcarousel', ['jquery'], factory);
        } else {
            var jCarousel = factory(window.jQuery);

            var _jCarousel = window.jCarousel;

            jCarousel.noConflict = function() {
                window.jCarousel = _jCarousel;
                return jCarousel;
            };

            window.jCarousel = jCarousel;
        }
    }(function ($) {
        var toFloat = function(val) {
            return parseFloat(val) || 0;
        };

        var arraySlice = Array.prototype.slice;

        var jCarousel = {};

        jCarousel.version = '@VERSION';

        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.basePrototype = function(pluginName) {
            return {
                version:     jCarousel.version,
                _options:    {},
                _element:    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;
                },
                _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) {
            return jCarousel.create(pluginName, $.extend({}, {
                    _carousel:   null,
                    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;
                    }
                },
                pluginPrototype
            ));
        };

        jCarousel.create = function(pluginName, pluginPrototype) {
            var Plugin = function(element, options) {
                this._element = $(element);
                this.options(options);

                this._init();
                this.create();
            };

            Plugin.prototype = $.extend(
                {},
                jCarousel.basePrototype(pluginName),
                pluginPrototype
            );

            $.fn[pluginName] = function(options) {
                var args = arraySlice.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;
        };

        jCarousel.create('jcarousel', {
            animating:     false,
            tail:          0,
            inTail:        false,
            resizeTimer:   null,
            lt:            null,
            vertical:      false,
            rtl:           false,
            circular:      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._element.data('jcarousel-vertical') === true;
                }

                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.closest();

                // _prepare() needs this here
                this.circular = this.options('wrap') === 'circular';
                this.list().css({'left': 0, 'top': 0});

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

                    // Force items reload
                    this._items = null;

                    this.circular = this.options('wrap') === 'circular' &&
                                    this._fullyvisible.size() < this.items().size();

                    this.list().css(this.lt, this._position(item) + 'px');
                }

                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;
            },
            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._last.index() < 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._first.index() > 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),
                        first,
                        index,
                        curr,
                        i,
                        wrap = this.options('wrap');

                    if (parsed.target > 0) {
                        var last = this._last.index();

                        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._target.index() + scroll, end), animate, callback);
                                }
                            }
                        } else {
                            if (last === end &&
                                (wrap === 'both' || wrap === 'last')) {
                                this._scroll(0, animate, callback);
                            } else {
                                first = this._target.index();
                                index = first + 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._first.index() - scroll) + 1, 0), animate, callback);
                        } else {
                            first = this._first.index();
                            index = first - scroll;

                            if (first === 0 &&
                                (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 {
                                    this._scroll(Math.max(first - scroll, 0), animate, callback);
                                }
                            }
                        }
                    }
                } else {
                    this._scroll(parsed.target, animate, callback);
                }

                this._trigger('scrollend');

                return this;
            },
            _scroll: function(item, animate, callback) {
                if (this.animating) {
                    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) {
                    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 (this.animating) {
                    return this;
                }

                if (false === this._trigger('animate')) {
                    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' ?
                                    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 = item.index(),
                    idx = index,
                    wh = this.dimension(item),
                    clip = this.clipping(),
                    update = {
                        target:       item,
                        first:        item,
                        last:         item,
                        visible:      item,
                        fullyvisible: wh <= clip ? item : $()
                    },
                    lrb = this.vertical ? 'bottom' : (this.rtl ? 'left'  : 'right'),
                    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' &&
                    update.last.index() === (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 ((item.index() > first.index() || 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 = (update.first || current.first).index() < current.first.index(),
                    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;
            }
        });

        return jCarousel;
    }));
}(window));

/*!
 * jCarousel Control Plugin v@VERSION
 * http://sorgalla.com/jcarousel/
 *
 * Copyright 2011, Jan Sorgalla
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * or GPL Version 2 (http://www.opensource.org/licenses/gpl-2.0.php) licenses.
 *
 * Date: @DATE
 */
(function (window) {
    'use strict';

    (function (factory) {
        if (typeof define === 'function' && define.amd) {
            define('jquery.jcarousel.control', ['jquery', 'jquery.jcarousel'], factory);
        } else {
            factory(window.jQuery, window.jCarousel);
        }
    }(function ($, jCarousel) {
        jCarousel.plugin('jcarouselControl', {
            _options: {
                target: '+=1',
                event:  'click'
            },
            _active: null,
            _init: function() {
                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', $.proxy(function() {
                        this._destroy();
                        this.carousel().one('createend.jcarousel', $.proxy(this._create, this));
                    }, this))
                    .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('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;
            }
        });
    }));
}(window));

/*!
 * jCarousel AutoScroll Plugin v@VERSION
 * http://sorgalla.com/jcarousel/
 *
 * Copyright 2011, Jan Sorgalla
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * or GPL Version 2 (http://www.opensource.org/licenses/gpl-2.0.php) licenses.
 *
 * Date: @DATE
 */
(function (window) {
    'use strict';

    (function (factory) {
        if (typeof define === 'function' && define.amd) {
            define('jquery.jcarousel.autoscroll', ['jquery', 'jquery.jcarousel'], factory);
        } else {
            factory(window.jQuery, window.jCarousel);
        }
    }(function ($, jCarousel) {
        jCarousel.plugin('jcarouselAutoscroll', {
            _options: {
                target:    '+=1',
                interval:  3000,
                autostart: true
            },
            _timer: null,
            _init: function () {
                this.onAnimateEnd = $.proxy(this.start, this);
            },
            _create: function() {
                this.carousel()
                    .one('destroy.jcarousel', $.proxy(function() {
                        this._destroy();
                        this.carousel().one('createend.jcarousel', $.proxy(this._create, this));
                    }, this));

                if (this.options('autostart')) {
                    this.start();
                }
            },
            _destroy: function() {
                this.stop();
            },
            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;
            }
        });
    }));
}(window));

/*!
 * jCarousel Pagination Plugin v@VERSION
 * http://sorgalla.com/jcarousel/
 *
 * Copyright 2011, Jan Sorgalla
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * or GPL Version 2 (http://www.opensource.org/licenses/gpl-2.0.php) licenses.
 *
 * Date: @DATE
 */
(function (window) {
    'use strict';

    (function (factory) {
        if (typeof define === 'function' && define.amd) {
            define('jquery.jcarousel.pagination', ['jquery', 'jquery.jcarousel'], factory);
        } else {
            factory(window.jQuery, window.jCarousel);
        }
    }(function ($, jCarousel) {
        jCarousel.plugin('jcarouselPagination', {
            _options: {
                perPage: null,
                item: function(page) {
                    return '<a href="#' + page + '">' + page + '</a>';
                }
            },
            _current: null,
            _pages: {},
            _items: {},
            _init: function() {
                this.onReload = $.proxy(this._reload, this);
                this.onScroll = $.proxy(this.update, this);
            },
            _create: function() {
                this.carousel()
                    .one('destroy.jcarousel', $.proxy(function() {
                        this._destroy();
                        this.carousel().one('createend.jcarousel', $.proxy(this._create, this));
                    }, this))
                    .bind('reloadend.jcarousel', this.onReload)
                    .bind('scrollend.jcarousel', this.onScroll);

                this._reload();
            },
            _destroy: function() {
                this._element.empty();

                this.carousel()
                    .unbind('reloadend.jcarousel', this.onReload)
                    .unbind('scrollend.jcarousel', this.onScroll);
            },
            _reload: function() {
                var perPage = this.options('perPage');

                this._pages = {};
                this._items = {};

                // Calculate pages
                if (perPage == null) {
                    this._pages = this._calculatePages();
                } else if ($.isFunction(perPage)) {
                    this._pages = perPage.call(this);
                } 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) {
                    self._items[page] = $(item.call(self, page, carouselItems))
                        .click(function(e) {
                            e.preventDefault();
                            self.carousel().jcarousel('scroll', carouselItems.eq(0));
                        })
                        .appendTo(element);
                });

                this._current = null;
                this.update();
            },
            current: function() {
                return this._current;
            },
            items: function() {
                return this._items;
            },
            update: function() {
                var target = this.carousel().jcarousel('target'),
                    current = null;

                $.each(this._pages, function(page, carouselItems) {
                    if (carouselItems.index(target) >= 0) {
                        current = page;
                        return false;
                    }
                });

                if (current !== this._current) {
                    if (this._current) {
                        this._trigger('iteminactive', this._items[this._current]);
                    }

                    this._trigger('itemactive', this._items[current]);
                    this._current = current;
                }
            },
            _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;
            }
        });
    }));
}(window));