PageSourceSearch

https://lmcc.net/wp-content/plugins/bb-plugin/js/libs/jquery.bxslider.js?ver=2.11.1

js lmcc.net collected 2026-09-24 17:16:51 UTC 67,597 bytes, 1,633 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: true,
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,830 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 || ( slider.settings.nextSelector && slider.settings.prevSelector )) { 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: 4,618 bytes, lines 754-892
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      updateDirectionControls();
895      // onSlideAfter callback
896      slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
897    };
898
899    /**
900     * Updates the auto controls state (either active, or combined switch)
901     *
902     * @param state (string) "start", "stop"
903     *  - the new state of the auto show
904     */
905    var updateAutoControls = function(state) {
906      // if autoControlsCombine is true, replace the current control with the new state
907      if (slider.settings.autoControlsCombine) {
908        var focused = slider.controls.autoEl.has($(document.activeElement)).length == 1;
909        slider.controls.autoEl.html(slider.controls[state]);
910        if(focused) {
911          slider.controls[state].find('a, button').focus();
912          if(slider.isFocused && state === 'stop') { slider.isFocused = null; }
913        }
914      // if autoControlsCombine is false, apply the "active" class to the appropriate control
915      } else {
916        slider.controls.autoEl.find('a, button').removeClass('active');
917        slider.controls.autoEl.find('a:not(.bx-' + state + '), button:not(.bx-' + state + ')').addClass('active');
918      }
919    };
920
921    /**
922     * Updates the direction controls (checks if either should be hidden)
923     */
924    var updateDirectionControls = function() {
925      const infinite = slider.settings.infiniteLoop;
926      const single = getPagerQty() === 1;
927      const start = slider.active.index === 0;
928      const end = slider.active.index === getPagerQty() - 1;
929      const forward = !single && (infinite || !end);
930      const backward = !single && (infinite || !start);
931      const next = slider.settings.nextSelector ? $(slider.settings.nextSelector) : slider.controls.next || $();
932      const prev = slider.settings.prevSelector ? $(slider.settings.prevSelector) : slider.controls.prev || $();
933      if (!forward && next.is(':focus')) { prev.focus(); }
934      if (!backward && prev.is(':focus')) { next.focus(); }
935      toggleDirectionControls(next, forward);
936      toggleDirectionControls(prev, backward);
937    };
938
939    /**
940     * Toggles direction controls
941     */
942    var toggleDirectionControls = function( element, active ) {
943      element.toggleClass('disabled', !active);
944      if (element.prop('tagName') === 'A') {
945        element.attr({ 'aria-disabled': !active, 'tabindex': active ? 0 : -1 });
946      } else if (element.prop('tagName') === 'BUTTON') {
947        element.attr('disabled', !active);
948      }
949    };
950
951    /**
952     * Initializes the auto process
953     */
954    var initAuto = function() {
955      // if autoDelay was supplied, launch the auto show using a setTimeout() call
956      if (slider.settings.autoDelay > 0) {
957       setTimeout(el.startAuto, slider.settings.autoDelay);
958      // if autoDelay was not supplied, start the auto show normally
959      } else {
960        el.startAuto();
961
962      }
963      // if autoHover is requested
964      if (slider.settings.autoHover) {
965        // on el hover
966        el.hover(function() {
967          // if the auto show is currently playing (has an active interval)
968          if (slider.interval) {
969            // stop the auto show and pass true argument which will prevent control update
970            el.stopAuto(true);
971            // create a new autoPaused value which will be used by the relative "mouseout" event
972            slider.autoPaused = true;
973          }
974        }, function() {
975          // if the autoPaused value was created be the prior "mouseover" event
976          if (slider.autoPaused) {
977            // start the auto show and pass true argument which will prevent control update
978            el.startAuto(true);
979            // reset the autoPaused value
980            slider.autoPaused = null;
981          }
982        });
983      }
984    };
985
986    /**
987     * Initializes the ticker process
988     */
989    var initTicker = function() {
990      var startPosition = 0,
991      position, transform, value, idx, ratio, property, newSpeed, totalDimens;
992      // if autoDirection is "next", append a clone of the entire slider
993      if (slider.settings.autoDirection === 'next') {
994        el.append(slider.children.clone().addClass('bx-clone'));
995      // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
996      } else {
vendor: 25,716 bytes, lines 997-1633
997        el.prepend(slider.children.clone().addClass('bx-clone'));
998        position = slider.children.first().position();
999        startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
1000      }
1001      setPositionProperty(startPosition, 'reset', 0);
1002      // do not allow controls in ticker mode
1003      slider.settings.pager = false;
1004      slider.settings.controls = false;
1005      slider.settings.autoControls = false;
1006      // if autoHover is requested
1007      if (slider.settings.tickerHover) {
1008        if (slider.usingCSS) {
1009          idx = slider.settings.mode === 'horizontal' ? 4 : 5;
1010          slider.viewport.hover(function() {
1011            transform = el.css('-' + slider.cssPrefix + '-transform');
1012            value = parseFloat(transform.split(',')[idx]);
1013            setPositionProperty(value, 'reset', 0);
1014          }, function() {
1015            totalDimens = 0;
1016            slider.children.each(function(index) {
1017              totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1018            });
1019            // calculate the speed ratio (used to determine the new speed to finish the paused animation)
1020            ratio = slider.settings.speed / totalDimens;
1021            // determine which property to use
1022            property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
1023            // calculate the new speed
1024            newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value))));
1025            tickerLoop(newSpeed);
1026          });
1027        } else {
1028          // on el hover
1029          slider.viewport.hover(function() {
1030            el.stop();
1031          }, function() {
1032            // calculate the total width of children (used to calculate the speed ratio)
1033            totalDimens = 0;
1034            slider.children.each(function(index) {
1035              totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1036            });
1037            // calculate the speed ratio (used to determine the new speed to finish the paused animation)
1038            ratio = slider.settings.speed / totalDimens;
1039            // determine which property to use
1040            property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
1041            // calculate the new speed
1042            newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
1043            tickerLoop(newSpeed);
1044          });
1045        }
1046      }
1047      // start the ticker loop
1048      tickerLoop();
1049    };
1050
1051    /**
1052     * Runs a continuous loop, news ticker-style
1053     */
1054    var tickerLoop = function(resumeSpeed) {
1055      var speed = resumeSpeed ? resumeSpeed : slider.settings.speed,
1056      position = {left: 0, top: 0},
1057      reset = {left: 0, top: 0},
1058      animateProperty, resetValue, params;
1059
1060      // if "next" animate left position to last child, then reset left to 0
1061      if (slider.settings.autoDirection === 'next') {
1062        position = el.find('.bx-clone').first().position();
1063      // if "prev" animate left position to 0, then reset left to first non-clone child
1064      } else {
1065        reset = slider.children.first().position();
1066      }
1067      animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
1068      resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top;
1069      params = {resetValue: resetValue};
1070      setPositionProperty(animateProperty, 'ticker', speed, params);
1071    };
1072
1073    /**
1074     * Check if el is on screen
1075     */
1076    var isOnScreen = function(el) {
1077      var win = $(window),
1078      viewport = {
1079        top: win.scrollTop(),
1080        left: win.scrollLeft()
1081      },
1082      bounds = el.offset();
1083
1084      viewport.right = viewport.left + win.width();
1085      viewport.bottom = viewport.top + win.height();
1086      bounds.right = bounds.left + el.outerWidth();
1087      bounds.bottom = bounds.top + el.outerHeight();
1088
1089      return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
1090    };
1091
1092    /**
1093     * Check if slider was out of focus
1094     */
1095    var isOutFocus = function(e) {
1096      if (slider.viewport.closest('.fl-module').has($(e.relatedTarget)).length === 0 && !slider.isFocused) {
1097        slider.isFocused = true;
1098        clickStopBind(e);
1099      }
1100    };
1101
1102    /**
1103     * Initializes keyboard events
1104     */
1105    var keyPress = function(e) {
1106      if (isOnScreen(el) && (e.keyCode === 39 || e.keyCode === 37)) {
1107        if (e.keyCode === 39) {
1108          clickNextBind(e);
1109        } else if (e.keyCode === 37) {
1110          clickPrevBind(e);
1111        }
1112        slider.viewport.closest('.' + slider.settings.wrapperClass).find('.bx-pager-link.active').focus();
1113        return false;
1114      }
1115    };
1116
1117    /**
1118     * Initializes touch events
1119     */
1120    var initTouch = function() {
1121      // initialize object to contain all touch values
1122      slider.touch = {
1123        start: {x: 0, y: 0},
1124        end: {x: 0, y: 0}
1125      };
1126      slider.viewport.bind('touchstart', onTouchStart);
1127
1128      //for browsers that have implemented pointer events and fire a click after
1129      //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not
1130      slider.viewport.on('click', '.bxslider a, .bxslider button', function(e) {
1131        if (slider.viewport.hasClass('click-disabled')) {
1132          e.preventDefault();
1133          slider.viewport.removeClass('click-disabled');
1134        }
1135      });
1136    };
1137
1138    /**
1139     * Event handler for "touchstart"
1140     *
1141     * @param e (event)
1142     *  - DOM event object
1143     */
1144    var onTouchStart = function(e) {
1145      //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
1146      slider.controls.el.addClass('disabled');
1147
1148      if (slider.working) {
1149        e.preventDefault();
1150        slider.controls.el.removeClass('disabled');
1151      } else {
1152        // record the original position when touch starts
1153        slider.touch.originalPos = el.position();
1154        var orig = e.originalEvent,
1155        touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig];
1156        // record the starting touch x, y coordinates
1157        slider.touch.start.x = touchPoints[0].pageX;
1158        slider.touch.start.y = touchPoints[0].pageY;
1159        // bind a "touchmove" event to the viewport
1160        slider.viewport.bind('touchmove', onTouchMove);
1161        // bind a "touchend" event to the viewport
1162        slider.viewport.bind('touchend', onTouchEnd);
1163      }
1164    };
1165
1166    /**
1167     * Event handler for "touchmove"
1168     *
1169     * @param e (event)
1170     *  - DOM event object
1171     */
1172    var onTouchMove = function(e) {
1173      var orig = e.originalEvent,
1174      touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1175      // if scrolling on y axis, do not prevent default
1176      xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x),
1177      yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y),
1178      value = 0,
1179      change = 0;
1180
1181      // x axis swipe
1182      if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) {
1183        e.preventDefault();
1184      // y axis swipe
1185      } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) {
1186        e.preventDefault();
1187      }
1188      if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) {
1189        // if horizontal, drag along x axis
1190        if (slider.settings.mode === 'horizontal') {
1191          change = touchPoints[0].pageX - slider.touch.start.x;
1192          value = slider.touch.originalPos.left + change;
1193        // if vertical, drag along y axis
1194        } else {
1195          change = touchPoints[0].pageY - slider.touch.start.y;
1196          value = slider.touch.originalPos.top + change;
1197        }
1198        setPositionProperty(value, 'reset', 0);
1199      }
1200    };
1201
1202    /**
1203     * Event handler for "touchend"
1204     *
1205     * @param e (event)
1206     *  - DOM event object
1207     */
1208    var onTouchEnd = function(e) {
1209      slider.viewport.unbind('touchmove', onTouchMove);
1210      //enable slider controls as soon as user stops interacing with slides
1211      slider.controls.el.removeClass('disabled');
1212      var orig    = e.originalEvent,
1213      touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1214      value       = 0,
1215      distance    = 0;
1216      // record end x, y positions
1217      slider.touch.end.x = touchPoints[0].pageX;
1218      slider.touch.end.y = touchPoints[0].pageY;
1219      // if fade mode, check if absolute x distance clears the threshold
1220      if (slider.settings.mode === 'fade') {
1221        distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
1222        if (distance >= slider.settings.swipeThreshold) {
1223          if (slider.touch.start.x > slider.touch.end.x) {
1224            el.goToNextSlide();
1225          } else {
1226            el.goToPrevSlide();
1227          }
1228          el.stopAuto();
1229        }
1230      // not fade mode
1231      } else {
1232        // calculate distance and el's animate property
1233        if (slider.settings.mode === 'horizontal') {
1234          distance = slider.touch.end.x - slider.touch.start.x;
1235          value = slider.touch.originalPos.left;
1236        } else {
1237          distance = slider.touch.end.y - slider.touch.start.y;
1238          value = slider.touch.originalPos.top;
1239        }
1240        // if not infinite loop and first / last slide, do not attempt a slide transition
1241        if (!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))) {
1242          setPositionProperty(value, 'reset', 200);
1243        } else {
1244          // check if distance clears threshold
1245          if (Math.abs(distance) >= slider.settings.swipeThreshold) {
1246            if (distance < 0) {
1247              el.goToNextSlide();
1248            } else {
1249              el.goToPrevSlide();
1250            }
1251            el.stopAuto();
1252          } else {
1253            // el.animate(property, 200);
1254            setPositionProperty(value, 'reset', 200);
1255          }
1256        }
1257      }
1258      slider.viewport.unbind('touchend', onTouchEnd);
1259      // fix for https://github.com/stevenwanderski/bxslider-4/issues/1086
1260      if ('function' === typeof PointerEvent && orig.pointerId === undefined) {
1261        return;
1262      }
1263      // end fix
1264      if (slider.viewport.get(0).releasePointerCapture) {
1265        slider.viewport.get(0).releasePointerCapture(slider.pointerId);
1266      }
1267    };
1268
1269    /**
1270     * Window resize event callback
1271     */
1272    var resizeWindow = function(e) {
1273      // don't do anything if slider isn't initialized.
1274      if (!slider.initialized) { return; }
1275      // Delay if slider working.
1276      if (slider.working) {
1277        window.setTimeout(resizeWindow, 10);
1278      } else {
1279        // get the new window dimens (again, thank you IE)
1280        var windowWidthNew = $(window).width(),
1281        windowHeightNew = $(window).height();
1282        // make sure that it is a true window resize
1283        // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
1284        // are resized. Can you just die already?*
1285        if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) {
1286          // set the new window dimens
1287          windowWidth = windowWidthNew;
1288          windowHeight = windowHeightNew;
1289          // update all dynamic elements
1290          el.redrawSlider();
1291          // Call user resize handler
1292          slider.settings.onSliderResize.call(el, slider.active.index);
1293        }
1294      }
1295    };
1296
1297    /**
1298     * Adds an aria-hidden=true attribute to each element
1299     *
1300     * @param startVisibleIndex (int)
1301     *  - the first visible element's index
1302     */
1303    var applyAriaHiddenAttributes = function(startVisibleIndex) {
1304      var numberOfSlidesShowing = getNumberSlidesShowing();
1305      // only apply attributes if the setting is enabled and not in ticker mode
1306      if (slider.settings.ariaHidden && !slider.settings.ticker) {
1307        // add aria-hidden=true to all elements
1308        slider.children.attr('aria-hidden', 'true');
1309        // prevent keyboard navigation on hidden elements
1310        slider.children.find('a, button').attr('tabindex', '-1');
1311        // get the visible elements and change to aria-hidden=false
1312        slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false');
1313        // allow keyboard navigation on visible elements
1314        slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).find('a, button').not('[aria-hidden="true"]').attr('tabindex', '0');
1315      }
1316    };
1317
1318    /**
1319     * Returns index according to present page range
1320     *
1321     * @param slideOndex (int)
1322     *  - the desired slide index
1323     */
1324    var setSlideIndex = function(slideIndex) {
1325      if (slideIndex < 0) {
1326        if (slider.settings.infiniteLoop) {
1327          return getPagerQty() - 1;
1328        }else {
1329          //we don't go to undefined slides
1330          return slider.active.index;
1331        }
1332      // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
1333      } else if (slideIndex >= getPagerQty()) {
1334        if (slider.settings.infiniteLoop) {
1335          return 0;
1336        } else {
1337          //we don't move to undefined pages
1338          return slider.active.index;
1339        }
1340      // set active index to requested slide
1341      } else {
1342        return slideIndex;
1343      }
1344    };
1345
1346    /**
1347     * ===================================================================================
1348     * = PUBLIC FUNCTIONS
1349     * ===================================================================================
1350     */
1351
1352    /**
1353     * Performs slide transition to the specified slide
1354     *
1355     * @param slideIndex (int)
1356     *  - the destination slide's index (zero-based)
1357     *
1358     * @param direction (string)
1359     *  - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
1360     */
1361    el.goToSlide = function(slideIndex, direction) {
1362      // onSlideBefore, onSlideNext, onSlidePrev callbacks
1363      // Allow transition canceling based on returned value
1364      var performTransition = true,
1365      moveBy = 0,
1366      position = {left: 0, top: 0},
1367      lastChild = null,
1368      lastShowingIndex, eq, value, requestEl,
1369      newIndex = setSlideIndex(slideIndex);
1370
1371      // if plugin is currently in motion, ignore request
1372      if (slider.working || newIndex === slider.active.index) { return; }
1373      // store the old index and set new index
1374      slider.oldIndex = slider.active.index;
1375      slider.active.index = newIndex;
1376      // declare that plugin is in motion
1377      slider.working = true;
1378      slider.viewport.closest('.fl-module').find('a, button').not('.bx-start, .bx-stop').addClass('disabled');
1379
1380      performTransition = slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1381
1382      // If transitions canceled, reset and return
1383      if (typeof (performTransition) !== 'undefined' && !performTransition) {
1384        slider.active.index = slider.oldIndex; // restore old index
1385        slider.working = false; // is not in motion
1386        return;
1387      }
1388
1389      if (direction === 'next') {
1390        // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1391        if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1392          performTransition = false;
1393        }
1394      } else if (direction === 'prev') {
1395        // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1396        if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1397          performTransition = false;
1398        }
1399      }
1400
1401      // check if last slide
1402      slider.active.last = slider.active.index >= getPagerQty() - 1;
1403      // update the pager with active class
1404      if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); }
1405      // if slider is set to mode: "fade"
1406      if (slider.settings.mode === 'fade') {
1407        // if adaptiveHeight is true and next height is different from current height, animate to the new height
1408        if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1409          slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1410        }
1411        // fade out the visible child and reset its z-index value
1412        slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
1413        // fade in the newly requested slide
1414        slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function() {
1415          $(this).css('zIndex', slider.settings.slideZIndex);
1416          updateAfterSlideTransition();
1417        });
1418      // slider mode is not "fade"
1419      } else {
1420        // if adaptiveHeight is true and next height is different from current height, animate to the new height
1421        if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1422          slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1423        }
1424        // if carousel and not infinite loop
1425        if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) {
1426          if (slider.settings.mode === 'horizontal') {
1427            // get the last child position
1428            lastChild = slider.children.eq(slider.children.length - 1);
1429            position = lastChild.position();
1430            // calculate the position of the last slide
1431            moveBy = slider.viewport.width() - lastChild.outerWidth();
1432          } else {
1433            // get last showing index position
1434            lastShowingIndex = slider.children.length - slider.settings.minSlides;
1435            position = slider.children.eq(lastShowingIndex).position();
1436          }
1437          // horizontal carousel, going previous while on first slide (infiniteLoop mode)
1438        } else if (slider.carousel && slider.active.last && direction === 'prev') {
1439          // get the last child position
1440          eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
1441          lastChild = el.children('.bx-clone').eq(eq);
1442          position = lastChild.position();
1443        // if infinite loop and "Next" is clicked on the last slide
1444        } else if (direction === 'next' && slider.active.index === 0) {
1445          // get the last clone position
1446          position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
1447          slider.active.last = false;
1448        // normal non-zero requests
1449        } else if (slideIndex >= 0) {
1450          //parseInt is applied to allow floats for slides/page
1451          requestEl = slideIndex * parseInt(getMoveBy());
1452          position = slider.children.eq(requestEl).position();
1453        }
1454
1455        /* If the position doesn't exist
1456         * (e.g. if you destroy the slider on a next click),
1457         * it doesn't throw an error.
1458         */
1459        if (typeof (position) !== 'undefined') {
1460          value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top;
1461          // plugin values to be animated
1462          setPositionProperty(value, 'slide', slider.settings.speed);
1463        } else {
1464          slider.working = false;
1465        }
1466      }
1467      if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1468    };
1469
1470    /**
1471     * Transitions to the next slide in the show
1472     */
1473    el.goToNextSlide = function() {
1474      // if infiniteLoop is false and last page is showing, disregard call
1475      if (!slider.settings.infiniteLoop && slider.active.last || slider.working) { return; }
1476      var pagerIndex = parseInt(slider.active.index) + 1;
1477      el.goToSlide(pagerIndex, 'next');
1478    };
1479
1480    /**
1481     * Transitions to the prev slide in the show
1482     */
1483    el.goToPrevSlide = function() {
1484      // if infiniteLoop is false and last page is showing, disregard call
1485      if (!slider.settings.infiniteLoop && slider.active.index === 0 || slider.working) { return; }
1486      var pagerIndex = parseInt(slider.active.index) - 1;
1487      el.goToSlide(pagerIndex, 'prev');
1488    };
1489
1490    /**
1491     * Starts the auto show
1492     *
1493     * @param preventControlUpdate (boolean)
1494     *  - if true, auto controls state will not be updated
1495     */
1496    el.startAuto = function(preventControlUpdate) {
1497      // if an interval already exists, disregard call
1498      if (slider.interval) { return; }
1499      // create an interval
1500      slider.interval = setInterval(function() {
1501        if (slider.settings.autoDirection === 'next') {
1502          el.goToNextSlide();
1503        } else {
1504          el.goToPrevSlide();
1505        }
1506      }, slider.settings.pause);
1507      // if auto controls are displayed and preventControlUpdate is not true
1508      if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('stop'); }
1509    };
1510
1511    /**
1512     * Stops the auto show
1513     *
1514     * @param preventControlUpdate (boolean)
1515     *  - if true, auto controls state will not be updated
1516     */
1517    el.stopAuto = function(preventControlUpdate) {
1518      // if no interval exists, disregard call
1519      if (!slider.interval) { return; }
1520      // clear the interval
1521      clearInterval(slider.interval);
1522      slider.interval = null;
1523      // if auto controls are displayed and preventControlUpdate is not true
1524      if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('start'); }
1525    };
1526
1527    /**
1528     * Returns current slide index (zero-based)
1529     */
1530    el.getCurrentSlide = function() {
1531      return slider.active.index;
1532    };
1533
1534    /**
1535     * Returns current slide element
1536     */
1537    el.getCurrentSlideElement = function() {
1538      return slider.children.eq(slider.active.index);
1539    };
1540
1541    /**
1542     * Returns a slide element
1543     * @param index (int)
1544     *  - The index (zero-based) of the element you want returned.
1545     */
1546    el.getSlideElement = function(index) {
1547      return slider.children.eq(index);
1548    };
1549
1550    /**
1551     * Returns number of slides in show
1552     */
1553    el.getSlideCount = function() {
1554      return slider.children.length;
1555    };
1556
1557    /**
1558     * Update all dynamic slider elements
1559     */
1560    el.redrawSlider = function() {
1561      // resize all children in ratio to new screen size
1562      slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth());
1563      // adjust the height
1564      slider.viewport.css('height', getViewportHeight());
1565      // update the slide position
1566      if (!slider.settings.ticker) { setSlidePosition(); }
1567      // if active.last was true before the screen resize, we want
1568      // to keep it last no matter what screen size we end on
1569      if (slider.active.last) { slider.active.index = getPagerQty() - 1; }
1570      // if the active index (page) no longer exists due to the resize, simply set the index as last
1571      if (slider.active.index >= getPagerQty()) { slider.active.last = true; }
1572      // if a pager is being displayed and a custom pager is not being used, update it
1573      if (slider.settings.pager && !slider.settings.pagerCustom) {
1574        populatePager();
1575        updatePagerActive(slider.active.index);
1576      }
1577      if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1578    };
1579
1580    /**
1581     * Destroy the current instance of the slider (revert everything back to original state)
1582     */
1583    el.destroySlider = function() {
1584      // don't do anything if slider has already been destroyed
1585      if (!slider.initialized) { return; }
1586      slider.initialized = false;
1587      $('.bx-clone', this).remove();
1588      slider.children.each(function() {
1589        if ($(this).data('origStyle') !== undefined) {
1590          $(this).attr('style', $(this).data('origStyle'));
1591        } else {
1592          $(this).removeAttr('style');
1593        }
1594      });
1595      if ($(this).data('origStyle') !== undefined) {
1596        this.attr('style', $(this).data('origStyle'));
1597      } else {
1598        $(this).removeAttr('style');
1599      }
1600      $(this).unwrap().unwrap();
1601      if (slider.controls.el) { slider.controls.el.remove(); }
1602      if (slider.controls.next) { slider.controls.next.remove(); }
1603      if (slider.controls.prev) { slider.controls.prev.remove(); }
1604      if (slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom) { slider.pagerEl.remove(); }
1605      $('.bx-caption', this).remove();
1606      if (slider.controls.autoEl) { slider.controls.autoEl.remove(); }
1607      clearInterval(slider.interval);
1608      if (slider.settings.responsive) { $(window).unbind('resize', resizeWindow); }
1609      if (slider.settings.keyboardEnabled) { slider.viewport.closest('.fl-module').unbind('keydown', keyPress); }
1610      //remove self reference in data
1611      $(this).removeData('bxSlider');
1612    };
1613
1614    /**
1615     * Reload the slider (revert all DOM changes, and re-initialize)
1616     */
1617    el.reloadSlider = function(settings) {
1618      if (settings !== undefined) { options = settings; }
1619      el.destroySlider();
1620      init();
1621      //store reference to self in order to access public functions later
1622      $(el).data('bxSlider', this);
1623    };
1624
1625    init();
1626
1627    $(el).data('bxSlider', this);
1628
1629    // returns the current jQuery object
1630    return this;
1631  };
1632
1633})(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.