PageSourceSearch

https://sib.org.bz/wp-content/plugins/everest-timeline/js/jquery.bxslider.js?ver=1.0.8

js sib.org.bz collected 2026-09-24 22:11:55 UTC 79,057 bytes, 1,797 lines download raw bytes

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