(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);
		}
		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);
					});
				}
			}
		}
		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);
		}
		function setAutoHover() {
			// hover over the slider window
			$outerWrapper.find('.bx-window').hover(function() {
				if (autoPlaying) {
					base.stopShow(false);
				}
			}, function() {
				if (autoPlaying) {
					base.startShow(false);
				}
			});
		}
		function setTickerHover() {
			// on hover stop the animation
			$parent.hover(function() {
				if (autoPlaying) {
					base.stopTicker(false);
				}
			}, function() {
				if (autoPlaying) {
					base.startTicker(false);
				}
			});
		}
		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));
					});
		}
		;
		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);
			}
		}
		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;');
				}
			}
		}

		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;
			});
		}

		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();
				}
			}
		}

		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;
		}

		function getWrapperWidth() {
			var wrapperWidth = $firstChild.outerWidth()
					* options.displaySlideQty;
			return wrapperWidth;
		}

		function getWrapperHeight() {
			// if displaying multiple slides, multiple wrapper width by number of slides to display
			var wrapperHeight = $firstChild.outerHeight()
					* options.displaySlideQty;
			return wrapperHeight;
		}

		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() {
			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);

