Revision 41 | Zur aktuellen Revision | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
/*** BxSlider v4.1.2 - Fully loaded, responsive content slider* http://bxslider.com** Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com* Written while drinking Belgian ales and listening to jazz** Released under the MIT license - http://opensource.org/licenses/MIT*/;(function($){var plugin = {};var defaults = {// GENERALmode: 'horizontal',slideSelector: '',infiniteLoop: true,hideControlOnEnd: false,speed: 500,easing: null,slideMargin: 0,startSlide: 0,randomStart: false,captions: false,ticker: false,tickerHover: false,adaptiveHeight: false,adaptiveHeightSpeed: 500,video: false,useCSS: true,preloadImages: 'visible',responsive: true,slideZIndex: 50,wrapperClass: 'bx-wrapper',// TOUCHtouchEnabled: true,swipeThreshold: 50,oneToOneTouch: true,preventDefaultSwipeX: true,preventDefaultSwipeY: false,// PAGERpager: true,pagerType: 'full',pagerShortSeparator: ' / ',pagerSelector: null,buildPager: null,pagerCustom: null,// CONTROLScontrols: true,nextText: 'Next',prevText: 'Prev',nextSelector: null,prevSelector: null,autoControls: false,startText: 'Start',stopText: 'Stop',autoControlsCombine: false,autoControlsSelector: null,// AUTOauto: false,pause: 4000,autoStart: true,autoDirection: 'next',autoHover: false,autoDelay: 0,autoSlideForOnePage: false,// CAROUSELminSlides: 1,maxSlides: 1,moveSlides: 0,slideWidth: 0,// CALLBACKSonSliderLoad: function() {},onSlideBefore: function() {},onSlideAfter: function() {},onSlideNext: function() {},onSlidePrev: function() {},onSliderResize: function() {}}$.fn.bxSlider = function(options){if(this.length == 0) return this;// support mutltiple elementsif(this.length > 1){this.each(function(){$(this).bxSlider(options)});return this;}// create a namespace to be used throughout the pluginvar slider = {};// set a reference to our slider elementvar el = this;plugin.el = this;/*** Makes slideshow responsive*/// first get the original window dimens (thanks alot IE)var windowWidth = $(window).width();var windowHeight = $(window).height();/*** ===================================================================================* = PRIVATE FUNCTIONS* ===================================================================================*//*** Initializes namespace settings to be used throughout plugin*/var init = function(){// merge user-supplied options with the defaultsslider.settings = $.extend({}, defaults, options);// parse slideWidth settingslider.settings.slideWidth = parseInt(slider.settings.slideWidth);// store the original childrenslider.children = el.children(slider.settings.slideSelector);// check if actual number of slides is less than minSlides / maxSlidesif(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length;if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length;// if random start, set the startSlide setting to random numberif(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length);// store active slide informationslider.active = { index: slider.settings.startSlide }// store if the slider is in carousel mode (displaying / moving multiple slides)slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1;// if carousel, force preloadImages = 'all'if(slider.carousel) slider.settings.preloadImages = 'all';// calculate the min / max width thresholds based on min / max number of slides// used to setup and update carousel slides dimensionsslider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin);slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);// store the current state of the slider (if currently animating, working is true)slider.working = false;// initialize the controls objectslider.controls = {};// initialize an auto intervalslider.interval = null;// determine which property to use for transitionsslider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left';// determine if hardware acceleration can be usedslider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){// create our test div elementvar div = document.createElement('div');// css transition propertiesvar props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];// test for each propertyfor(var i in props){if(div.style[props[i]] !== undefined){slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();slider.animProp = '-' + slider.cssPrefix + '-transform';return true;}}return false;}());// if vertical mode always make maxSlides and minSlides equalif(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides;// save original style datael.data("origStyle", el.attr("style"));el.children(slider.settings.slideSelector).each(function() {$(this).data("origStyle", $(this).attr("style"));});// perform all DOM / CSS modificationssetup();}/*** Performs all DOM and CSS modifications*/var setup = function(){// wrap el in a wrapperel.wrap('<div class="' + slider.settings.wrapperClass + '"><div class="bx-viewport"></div></div>');// store a namspace reference to .bx-viewportslider.viewport = el.parent();// add a loading div to display while images are loadingslider.loader = $('<div class="bx-loading" />');slider.viewport.prepend(slider.loader);// set el to a massive width, to hold any needed slides// also strip any margin and padding from elel.css({width: slider.settings.mode == 'horizontal' ? (slider.children.length * 100 + 215) + '%' : 'auto',position: 'relative'});// if using CSS, add the easing propertyif(slider.usingCSS && slider.settings.easing){el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);// if not using CSS and no easing value was supplied, use the default JS animation easing (swing)}else if(!slider.settings.easing){slider.settings.easing = 'swing';}var slidesShowing = getNumberSlidesShowing();// make modifications to the viewport (.bx-viewport)slider.viewport.css({width: '100%',overflow: 'hidden',position: 'relative'});slider.viewport.parent().css({maxWidth: getViewportMaxWidth()});// make modification to the wrapper (.bx-wrapper)if(!slider.settings.pager) {slider.viewport.parent().css({margin: '0 auto 0px'});}// apply css to all slider childrenslider.children.css({'float': slider.settings.mode == 'horizontal' ? 'left' : 'none',listStyle: 'none',position: 'relative'});// apply the calculated width after the float is applied to prevent scrollbar interferenceslider.children.css('width', getSlideWidth());// if slideMargin is supplied, add the cssif(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin);if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin);// if "fade" mode, add positioning and z-index CSSif(slider.settings.mode == 'fade'){slider.children.css({position: 'absolute',zIndex: 0,display: 'none'});// prepare the z-index on the showing elementslider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'});}// create an element to contain all slider controls (pager, start / stop, etc)slider.controls.el = $('<div class="bx-controls" />');// if captions are requested, add themif(slider.settings.captions) appendCaptions();// check if startSlide is last slideslider.active.last = slider.settings.startSlide == getPagerQty() - 1;// if video is true, set up the fitVids pluginif(slider.settings.video) el.fitVids();// set the default preload selector (visible)var preloadSelector = slider.children.eq(slider.settings.startSlide);if (slider.settings.preloadImages == "all") preloadSelector = slider.children;// only check for control addition if not in "ticker" modeif(!slider.settings.ticker){// if pager is requested, add itif(slider.settings.pager) appendPager();// if controls are requested, add themif(slider.settings.controls) appendControls();// if auto is true, and auto controls are requested, add themif(slider.settings.auto && slider.settings.autoControls) appendControlsAuto();// if any control option is requested, add the controls wrapperif(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el);// if ticker mode, do not allow a pager}else{slider.settings.pager = false;}// preload all images, then perform final DOM / CSS modifications that depend on images being loadedloadElements(preloadSelector, start);}var loadElements = function(selector, callback){var total = selector.find('img, iframe').length;if (total == 0){callback();return;}var count = 0;selector.find('img, iframe').each(function(){$(this).one('load', function() {if(++count == total) callback();}).each(function() {if(this.complete) $(this).load();});});}/*** Start the slider*/var start = function(){// if infinite loop, prepare additional slidesif(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides;var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone');var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone');el.append(sliceAppend).prepend(slicePrepend);}// remove the loading DOM elementslider.loader.remove();// set the left / top position of "el"setSlidePosition();// if "vertical" mode, always use adaptiveHeight to prevent odd behaviorif (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true;// set the viewport heightslider.viewport.height(getViewportHeight());// make sure everything is positioned just right (same as a window resize)el.redrawSlider();// onSliderLoad callbackslider.settings.onSliderLoad(slider.active.index);// slider has been fully initializedslider.initialized = true;// bind the resize call to the windowif (slider.settings.responsive) $(window).bind('resize', resizeWindow);// if auto is true and has more than 1 page, start the showif (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) initAuto();// if ticker is true, start the tickerif (slider.settings.ticker) initTicker();// if pager is requested, make the appropriate pager link activeif (slider.settings.pager) updatePagerActive(slider.settings.startSlide);// check for any updates to the controls (like hideControlOnEnd updates)if (slider.settings.controls) updateDirectionControls();// if touchEnabled is true, setup the touch eventsif (slider.settings.touchEnabled && !slider.settings.ticker) initTouch();}/*** Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value*/var getViewportHeight = function(){var height = 0;// first determine which children (slides) should be used in our height calculationvar children = $();// if mode is not "vertical" and adaptiveHeight is false, include all childrenif(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){children = slider.children;}else{// if not carousel, return the single active childif(!slider.carousel){children = slider.children.eq(slider.active.index);// if carousel, return a slice of children}else{// get the individual slide indexvar currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy();// add the current slide to the childrenchildren = slider.children.eq(currentIndex);// cycle through the remaining "showing" slidesfor (i = 1; i <= slider.settings.maxSlides - 1; i++){// if looped back to the startif(currentIndex + i >= slider.children.length){children = children.add(slider.children.eq(i - 1));}else{children = children.add(slider.children.eq(currentIndex + i));}}}}// if "vertical" mode, calculate the sum of the heights of the childrenif(slider.settings.mode == 'vertical'){children.each(function(index) {height += $(this).outerHeight();});// add user-supplied marginsif(slider.settings.slideMargin > 0){height += slider.settings.slideMargin * (slider.settings.minSlides - 1);}// if not "vertical" mode, calculate the max height of the children}else{height = Math.max.apply(Math, children.map(function(){return $(this).outerHeight(false);}).get());}if(slider.viewport.css('box-sizing') == 'border-box'){height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) +parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));}else if(slider.viewport.css('box-sizing') == 'padding-box'){height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));}return height;}/*** Returns the calculated width to be used for the outer wrapper / viewport*/var getViewportMaxWidth = function(){var width = '100%';if(slider.settings.slideWidth > 0){if(slider.settings.mode == 'horizontal'){width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);}else{width = slider.settings.slideWidth;}}return width;}/*** Returns the calculated width to be applied to each slide*/var getSlideWidth = function(){// start with any user-supplied slide widthvar newElWidth = slider.settings.slideWidth;// get the current viewport widthvar wrapWidth = slider.viewport.width();// if slide width was not supplied, or is larger than the viewport use the viewport widthif(slider.settings.slideWidth == 0 ||(slider.settings.slideWidth > wrapWidth && !slider.carousel) ||slider.settings.mode == 'vertical'){newElWidth = wrapWidth;// if carousel, use the thresholds to determine the width}else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){if(wrapWidth > slider.maxThreshold){// newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides;}else if(wrapWidth < slider.minThreshold){newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;}}return newElWidth;}/*** Returns the number of slides currently visible in the viewport (includes partially visible slides)*/var getNumberSlidesShowing = function(){var slidesShowing = 1;if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){// if viewport is smaller than minThreshold, return minSlidesif(slider.viewport.width() < slider.minThreshold){slidesShowing = slider.settings.minSlides;// if viewport is larger than minThreshold, return maxSlides}else if(slider.viewport.width() > slider.maxThreshold){slidesShowing = slider.settings.maxSlides;// if viewport is between min / max thresholds, divide viewport width by first child width}else{var childWidth = slider.children.first().width() + slider.settings.slideMargin;slidesShowing = Math.floor((slider.viewport.width() +slider.settings.slideMargin) / childWidth);}// if "vertical" mode, slides showing will always be minSlides}else if(slider.settings.mode == 'vertical'){slidesShowing = slider.settings.minSlides;}return slidesShowing;}/*** Returns the number of pages (one full viewport of slides is one "page")*/var getPagerQty = function(){var pagerQty = 0;// if moveSlides is specified by the userif(slider.settings.moveSlides > 0){if(slider.settings.infiniteLoop){pagerQty = Math.ceil(slider.children.length / getMoveBy());}else{// use a while loop to determine pagesvar breakPoint = 0;var counter = 0// when breakpoint goes above children length, counter is the number of pageswhile (breakPoint < slider.children.length){++pagerQty;breakPoint = counter + getNumberSlidesShowing();counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();}}// if moveSlides is 0 (auto) divide children length by sides showing, then round up}else{pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());}return pagerQty;}/*** Returns the number of indivual slides by which to shift the slider*/var getMoveBy = function(){// if moveSlides was set by the user and moveSlides is less than number of slides showingif(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){return slider.settings.moveSlides;}// if moveSlides is 0 (auto)return getNumberSlidesShowing();}/*** Sets the slider's (el) left or top position*/var setSlidePosition = function(){// if last slide, not infinite loop, and number of children is larger than specified maxSlidesif(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){if (slider.settings.mode == 'horizontal'){// get the last child's positionvar lastChild = slider.children.last();var position = lastChild.position();// set the left positionsetPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);}else if(slider.settings.mode == 'vertical'){// get the last showing index's positionvar lastShowingIndex = slider.children.length - slider.settings.minSlides;var position = slider.children.eq(lastShowingIndex).position();// set the top positionsetPositionProperty(-position.top, 'reset', 0);}// if not last slide}else{// get the position of the first showing slidevar position = slider.children.eq(slider.active.index * getMoveBy()).position();// check for last slideif (slider.active.index == getPagerQty() - 1) slider.active.last = true;// set the repective positionif (position != undefined){if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0);else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0);}}}/*** Sets the el's animating property position (which in turn will sometimes animate el).* If using CSS, sets the transform property. If not using CSS, sets the top / left property.** @param value (int)* - the animating property's value** @param type (string) 'slider', 'reset', 'ticker'* - the type of instance for which the function is being** @param duration (int)* - the amount of time (in ms) the transition should occupy** @param params (array) optional* - an optional parameter containing any variables that need to be passed in*/var setPositionProperty = function(value, type, duration, params){// use CSS transformif(slider.usingCSS){// determine the translate3d valuevar propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';// add the CSS transition-durationel.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');if(type == 'slide'){// set the property valueel.css(slider.animProp, propValue);// bind a callback method - executes when CSS transition completesel.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){// unbind the callbackel.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');updateAfterSlideTransition();});}else if(type == 'reset'){el.css(slider.animProp, propValue);}else if(type == 'ticker'){// make the transition use 'linear'el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');el.css(slider.animProp, propValue);// bind a callback method - executes when CSS transition completesel.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){// unbind the callbackel.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');// reset the positionsetPositionProperty(params['resetValue'], 'reset', 0);// start the loop againtickerLoop();});}// use JS animate}else{var animateObj = {};animateObj[slider.animProp] = value;if(type == 'slide'){el.animate(animateObj, duration, slider.settings.easing, function(){updateAfterSlideTransition();});}else if(type == 'reset'){el.css(slider.animProp, value)}else if(type == 'ticker'){el.animate(animateObj, speed, 'linear', function(){setPositionProperty(params['resetValue'], 'reset', 0);// run the recursive loop after animationtickerLoop();});}}}/*** Populates the pager with proper amount of pages*/var populatePager = function(){var pagerHtml = '';var pagerQty = getPagerQty();// loop through each pager itemfor(var i=0; i < pagerQty; i++){var linkContent = '';// if a buildPager function is supplied, use it to get pager link value, else use index + 1if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){linkContent = slider.settings.buildPager(i);slider.pagerEl.addClass('bx-custom-pager');}else{linkContent = i + 1;slider.pagerEl.addClass('bx-default-pager');}// var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;// add the markup to the stringpagerHtml += '<div class="bx-pager-item"><a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>';};// populate the pager element with pager linksslider.pagerEl.html(pagerHtml);}/*** Appends the pager to the controls element*/var appendPager = function(){if(!slider.settings.pagerCustom){// create the pager DOM elementslider.pagerEl = $('<div class="bx-pager" />');// if a pager selector was supplied, populate it with the pagerif(slider.settings.pagerSelector){$(slider.settings.pagerSelector).html(slider.pagerEl);// if no pager selector was supplied, add it after the wrapper}else{slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);}// populate the pagerpopulatePager();}else{slider.pagerEl = $(slider.settings.pagerCustom);}// assign the pager click bindingslider.pagerEl.on('click', 'a', clickPagerBind);}/*** Appends prev / next controls to the controls element*/var appendControls = function(){slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>');slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>');// bind click actions to the controlsslider.controls.next.bind('click', clickNextBind);slider.controls.prev.bind('click', clickPrevBind);// if nextSlector was supplied, populate itif(slider.settings.nextSelector){$(slider.settings.nextSelector).append(slider.controls.next);}// if prevSlector was supplied, populate itif(slider.settings.prevSelector){$(slider.settings.prevSelector).append(slider.controls.prev);}// if no custom selectors were suppliedif(!slider.settings.nextSelector && !slider.settings.prevSelector){// add the controls to the DOMslider.controls.directionEl = $('<div class="bx-controls-direction" />');// add the control elements to the directionElslider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);// slider.viewport.append(slider.controls.directionEl);slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);}}/*** Appends start / stop auto controls to the controls element*/var appendControlsAuto = function(){slider.controls.start = $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>');slider.controls.stop = $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>');// add the controls to the DOMslider.controls.autoEl = $('<div class="bx-controls-auto" />');// bind click actions to the controlsslider.controls.autoEl.on('click', '.bx-start', clickStartBind);slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);// if autoControlsCombine, insert only the "start" controlif(slider.settings.autoControlsCombine){slider.controls.autoEl.append(slider.controls.start);// if autoControlsCombine is false, insert both controls}else{slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);}// if auto controls selector was supplied, populate it with the controlsif(slider.settings.autoControlsSelector){$(slider.settings.autoControlsSelector).html(slider.controls.autoEl);// if auto controls selector was not supplied, add it after the wrapper}else{slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);}// update the auto controlsupdateAutoControls(slider.settings.autoStart ? 'stop' : 'start');}/*** Appends image captions to the DOM*/var appendCaptions = function(){// cycle through each childslider.children.each(function(index){// get the image title attributevar title = $(this).find('img:first').attr('title');// append the captionif (title != undefined && ('' + title).length) {$(this).append('<div class="bx-caption"><span>' + title + '</span></div>');}});}/*** Click next binding** @param e (event)* - DOM event object*/var clickNextBind = function(e){// if auto show is running, stop itif (slider.settings.auto) el.stopAuto();el.goToNextSlide();e.preventDefault();}/*** Click prev binding** @param e (event)* - DOM event object*/var clickPrevBind = function(e){// if auto show is running, stop itif (slider.settings.auto) el.stopAuto();el.goToPrevSlide();e.preventDefault();}/*** Click start binding** @param e (event)* - DOM event object*/var clickStartBind = function(e){el.startAuto();e.preventDefault();}/*** Click stop binding** @param e (event)* - DOM event object*/var clickStopBind = function(e){el.stopAuto();e.preventDefault();}/*** Click pager binding** @param e (event)* - DOM event object*/var clickPagerBind = function(e){// if auto show is running, stop itif (slider.settings.auto) el.stopAuto();var pagerLink = $(e.currentTarget);if(pagerLink.attr('data-slide-index') !== undefined){var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));// if clicked pager link is not active, continue with the goToSlide callif(pagerIndex != slider.active.index) el.goToSlide(pagerIndex);e.preventDefault();}}/*** Updates the pager links with an active class** @param slideIndex (int)* - index of slide to make active*/var updatePagerActive = function(slideIndex){// if "short" pager typevar len = slider.children.length; // nb of childrenif(slider.settings.pagerType == 'short'){if(slider.settings.maxSlides > 1) {len = Math.ceil(slider.children.length/slider.settings.maxSlides);}slider.pagerEl.html( (slideIndex + 1) + slider.settings.pagerShortSeparator + len);return;}// remove all pager active classesslider.pagerEl.find('a').removeClass('active');// apply the active class for all pagersslider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); });}/*** Performs needed actions after a slide transition*/var updateAfterSlideTransition = function(){// if infinte loop is trueif(slider.settings.infiniteLoop){var position = '';// first slideif(slider.active.index == 0){// set the new positionposition = slider.children.eq(0).position();// carousel, last slide}else if(slider.active.index == getPagerQty() - 1 && slider.carousel){position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();// last slide}else if(slider.active.index == slider.children.length - 1){position = slider.children.eq(slider.children.length - 1).position();}if(position){if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0); }}}// declare that the transition is completeslider.working = false;// onSlideAfter callbackslider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);}/*** Updates the auto controls state (either active, or combined switch)** @param state (string) "start", "stop"* - the new state of the auto show*/var updateAutoControls = function(state){// if autoControlsCombine is true, replace the current control with the new stateif(slider.settings.autoControlsCombine){slider.controls.autoEl.html(slider.controls[state]);// if autoControlsCombine is false, apply the "active" class to the appropriate control}else{slider.controls.autoEl.find('a').removeClass('active');slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');}}/*** Updates the direction controls (checks if either should be hidden)*/var updateDirectionControls = function(){if(getPagerQty() == 1){slider.controls.prev.addClass('disabled');slider.controls.next.addClass('disabled');}else if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){// if first slideif (slider.active.index == 0){slider.controls.prev.addClass('disabled');slider.controls.next.removeClass('disabled');// if last slide}else if(slider.active.index == getPagerQty() - 1){slider.controls.next.addClass('disabled');slider.controls.prev.removeClass('disabled');// if any slide in the middle}else{slider.controls.prev.removeClass('disabled');slider.controls.next.removeClass('disabled');}}}/*** Initialzes the auto process*/var initAuto = function(){// if autoDelay was supplied, launch the auto show using a setTimeout() callif(slider.settings.autoDelay > 0){var timeout = setTimeout(el.startAuto, slider.settings.autoDelay);// if autoDelay was not supplied, start the auto show normally}else{el.startAuto();}// if autoHover is requestedif(slider.settings.autoHover){// on el hoverel.hover(function(){// if the auto show is currently playing (has an active interval)if(slider.interval){// stop the auto show and pass true agument which will prevent control updateel.stopAuto(true);// create a new autoPaused value which will be used by the relative "mouseout" eventslider.autoPaused = true;}}, function(){// if the autoPaused value was created be the prior "mouseover" eventif(slider.autoPaused){// start the auto show and pass true agument which will prevent control updateel.startAuto(true);// reset the autoPaused valueslider.autoPaused = null;}});}}/*** Initialzes the ticker process*/var initTicker = function(){var startPosition = 0;// if autoDirection is "next", append a clone of the entire sliderif(slider.settings.autoDirection == 'next'){el.append(slider.children.clone().addClass('bx-clone'));// if autoDirection is "prev", prepend a clone of the entire slider, and set the left position}else{el.prepend(slider.children.clone().addClass('bx-clone'));var position = slider.children.first().position();startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top;}setPositionProperty(startPosition, 'reset', 0);// do not allow controls in ticker modeslider.settings.pager = false;slider.settings.controls = false;slider.settings.autoControls = false;// if autoHover is requestedif(slider.settings.tickerHover && !slider.usingCSS){// on el hoverslider.viewport.hover(function(){el.stop();}, function(){// calculate the total width of children (used to calculate the speed ratio)var totalDimens = 0;slider.children.each(function(index){totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);});// calculate the speed ratio (used to determine the new speed to finish the paused animation)var ratio = slider.settings.speed / totalDimens;// determine which property to usevar property = slider.settings.mode == 'horizontal' ? 'left' : 'top';// calculate the new speedvar newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));tickerLoop(newSpeed);});}// start the ticker looptickerLoop();}/*** Runs a continuous loop, news ticker-style*/var tickerLoop = function(resumeSpeed){speed = resumeSpeed ? resumeSpeed : slider.settings.speed;var position = {left: 0, top: 0};var reset = {left: 0, top: 0};// if "next" animate left position to last child, then reset left to 0if(slider.settings.autoDirection == 'next'){position = el.find('.bx-clone').first().position();// if "prev" animate left position to 0, then reset left to first non-clone child}else{reset = slider.children.first().position();}var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top;var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top;var params = {resetValue: resetValue};setPositionProperty(animateProperty, 'ticker', speed, params);}/*** Initializes touch events*/var initTouch = function(){// initialize object to contain all touch valuesslider.touch = {start: {x: 0, y: 0},end: {x: 0, y: 0}}slider.viewport.bind('touchstart', onTouchStart);}/*** Event handler for "touchstart"** @param e (event)* - DOM event object*/var onTouchStart = function(e){if(slider.working){e.preventDefault();}else{// record the original position when touch startsslider.touch.originalPos = el.position();var orig = e.originalEvent;// record the starting touch x, y coordinatesslider.touch.start.x = orig.changedTouches[0].pageX;slider.touch.start.y = orig.changedTouches[0].pageY;// bind a "touchmove" event to the viewportslider.viewport.bind('touchmove', onTouchMove);// bind a "touchend" event to the viewportslider.viewport.bind('touchend', onTouchEnd);}}/*** Event handler for "touchmove"** @param e (event)* - DOM event object*/var onTouchMove = function(e){var orig = e.originalEvent;// if scrolling on y axis, do not prevent defaultvar xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x);var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y);// x axis swipeif((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){e.preventDefault();// y axis swipe}else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){e.preventDefault();}if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){var value = 0;// if horizontal, drag along x axisif(slider.settings.mode == 'horizontal'){var change = orig.changedTouches[0].pageX - slider.touch.start.x;value = slider.touch.originalPos.left + change;// if vertical, drag along y axis}else{var change = orig.changedTouches[0].pageY - slider.touch.start.y;value = slider.touch.originalPos.top + change;}setPositionProperty(value, 'reset', 0);}}/*** Event handler for "touchend"** @param e (event)* - DOM event object*/var onTouchEnd = function(e){slider.viewport.unbind('touchmove', onTouchMove);var orig = e.originalEvent;var value = 0;// record end x, y positionsslider.touch.end.x = orig.changedTouches[0].pageX;slider.touch.end.y = orig.changedTouches[0].pageY;// if fade mode, check if absolute x distance clears the thresholdif(slider.settings.mode == 'fade'){var distance = Math.abs(slider.touch.start.x - slider.touch.end.x);if(distance >= slider.settings.swipeThreshold){slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide();el.stopAuto();}// not fade mode}else{var distance = 0;// calculate distance and el's animate propertyif(slider.settings.mode == 'horizontal'){distance = slider.touch.end.x - slider.touch.start.x;value = slider.touch.originalPos.left;}else{distance = slider.touch.end.y - slider.touch.start.y;value = slider.touch.originalPos.top;}// if not infinite loop and first / last slide, do not attempt a slide transitionif(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){setPositionProperty(value, 'reset', 200);}else{// check if distance clears thresholdif(Math.abs(distance) >= slider.settings.swipeThreshold){distance < 0 ? el.goToNextSlide() : el.goToPrevSlide();el.stopAuto();}else{// el.animate(property, 200);setPositionProperty(value, 'reset', 200);}}}slider.viewport.unbind('touchend', onTouchEnd);}/*** Window resize event callback*/var resizeWindow = function(e){// don't do anything if slider isn't initialized.if(!slider.initialized) return;// get the new window dimens (again, thank you IE)var windowWidthNew = $(window).width();var windowHeightNew = $(window).height();// make sure that it is a true window resize// *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements// are resized. Can you just die already?*if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){// set the new window dimenswindowWidth = windowWidthNew;windowHeight = windowHeightNew;// update all dynamic elementsel.redrawSlider();// Call user resize handlerslider.settings.onSliderResize.call(el, slider.active.index);}}/*** ===================================================================================* = PUBLIC FUNCTIONS* ===================================================================================*//*** Performs slide transition to the specified slide** @param slideIndex (int)* - the destination slide's index (zero-based)** @param direction (string)* - INTERNAL USE ONLY - the direction of travel ("prev" / "next")*/el.goToSlide = function(slideIndex, direction){// if plugin is currently in motion, ignore requestif(slider.working || slider.active.index == slideIndex) return;// declare that plugin is in motionslider.working = true;// store the old indexslider.oldIndex = slider.active.index;// if slideIndex is less than zero, set active index to last child (this happens during infinite loop)if(slideIndex < 0){slider.active.index = getPagerQty() - 1;// if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)}else if(slideIndex >= getPagerQty()){slider.active.index = 0;// set active index to requested slide}else{slider.active.index = slideIndex;}// onSlideBefore, onSlideNext, onSlidePrev callbacksslider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);if(direction == 'next'){slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);}else if(direction == 'prev'){slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);}// check if last slideslider.active.last = slider.active.index >= getPagerQty() - 1;// update the pager with active classif(slider.settings.pager) updatePagerActive(slider.active.index);// // check for direction control updateif(slider.settings.controls) updateDirectionControls();// if slider is set to mode: "fade"if(slider.settings.mode == 'fade'){// if adaptiveHeight is true and next height is different from current height, animate to the new heightif(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);}// fade out the visible child and reset its z-index valueslider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});// fade in the newly requested slideslider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex+1).fadeIn(slider.settings.speed, function(){$(this).css('zIndex', slider.settings.slideZIndex);updateAfterSlideTransition();});// slider mode is not "fade"}else{// if adaptiveHeight is true and next height is different from current height, animate to the new heightif(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);}var moveBy = 0;var position = {left: 0, top: 0};// if carousel and not infinite loopif(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){if(slider.settings.mode == 'horizontal'){// get the last child positionvar lastChild = slider.children.eq(slider.children.length - 1);position = lastChild.position();// calculate the position of the last slidemoveBy = slider.viewport.width() - lastChild.outerWidth();}else{// get last showing index positionvar lastShowingIndex = slider.children.length - slider.settings.minSlides;position = slider.children.eq(lastShowingIndex).position();}// horizontal carousel, going previous while on first slide (infiniteLoop mode)}else if(slider.carousel && slider.active.last && direction == 'prev'){// get the last child positionvar eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);var lastChild = el.children('.bx-clone').eq(eq);position = lastChild.position();// if infinite loop and "Next" is clicked on the last slide}else if(direction == 'next' && slider.active.index == 0){// get the last clone positionposition = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();slider.active.last = false;// normal non-zero requests}else if(slideIndex >= 0){var requestEl = slideIndex * getMoveBy();position = slider.children.eq(requestEl).position();}/* If the position doesn't exist* (e.g. if you destroy the slider on a next click),* it doesn't throw an error.*/if ("undefined" !== typeof(position)) {var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top;// plugin values to be animatedsetPositionProperty(value, 'slide', slider.settings.speed);}}}/*** Transitions to the next slide in the show*/el.goToNextSlide = function(){// if infiniteLoop is false and last page is showing, disregard callif (!slider.settings.infiniteLoop && slider.active.last) return;var pagerIndex = parseInt(slider.active.index) + 1;el.goToSlide(pagerIndex, 'next');}/*** Transitions to the prev slide in the show*/el.goToPrevSlide = function(){// if infiniteLoop is false and last page is showing, disregard callif (!slider.settings.infiniteLoop && slider.active.index == 0) return;var pagerIndex = parseInt(slider.active.index) - 1;el.goToSlide(pagerIndex, 'prev');}/*** Starts the auto show** @param preventControlUpdate (boolean)* - if true, auto controls state will not be updated*/el.startAuto = function(preventControlUpdate){// if an interval already exists, disregard callif(slider.interval) return;// create an intervalslider.interval = setInterval(function(){slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide();}, slider.settings.pause);// if auto controls are displayed and preventControlUpdate is not trueif (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop');}/*** Stops the auto show** @param preventControlUpdate (boolean)* - if true, auto controls state will not be updated*/el.stopAuto = function(preventControlUpdate){// if no interval exists, disregard callif(!slider.interval) return;// clear the intervalclearInterval(slider.interval);slider.interval = null;// if auto controls are displayed and preventControlUpdate is not trueif (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start');}/*** Returns current slide index (zero-based)*/el.getCurrentSlide = function(){return slider.active.index;}/*** Returns current slide element*/el.getCurrentSlideElement = function(){return slider.children.eq(slider.active.index);}/*** Returns number of slides in show*/el.getSlideCount = function(){return slider.children.length;}/*** Update all dynamic slider elements*/el.redrawSlider = function(){// resize all children in ratio to new screen sizeslider.children.add(el.find('.bx-clone')).width(getSlideWidth());// adjust the heightslider.viewport.css('height', getViewportHeight());// update the slide positionif(!slider.settings.ticker) setSlidePosition();// if active.last was true before the screen resize, we want// to keep it last no matter what screen size we end onif (slider.active.last) slider.active.index = getPagerQty() - 1;// if the active index (page) no longer exists due to the resize, simply set the index as lastif (slider.active.index >= getPagerQty()) slider.active.last = true;// if a pager is being displayed and a custom pager is not being used, update itif(slider.settings.pager && !slider.settings.pagerCustom){populatePager();updatePagerActive(slider.active.index);}}/*** Destroy the current instance of the slider (revert everything back to original state)*/el.destroySlider = function(){// don't do anything if slider has already been destroyedif(!slider.initialized) return;slider.initialized = false;$('.bx-clone', this).remove();slider.children.each(function() {$(this).data("origStyle") != undefined ? $(this).attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');});$(this).data("origStyle") != undefined ? this.attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');$(this).unwrap().unwrap();if(slider.controls.el) slider.controls.el.remove();if(slider.controls.next) slider.controls.next.remove();if(slider.controls.prev) slider.controls.prev.remove();if(slider.pagerEl && slider.settings.controls) slider.pagerEl.remove();$('.bx-caption', this).remove();if(slider.controls.autoEl) slider.controls.autoEl.remove();clearInterval(slider.interval);if(slider.settings.responsive) $(window).unbind('resize', resizeWindow);}/*** Reload the slider (revert all DOM changes, and re-initialize)*/el.reloadSlider = function(settings){if (settings != undefined) options = settings;el.destroySlider();init();}init();// returns the current jQuery objectreturn this;}})(jQuery);