popsu-d7/sites/all/libraries/bxSlider/source/jquery.bxSlider.js
Bachir Soussi Chiadmi 1bc61b12ad first import
2015-04-08 11:40:19 +02:00

1261 lines
42 KiB
JavaScript

/**
* jQuery bxSlider v3.0
* http://bxslider.com
*
* Copyright 2011, Steven Wanderski
* http://bxcreative.com
*
* Free to use and abuse under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
*/
(function($){
$.fn.bxSlider = function(options){
var defaults = {
mode: 'horizontal', // 'horizontal', 'vertical', 'fade'
infiniteLoop: true, // true, false - display first slide after last
hideControlOnEnd: false, // true, false - if true, will hide 'next' control on last slide and 'prev' control on first
controls: true, // true, false - previous and next controls
speed: 500, // integer - in ms, duration of time slide transitions will occupy
easing: 'swing', // used with jquery.easing.1.3.js - see http://gsgd.co.uk/sandbox/jquery/easing/ for available options
pager: false, // true / false - display a pager
pagerSelector: null, // jQuery selector - element to contain the pager. ex: '#pager'
pagerType: 'full', // 'full', 'short' - if 'full' pager displays 1,2,3... if 'short' pager displays 1 / 4
pagerLocation: 'bottom', // 'bottom', 'top' - location of pager
pagerShortSeparator: '/', // string - ex: 'of' pager would display 1 of 4
pagerActiveClass: 'pager-active', // string - classname attached to the active pager link
nextText: 'next', // string - text displayed for 'next' control
nextImage: '', // string - filepath of image used for 'next' control. ex: 'images/next.jpg'
nextSelector: null, // jQuery selector - element to contain the next control. ex: '#next'
prevText: 'prev', // string - text displayed for 'previous' control
prevImage: '', // string - filepath of image used for 'previous' control. ex: 'images/prev.jpg'
prevSelector: null, // jQuery selector - element to contain the previous control. ex: '#next'
captions: false, // true, false - display image captions (reads the image 'title' tag)
captionsSelector: null, // jQuery selector - element to contain the captions. ex: '#captions'
auto: false, // true, false - make slideshow change automatically
autoDirection: 'next', // 'next', 'prev' - direction in which auto show will traverse
autoControls: false, // true, false - show 'start' and 'stop' controls for auto show
autoControlsSelector: null, // jQuery selector - element to contain the auto controls. ex: '#auto-controls'
autoStart: true, // true, false - if false show will wait for 'start' control to activate
autoHover: false, // true, false - if true show will pause on mouseover
autoDelay: 0, // integer - in ms, the amount of time before starting the auto show
pause: 3000, // integer - in ms, the duration between each slide transition
startText: 'start', // string - text displayed for 'start' control
startImage: '', // string - filepath of image used for 'start' control. ex: 'images/start.jpg'
stopText: 'stop', // string - text displayed for 'stop' control
stopImage: '', // string - filepath of image used for 'stop' control. ex: 'images/stop.jpg'
ticker: false, // true, false - continuous motion ticker mode (think news ticker)
// note: autoControls, autoControlsSelector, and autoHover apply to ticker!
tickerSpeed: 5000, // float - use value between 1 and 5000 to determine ticker speed - the smaller the value the faster the ticker speed
tickerDirection: 'next', // 'next', 'prev' - direction in which ticker show will traverse
tickerHover: false, // true, false - if true ticker will pause on mouseover
wrapperClass: 'bx-wrapper', // string - classname attached to the slider wraper
startingSlide: 0, // integer - show will start on specified slide. note: slides are zero based!
displaySlideQty: 1, // integer - number of slides to display at once
moveSlideQty: 1, // integer - number of slides to move at once
randomStart: false, // true, false - if true show will start on a random slide
onBeforeSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
onAfterSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
onLastSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
onFirstSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
onNextSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
onPrevSlide: function(){}, // function(currentSlideNumber, totalSlideQty, currentSlideHtmlObject) - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
buildPager: null // function(slideIndex, slideHtmlObject){ return string; } - advanced use only! see the tutorial here: http://bxslider.com/custom-pager
}
var options = $.extend(defaults, options);
// cache the base element
var base = this;
// initialize (and localize) all variables
var $parent = '';
var $origElement = '';
var $children = '';
var $outerWrapper = '';
var $firstChild = '';
var childrenWidth = '';
var childrenOuterWidth = '';
var wrapperWidth = '';
var wrapperHeight = '';
var $pager = '';
var interval = '';
var $autoControls = '';
var $stopHtml = '';
var $startContent = '';
var $stopContent = '';
var autoPlaying = true;
var loaded = false;
var childrenMaxWidth = 0;
var childrenMaxHeight = 0;
var currentSlide = 0;
var origLeft = 0;
var origTop = 0;
var origShowWidth = 0;
var origShowHeight = 0;
var tickerLeft = 0;
var tickerTop = 0;
var isWorking = false;
var firstSlide = 0;
var lastSlide = $children.length - 1;
// PUBLIC FUNCTIONS
/**
* Go to specified slide
*/
this.goToSlide = function(number, stopAuto){
if(!isWorking){
isWorking = true;
// set current slide to argument
currentSlide = number;
options.onBeforeSlide(currentSlide, $children.length, $children.eq(currentSlide));
// check if stopAuto argument is supplied
if(typeof(stopAuto) == 'undefined'){
var stopAuto = true;
}
if(stopAuto){
// if show is auto playing, stop it
if(options.auto){
base.stopShow(true);
}
}
slide = number;
// check for first slide callback
if(slide == firstSlide){
options.onFirstSlide(currentSlide, $children.length, $children.eq(currentSlide));
}
// check for last slide callback
if(slide == lastSlide){
options.onLastSlide(currentSlide, $children.length, $children.eq(currentSlide));
}
// horizontal
if(options.mode == 'horizontal'){
$parent.animate({'left': '-'+getSlidePosition(slide, 'left')+'px'}, options.speed, options.easing, function(){
isWorking = false;
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
// vertical
}else if(options.mode == 'vertical'){
$parent.animate({'top': '-'+getSlidePosition(slide, 'top')+'px'}, options.speed, options.easing, function(){
isWorking = false;
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
// fade
}else if(options.mode == 'fade'){
setChildrenFade();
}
// check to remove controls on last/first slide
checkEndControls();
// accomodate multi slides
if(options.moveSlideQty > 1){
number = Math.floor(number / options.moveSlideQty);
}
// make the current slide active
makeSlideActive(number);
// display the caption
showCaptions();
}
}
/**
* Go to next slide
*/
this.goToNextSlide = function(stopAuto){
// check if stopAuto argument is supplied
if(typeof(stopAuto) == 'undefined'){
var stopAuto = true;
}
if(stopAuto){
// if show is auto playing, stop it
if(options.auto){
base.stopShow(true);
}
}
// makes slideshow finite
if(!options.infiniteLoop){
if(!isWorking){
var slideLoop = false;
// make current slide the old value plus moveSlideQty
currentSlide = (currentSlide + (options.moveSlideQty));
// if current slide has looped on itself
if(currentSlide <= lastSlide){
checkEndControls();
// next slide callback
options.onNextSlide(currentSlide, $children.length, $children.eq(currentSlide));
// move to appropriate slide
base.goToSlide(currentSlide);
}else{
currentSlide -= options.moveSlideQty;
}
} // end if(!isWorking)
}else{
if(!isWorking){
isWorking = true;
var slideLoop = false;
// make current slide the old value plus moveSlideQty
currentSlide = (currentSlide + options.moveSlideQty);
// if current slide has looped on itself
if(currentSlide > lastSlide){
currentSlide = currentSlide % $children.length;
slideLoop = true;
}
// next slide callback
options.onNextSlide(currentSlide, $children.length, $children.eq(currentSlide));
// slide before callback
options.onBeforeSlide(currentSlide, $children.length, $children.eq(currentSlide));
if(options.mode == 'horizontal'){
// get the new 'left' property for $parent
var parentLeft = (options.moveSlideQty * childrenOuterWidth);
// animate to the new 'left'
$parent.animate({'left': '-='+parentLeft+'px'}, options.speed, options.easing, function(){
isWorking = false;
// if its time to loop, reset the $parent
if(slideLoop){
$parent.css('left', '-'+getSlidePosition(currentSlide, 'left')+'px');
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
}else if(options.mode == 'vertical'){
// get the new 'left' property for $parent
var parentTop = (options.moveSlideQty * childrenMaxHeight);
// animate to the new 'left'
$parent.animate({'top': '-='+parentTop+'px'}, options.speed, options.easing, function(){
isWorking = false;
// if its time to loop, reset the $parent
if(slideLoop){
$parent.css('top', '-'+getSlidePosition(currentSlide, 'top')+'px');
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
}else if(options.mode == 'fade'){
setChildrenFade();
}
// make the current slide active
if(options.moveSlideQty > 1){
makeSlideActive(Math.ceil(currentSlide / options.moveSlideQty));
}else{
makeSlideActive(currentSlide);
}
// display the caption
showCaptions();
} // end if(!isWorking)
}
} // end function
/**
* Go to previous slide
*/
this.goToPreviousSlide = function(stopAuto){
// check if stopAuto argument is supplied
if(typeof(stopAuto) == 'undefined'){
var stopAuto = true;
}
if(stopAuto){
// if show is auto playing, stop it
if(options.auto){
base.stopShow(true);
}
}
// makes slideshow finite
if(!options.infiniteLoop){
if(!isWorking){
var slideLoop = false;
// make current slide the old value plus moveSlideQty
currentSlide = currentSlide - options.moveSlideQty;
// if current slide has looped on itself
if(currentSlide < 0){
currentSlide = 0;
// if specified, hide the control on the last slide
if(options.hideControlOnEnd){
$('.bx-prev', $outerWrapper).hide();
}
}
checkEndControls();
// next slide callback
options.onPrevSlide(currentSlide, $children.length, $children.eq(currentSlide));
// move to appropriate slide
base.goToSlide(currentSlide);
}
}else{
if(!isWorking){
isWorking = true;
var slideLoop = false;
// make current slide the old value plus moveSlideQty
currentSlide = (currentSlide - (options.moveSlideQty));
// if current slide has looped on itself
if(currentSlide < 0){
negativeOffset = (currentSlide % $children.length);
if(negativeOffset == 0){
currentSlide = 0;
}else{
currentSlide = ($children.length) + negativeOffset;
}
slideLoop = true;
}
// next slide callback
options.onPrevSlide(currentSlide, $children.length, $children.eq(currentSlide));
// slide before callback
options.onBeforeSlide(currentSlide, $children.length, $children.eq(currentSlide));
if(options.mode == 'horizontal'){
// get the new 'left' property for $parent
var parentLeft = (options.moveSlideQty * childrenOuterWidth);
// animate to the new 'left'
$parent.animate({'left': '+='+parentLeft+'px'}, options.speed, options.easing, function(){
isWorking = false;
// if its time to loop, reset the $parent
if(slideLoop){
$parent.css('left', '-'+getSlidePosition(currentSlide, 'left')+'px');
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
}else if(options.mode == 'vertical'){
// get the new 'left' property for $parent
var parentTop = (options.moveSlideQty * childrenMaxHeight);
// animate to the new 'left'
$parent.animate({'top': '+='+parentTop+'px'}, options.speed, options.easing, function(){
isWorking = false;
// if its time to loop, reset the $parent
if(slideLoop){
$parent.css('top', '-'+getSlidePosition(currentSlide, 'top')+'px');
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
}else if(options.mode == 'fade'){
setChildrenFade();
}
// make the current slide active
if(options.moveSlideQty > 1){
makeSlideActive(Math.ceil(currentSlide / options.moveSlideQty));
}else{
makeSlideActive(currentSlide);
}
// display the caption
showCaptions();
} // end if(!isWorking)
}
} // end function
/**
* Go to first slide
*/
this.goToFirstSlide = function(stopAuto){
// check if stopAuto argument is supplied
if(typeof(stopAuto) == 'undefined'){
var stopAuto = true;
}
base.goToSlide(firstSlide, stopAuto);
}
/**
* Go to last slide
*/
this.goToLastSlide = function(){
// check if stopAuto argument is supplied
if(typeof(stopAuto) == 'undefined'){
var stopAuto = true;
}
base.goToSlide(lastSlide, stopAuto);
}
/**
* Get the current slide
*/
this.getCurrentSlide = function(){
return currentSlide;
}
/**
* Get the total slide count
*/
this.getSlideCount = function(){
return $children.length;
}
/**
* Stop the slideshow
*/
this.stopShow = function(changeText){
clearInterval(interval);
// check if changeText argument is supplied
if(typeof(changeText) == 'undefined'){
var changeText = true;
}
if(changeText && options.autoControls){
$autoControls.html($startContent).removeClass('stop').addClass('start');
autoPlaying = false;
}
}
/**
* Start the slideshow
*/
this.startShow = function(changeText){
// check if changeText argument is supplied
if(typeof(changeText) == 'undefined'){
var changeText = true;
}
setAutoInterval();
if(changeText && options.autoControls){
$autoControls.html($stopContent).removeClass('start').addClass('stop');
autoPlaying = true;
}
}
/**
* Stops the ticker
*/
this.stopTicker = function(changeText){
$parent.stop();
// check if changeText argument is supplied
if(typeof(changeText) == 'undefined'){
var changeText = true;
}
if(changeText && options.ticker){
$autoControls.html($startContent).removeClass('stop').addClass('start');
autoPlaying = false;
}
}
/**
* Starts the ticker
*/
this.startTicker = function(changeText){
if(options.mode == 'horizontal'){
if(options.tickerDirection == 'next'){
// get the 'left' property where the ticker stopped
var stoppedLeft = parseInt($parent.css('left'));
// calculate the remaining distance the show must travel until the loop
var remainingDistance = (origShowWidth + stoppedLeft) + $children.eq(0).width();
}else if(options.tickerDirection == 'prev'){
// get the 'left' property where the ticker stopped
var stoppedLeft = -parseInt($parent.css('left'));
// calculate the remaining distance the show must travel until the loop
var remainingDistance = (stoppedLeft) - $children.eq(0).width();
}
// calculate the speed ratio to seamlessly finish the loop
var finishingSpeed = (remainingDistance * options.tickerSpeed) / origShowWidth;
// call the show
moveTheShow(tickerLeft, remainingDistance, finishingSpeed);
}else if(options.mode == 'vertical'){
if(options.tickerDirection == 'next'){
// get the 'top' property where the ticker stopped
var stoppedTop = parseInt($parent.css('top'));
// calculate the remaining distance the show must travel until the loop
var remainingDistance = (origShowHeight + stoppedTop) + $children.eq(0).height();
}else if(options.tickerDirection == 'prev'){
// get the 'left' property where the ticker stopped
var stoppedTop = -parseInt($parent.css('top'));
// calculate the remaining distance the show must travel until the loop
var remainingDistance = (stoppedTop) - $children.eq(0).height();
}
// calculate the speed ratio to seamlessly finish the loop
var finishingSpeed = (remainingDistance * options.tickerSpeed) / origShowHeight;
// call the show
moveTheShow(tickerTop, remainingDistance, finishingSpeed);
// check if changeText argument is supplied
if(typeof(changeText) == 'undefined'){
var changeText = true;
}
if(changeText && options.ticker){
$autoControls.html($stopContent).removeClass('start').addClass('stop');
autoPlaying = true;
}
}
}
/**
* Initialize a new slideshow
*/
this.initShow = function(){
// reinitialize all variables
// base = this;
$parent = $(this);
$origElement = $parent.clone();
$children = $parent.children();
$outerWrapper = '';
$firstChild = $parent.children(':first');
childrenWidth = $firstChild.width();
childrenMaxWidth = 0;
childrenOuterWidth = $firstChild.outerWidth();
childrenMaxHeight = 0;
wrapperWidth = getWrapperWidth();
wrapperHeight = getWrapperHeight();
isWorking = false;
$pager = '';
currentSlide = 0;
origLeft = 0;
origTop = 0;
interval = '';
$autoControls = '';
$stopHtml = '';
$startContent = '';
$stopContent = '';
autoPlaying = true;
loaded = false;
origShowWidth = 0;
origShowHeight = 0;
tickerLeft = 0;
tickerTop = 0;
firstSlide = 0;
lastSlide = $children.length - 1;
// get the largest child's height and width
$children.each(function(index) {
if($(this).outerHeight() > childrenMaxHeight){
childrenMaxHeight = $(this).outerHeight();
}
if($(this).outerWidth() > childrenMaxWidth){
childrenMaxWidth = $(this).outerWidth();
}
});
// get random slide number
if(options.randomStart){
var randomNumber = Math.floor(Math.random() * $children.length);
currentSlide = randomNumber;
origLeft = childrenOuterWidth * (options.moveSlideQty + randomNumber);
origTop = childrenMaxHeight * (options.moveSlideQty + randomNumber);
// start show at specific slide
}else{
currentSlide = options.startingSlide;
origLeft = childrenOuterWidth * (options.moveSlideQty + options.startingSlide);
origTop = childrenMaxHeight * (options.moveSlideQty + options.startingSlide);
}
// set initial css
initCss();
// check to show pager
if(options.pager && !options.ticker){
if(options.pagerType == 'full'){
showPager('full');
}else if(options.pagerType == 'short'){
showPager('short');
}
}
// check to show controls
if(options.controls && !options.ticker){
setControlsVars();
}
// check if auto
if(options.auto || options.ticker){
// check if auto controls are displayed
if(options.autoControls){
setAutoControlsVars();
}
// check if show should auto start
if(options.autoStart){
// check if autostart should delay
setTimeout(function(){
base.startShow(true);
}, options.autoDelay);
}else{
base.stopShow(true);
}
// check if show should pause on hover
if(options.autoHover && !options.ticker){
setAutoHover();
}
}
// make the starting slide active
if(options.moveSlideQty > 1){
makeSlideActive(Math.ceil(currentSlide / options.moveSlideQty));
}else{
makeSlideActive(currentSlide);
}
// check for finite show and if controls should be hidden
checkEndControls();
// show captions
if(options.captions){
showCaptions();
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
}
/**
* Destroy the current slideshow
*/
this.destroyShow = function(){
// stop the auto show
clearInterval(interval);
// remove any controls / pagers that have been appended
$('.bx-next, .bx-prev, .bx-pager, .bx-auto', $outerWrapper).remove();
// unwrap all bx-wrappers
$parent.unwrap().unwrap().removeAttr('style');
// remove any styles that were appended
$parent.children().removeAttr('style').not('.pager').remove();
// remove any childrent that were appended
$children.removeClass('pager');
}
/**
* Reload the current slideshow
*/
this.reloadShow = function(){
base.destroyShow();
base.initShow();
}
// PRIVATE FUNCTIONS
/**
* Creates all neccessary styling for the slideshow
*/
function initCss(){
// layout the children
setChildrenLayout(options.startingSlide);
// CSS for horizontal mode
if(options.mode == 'horizontal'){
// wrap the <ul> in div that acts as a window and make the <ul> uber wide
$parent
.wrap('<div class="'+options.wrapperClass+'" style="width:'+wrapperWidth+'px; position:relative;"></div>')
.wrap('<div class="bx-window" style="position:relative; overflow:hidden; width:'+wrapperWidth+'px;"></div>')
.css({
width: '999999px',
position: 'relative',
left: '-'+(origLeft)+'px'
});
$parent.children().css({
width: childrenWidth,
'float': 'left',
listStyle: 'none'
});
$outerWrapper = $parent.parent().parent();
$children.addClass('pager');
// CSS for vertical mode
}else if(options.mode == 'vertical'){
// wrap the <ul> in div that acts as a window and make the <ul> uber tall
$parent
.wrap('<div class="'+options.wrapperClass+'" style="width:'+childrenMaxWidth+'px; position:relative;"></div>')
.wrap('<div class="bx-window" style="width:'+childrenMaxWidth+'px; height:'+wrapperHeight+'px; position:relative; overflow:hidden;"></div>')
.css({
height: '999999px',
position: 'relative',
top: '-'+(origTop)+'px'
});
$parent.children().css({
listStyle: 'none',
height: childrenMaxHeight
});
$outerWrapper = $parent.parent().parent();
$children.addClass('pager');
// CSS for fade mode
}else if(options.mode == 'fade'){
// wrap the <ul> in div that acts as a window
$parent
.wrap('<div class="'+options.wrapperClass+'" style="width:'+childrenMaxWidth+'px; position:relative;"></div>')
.wrap('<div class="bx-window" style="height:'+childrenMaxHeight+'px; width:'+childrenMaxWidth+'px; position:relative; overflow:hidden;"></div>');
$parent.children().css({
listStyle: 'none',
position: 'absolute',
top: 0,
left: 0,
zIndex: 98
});
$outerWrapper = $parent.parent().parent();
$children.not(':eq('+currentSlide+')').fadeTo(0, 0);
$children.eq(currentSlide).css('zIndex', 99);
}
// if captions = true setup a div placeholder
if(options.captions && options.captionsSelector == null){
$outerWrapper.append('<div class="bx-captions"></div>');
}
}
/**
* Depending on mode, lays out children in the proper setup
*/
function setChildrenLayout(){
// lays out children for horizontal or vertical modes
if(options.mode == 'horizontal' || options.mode == 'vertical'){
// get the children behind
var $prependedChildren = getArraySample($children, 0, options.moveSlideQty, 'backward');
// add each prepended child to the back of the original element
$.each($prependedChildren, function(index) {
$parent.prepend($(this));
});
// total number of slides to be hidden after the window
var totalNumberAfterWindow = ($children.length + options.moveSlideQty) - 1;
// number of original slides hidden after the window
var pagerExcess = $children.length - options.displaySlideQty;
// number of slides to append to the original hidden slides
var numberToAppend = totalNumberAfterWindow - pagerExcess;
// get the sample of extra slides to append
var $appendedChildren = getArraySample($children, 0, numberToAppend, 'forward');
if(options.infiniteLoop){
// add each appended child to the front of the original element
$.each($appendedChildren, function(index) {
$parent.append($(this));
});
}
}
}
/**
* Sets all variables associated with the controls
*/
function setControlsVars(){
// check if text or images should be used for controls
// check "next"
if(options.nextImage != ''){
nextContent = options.nextImage;
nextType = 'image';
}else{
nextContent = options.nextText;
nextType = 'text';
}
// check "prev"
if(options.prevImage != ''){
prevContent = options.prevImage;
prevType = 'image';
}else{
prevContent = options.prevText;
prevType = 'text';
}
// show the controls
showControls(nextType, nextContent, prevType, prevContent);
}
/**
* Puts slideshow into auto mode
*
* @param int pause number of ms the slideshow will wait between slides
* @param string direction 'forward', 'backward' sets the direction of the slideshow (forward/backward)
* @param bool controls determines if start/stop controls will be displayed
*/
function setAutoInterval(){
if(options.auto){
// finite loop
if(!options.infiniteLoop){
if(options.autoDirection == 'next'){
interval = setInterval(function(){
currentSlide += options.moveSlideQty;
// if currentSlide has exceeded total number
if(currentSlide > lastSlide){
currentSlide = currentSlide % $children.length;
}
base.goToSlide(currentSlide, false);
}, options.pause);
}else if(options.autoDirection == 'prev'){
interval = setInterval(function(){
currentSlide -= options.moveSlideQty;
// if currentSlide is smaller than zero
if(currentSlide < 0){
negativeOffset = (currentSlide % $children.length);
if(negativeOffset == 0){
currentSlide = 0;
}else{
currentSlide = ($children.length) + negativeOffset;
}
}
base.goToSlide(currentSlide, false);
}, options.pause);
}
// infinite loop
}else{
if(options.autoDirection == 'next'){
interval = setInterval(function(){
base.goToNextSlide(false);
}, options.pause);
}else if(options.autoDirection == 'prev'){
interval = setInterval(function(){
base.goToPreviousSlide(false);
}, options.pause);
}
}
}else if(options.ticker){
options.tickerSpeed *= 10;
// get the total width of the original show
$('.pager', $outerWrapper).each(function(index) {
origShowWidth += $(this).width();
origShowHeight += $(this).height();
});
// if prev start the show from the last slide
if(options.tickerDirection == 'prev' && options.mode == 'horizontal'){
$parent.css('left', '-'+(origShowWidth+origLeft)+'px');
}else if(options.tickerDirection == 'prev' && options.mode == 'vertical'){
$parent.css('top', '-'+(origShowHeight+origTop)+'px');
}
if(options.mode == 'horizontal'){
// get the starting left position
tickerLeft = parseInt($parent.css('left'));
// start the ticker
moveTheShow(tickerLeft, origShowWidth, options.tickerSpeed);
}else if(options.mode == 'vertical'){
// get the starting top position
tickerTop = parseInt($parent.css('top'));
// start the ticker
moveTheShow(tickerTop, origShowHeight, options.tickerSpeed);
}
// check it tickerHover applies
if(options.tickerHover){
setTickerHover();
}
}
}
function moveTheShow(leftCss, distance, speed){
// if horizontal
if(options.mode == 'horizontal'){
// if next
if(options.tickerDirection == 'next'){
$parent.animate({'left': '-='+distance+'px'}, speed, 'linear', function(){
$parent.css('left', leftCss);
moveTheShow(leftCss, origShowWidth, options.tickerSpeed);
});
// if prev
}else if(options.tickerDirection == 'prev'){
$parent.animate({'left': '+='+distance+'px'}, speed, 'linear', function(){
$parent.css('left', leftCss);
moveTheShow(leftCss, origShowWidth, options.tickerSpeed);
});
}
// if vertical
}else if(options.mode == 'vertical'){
// if next
if(options.tickerDirection == 'next'){
$parent.animate({'top': '-='+distance+'px'}, speed, 'linear', function(){
$parent.css('top', leftCss);
moveTheShow(leftCss, origShowHeight, options.tickerSpeed);
});
// if prev
}else if(options.tickerDirection == 'prev'){
$parent.animate({'top': '+='+distance+'px'}, speed, 'linear', function(){
$parent.css('top', leftCss);
moveTheShow(leftCss, origShowHeight, options.tickerSpeed);
});
}
}
}
/**
* Sets all variables associated with the controls
*/
function setAutoControlsVars(){
// check if text or images should be used for controls
// check "start"
if(options.startImage != ''){
startContent = options.startImage;
startType = 'image';
}else{
startContent = options.startText;
startType = 'text';
}
// check "stop"
if(options.stopImage != ''){
stopContent = options.stopImage;
stopType = 'image';
}else{
stopContent = options.stopText;
stopType = 'text';
}
// show the controls
showAutoControls(startType, startContent, stopType, stopContent);
}
/**
* Handles hover events for auto shows
*/
function setAutoHover(){
// hover over the slider window
$outerWrapper.find('.bx-window').hover(function() {
if(autoPlaying){
base.stopShow(false);
}
}, function() {
if(autoPlaying){
base.startShow(false);
}
});
}
/**
* Handles hover events for ticker mode
*/
function setTickerHover(){
// on hover stop the animation
$parent.hover(function() {
if(autoPlaying){
base.stopTicker(false);
}
}, function() {
if(autoPlaying){
base.startTicker(false);
}
});
}
/**
* Handles fade animation
*/
function setChildrenFade(){
// fade out any other child besides the current
$children.not(':eq('+currentSlide+')').fadeTo(options.speed, 0).css('zIndex', 98);
// fade in the current slide
$children.eq(currentSlide).css('zIndex', 99).fadeTo(options.speed, 1, function(){
isWorking = false;
// ie fade fix
if(jQuery.browser.msie){
$children.eq(currentSlide).get(0).style.removeAttribute('filter');
}
// perform the callback function
options.onAfterSlide(currentSlide, $children.length, $children.eq(currentSlide));
});
};
/**
* Makes slide active
*/
function makeSlideActive(number){
if(options.pagerType == 'full' && options.pager){
// remove all active classes
$('a', $pager).removeClass(options.pagerActiveClass);
// assign active class to appropriate slide
$('a', $pager).eq(number).addClass(options.pagerActiveClass);
}else if(options.pagerType == 'short' && options.pager){
$('.bx-pager-current', $pager).html(currentSlide+1);
}
}
/**
* Displays next/prev controls
*
* @param string nextType 'image', 'text'
* @param string nextContent if type='image', specify a filepath to the image. if type='text', specify text.
* @param string prevType 'image', 'text'
* @param string prevContent if type='image', specify a filepath to the image. if type='text', specify text.
*/
function showControls(nextType, nextContent, prevType, prevContent){
// create pager html elements
var $nextHtml = $('<a href="" class="bx-next"></a>');
var $prevHtml = $('<a href="" class="bx-prev"></a>');
// check if next is 'text' or 'image'
if(nextType == 'text'){
$nextHtml.html(nextContent);
}else{
$nextHtml.html('<img src="'+nextContent+'" />');
}
// check if prev is 'text' or 'image'
if(prevType == 'text'){
$prevHtml.html(prevContent);
}else{
$prevHtml.html('<img src="'+prevContent+'" />');
}
// check if user supplied a selector to populate next control
if(options.prevSelector){
$(options.prevSelector).append($prevHtml);
}else{
$outerWrapper.append($prevHtml);
}
// check if user supplied a selector to populate next control
if(options.nextSelector){
$(options.nextSelector).append($nextHtml);
}else{
$outerWrapper.append($nextHtml);
}
// click next control
$nextHtml.click(function() {
base.goToNextSlide();
return false;
});
// click prev control
$prevHtml.click(function() {
base.goToPreviousSlide();
return false;
});
}
/**
* Displays the pager
*
* @param string type 'full', 'short'
*/
function showPager(type){
// sets up logic for finite multi slide shows
var pagerQty = $children.length;
// if we are moving more than one at a time and we have a finite loop
if(options.moveSlideQty > 1){
// if slides create an odd number of pages
if($children.length % options.moveSlideQty != 0){
// pagerQty = $children.length / options.moveSlideQty + 1;
pagerQty = Math.ceil($children.length / options.moveSlideQty);
// if slides create an even number of pages
}else{
pagerQty = $children.length / options.moveSlideQty;
}
}
var pagerString = '';
// check if custom build function was supplied
if(options.buildPager){
for(var i=0; i<pagerQty; i++){
pagerString += options.buildPager(i, $children.eq(i * options.moveSlideQty));
}
// if not, use default pager
}else if(type == 'full'){
// build the full pager
for(var i=1; i<=pagerQty; i++){
pagerString += '<a href="" class="pager-link pager-'+i+'">'+i+'</a>';
}
}else if(type == 'short') {
// build the short pager
pagerString = '<span class="bx-pager-current">'+(options.startingSlide+1)+'</span> '+options.pagerShortSeparator+' <span class="bx-pager-total">'+$children.length+'</span>';
}
// check if user supplied a pager selector
if(options.pagerSelector){
$(options.pagerSelector).append(pagerString);
$pager = $(options.pagerSelector);
}else{
var $pagerContainer = $('<div class="bx-pager"></div>');
$pagerContainer.append(pagerString);
// attach the pager to the DOM
if(options.pagerLocation == 'top'){
$outerWrapper.prepend($pagerContainer);
}else if(options.pagerLocation == 'bottom'){
$outerWrapper.append($pagerContainer);
}
// cache the pager element
$pager = $('.bx-pager', $outerWrapper);
}
$pager.children().click(function() {
// only if pager is full mode
if(options.pagerType == 'full'){
// get the index from the link
var slideIndex = $pager.children().index(this);
// accomodate moving more than one slide
if(options.moveSlideQty > 1){
slideIndex *= options.moveSlideQty;
}
base.goToSlide(slideIndex);
}
return false;
});
}
/**
* Displays captions
*/
function showCaptions(){
// get the title from each image
var caption = $('img', $children.eq(currentSlide)).attr('title');
// if the caption exists
if(caption != ''){
// if user supplied a selector
if(options.captionsSelector){
$(options.captionsSelector).html(caption);
}else{
$('.bx-captions', $outerWrapper).html(caption);
}
}else{
// if user supplied a selector
if(options.captionsSelector){
$(options.captionsSelector).html('&nbsp;');
}else{
$('.bx-captions', $outerWrapper).html('&nbsp;');
}
}
}
/**
* Displays start/stop controls for auto and ticker mode
*
* @param string type 'image', 'text'
* @param string next [optional] if type='image', specify a filepath to the image. if type='text', specify text.
* @param string prev [optional] if type='image', specify a filepath to the image. if type='text', specify text.
*/
function showAutoControls(startType, startContent, stopType, stopContent){
// create pager html elements
$autoControls = $('<a href="" class="bx-start"></a>');
// check if start is 'text' or 'image'
if(startType == 'text'){
$startContent = startContent;
}else{
$startContent = '<img src="'+startContent+'" />';
}
// check if stop is 'text' or 'image'
if(stopType == 'text'){
$stopContent = stopContent;
}else{
$stopContent = '<img src="'+stopContent+'" />';
}
// check if user supplied a selector to populate next control
if(options.autoControlsSelector){
$(options.autoControlsSelector).append($autoControls);
}else{
$outerWrapper.append('<div class="bx-auto"></div>');
$('.bx-auto', $outerWrapper).html($autoControls);
}
// click start control
$autoControls.click(function() {
if(options.ticker){
if($(this).hasClass('stop')){
base.stopTicker();
}else if($(this).hasClass('start')){
base.startTicker();
}
}else{
if($(this).hasClass('stop')){
base.stopShow(true);
}else if($(this).hasClass('start')){
base.startShow(true);
}
}
return false;
});
}
/**
* Checks if show is in finite mode, and if slide is either first or last, then hides the respective control
*/
function checkEndControls(){
if(!options.infiniteLoop && options.hideControlOnEnd){
// check previous
if(currentSlide == firstSlide){
$('.bx-prev', $outerWrapper).hide();
}else{
$('.bx-prev', $outerWrapper).show();
}
// check next
if(currentSlide == lastSlide){
$('.bx-next', $outerWrapper).hide();
}else{
$('.bx-next', $outerWrapper).show();
}
}
}
/**
* Returns the left offset of the slide from the parent container
*/
function getSlidePosition(number, side){
if(side == 'left'){
var position = $('.pager', $outerWrapper).eq(number).position().left;
}else if(side == 'top'){
var position = $('.pager', $outerWrapper).eq(number).position().top;
}
return position;
}
/**
* Returns the width of the wrapper
*/
function getWrapperWidth(){
var wrapperWidth = $firstChild.outerWidth() * options.displaySlideQty;
return wrapperWidth;
}
/**
* Returns the height of the wrapper
*/
function getWrapperHeight(){
// if displaying multiple slides, multiple wrapper width by number of slides to display
var wrapperHeight = $firstChild.outerHeight() * options.displaySlideQty;
return wrapperHeight;
}
/**
* Returns a sample of an arry and loops back on itself if the end of the array is reached
*
* @param array array original array the sample is derived from
* @param int start array index sample will start
* @param int length number of items in the sample
* @param string direction 'forward', 'backward' direction the loop should travel in the array
*/
function getArraySample(array, start, length, direction){
// initialize empty array
var sample = [];
// clone the length argument
var loopLength = length;
// determines when the empty array should start being populated
var startPopulatingArray = false;
// reverse the array if direction = 'backward'
if(direction == 'backward'){
array = $.makeArray(array);
array.reverse();
}
// loop through original array until the length argument is met
while(loopLength > 0){
// loop through original array
$.each(array, function(index, val) {
// check if length has been met
if(loopLength > 0){
// don't do anything unless first index has been reached
if(!startPopulatingArray){
// start populating empty array
if(index == start){
startPopulatingArray = true;
// add element to array
sample.push($(this).clone());
// decrease the length clone variable
loopLength--;
}
}else{
// add element to array
sample.push($(this).clone());
// decrease the length clone variable
loopLength--;
}
// if length has been met, break loose
}else{
return false;
}
});
}
return sample;
}
this.each(function(){
// make sure the element has children
if($(this).children().length > 0){
base.initShow();
}
});
return this;
}
jQuery.fx.prototype.cur = function(){
if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
return this.elem[ this.prop ];
}
var r = parseFloat( jQuery.css( this.elem, this.prop ) );
// return r && r > -10000 ? r : 0;
return r;
}
})(jQuery);