(function ($, undefined) { var $window = $(window); var defaults = { btnPrev: null, btnNext: null, btnGo: null, auto: null, speed: 'fast', easing: null, editMode: false, vertical: false, circular: true, visible: 3, start: 0, scroll: 1, hideScrollButtons: false, resizeListItems: false, beforeStart: null, afterEnd: null, afterScroll: null }; function Layout(dimension, position, float) { this.d = dimension; this.p = position; this.itemFloat = float; } Layout.prototype = { dimension: function (element, value) { return element[this.d](value); }, positionCss: function (value) { var result = {}; result[this.p] = value; return result; }, setPosition: function (element, value) { element.css(this.p, value); } }; var VerticalLayout = new Layout('height', 'top', 'none'); var HorizontalLayout = new Layout('width', 'left', 'left'); var HorizontalRtlLayout = new Layout('width', 'right', 'right'); function Filmstrip(e, options) { var self = this; var rtl = false; var autoEnabled, autoTimer; var first, last, layout, animating; var $container, $list, $items; var $btnNext, $btnPrev; $container = $(e); $list = $container.find('ul, ol').first(); $items = listItems(); options = $.extend({}, defaults, options); rtl = ($container.css('direction') == 'rtl') first = options.start; last = first + options.visible; layout = options.vertical ? VerticalLayout : rtl ? HorizontalRtlLayout : HorizontalLayout; animating = false; autoTimer = null; autoEnabled = false; self.$container = $container; self.$list = $list; if (options.btnNext) { $btnNext = $(options.btnNext); $btnNext.click(function (e) { self.next(); e.preventDefault(); }); self.$btnNext = $btnNext; } if (options.btnPrev) { $btnPrev = $(options.btnPrev); $btnPrev.click(function (e) { self.prev(); e.preventDefault(); }); self.$btnPrev = $btnPrev; } function listItems() { return $list.children('li'); } function updateItems() { $items = listItems(); if (options.resizeListItems) { var itemDimension = Math.floor(layout.dimension($container) / options.visible); layout.dimension($items, itemDimension); } $items.css({ height: '100%', display: 'block', float: layout.itemFloat }); } function updateList() { updateItems(); var width = 0; $items.each(function () { width += $(this).outerWidth(true); }); layout.dimension($list, width); $list.css('height', '100%'); } function pos(delta, animate) { if (animating) { return; } var newFirst = first + (delta || 0); var newLast = newFirst + options.visible; var $itemsToClone, $clonedItems; updateList(); pauseAutoScroll(); if (options.visible >= $items.length) { newFirst = 0; } else if (newFirst < 0) { $itemsToClone = $items.slice(newFirst); $clonedItems = $itemsToClone .clone() .prependTo($list); updateList(); newFirst += $itemsToClone.length; if ($clonedItems) { var pos = 0; $clonedItems.each(function () { pos -= $(this).outerWidth(true); }); layout.setPosition($list, pos); } } else if (newLast > $items.length) { $itemsToClone = $items.slice(0, newLast - $items.length); $clonedItems = $itemsToClone .clone() .appendTo($list); updateList(); } var destPos = 0; $items.slice(0, newFirst).each(function () { destPos -= $(this).outerWidth(true); }); var properties = layout.positionCss(destPos); if (animate) { animating = true; $list.animate(properties, options.speed, function () { animating = false; callback(); }); } else { $list.css(properties); callback(); } function callback() { if ($itemsToClone) { $itemsToClone.remove(); updateList(); if (newLast > $items.length) { newFirst -= $itemsToClone.length; var destPos = 0; var includeMargin = true; $items.slice(0, newFirst).each(function () { destPos -= $(this).outerWidth(includeMargin); }); layout.setPosition($list, destPos); } } first = newFirst; last = newLast; self.first = newFirst; if (options.afterScroll) { options.afterScroll(self); } if (autoEnabled) { autoScroll(); } } } function pauseAutoScroll() { if (autoTimer !== null) { window.clearTimeout(autoTimer); autoTimer = null; } } function autoScroll(timeout) { if (timeout !== undefined) { options.auto = timeout; } pauseAutoScroll(); autoEnabled = (0 < options.auto); if (autoEnabled) { autoTimer = window.setTimeout(function () { self.next(); }, options.auto); } } function update() { delete self.next; delete self.prev; pos(0); if ((options.visible < $items.length) && (options.scroll < $items.length)) { $btnNext.show(); $btnPrev.show(); var scroll = options.scroll; if (rtl) { scroll = -scroll; } self.next = function () { pos(+scroll, true); }; self.prev = function () { pos(-scroll, true); }; } else if (options.hideScrollButtons) { $btnNext.css('visibility', 'hidden'); $btnPrev.css('visibility', 'hidden'); } } $container.css({ overflow: 'hidden', position: 'relative' }); $window.bind('resize.filmstrip', function () { pos(0); }); $list.css({ margin: 0, padding: 0, border: 'none', display: 'block', position: 'absolute', listStyleType: 'none' }); self.update = update; self.autoScroll = autoScroll; self.pauseAutoScroll = pauseAutoScroll; self.resumeAutoScroll = function () { autoScroll(); } self.options = options; setTimeout(function () { self.update(); autoScroll(); }, 0); } Filmstrip.fn = Filmstrip.prototype = { filmstrip: '1.0.0', next: $.noop, prev: $.noop }; $.fn.filmstrip = function () { var fs; var slice = Array.prototype.slice; if (typeof arguments[0] === 'string') { fs = this.data('filmstrip'); fs[arguments[0]].apply(fs, slice.call(arguments, 1)); } else { fs = new Filmstrip(this, arguments[0]); this.data('filmstrip', fs); } return this; } })(jQuery);