PageSourceSearch

https://creativeleadersretreat.com/wp-content/plugins/bb-plugin/js/libs/jquery.bxslider.js?ver=2.10.1.5

js creativeleadersretreat.com collected 2026-10-04 13:45:52 UTC 67,221 bytes, 1,628 lines download raw bytes

1/**
2 * bxSlider v4.2.5
3 * Copyright 2013-2015 Steven Wanderski
4 * Written while drinking Belgian ales and listening to jazz
5
6 * Licensed under MIT (http://opensource.org/licenses/MIT)
7 */
8 /*
9 Patched to fix issue #960
10 See: https://github.com/stevenwanderski/bxslider-4/pull/1133/commits/c32dd309ef6801fd294c631a2ecb889084e713d5
11
12 Patched to fix https://bitbucket.org/fastlinemedia/beaver-builder-plugin/issues/1292/bx-slider-bug-with-links-in-firefox-59
13 Ref: https://github.com/stevenwanderski/bxslider-4/issues/1188
14 */
15;(function($) {
16
17  var defaults = {
18
19    // GENERAL
20    mode: 'horizontal',
21    slideSelector: '',
22    infiniteLoop: true,
23    hideControlOnEnd: false,
24    speed: 500,
25    easing: null,
26    slideMargin: 0,
27    startSlide: 0,
28    randomStart: false,
29    captions: false,
30    ticker: false,
31    tickerHover: false,
32    adaptiveHeight: false,
33    adaptiveHeightSpeed: 500,
34    video: false,
35    useCSS: true,
36    preloadImages: 'visible',
37    responsive: true,
38    slideZIndex: 50,
39    wrapperClass: 'bx-wrapper',
vendor: 26,762 bytes, lines 40-653
40    fallbackHTML: false,
41
42    // TOUCH
43    touchEnabled: true,
44    swipeThreshold: 50,
45    oneToOneTouch: true,
46    preventDefaultSwipeX: true,
47    preventDefaultSwipeY: false,
48
49    // ACCESSIBILITY
50    ariaLive: true,
51    ariaHidden: true,
52
53    // KEYBOARD
54    keyboardEnabled: true,
55
56    // PAGER
57    pager: true,
58    pagerType: 'full',
59    pagerShortSeparator: ' / ',
60    pagerSelector: null,
61    buildPager: null,
62    pagerCustom: null,
63
64    // CONTROLS
65    controls: true,
66    nextText: 'Next',
67    prevText: 'Prev',
68    nextSelector: null,
69    prevSelector: null,
70    autoControls: false,
71    startText: 'Start',
72    stopText: 'Stop',
73    autoControlsCombine: false,
74    autoControlsSelector: null,
75
76    // AUTO
77    auto: false,
78    pause: 4000,
79    autoStart: true,
80    autoDirection: 'next',
81    stopAutoOnClick: false,
82    autoHover: true,
83    autoDelay: 0,
84    autoSlideForOnePage: false,
85
86    // CAROUSEL
87    minSlides: 1,
88    maxSlides: 1,
89    moveSlides: 0,
90    slideWidth: 0,
91    shrinkItems: false,
92
93    // CALLBACKS
94    onSliderLoad: function() { return true; },
95    onSlideBefore: function() { return true; },
96    onSlideAfter: function() { return true; },
97    onSlideNext: function() { return true; },
98    onSlidePrev: function() { return true; },
99    onSliderResize: function() { return true; }
100  };
101
102  $.fn.bxSlider = function(options) {
103
104    if (this.length === 0) {
105      return this;
106    }
107
108    // support multiple elements
109    if (this.length > 1) {
110      this.each(function() {
111        $(this).bxSlider(options);
112      });
113      return this;
114    }
115
116    // create a namespace to be used throughout the plugin
117    var slider = {},
118    // set a reference to our slider element
119    el = this,
120    // get the original window dimens (thanks a lot IE)
121    windowWidth = $(window).width(),
122    windowHeight = $(window).height();
123
124    // Return if slider is already initialized
125    if ($(el).data('bxSlider')) { return; }
126
127    /**
128     * ===================================================================================
129     * = PRIVATE FUNCTIONS
130     * ===================================================================================
131     */
132
133    /**
134     * Initializes namespace settings to be used throughout plugin
135     */
136    var init = function() {
137      // Return if slider is already initialized
138      if ($(el).data('bxSlider')) { return; }
139      // merge user-supplied options with the defaults
140      slider.settings = $.extend({}, defaults, options);
141      // disable effects by setting the speed to zero if reduce motion is enabled
142      if ( window.matchMedia("(prefers-reduced-motion: reduce)").matches ) { slider.settings.speed = 0; }
143      // parse slideWidth setting
144      slider.settings.slideWidth = parseInt(slider.settings.slideWidth);
145      // store the original children
146      slider.children = el.children(slider.settings.slideSelector);
147      // check if actual number of slides is less than minSlides / maxSlides
148      if (slider.children.length < slider.settings.minSlides) { slider.settings.minSlides = slider.children.length; }
149      if (slider.children.length < slider.settings.maxSlides) { slider.settings.maxSlides = slider.children.length; }
150      // if random start, set the startSlide setting to random number
151      if (slider.settings.randomStart) { slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); }
152      // store active slide information
153      slider.active = { index: slider.settings.startSlide };
154      // store if the slider is in carousel mode (displaying / moving multiple slides)
155      slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1 ? true : false;
156      // if carousel, force preloadImages = 'all'
157      if (slider.carousel) { slider.settings.preloadImages = 'all'; }
158      // calculate the min / max width thresholds based on min / max number of slides
159      // used to setup and update carousel slides dimensions
160      slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin);
161      slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
162      // store the current state of the slider (if currently animating, working is true)
163      slider.working = false;
164      // initialize the controls object
165      slider.controls = {};
166      // initialize an auto interval
167      slider.interval = null;
168      // determine which property to use for transitions
169      slider.animProp = slider.settings.mode === 'vertical' ? 'top' : 'left';
170      // determine if hardware acceleration can be used
171      slider.usingCSS = slider.settings.useCSS && slider.settings.mode !== 'fade' && (function() {
172        // create our test div element
173        var div = document.createElement('div'),
174        // css transition properties
175        props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
176        // test for each property
177        for (var i = 0; i < props.length; i++) {
178          if (div.style[props[i]] !== undefined) {
179            slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();
180            slider.animProp = '-' + slider.cssPrefix + '-transform';
181            return true;
182          }
183        }
184        return false;
185      }());
186      // if vertical mode always make maxSlides and minSlides equal
187      if (slider.settings.mode === 'vertical') { slider.settings.maxSlides = slider.settings.minSlides; }
188      // save original style data
189      el.data('origStyle', el.attr('style'));
190      el.children(slider.settings.slideSelector).each(function() {
191        $(this).data('origStyle', $(this).attr('style'));
192      });
193
194      // perform all DOM / CSS modifications
195      setup();
196    };
197
198    /**
199     * Performs all DOM and CSS modifications
200     */
201    var setup = function() {
202      var preloadSelector = slider.children.eq(slider.settings.startSlide); // set the default preload selector (visible)
203
204      // wrap el in a wrapper
205      el.wrap('<div class="' + slider.settings.wrapperClass + '"><div class="bx-viewport"></div></div>');
206      // store a namespace reference to .bx-viewport
207      slider.viewport = el.parent();
208
209      // add aria-live if the setting is enabled and ticker mode is disabled
210      if (slider.settings.ariaLive && !slider.settings.ticker) {
211        slider.viewport.attr('aria-live', 'polite');
212      }
213      // add a loading div to display while images are loading
214      slider.loader = $('<div class="bx-loading" />');
215      slider.viewport.prepend(slider.loader);
216      // set el to a massive width, to hold any needed slides
217      // also strip any margin and padding from el
218      el.css({
219        width: slider.settings.mode === 'horizontal' ? (slider.children.length * 1000 + 215) + '%' : 'auto',
220        position: 'relative'
221      });
222      // if using CSS, add the easing property
223      if (slider.usingCSS && slider.settings.easing) {
224        el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
225      // if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
226      } else if (!slider.settings.easing) {
227        slider.settings.easing = 'swing';
228      }
229      // make modifications to the viewport (.bx-viewport)
230      slider.viewport.css({
231        width: '100%',
232        overflow: 'hidden',
233        position: 'relative'
234      });
235      slider.viewport.parent().css({
236        maxWidth: getViewportMaxWidth()
237      });
238      // make modification to the wrapper (.bx-wrapper)
239      if (!slider.settings.pager && !slider.settings.controls) {
240        slider.viewport.parent().css({
241          margin: '0 auto 0px'
242        });
243      }
244      // apply css to all slider children
245      slider.children.css({
246        float: slider.settings.mode === 'horizontal' ? 'left' : 'none',
247        listStyle: 'none',
248        position: 'relative'
249      });
250      // apply the calculated width after the float is applied to prevent scrollbar interference
251      slider.children.css('width', getSlideWidth());
252      // if slideMargin is supplied, add the css
253      if (slider.settings.mode === 'horizontal' && slider.settings.slideMargin > 0) { slider.children.css('marginRight', slider.settings.slideMargin); }
254      if (slider.settings.mode === 'vertical' && slider.settings.slideMargin > 0) { slider.children.css('marginBottom', slider.settings.slideMargin); }
255      // if "fade" mode, add positioning and z-index CSS
256      if (slider.settings.mode === 'fade') {
257        slider.children.css({
258          position: 'absolute',
259          zIndex: 0,
260          display: 'none'
261        });
262        // prepare the z-index on the showing element
263        slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'});
264      }
265      // create an element to contain all slider controls (pager, start / stop, etc)
266      slider.controls.el = $('<div class="bx-controls" />');
267      // if captions are requested, add them
268      if (slider.settings.captions) { appendCaptions(); }
269      // check if startSlide is last slide
270      slider.active.last = slider.settings.startSlide === getPagerQty() - 1;
271      // if video is true, set up the fitVids plugin
272      if (slider.settings.video) { el.fitVids(); }
273      if (slider.settings.preloadImages === 'all' || slider.settings.ticker) { preloadSelector = slider.children; }
274      // only check for control addition if not in "ticker" mode
275      if (!slider.settings.ticker) {
276        // if controls are requested, add them
277        if (slider.settings.controls) { appendControls(); }
278        // if pager is requested, add it
279        if (slider.settings.pager) { appendPager(); }
280        // if auto is true, and auto controls are requested, add them
281        if (slider.settings.auto && slider.settings.autoControls) { appendControlsAuto(); }
282        // if any control option is requested, add the controls wrapper
283        if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) { slider.viewport.after(slider.controls.el); }
284      // if ticker mode, do not allow a pager
285      } else {
286        slider.settings.pager = false;
287      }
288      loadElements(preloadSelector, start);
289    };
290
291    var loadElements = function(selector, callback) {
292      var total = selector.find('img:not([src=""]), iframe').length,
293      count = 0;
294      if (total === 0) {
295        callback();
296        return;
297      }
298      selector.find('img:not([src=""]), iframe').each(function() {
299        $(this).one('load error', function() {
300          if (++count === total) { callback(); }
301        }).each(function() {
302          setTimeout(() => {
303            if (this.complete || this.src == '') { $(this).trigger('load'); }
304          },0);
305        });
306      });
307    };
308
309    /**
310     * Start the slider
311     */
312    var start = function() {
313      // if infinite loop, prepare additional slides
314      if (slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker) {
315        var slice    = slider.settings.mode === 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides,
316        sliceAppend  = slider.children.slice(0, slice).clone(true).addClass('bx-clone'),
317        slicePrepend = slider.children.slice(-slice).clone(true).addClass('bx-clone');
318        if (slider.settings.ariaHidden) {
319          sliceAppend.attr('aria-hidden', true);
320          slicePrepend.attr('aria-hidden', true);
321          sliceAppend.find('a, button').attr('tabindex', -1);
322          slicePrepend.find('a, button').attr('tabindex', -1);
323        }
324        el.append(sliceAppend).prepend(slicePrepend);
325      }
326      // remove the loading DOM element
327      slider.loader.remove();
328      // set the left / top position of "el"
329      setSlidePosition();
330      // if "vertical" mode, always use adaptiveHeight to prevent odd behavior
331      if (slider.settings.mode === 'vertical') { slider.settings.adaptiveHeight = true; }
332      // set the viewport height
333      slider.viewport.height(getViewportHeight());
334      // make sure everything is positioned just right (same as a window resize)
335      el.redrawSlider();
336      // onSliderLoad callback
337      slider.settings.onSliderLoad.call(el, slider.active.index);
338      // slider has been fully initialized
339      slider.initialized = true;
340      // bind the resize call to the window
341      if (slider.settings.responsive) { $(window).bind('resize', resizeWindow); }
342      // if auto is true and has more than 1 page, start the show
343      if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) { initAuto(); }
344      // if ticker is true, start the ticker
345      if (slider.settings.ticker) { initTicker(); }
346      // if pager is requested, make the appropriate pager link active
347      if (slider.settings.pager) { updatePagerActive(slider.settings.startSlide); }
348      // check for any updates to the controls (like hideControlOnEnd updates)
349      if (slider.settings.controls) { updateDirectionControls(); }
350      // if touchEnabled is true, setup the touch events
351      if ('ontouchstart' in window) { initTouch(); }
352      // if keyboardEnabled is true, setup the keyboard events
353      if (slider.settings.keyboardEnabled && !slider.settings.ticker) {
354        slider.viewport.closest('.fl-module').keydown(keyPress).focusin(isOutFocus);
355      }
356    };
357
358    /**
359     * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
360     */
361    var getViewportHeight = function() {
362      var height = 0;
363      // first determine which children (slides) should be used in our height calculation
364      var children = $();
365      // if mode is not "vertical" and adaptiveHeight is false, include all children
366      if (slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight) {
367        children = slider.children;
368      } else {
369        // if not carousel, return the single active child
370        if (!slider.carousel) {
371          children = slider.children.eq(slider.active.index);
372        // if carousel, return a slice of children
373        } else {
374          // get the individual slide index
375          var currentIndex = slider.settings.moveSlides === 1 ? slider.active.index : slider.active.index * getMoveBy();
376          // add the current slide to the children
377          children = slider.children.eq(currentIndex);
378          // cycle through the remaining "showing" slides
379          for (i = 1; i <= slider.settings.maxSlides - 1; i++) {
380            // if looped back to the start
381            if (currentIndex + i >= slider.children.length) {
382              children = children.add(slider.children.eq(i - 1));
383            } else {
384              children = children.add(slider.children.eq(currentIndex + i));
385            }
386          }
387        }
388      }
389      // if "vertical" mode, calculate the sum of the heights of the children
390      if (slider.settings.mode === 'vertical') {
391        children.each(function(index) {
392          height += $(this).outerHeight();
393        });
394        // add user-supplied margins
395        if (slider.settings.slideMargin > 0) {
396          height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
397        }
398      // if not "vertical" mode, calculate the max height of the children
399      } else {
400        height = Math.max.apply(Math, children.map(function() {
401          return $(this).outerHeight(false);
402        }).get());
403      }
404
405      if (slider.viewport.css('box-sizing') === 'border-box') {
406        height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) +
407              parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));
408      } else if (slider.viewport.css('box-sizing') === 'padding-box') {
409        height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));
410      }
411
412      return height;
413    };
414
415    /**
416     * Returns the calculated width to be used for the outer wrapper / viewport
417     */
418    var getViewportMaxWidth = function() {
419      var width = '100%';
420      if (slider.settings.slideWidth > 0) {
421        if (slider.settings.mode === 'horizontal') {
422          width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
423        } else {
424          width = slider.settings.slideWidth;
425        }
426      }
427      return width;
428    };
429
430    /**
431     * Returns the calculated width to be applied to each slide
432     */
433    var getSlideWidth = function() {
434      var newElWidth = slider.settings.slideWidth, // start with any user-supplied slide width
435      wrapWidth      = slider.viewport.width();    // get the current viewport width
436      // if slide width was not supplied, or is larger than the viewport use the viewport width
437      if (slider.settings.slideWidth === 0 ||
438        (slider.settings.slideWidth > wrapWidth && !slider.carousel) ||
439        slider.settings.mode === 'vertical') {
440        newElWidth = wrapWidth;
441      // if carousel, use the thresholds to determine the width
442      } else if (slider.settings.maxSlides > 1 && slider.settings.mode === 'horizontal') {
443        if (wrapWidth > slider.maxThreshold) {
444          return newElWidth;
445        } else if (wrapWidth < slider.minThreshold) {
446          newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;
447        } else if (slider.settings.shrinkItems) {
448          newElWidth = Math.floor((wrapWidth + slider.settings.slideMargin) / (Math.ceil((wrapWidth + slider.settings.slideMargin) / (newElWidth + slider.settings.slideMargin))) - slider.settings.slideMargin);
449        }
450      }
451      return newElWidth;
452    };
453
454    /**
455     * Returns the number of slides currently visible in the viewport (includes partially visible slides)
456     */
457    var getNumberSlidesShowing = function() {
458      var slidesShowing = 1,
459      childWidth = null;
460      if (slider.settings.mode === 'horizontal' && slider.settings.slideWidth > 0) {
461        // if viewport is smaller than minThreshold, return minSlides
462        if (slider.viewport.width() < slider.minThreshold) {
463          slidesShowing = slider.settings.minSlides;
464        // if viewport is larger than maxThreshold, return maxSlides
465        } else if (slider.viewport.width() > slider.maxThreshold) {
466          slidesShowing = slider.settings.maxSlides;
467        // if viewport is between min / max thresholds, divide viewport width by first child width
468        } else {
469          childWidth = slider.children.first().width() + slider.settings.slideMargin;
470          slidesShowing = Math.floor((slider.viewport.width() +
471            slider.settings.slideMargin) / childWidth);
472        }
473      // if "vertical" mode, slides showing will always be minSlides
474      } else if (slider.settings.mode === 'vertical') {
475        slidesShowing = slider.settings.minSlides;
476      }
477      return slidesShowing;
478    };
479
480    /**
481     * Returns the number of pages (one full viewport of slides is one "page")
482     */
483    var getPagerQty = function() {
484      var pagerQty = 0,
485      breakPoint = 0,
486      counter = 0;
487      // if moveSlides is specified by the user
488      if (slider.settings.moveSlides > 0) {
489        if (slider.settings.infiniteLoop) {
490          pagerQty = Math.ceil(slider.children.length / getMoveBy());
491        } else {
492          // when breakpoint goes above children length, counter is the number of pages
493          while (breakPoint < slider.children.length) {
494            ++pagerQty;
495            breakPoint = counter + getNumberSlidesShowing();
496            counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
497          }
498        }
499      // if moveSlides is 0 (auto) divide children length by sides showing, then round up
500      } else {
501        pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
502      }
503      return pagerQty;
504    };
505
506    /**
507     * Returns the number of individual slides by which to shift the slider
508     */
509    var getMoveBy = function() {
510      // if moveSlides was set by the user and moveSlides is less than number of slides showing
511      if (slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) {
512        return slider.settings.moveSlides;
513      }
514      // if moveSlides is 0 (auto)
515      return getNumberSlidesShowing();
516    };
517
518    /**
519     * Sets the slider's (el) left or top position
520     */
521    var setSlidePosition = function() {
522      var position, lastChild, lastShowingIndex;
523      // if last slide, not infinite loop, and number of children is larger than specified maxSlides
524      if (slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) {
525        if (slider.settings.mode === 'horizontal') {
526          // get the last child's position
527          lastChild = slider.children.last();
528          position = lastChild.position();
529          // set the left position
530          setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);
531        } else if (slider.settings.mode === 'vertical') {
532          // get the last showing index's position
533          lastShowingIndex = slider.children.length - slider.settings.minSlides;
534          position = slider.children.eq(lastShowingIndex).position();
535          // set the top position
536          setPositionProperty(-position.top, 'reset', 0);
537        }
538      // if not last slide
539      } else {
540        // get the position of the first showing slide
541        position = slider.children.eq(slider.active.index * getMoveBy()).position();
542        // check for last slide
543        if (slider.active.index === getPagerQty() - 1) { slider.active.last = true; }
544        // set the respective position
545        if (position !== undefined) {
546          if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }
547          else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); }
548        }
549      }
550    };
551
552    /**
553     * Sets the el's animating property position (which in turn will sometimes animate el).
554     * If using CSS, sets the transform property. If not using CSS, sets the top / left property.
555     *
556     * @param value (int)
557     *  - the animating property's value
558     *
559     * @param type (string) 'slide', 'reset', 'ticker'
560     *  - the type of instance for which the function is being
561     *
562     * @param duration (int)
563     *  - the amount of time (in ms) the transition should occupy
564     *
565     * @param params (array) optional
566     *  - an optional parameter containing any variables that need to be passed in
567     */
568    var setPositionProperty = function(value, type, duration, params) {
569      var animateObj, propValue;
570      // use CSS transform
571      if (slider.usingCSS) {
572        // determine the translate3d value
573        propValue = slider.settings.mode === 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
574        // add the CSS transition-duration
575        el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
576        if (type === 'slide') {
577          // set the property value
578          el.css(slider.animProp, propValue);
579          if (duration !== 0) {
580            // bind a callback method - executes when CSS transition completes
581            el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
582              //make sure it's the correct one
583              if (!$(e.target).is(el)) { return; }
584              // unbind the callback
585              el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
586              updateAfterSlideTransition();
587            });
588          } else { //duration = 0
589            updateAfterSlideTransition();
590          }
591        } else if (type === 'reset') {
592          el.css(slider.animProp, propValue);
593        } else if (type === 'ticker') {
594          // make the transition use 'linear'
595          el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
596          el.css(slider.animProp, propValue);
597          if (duration !== 0) {
598            el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) {
599              //make sure it's the correct one
600              if (!$(e.target).is(el)) { return; }
601              // unbind the callback
602              el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
603              // reset the position
604              setPositionProperty(params.resetValue, 'reset', 0);
605              // start the loop again
606              tickerLoop();
607            });
608          } else { //duration = 0
609            setPositionProperty(params.resetValue, 'reset', 0);
610            tickerLoop();
611          }
612        }
613      // use JS animate
614      } else {
615        animateObj = {};
616        animateObj[slider.animProp] = value;
617        if (type === 'slide') {
618          el.animate(animateObj, duration, slider.settings.easing, function() {
619            updateAfterSlideTransition();
620          });
621        } else if (type === 'reset') {
622          el.css(slider.animProp, value);
623        } else if (type === 'ticker') {
624          el.animate(animateObj, duration, 'linear', function() {
625            setPositionProperty(params.resetValue, 'reset', 0);
626            // run the recursive loop after animation
627            tickerLoop();
628          });
629        }
630      }
631    };
632
633    /**
634     * Populates the pager with proper amount of pages
635     */
636    var populatePager = function() {
637      var pagerHtml = '',
638      linkContent = '',
639      pagerQty = getPagerQty();
640      // loop through each pager item
641      for (var i = 0; i < pagerQty; i++) {
642        linkContent = '';
643        // if a buildPager function is supplied, use it to get pager link value, else use index + 1
644        if (slider.settings.buildPager && typeof slider.settings.buildPager === 'function' || slider.settings.pagerCustom) {
645          linkContent = slider.settings.buildPager(i);
646        } else {
647          linkContent = i + 1;
648        }
649        slider.pagerEl.addClass('bx-default-pager');
650        // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
651        // add the markup to the string
652        if ( slider.settings.fallbackHTML ) {
653          pagerHtml += '<div class="bx-pager-item">
653<a data-slide-index="' + i + '" class="bx-pager-link" role="button" tabindex="0">' + linkContent + '</a></div>';
654        } else {
655          pagerHtml += '<div class="bx-pager-item"><button data-slide-index="' + i + '" class="bx-pager-link fl-content-ui-button" type="button">' + linkContent + '</button></div>';
656        }
657      }
658      // populate the pager element with pager links
659      slider.pagerEl.html(pagerHtml);
660    };
661
662    /**
663     * Appends the pager to the controls element
664     */
665    var appendPager = function() {
666      if (!slider.settings.pagerCustom) {
667        // create the pager DOM element
668        slider.pagerEl = $('<div class="bx-pager" />');
669        // if a pager selector was supplied, populate it with the pager
670        if (slider.settings.pagerSelector) {
671          $(slider.settings.pagerSelector).html(slider.pagerEl);
672        // if no pager selector was supplied, add it after the wrapper
673        } else {
674          slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);
675        }
676        // populate the pager
677        populatePager();
678      } else {
679        slider.pagerEl = $(slider.settings.pagerCustom);
680      }
681      // assign the pager click binding
682      slider.pagerEl.on('click touchend', 'a, button', clickPagerBind);
683    };
684
685    /**
686     * Appends prev / next controls to the controls element
687     */
688    var appendControls = function() {
689      if ( slider.settings.fallbackHTML ) {
690        slider.controls.next = $('<a class="bx-next" role="button" tabindex="0">' + slider.settings.nextText + '</a>');
691        slider.controls.prev = $('<a class="bx-prev" role="button" tabindex="0">' + slider.settings.prevText + '</a>');
692      } else {
693        slider.controls.next = $('<button class="bx-next fl-content-ui-button" type="button">' + slider.settings.nextText + '</button>');
694        slider.controls.prev = $('<button class="bx-prev fl-content-ui-button" type="button">' + slider.settings.prevText + '</button>');
695      }
696      // bind click actions to the controls
697      slider.controls.next.bind('click touchend', clickNextBind);
698      slider.controls.prev.bind('click touchend', clickPrevBind);
699      // if nextSelector was supplied, populate it
700      if (slider.settings.nextSelector) {
701        $(slider.settings.nextSelector).append(slider.controls.next);
702      }
703      // if prevSelector was supplied, populate it
704      if (slider.settings.prevSelector) {
705        $(slider.settings.prevSelector).append(slider.controls.prev);
706      }
707      // if no custom selectors were supplied
708      if (!slider.settings.nextSelector && !slider.settings.prevSelector) {
709        // add the controls to the DOM
710        slider.controls.directionEl = $('<div class="bx-controls-direction" />');
711        // add the control elements to the directionEl
712        slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);
713        // slider.viewport.append(slider.controls.directionEl);
714        slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);
715      }
716    };
717
718    /**
719     * Appends start / stop auto controls to the controls element
720     */
721    var appendControlsAuto = function() {
722      ['start', 'stop'].forEach(function(state) {
723        var element = null;
724        var pressed = state === 'start' ? 'false' : 'true';
725        if (slider.settings.fallbackHTML) {
726          var attributes = 'class="bx-' + state + '" role="button" tabindex="0" aria-pressed="' + pressed + '"';
727          element = '<a ' + attributes + '>' + slider.settings[state + 'Text'] + '</a>';
728        } else {
729          var attributes = 'class="bx-' + state + ' fl-content-ui-button" type="button" aria-pressed="' + pressed + '"';
730          element = '<button ' + attributes + '>' + slider.settings[state + 'Text'] + '</button>';
731        }
732        slider.controls[state] = $('<div class="bx-controls-auto-item">' + element + '</div>');
733      });
734      // add the controls to the DOM
735      slider.controls.autoEl = $('<div class="bx-controls-auto" />');
736      // bind click actions to the controls
737      slider.controls.autoEl.on('click', '.bx-start', clickStartBind);
738      slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);
739      // if autoControlsCombine, insert only the "start" control
740      if (slider.settings.autoControlsCombine) {
741        slider.controls.autoEl.append(slider.controls.start);
742      // if autoControlsCombine is false, insert both controls
743      } else {
744        slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
745      }
746      // if auto controls selector was supplied, populate it with the controls
747      if (slider.settings.autoControlsSelector) {
748        $(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
749      // if auto controls selector was not supplied, add it after the wrapper
750      } else {
751        slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
752      }
753      // update the auto controls
vendor: 34,415 bytes, lines 754-1628
754      updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
755    };
756
757    /**
758     * Appends image captions to the DOM
759     */
760    var appendCaptions = function() {
761      // cycle through each child
762      slider.children.each(function(index) {
763        // get the image title attribute
764        var title = $(this).find('img:first').attr('title');
765        // append the caption
766        if (title !== undefined && ('' + title).length) {
767          $(this).append('<div class="bx-caption"><span>' + title + '</span></div>');
768        }
769      });
770    };
771
772    /**
773     * Click next binding
774     *
775     * @param e (event)
776     *  - DOM event object
777     */
778    var clickNextBind = function(e) {
779      e.preventDefault();
780      if (slider.controls.el.hasClass('disabled')) { return; }
781      // if auto show is running, stop it
782      if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); }
783      el.goToNextSlide();
784    };
785
786    /**
787     * Click prev binding
788     *
789     * @param e (event)
790     *  - DOM event object
791     */
792    var clickPrevBind = function(e) {
793      e.preventDefault();
794      if (slider.controls.el.hasClass('disabled')) { return; }
795      // if auto show is running, stop it
796      if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); }
797      el.goToPrevSlide();
798    };
799
800    /**
801     * Click start binding
802     *
803     * @param e (event)
804     *  - DOM event object
805     */
806    var clickStartBind = function(e) {
807      el.startAuto();
808      e.preventDefault();
809    };
810
811    /**
812     * Click stop binding
813     *
814     * @param e (event)
815     *  - DOM event object
816     */
817    var clickStopBind = function(e) {
818      el.stopAuto();
819      e.preventDefault();
820    };
821
822    /**
823     * Click pager binding
824     *
825     * @param e (event)
826     *  - DOM event object
827     */
828    var clickPagerBind = function(e) {
829      var pagerLink, pagerIndex;
830      e.preventDefault();
831      if (slider.controls.el.hasClass('disabled')) {
832        return;
833      }
834      // if auto show is running, stop it
835      if (slider.settings.auto  && slider.settings.stopAutoOnClick) { el.stopAuto(); }
836      pagerLink = $(e.currentTarget);
837      if (pagerLink.attr('data-slide-index') !== undefined) {
838        pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
839        // if clicked pager link is not active, continue with the goToSlide call
840        if (pagerIndex !== slider.active.index) { el.goToSlide(pagerIndex); }
841      }
842    };
843
844    /**
845     * Updates the pager links with an active class
846     *
847     * @param slideIndex (int)
848     *  - index of slide to make active
849     */
850    var updatePagerActive = function(slideIndex) {
851      // if "short" pager type
852      var len = slider.children.length; // nb of children
853      if (slider.settings.pagerType === 'short') {
854        if (slider.settings.maxSlides > 1) {
855          len = Math.ceil(slider.children.length / slider.settings.maxSlides);
856        }
857        slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + len);
858        return;
859      }
860      // remove all pager active classes
861      slider.pagerEl.find('a, button').removeClass('active');
862      // set all pager aria current to false
863      slider.pagerEl.find('a, button').attr('aria-current', false);
864      // apply the active class & aria current for all pagers
865      slider.pagerEl.each(function(i, el) { $(el).find('a, button').eq(slideIndex).addClass('active'); $(el).find('a, button').eq(slideIndex).attr('aria-current', true); });
866    };
867
868    /**
869     * Performs needed actions after a slide transition
870     */
871    var updateAfterSlideTransition = function() {
872      // if infinite loop is true
873      if (slider.settings.infiniteLoop) {
874        var position = '';
875        // first slide
876        if (slider.active.index === 0) {
877          // set the new position
878          position = slider.children.eq(0).position();
879        // carousel, last slide
880        } else if (slider.active.index === getPagerQty() - 1 && slider.carousel) {
881          position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
882        // last slide
883        } else if (slider.active.index === slider.children.length - 1) {
884          position = slider.children.eq(slider.children.length - 1).position();
885        }
886        if (position) {
887          if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }
888          else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); }
889        }
890      }
891      // declare that the transition is complete
892      slider.working = false;
893      slider.viewport.closest('.fl-module').find('a, button').not('.bx-start, .bx-stop').removeClass('disabled');
894      // onSlideAfter callback
895      slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
896    };
897
898    /**
899     * Updates the auto controls state (either active, or combined switch)
900     *
901     * @param state (string) "start", "stop"
902     *  - the new state of the auto show
903     */
904    var updateAutoControls = function(state) {
905      // if autoControlsCombine is true, replace the current control with the new state
906      if (slider.settings.autoControlsCombine) {
907        var focused = slider.controls.autoEl.has($(document.activeElement)).length == 1;
908        slider.controls.autoEl.html(slider.controls[state]);
909        if(focused) {
910          slider.controls[state].find('a, button').focus();
911          if(slider.isFocused && state === 'stop') { slider.isFocused = null; }
912        }
913      // if autoControlsCombine is false, apply the "active" class to the appropriate control
914      } else {
915        slider.controls.autoEl.find('a, button').removeClass('active');
916        slider.controls.autoEl.find('a:not(.bx-' + state + '), button:not(.bx-' + state + ')').addClass('active');
917      }
918    };
919
920    /**
921     * Updates the direction controls (checks if either should be hidden)
922     */
923    var updateDirectionControls = function() {
924      if (getPagerQty() === 1) {
925        slider.controls.prev.addClass('disabled');
926        slider.controls.next.addClass('disabled');
927      } else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) {
928        // if first slide
929        if (slider.active.index === 0) {
930          slider.controls.prev.addClass('disabled');
931          slider.controls.next.removeClass('disabled');
932        // if last slide
933        } else if (slider.active.index === getPagerQty() - 1) {
934          slider.controls.next.addClass('disabled');
935          slider.controls.prev.removeClass('disabled');
936        // if any slide in the middle
937        } else {
938          slider.controls.prev.removeClass('disabled');
939          slider.controls.next.removeClass('disabled');
940        }
941      }
942    };
943
944    /**
945     * Initializes the auto process
946     */
947    var initAuto = function() {
948      // if autoDelay was supplied, launch the auto show using a setTimeout() call
949      if (slider.settings.autoDelay > 0) {
950       setTimeout(el.startAuto, slider.settings.autoDelay);
951      // if autoDelay was not supplied, start the auto show normally
952      } else {
953        el.startAuto();
954
955      }
956      // if autoHover is requested
957      if (slider.settings.autoHover) {
958        // on el hover
959        el.hover(function() {
960          // if the auto show is currently playing (has an active interval)
961          if (slider.interval) {
962            // stop the auto show and pass true argument which will prevent control update
963            el.stopAuto(true);
964            // create a new autoPaused value which will be used by the relative "mouseout" event
965            slider.autoPaused = true;
966          }
967        }, function() {
968          // if the autoPaused value was created be the prior "mouseover" event
969          if (slider.autoPaused) {
970            // start the auto show and pass true argument which will prevent control update
971            el.startAuto(true);
972            // reset the autoPaused value
973            slider.autoPaused = null;
974          }
975        });
976      }
977    };
978
979    /**
980     * Initializes the ticker process
981     */
982    var initTicker = function() {
983      var startPosition = 0,
984      position, transform, value, idx, ratio, property, newSpeed, totalDimens;
985      // if autoDirection is "next", append a clone of the entire slider
986      if (slider.settings.autoDirection === 'next') {
987        el.append(slider.children.clone().addClass('bx-clone'));
988      // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
989      } else {
990        el.prepend(slider.children.clone().addClass('bx-clone'));
991        position = slider.children.first().position();
992        startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
993      }
994      setPositionProperty(startPosition, 'reset', 0);
995      // do not allow controls in ticker mode
996      slider.settings.pager = false;
997      slider.settings.controls = false;
998      slider.settings.autoControls = false;
999      // if autoHover is requested
1000      if (slider.settings.tickerHover) {
1001        if (slider.usingCSS) {
1002          idx = slider.settings.mode === 'horizontal' ? 4 : 5;
1003          slider.viewport.hover(function() {
1004            transform = el.css('-' + slider.cssPrefix + '-transform');
1005            value = parseFloat(transform.split(',')[idx]);
1006            setPositionProperty(value, 'reset', 0);
1007          }, function() {
1008            totalDimens = 0;
1009            slider.children.each(function(index) {
1010              totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1011            });
1012            // calculate the speed ratio (used to determine the new speed to finish the paused animation)
1013            ratio = slider.settings.speed / totalDimens;
1014            // determine which property to use
1015            property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
1016            // calculate the new speed
1017            newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value))));
1018            tickerLoop(newSpeed);
1019          });
1020        } else {
1021          // on el hover
1022          slider.viewport.hover(function() {
1023            el.stop();
1024          }, function() {
1025            // calculate the total width of children (used to calculate the speed ratio)
1026            totalDimens = 0;
1027            slider.children.each(function(index) {
1028              totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1029            });
1030            // calculate the speed ratio (used to determine the new speed to finish the paused animation)
1031            ratio = slider.settings.speed / totalDimens;
1032            // determine which property to use
1033            property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
1034            // calculate the new speed
1035            newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
1036            tickerLoop(newSpeed);
1037          });
1038        }
1039      }
1040      // start the ticker loop
1041      tickerLoop();
1042    };
1043
1044    /**
1045     * Runs a continuous loop, news ticker-style
1046     */
1047    var tickerLoop = function(resumeSpeed) {
1048      var speed = resumeSpeed ? resumeSpeed : slider.settings.speed,
1049      position = {left: 0, top: 0},
1050      reset = {left: 0, top: 0},
1051      animateProperty, resetValue, params;
1052
1053      // if "next" animate left position to last child, then reset left to 0
1054      if (slider.settings.autoDirection === 'next') {
1055        position = el.find('.bx-clone').first().position();
1056      // if "prev" animate left position to 0, then reset left to first non-clone child
1057      } else {
1058        reset = slider.children.first().position();
1059      }
1060      animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
1061      resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top;
1062      params = {resetValue: resetValue};
1063      setPositionProperty(animateProperty, 'ticker', speed, params);
1064    };
1065
1066    /**
1067     * Check if el is on screen
1068     */
1069    var isOnScreen = function(el) {
1070      var win = $(window),
1071      viewport = {
1072        top: win.scrollTop(),
1073        left: win.scrollLeft()
1074      },
1075      bounds = el.offset();
1076
1077      viewport.right = viewport.left + win.width();
1078      viewport.bottom = viewport.top + win.height();
1079      bounds.right = bounds.left + el.outerWidth();
1080      bounds.bottom = bounds.top + el.outerHeight();
1081
1082      return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
1083    };
1084
1085    /**
1086     * Check if slider was out of focus
1087     */
1088    var isOutFocus = function(e) {
1089      if (slider.viewport.closest('.fl-module').has($(e.relatedTarget)).length === 0 && !slider.isFocused) {
1090        slider.isFocused = true;
1091        clickStopBind(e);
1092      }
1093    };
1094
1095    /**
1096     * Initializes keyboard events
1097     */
1098    var keyPress = function(e) {
1099      if (isOnScreen(el) && (e.keyCode === 39 || e.keyCode === 37)) {
1100        if (e.keyCode === 39) {
1101          clickNextBind(e);
1102        } else if (e.keyCode === 37) {
1103          clickPrevBind(e);
1104        }
1105        slider.viewport.closest('.' + slider.settings.wrapperClass).find('.bx-pager-link.active').focus();
1106        return false;
1107      }
1108    };
1109
1110    /**
1111     * Initializes touch events
1112     */
1113    var initTouch = function() {
1114      // initialize object to contain all touch values
1115      slider.touch = {
1116        start: {x: 0, y: 0},
1117        end: {x: 0, y: 0}
1118      };
1119      slider.viewport.bind('touchstart', onTouchStart);
1120
1121      //for browsers that have implemented pointer events and fire a click after
1122      //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not
1123      slider.viewport.on('click', '.bxslider a, .bxslider button', function(e) {
1124        if (slider.viewport.hasClass('click-disabled')) {
1125          e.preventDefault();
1126          slider.viewport.removeClass('click-disabled');
1127        }
1128      });
1129    };
1130
1131    /**
1132     * Event handler for "touchstart"
1133     *
1134     * @param e (event)
1135     *  - DOM event object
1136     */
1137    var onTouchStart = function(e) {
1138      //disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls
1139      slider.controls.el.addClass('disabled');
1140
1141      if (slider.working) {
1142        e.preventDefault();
1143        slider.controls.el.removeClass('disabled');
1144      } else {
1145        // record the original position when touch starts
1146        slider.touch.originalPos = el.position();
1147        var orig = e.originalEvent,
1148        touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig];
1149        // record the starting touch x, y coordinates
1150        slider.touch.start.x = touchPoints[0].pageX;
1151        slider.touch.start.y = touchPoints[0].pageY;
1152        // bind a "touchmove" event to the viewport
1153        slider.viewport.bind('touchmove', onTouchMove);
1154        // bind a "touchend" event to the viewport
1155        slider.viewport.bind('touchend', onTouchEnd);
1156      }
1157    };
1158
1159    /**
1160     * Event handler for "touchmove"
1161     *
1162     * @param e (event)
1163     *  - DOM event object
1164     */
1165    var onTouchMove = function(e) {
1166      var orig = e.originalEvent,
1167      touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1168      // if scrolling on y axis, do not prevent default
1169      xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x),
1170      yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y),
1171      value = 0,
1172      change = 0;
1173
1174      // x axis swipe
1175      if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) {
1176        e.preventDefault();
1177      // y axis swipe
1178      } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) {
1179        e.preventDefault();
1180      }
1181      if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) {
1182        // if horizontal, drag along x axis
1183        if (slider.settings.mode === 'horizontal') {
1184          change = touchPoints[0].pageX - slider.touch.start.x;
1185          value = slider.touch.originalPos.left + change;
1186        // if vertical, drag along y axis
1187        } else {
1188          change = touchPoints[0].pageY - slider.touch.start.y;
1189          value = slider.touch.originalPos.top + change;
1190        }
1191        setPositionProperty(value, 'reset', 0);
1192      }
1193    };
1194
1195    /**
1196     * Event handler for "touchend"
1197     *
1198     * @param e (event)
1199     *  - DOM event object
1200     */
1201    var onTouchEnd = function(e) {
1202      slider.viewport.unbind('touchmove', onTouchMove);
1203      //enable slider controls as soon as user stops interacing with slides
1204      slider.controls.el.removeClass('disabled');
1205      var orig    = e.originalEvent,
1206      touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1207      value       = 0,
1208      distance    = 0;
1209      // record end x, y positions
1210      slider.touch.end.x = touchPoints[0].pageX;
1211      slider.touch.end.y = touchPoints[0].pageY;
1212      // if fade mode, check if absolute x distance clears the threshold
1213      if (slider.settings.mode === 'fade') {
1214        distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
1215        if (distance >= slider.settings.swipeThreshold) {
1216          if (slider.touch.start.x > slider.touch.end.x) {
1217            el.goToNextSlide();
1218          } else {
1219            el.goToPrevSlide();
1220          }
1221          el.stopAuto();
1222        }
1223      // not fade mode
1224      } else {
1225        // calculate distance and el's animate property
1226        if (slider.settings.mode === 'horizontal') {
1227          distance = slider.touch.end.x - slider.touch.start.x;
1228          value = slider.touch.originalPos.left;
1229        } else {
1230          distance = slider.touch.end.y - slider.touch.start.y;
1231          value = slider.touch.originalPos.top;
1232        }
1233        // if not infinite loop and first / last slide, do not attempt a slide transition
1234        if (!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))) {
1235          setPositionProperty(value, 'reset', 200);
1236        } else {
1237          // check if distance clears threshold
1238          if (Math.abs(distance) >= slider.settings.swipeThreshold) {
1239            if (distance < 0) {
1240              el.goToNextSlide();
1241            } else {
1242              el.goToPrevSlide();
1243            }
1244            el.stopAuto();
1245          } else {
1246            // el.animate(property, 200);
1247            setPositionProperty(value, 'reset', 200);
1248          }
1249        }
1250      }
1251      slider.viewport.unbind('touchend', onTouchEnd);
1252      // fix for https://github.com/stevenwanderski/bxslider-4/issues/1086
1253      if ('function' === typeof PointerEvent && orig.pointerId === undefined) {
1254        return;
1255      }
1256      // end fix
1257      if (slider.viewport.get(0).releasePointerCapture) {
1258        slider.viewport.get(0).releasePointerCapture(slider.pointerId);
1259      }
1260    };
1261
1262    /**
1263     * Window resize event callback
1264     */
1265    var resizeWindow = function(e) {
1266      // don't do anything if slider isn't initialized.
1267      if (!slider.initialized) { return; }
1268      // Delay if slider working.
1269      if (slider.working) {
1270        window.setTimeout(resizeWindow, 10);
1271      } else {
1272        // get the new window dimens (again, thank you IE)
1273        var windowWidthNew = $(window).width(),
1274        windowHeightNew = $(window).height();
1275        // make sure that it is a true window resize
1276        // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
1277        // are resized. Can you just die already?*
1278        if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) {
1279          // set the new window dimens
1280          windowWidth = windowWidthNew;
1281          windowHeight = windowHeightNew;
1282          // update all dynamic elements
1283          el.redrawSlider();
1284          // Call user resize handler
1285          slider.settings.onSliderResize.call(el, slider.active.index);
1286        }
1287      }
1288    };
1289
1290    /**
1291     * Adds an aria-hidden=true attribute to each element
1292     *
1293     * @param startVisibleIndex (int)
1294     *  - the first visible element's index
1295     */
1296    var applyAriaHiddenAttributes = function(startVisibleIndex) {
1297      var numberOfSlidesShowing = getNumberSlidesShowing();
1298      // only apply attributes if the setting is enabled and not in ticker mode
1299      if (slider.settings.ariaHidden && !slider.settings.ticker) {
1300        // add aria-hidden=true to all elements
1301        slider.children.attr('aria-hidden', 'true');
1302        // prevent keyboard navigation on hidden elements
1303        slider.children.find('a, button').attr('tabindex', '-1');
1304        // get the visible elements and change to aria-hidden=false
1305        slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false');
1306        // allow keyboard navigation on visible elements
1307        slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).find('a, button').not('[aria-hidden="true"]').attr('tabindex', '0');
1308      }
1309    };
1310
1311    /**
1312     * Returns index according to present page range
1313     *
1314     * @param slideOndex (int)
1315     *  - the desired slide index
1316     */
1317    var setSlideIndex = function(slideIndex) {
1318      if (slideIndex < 0) {
1319        if (slider.settings.infiniteLoop) {
1320          return getPagerQty() - 1;
1321        }else {
1322          //we don't go to undefined slides
1323          return slider.active.index;
1324        }
1325      // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
1326      } else if (slideIndex >= getPagerQty()) {
1327        if (slider.settings.infiniteLoop) {
1328          return 0;
1329        } else {
1330          //we don't move to undefined pages
1331          return slider.active.index;
1332        }
1333      // set active index to requested slide
1334      } else {
1335        return slideIndex;
1336      }
1337    };
1338
1339    /**
1340     * ===================================================================================
1341     * = PUBLIC FUNCTIONS
1342     * ===================================================================================
1343     */
1344
1345    /**
1346     * Performs slide transition to the specified slide
1347     *
1348     * @param slideIndex (int)
1349     *  - the destination slide's index (zero-based)
1350     *
1351     * @param direction (string)
1352     *  - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
1353     */
1354    el.goToSlide = function(slideIndex, direction) {
1355      // onSlideBefore, onSlideNext, onSlidePrev callbacks
1356      // Allow transition canceling based on returned value
1357      var performTransition = true,
1358      moveBy = 0,
1359      position = {left: 0, top: 0},
1360      lastChild = null,
1361      lastShowingIndex, eq, value, requestEl;
1362      // store the old index
1363      slider.oldIndex = slider.active.index;
1364      //set new index
1365      slider.active.index = setSlideIndex(slideIndex);
1366
1367      // if plugin is currently in motion, ignore request
1368      if (slider.working || slider.active.index === slider.oldIndex) { return; }
1369      // declare that plugin is in motion
1370      slider.working = true;
1371      slider.viewport.closest('.fl-module').find('a, button').not('.bx-start, .bx-stop').addClass('disabled');
1372
1373      performTransition = slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1374
1375      // If transitions canceled, reset and return
1376      if (typeof (performTransition) !== 'undefined' && !performTransition) {
1377        slider.active.index = slider.oldIndex; // restore old index
1378        slider.working = false; // is not in motion
1379        return;
1380      }
1381
1382      if (direction === 'next') {
1383        // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1384        if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1385          performTransition = false;
1386        }
1387      } else if (direction === 'prev') {
1388        // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1389        if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1390          performTransition = false;
1391        }
1392      }
1393
1394      // check if last slide
1395      slider.active.last = slider.active.index >= getPagerQty() - 1;
1396      // update the pager with active class
1397      if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); }
1398      // // check for direction control update
1399      if (slider.settings.controls) { updateDirectionControls(); }
1400      // if slider is set to mode: "fade"
1401      if (slider.settings.mode === 'fade') {
1402        // if adaptiveHeight is true and next height is different from current height, animate to the new height
1403        if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1404          slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1405        }
1406        // fade out the visible child and reset its z-index value
1407        slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
1408        // fade in the newly requested slide
1409        slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function() {
1410          $(this).css('zIndex', slider.settings.slideZIndex);
1411          updateAfterSlideTransition();
1412        });
1413      // slider mode is not "fade"
1414      } else {
1415        // if adaptiveHeight is true and next height is different from current height, animate to the new height
1416        if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1417          slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1418        }
1419        // if carousel and not infinite loop
1420        if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) {
1421          if (slider.settings.mode === 'horizontal') {
1422            // get the last child position
1423            lastChild = slider.children.eq(slider.children.length - 1);
1424            position = lastChild.position();
1425            // calculate the position of the last slide
1426            moveBy = slider.viewport.width() - lastChild.outerWidth();
1427          } else {
1428            // get last showing index position
1429            lastShowingIndex = slider.children.length - slider.settings.minSlides;
1430            position = slider.children.eq(lastShowingIndex).position();
1431          }
1432          // horizontal carousel, going previous while on first slide (infiniteLoop mode)
1433        } else if (slider.carousel && slider.active.last && direction === 'prev') {
1434          // get the last child position
1435          eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
1436          lastChild = el.children('.bx-clone').eq(eq);
1437          position = lastChild.position();
1438        // if infinite loop and "Next" is clicked on the last slide
1439        } else if (direction === 'next' && slider.active.index === 0) {
1440          // get the last clone position
1441          position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
1442          slider.active.last = false;
1443        // normal non-zero requests
1444        } else if (slideIndex >= 0) {
1445          //parseInt is applied to allow floats for slides/page
1446          requestEl = slideIndex * parseInt(getMoveBy());
1447          position = slider.children.eq(requestEl).position();
1448        }
1449
1450        /* If the position doesn't exist
1451         * (e.g. if you destroy the slider on a next click),
1452         * it doesn't throw an error.
1453         */
1454        if (typeof (position) !== 'undefined') {
1455          value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top;
1456          // plugin values to be animated
1457          setPositionProperty(value, 'slide', slider.settings.speed);
1458        } else {
1459          slider.working = false;
1460        }
1461      }
1462      if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1463    };
1464
1465    /**
1466     * Transitions to the next slide in the show
1467     */
1468    el.goToNextSlide = function() {
1469      // if infiniteLoop is false and last page is showing, disregard call
1470      if (!slider.settings.infiniteLoop && slider.active.last || slider.working) { return; }
1471      var pagerIndex = parseInt(slider.active.index) + 1;
1472      el.goToSlide(pagerIndex, 'next');
1473    };
1474
1475    /**
1476     * Transitions to the prev slide in the show
1477     */
1478    el.goToPrevSlide = function() {
1479      // if infiniteLoop is false and last page is showing, disregard call
1480      if (!slider.settings.infiniteLoop && slider.active.index === 0 || slider.working) { return; }
1481      var pagerIndex = parseInt(slider.active.index) - 1;
1482      el.goToSlide(pagerIndex, 'prev');
1483    };
1484
1485    /**
1486     * Starts the auto show
1487     *
1488     * @param preventControlUpdate (boolean)
1489     *  - if true, auto controls state will not be updated
1490     */
1491    el.startAuto = function(preventControlUpdate) {
1492      // if an interval already exists, disregard call
1493      if (slider.interval) { return; }
1494      // create an interval
1495      slider.interval = setInterval(function() {
1496        if (slider.settings.autoDirection === 'next') {
1497          el.goToNextSlide();
1498        } else {
1499          el.goToPrevSlide();
1500        }
1501      }, slider.settings.pause);
1502      // if auto controls are displayed and preventControlUpdate is not true
1503      if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('stop'); }
1504    };
1505
1506    /**
1507     * Stops the auto show
1508     *
1509     * @param preventControlUpdate (boolean)
1510     *  - if true, auto controls state will not be updated
1511     */
1512    el.stopAuto = function(preventControlUpdate) {
1513      // if no interval exists, disregard call
1514      if (!slider.interval) { return; }
1515      // clear the interval
1516      clearInterval(slider.interval);
1517      slider.interval = null;
1518      // if auto controls are displayed and preventControlUpdate is not true
1519      if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('start'); }
1520    };
1521
1522    /**
1523     * Returns current slide index (zero-based)
1524     */
1525    el.getCurrentSlide = function() {
1526      return slider.active.index;
1527    };
1528
1529    /**
1530     * Returns current slide element
1531     */
1532    el.getCurrentSlideElement = function() {
1533      return slider.children.eq(slider.active.index);
1534    };
1535
1536    /**
1537     * Returns a slide element
1538     * @param index (int)
1539     *  - The index (zero-based) of the element you want returned.
1540     */
1541    el.getSlideElement = function(index) {
1542      return slider.children.eq(index);
1543    };
1544
1545    /**
1546     * Returns number of slides in show
1547     */
1548    el.getSlideCount = function() {
1549      return slider.children.length;
1550    };
1551
1552    /**
1553     * Update all dynamic slider elements
1554     */
1555    el.redrawSlider = function() {
1556      // resize all children in ratio to new screen size
1557      slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth());
1558      // adjust the height
1559      slider.viewport.css('height', getViewportHeight());
1560      // update the slide position
1561      if (!slider.settings.ticker) { setSlidePosition(); }
1562      // if active.last was true before the screen resize, we want
1563      // to keep it last no matter what screen size we end on
1564      if (slider.active.last) { slider.active.index = getPagerQty() - 1; }
1565      // if the active index (page) no longer exists due to the resize, simply set the index as last
1566      if (slider.active.index >= getPagerQty()) { slider.active.last = true; }
1567      // if a pager is being displayed and a custom pager is not being used, update it
1568      if (slider.settings.pager && !slider.settings.pagerCustom) {
1569        populatePager();
1570        updatePagerActive(slider.active.index);
1571      }
1572      if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1573    };
1574
1575    /**
1576     * Destroy the current instance of the slider (revert everything back to original state)
1577     */
1578    el.destroySlider = function() {
1579      // don't do anything if slider has already been destroyed
1580      if (!slider.initialized) { return; }
1581      slider.initialized = false;
1582      $('.bx-clone', this).remove();
1583      slider.children.each(function() {
1584        if ($(this).data('origStyle') !== undefined) {
1585          $(this).attr('style', $(this).data('origStyle'));
1586        } else {
1587          $(this).removeAttr('style');
1588        }
1589      });
1590      if ($(this).data('origStyle') !== undefined) {
1591        this.attr('style', $(this).data('origStyle'));
1592      } else {
1593        $(this).removeAttr('style');
1594      }
1595      $(this).unwrap().unwrap();
1596      if (slider.controls.el) { slider.controls.el.remove(); }
1597      if (slider.controls.next) { slider.controls.next.remove(); }
1598      if (slider.controls.prev) { slider.controls.prev.remove(); }
1599      if (slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom) { slider.pagerEl.remove(); }
1600      $('.bx-caption', this).remove();
1601      if (slider.controls.autoEl) { slider.controls.autoEl.remove(); }
1602      clearInterval(slider.interval);
1603      if (slider.settings.responsive) { $(window).unbind('resize', resizeWindow); }
1604      if (slider.settings.keyboardEnabled) { slider.viewport.closest('.fl-module').unbind('keydown', keyPress); }
1605      //remove self reference in data
1606      $(this).removeData('bxSlider');
1607    };
1608
1609    /**
1610     * Reload the slider (revert all DOM changes, and re-initialize)
1611     */
1612    el.reloadSlider = function(settings) {
1613      if (settings !== undefined) { options = settings; }
1614      el.destroySlider();
1615      init();
1616      //store reference to self in order to access public functions later
1617      $(el).data('bxSlider', this);
1618    };
1619
1620    init();
1621
1622    $(el).data('bxSlider', this);
1623
1624    // returns the current jQuery object
1625    return this;
1626  };
1627
1628})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.