/*! * waterwheel carousel * version 2.3.0 * http://www.bkosborne.com * * copyright 2011-2013 brian osborne * dual licensed under gplv3 or mit * copies of the licenses have been distributed * with this plugin. * * plugin written by brian osborne * for use with the jquery javascript framework * http://www.jquery.com */ ; (function ($) { 'use strict'; $.fn.waterwheelcarousel = function (startingoptions) { if (this.length > 1) { this.each(function () { $(this).waterwheelcarousel(startingoptions); }); return this; } var carousel = this; var options = {}; var data = {}; function initializecarouseldata() { data = { itemscontainer: $(carousel), totalitems: $(carousel).find('img').length, containerwidth: $(carousel).width(), containerheight: $(carousel).height(), currentcenteritem: null, previouscenteritem: null, items: [], calculations: [], carouselrotationsleft: 10, currentlymoving: false, itemsanimating: 0, currentspeed: options.speed, intervaltimer: null, currentdirection: 'forward', leftitemscount: 0, rightitemscount: 0, performingsetup: true }; data.itemscontainer.find('img').removeclass(options.activeclassname); } function autoplay(stop) { cleartimeout(data.autoplaytimer); if (!stop && options.autoplay !== 0) { data.autoplaytimer = settimeout(function () { if (options.autoplay > 0) { moveonce('forward'); } else { moveonce('backward'); } }, math.abs(options.autoplay)); } } function preload(callback) { if (options.preloadimages === false) { callback(); return; } var $imageelements = data.itemscontainer.find('img'), loadedimages = 0, totalimages = $imageelements.length; $imageelements.each(function () { $(this).bind('load', function () { loadedimages += 1; if (loadedimages === totalimages) { callback(); return; } }); $(this).attr('src', $(this).attr('src')); if (this.complete) { $(this).trigger('load'); } }); } function setoriginalitemdimensions() { data.itemscontainer.find('img').each(function () { if ($(this).data('original_width') == undefined || options.forcedimagewidth > 0) { $(this).data('original_width', $(this).width()); } if ($(this).data('original_height') == undefined || options.forcedimageheight > 0) { $(this).data('original_height', $(this).height()); } }); } function forceimagedimensionsifenabled() { if (options.forcedimagewidth && options.forcedimageheight) { data.itemscontainer.find('img').each(function () { $(this).width(options.forcedimagewidth); $(this).height(options.forcedimageheight); }); } } function precalculatepositionproperties() { var $firstitem = data.itemscontainer.find('img:first'); data.calculations[0] = { distance: 0, offset: 0, opacity: 1 } var horizonoffset = options.horizonoffset; var separation = options.separation; for (var i = 1; i <= options.flankingitems + 2; i++) { if (i > 1) { horizonoffset *= options.horizonoffsetmultiplier; separation *= options.separationmultiplier; } data.calculations[i] = { distance: data.calculations[i - 1].distance + separation, offset: data.calculations[i - 1].offset + horizonoffset, opacity: data.calculations[i - 1].opacity * options.opacitymultiplier } } if (options.edgefadeenabled) { data.calculations[options.flankingitems + 1].opacity = 0; } else { data.calculations[options.flankingitems + 1] = { distance: 0, offset: 0, opacity: 0 } } } function setupcarousel() { data.items = data.itemscontainer.find('img'); for (var i = 0; i < data.totalitems; i++) { data.items[i] = $(data.items[i]); } if (options.horizon === 0) { if (options.orientation === 'horizontal') { options.horizon = data.containerheight / 2; } else { options.horizon = data.containerwidth / 2; } } data.itemscontainer.css('position', 'relative').find('img').each(function () { var centerposleft, centerpostop; if (options.orientation === 'horizontal') { centerposleft = (data.containerwidth / 2) - ($(this).data('original_width') / 2); centerpostop = options.horizon - ($(this).data('original_height') / 2); } else { centerposleft = options.horizon - ($(this).data('original_width') / 2); centerpostop = (data.containerheight / 2) - ($(this).data('original_height') / 2); } $(this).css({ 'left': centerposleft, 'top': centerpostop, 'visibility': 'visible', 'position': 'absolute', 'z-index': 0, 'opacity': 0 }).data({ top: centerpostop, left: centerposleft, oldposition: 0, currentposition: 0, depth: 0, opacity: 0 }).show(); }); } function setupstarterrotation() { options.startingitem = (options.startingitem === 0) ? math.round(data.totalitems / 2) : options.startingitem; data.rightitemscount = math.ceil((data.totalitems - 1) / 2); data.leftitemscount = math.floor((data.totalitems - 1) / 2); data.carouselrotationsleft = 1; moveitem(data.items[options.startingitem - 1], 0); data.items[options.startingitem - 1].css('opacity', 1); var itemindex = options.startingitem - 1; for (var pos = 1; pos <= data.rightitemscount; pos++) { (itemindex < data.totalitems - 1) ? itemindex += 1: itemindex = 0; data.items[itemindex].css('opacity', 1); moveitem(data.items[itemindex], pos); } var itemindex = options.startingitem - 1; for (var pos = -1; pos >= data.leftitemscount * -1; pos--) { (itemindex > 0) ? itemindex -= 1: itemindex = data.totalitems - 1; data.items[itemindex].css('opacity', 1); moveitem(data.items[itemindex], pos); } } function performcalculations($item, newposition) { var newdistancefromcenter = math.abs(newposition); if (newdistancefromcenter < options.flankingitems + 1) { var calculations = data.calculations[newdistancefromcenter]; } else { var calculations = data.calculations[options.flankingitems + 1]; } var distancefactor = math.pow(options.sizemultiplier, newdistancefromcenter) var newwidth = distancefactor * $item.data('original_width'); var newheight = distancefactor * $item.data('original_height'); var widthdifference = math.abs($item.width() - newwidth); var heightdifference = math.abs($item.height() - newheight); var newoffset = calculations.offset var newdistance = calculations.distance; if (newposition < 0) { newdistance *= -1; } if (options.orientation == 'horizontal') { var center = data.containerwidth / 2; var newleft = center + newdistance - (newwidth / 2); var newtop = options.horizon - newoffset - (newheight / 2); } else { var center = data.containerheight / 2; var newleft = options.horizon - newoffset - (newwidth / 2); var newtop = center + newdistance - (newheight / 2); } var newopacity; if (newposition === 0) { newopacity = 1; } else { newopacity = calculations.opacity; } var newdepth = options.flankingitems + 2 - newdistancefromcenter; $item.data('width', newwidth); $item.data('height', newheight); $item.data('top', newtop); $item.data('left', newleft); $item.data('oldposition', $item.data('currentposition')); $item.data('depth', newdepth); $item.data('opacity', newopacity); } function moveitem($item, newposition) { if (math.abs(newposition) <= options.flankingitems + 1) { performcalculations($item, newposition); data.itemsanimating++; $item.css('z-index', $item.data().depth).animate({ left: $item.data().left, width: $item.data().width, height: $item.data().height, top: $item.data().top, opacity: $item.data().opacity }, data.currentspeed, options.animationeasing, function () { itemanimationcomplete($item, newposition); }); } else { $item.data('currentposition', newposition) if ($item.data('oldposition') === 0) { $item.css({ 'left': $item.data().left, 'width': $item.data().width, 'height': $item.data().height, 'top': $item.data().top, 'opacity': $item.data().opacity, 'z-index': $item.data().depth }); } } } function itemanimationcomplete($item, newposition) { data.itemsanimating--; $item.data('currentposition', newposition); if (newposition === 0) { data.currentcenteritem = $item; } if (data.itemsanimating === 0) { data.carouselrotationsleft -= 1; data.currentlymoving = false; if (data.carouselrotationsleft > 0) { rotatecarousel(0); } else { data.currentspeed = options.speed; data.currentcenteritem.addclass(options.activeclassname); if (data.performingsetup === false) { options.movedtocenter(data.currentcenteritem); options.movedfromcenter(data.previouscenteritem); } data.performingsetup = false; autoplay(); } } } function rotatecarousel(rotations) { if (data.currentlymoving === false) { data.currentcenteritem.removeclass(options.activeclassname); data.currentlymoving = true; data.itemsanimating = 0; data.carouselrotationsleft += rotations; if (options.quickerforfurther === true) { if (rotations > 1) { data.currentspeed = options.speed / rotations; } data.currentspeed = (data.currentspeed < 100) ? 100 : data.currentspeed; } for (var i = 0; i < data.totalitems; i++) { var $item = $(data.items[i]); var currentposition = $item.data('currentposition'); var newposition; if (data.currentdirection == 'forward') { newposition = currentposition - 1; } else { newposition = currentposition + 1; } var flankingallowance = (newposition > 0) ? data.rightitemscount : data.leftitemscount; if (math.abs(newposition) > flankingallowance) { newposition = currentposition * -1; if (data.totalitems % 2 == 0) { newposition += 1; } } moveitem($item, newposition); } } } $(this).find('img').bind("click", function () { var itemposition = $(this).data().currentposition; if (options.imagenav == false) { return; } if (math.abs(itemposition) >= options.flankingitems + 1) { return; } if (data.currentlymoving) { return; } data.previouscenteritem = data.currentcenteritem; autoplay(true); options.autoplay = 0; var rotations = math.abs(itemposition); if (itemposition == 0) { options.clickedcenter($(this)); } else { options.movingfromcenter(data.currentcenteritem); options.movingtocenter($(this)); if (itemposition < 0) { data.currentdirection = 'backward'; rotatecarousel(rotations); } else if (itemposition > 0) { data.currentdirection = 'forward'; rotatecarousel(rotations); } } }); $(this).find('a').bind("click", function (event) { var iscenter = $(this).find('img').data('currentposition') == 0; if (options.linkhandling === 1 || (options.linkhandling === 2 && !iscenter)) { event.preventdefault(); return false; } }); function nextitemfromcenter() { var $next = data.currentcenteritem.next(); if ($next.length <= 0) { $next = data.currentcenteritem.parent().children().first(); } return $next; } function previtemfromcenter() { var $prev = data.currentcenteritem.prev(); if ($prev.length <= 0) { $prev = data.currentcenteritem.parent().children().last(); } return $prev; } function moveonce(direction) { if (data.currentlymoving === false) { data.previouscenteritem = data.currentcenteritem; options.movingfromcenter(data.currentcenteritem); if (direction == 'backward') { options.movingtocenter(previtemfromcenter()); data.currentdirection = 'backward'; } else if (direction == 'forward') { options.movingtocenter(nextitemfromcenter()); data.currentdirection = 'forward'; } } rotatecarousel(1); } $(document).keydown(function (e) { if (options.keyboardnav) { if ((e.which === 37 && options.orientation == 'horizontal') || (e.which === 38 && options.orientation == 'vertical')) { autoplay(true); options.autoplay = 0; moveonce('backward'); } else if ((e.which === 39 && options.orientation == 'horizontal') || (e.which === 40 && options.orientation == 'vertical')) { autoplay(true); options.autoplay = 0; moveonce('forward'); } if (options.keyboardnavoverride && ((options.orientation == 'horizontal' && (e.which === 37 || e.which === 39)) || (options.orientation == 'vertical' && (e.which === 38 || e.which === 40)))) { e.preventdefault(); return false; } } }); this.reload = function (newoptions) { if (typeof newoptions === "object") { var combinedefaultwith = newoptions; } else { var combinedefaultwith = {}; } options = $.extend({}, $.fn.waterwheelcarousel.defaults, newoptions); initializecarouseldata(); data.itemscontainer.find('img').hide(); forceimagedimensionsifenabled(); preload(function () { setoriginalitemdimensions(); precalculatepositionproperties(); setupcarousel(); setupstarterrotation(); }); } this.next = function () { autoplay(true); options.autoplay = 0; moveonce('forward'); } this.prev = function () { autoplay(true); options.autoplay = 0; moveonce('backward'); } this.reload(startingoptions); return this; }; $.fn.waterwheelcarousel.defaults = { startingitem: 1, separation: 175, separationmultiplier: 0.6, horizonoffset: 0, horizonoffsetmultiplier: 1, sizemultiplier: 0.7, opacitymultiplier: 0.8, horizon: 0, flankingitems: 3, speed: 300, animationeasing: 'linear', quickerforfurther: true, edgefadeenabled: false, linkhandling: 2, autoplay: 0, orientation: 'horizontal', activeclassname: 'carousel-center', keyboardnav: false, keyboardnavoverride: true, imagenav: true, preloadimages: true, forcedimagewidth: 0, forcedimageheight: 0, movingtocenter: $.noop, movedtocenter: $.noop, clickedcenter: $.noop, movingfromcenter: $.noop, movedfromcenter: $.noop }; })(jquery);