`. Note that the call must be made inside of a $(document).ready() call, or the plugin will not work!
60 |
61 | ```javascript
62 | $(document).ready(function(){
63 | $('.bxslider').bxSlider();
64 | });
65 | ```
66 |
67 | ## Configuration options
68 |
69 | ### General
70 |
71 | **mode**
72 |
73 | Type of transition between slides
74 | ```
75 | default: 'horizontal'
76 | options: 'horizontal', 'vertical', 'fade'
77 | ```
78 |
79 | **speed**
80 |
81 | Slide transition duration (in ms)
82 | ```
83 | default: 500
84 | options: integer
85 | ```
86 |
87 | **slideMargin**
88 |
89 | Margin between each slide
90 | ```
91 | default: 0
92 | options: integer
93 | ```
94 |
95 | **startSlide**
96 |
97 | Starting slide index (zero-based)
98 | ```
99 | default: 0
100 | options: integer
101 | ```
102 |
103 | **randomStart**
104 |
105 | Start slider on a random slide
106 | ```
107 | default: false
108 | options: boolean (true / false)
109 | ```
110 |
111 | **slideSelector**
112 |
113 | Element to use as slides (ex. 'div.slide'). Note: by default, bxSlider will use all immediate children of the slider element
114 | ```
115 | default: ''
116 | options: jQuery selector
117 | ```
118 |
119 | **infiniteLoop**
120 |
121 | If true, clicking "Next" while on the last slide will transition to the first slide and vice-versa
122 | ```
123 | default: true
124 | options: boolean (true / false)
125 | ```
126 |
127 | **hideControlOnEnd**
128 |
129 | If true, "Prev" and "Next" controls will receive a class disabled when slide is the first or the last Note: Only used when infiniteLoop: false
130 | ```
131 | default: false
132 | options: boolean (true / false)
133 | ```
134 |
135 | **easing**
136 |
137 | The type of "easing" to use during transitions. If using CSS transitions, include a value for the transition-timing-function property. If not using CSS transitions, you may include plugins/jquery.easing.1.3.js for many options. See http://gsgd.co.uk/sandbox/jquery/easing/ for more info.
138 | ```
139 | default: null
140 | options: if using CSS: 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'cubic-bezier(n,n,n,n)'. If not using CSS: 'swing', 'linear' (see the above file for more options)
141 | ```
142 |
143 | **captions**
144 |
145 | Include image captions. Captions are derived from the image's title attribute
146 | ```
147 | default: false
148 | options: boolean (true / false)
149 | ```
150 |
151 | **ticker**
152 |
153 | Use slider in ticker mode (similar to a news ticker)
154 | ```
155 | default: false
156 | options: boolean (true / false)
157 | ```
158 |
159 | **tickerHover**
160 |
161 | Ticker will pause when mouse hovers over slider. Note: this functionality does NOT work if using CSS transitions!
162 | ```
163 | default: false
164 | options: boolean (true / false)
165 | ```
166 |
167 | **adaptiveHeight**
168 |
169 | Dynamically adjust slider height based on each slide's height
170 | ```
171 | default: false
172 | options: boolean (true / false)
173 | ```
174 |
175 | **adaptiveHeightSpeed**
176 |
177 | Slide height transition duration (in ms). Note: only used if adaptiveHeight: true
178 | ```
179 | default: 500
180 | options: integer
181 | ```
182 |
183 | **video**
184 |
185 | If any slides contain video, set this to true. Also, include plugins/jquery.fitvids.js See http://fitvidsjs.com/ for more info
186 | ```
187 | default: false
188 | options: boolean (true / false)
189 | ```
190 |
191 | **responsive**
192 |
193 | Enable or disable auto resize of the slider. Useful if you need to use fixed width sliders.
194 | ```
195 | default: true
196 | options: boolean (true /false)
197 | ```
198 |
199 | **useCSS**
200 |
201 | If true, CSS transitions will be used for horizontal and vertical slide animations (this uses native hardware acceleration). If false, jQuery animate() will be used.
202 | ```
203 | default: true
204 | options: boolean (true / false)
205 | ```
206 |
207 | **preloadImages**
208 |
209 | If 'all', preloads all images before starting the slider. If 'visible', preloads only images in the initially visible slides before starting the slider (tip: use 'visible' if all slides are identical dimensions)
210 | ```
211 | default: 'visible'
212 | options: 'all', 'visible', 'none'
213 | ```
214 |
215 | **touchEnabled**
216 |
217 | If true, slider will allow touch swipe transitions
218 | ```
219 | default: true
220 | options: boolean (true / false)
221 | ```
222 |
223 | **swipeThreshold**
224 |
225 | Amount of pixels a touch swipe needs to exceed in order to execute a slide transition. Note: only used if touchEnabled: true
226 | ```
227 | default: 50
228 | options: integer
229 | ```
230 |
231 | **oneToOneTouch**
232 |
233 | If true, non-fade slides follow the finger as it swipes
234 | ```
235 | default: true
236 | options: boolean (true / false)
237 | ```
238 |
239 | **preventDefaultSwipeX**
240 |
241 | If true, touch screen will not move along the x-axis as the finger swipes
242 | ```
243 | default: true
244 | options: boolean (true / false)
245 | ```
246 |
247 | **preventDefaultSwipeY**
248 |
249 | If true, touch screen will not move along the y-axis as the finger swipes
250 | ```
251 | default: false
252 | options: boolean (true / false)
253 | ```
254 |
255 | **wrapperClass**
256 |
257 | Class to wrap the slider in. Change to prevent from using default bxSlider styles.
258 | ```
259 | default: 'bx-wrapper'
260 | options: string
261 | ```
262 |
263 | ### Pager
264 |
265 | **pager**
266 |
267 | If true, a pager will be added
268 | ```
269 | default: true
270 | options: boolean (true / false)
271 | ```
272 |
273 | **pagerType**
274 |
275 | If 'full', a pager link will be generated for each slide. If 'short', a x / y pager will be used (ex. 1 / 5)
276 | ```
277 | default: 'full'
278 | options: 'full', 'short'
279 | ```
280 |
281 | **pagerShortSeparator**
282 |
283 | If pagerType: 'short', pager will use this value as the separating character
284 | ```
285 | default: ' / '
286 | options: string
287 | ```
288 |
289 | **pagerSelector**
290 |
291 | Element used to populate the populate the pager. By default, the pager is appended to the bx-viewport
292 | ```
293 | default: ''
294 | options: jQuery selector
295 | ```
296 |
297 | **pagerCustom**
298 |
299 | Parent element to be used as the pager. Parent element must contain a <a data-slide-index="x"> element for each slide. See example here. Not for use with dynamic carousels.
300 | ```
301 | default: null
302 | options: jQuery selector
303 | ```
304 |
305 | **buildPager**
306 |
307 | If supplied, function is called on every slide element, and the returned value is used as the pager item markup. See examples for detailed implementation
308 | ```
309 | default: null
310 | options: function(slideIndex)
311 | ```
312 |
313 | ### Controls
314 |
315 | **controls**
316 |
317 | If true, "Next" / "Prev" controls will be added
318 | ```
319 | default: true
320 | options: boolean (true / false)
321 | ```
322 |
323 | **nextText**
324 |
325 | Text to be used for the "Next" control
326 | ```
327 | default: 'Next'
328 | options: string
329 | ```
330 |
331 | **prevText**
332 |
333 | Text to be used for the "Prev" control
334 | ```
335 | default: 'Prev'
336 | options: string
337 | ```
338 |
339 | **nextSelector**
340 |
341 | Element used to populate the "Next" control
342 | ```
343 | default: null
344 | options: jQuery selector
345 | ```
346 |
347 | **prevSelector**
348 |
349 | Element used to populate the "Prev" control
350 | ```
351 | default: null
352 | options: jQuery selector
353 | ```
354 |
355 | **autoControls**
356 |
357 | If true, "Start" / "Stop" controls will be added
358 | ```
359 | default: false
360 | options: boolean (true / false)
361 | ```
362 |
363 | **startText**
364 |
365 | Text to be used for the "Start" control
366 | ```
367 | default: 'Start'
368 | options: string
369 | ```
370 |
371 | **stopText**
372 |
373 | Text to be used for the "Stop" control
374 | ```
375 | default: 'Stop'
376 | options: string
377 | ```
378 |
379 | **autoControlsCombine**
380 |
381 | When slideshow is playing only "Stop" control is displayed and vice-versa
382 | ```
383 | default: false
384 | options: boolean (true / false)
385 | ```
386 |
387 | **autoControlsSelector**
388 |
389 | Element used to populate the auto controls
390 | ```
391 | default: null
392 | options: jQuery selector
393 | ```
394 |
395 | **keyboardEnabled**
396 |
397 | Enable keyboard navigation for visible sliders
398 | ```
399 | default: false
400 | options: boolean (true / false)
401 | ```
402 |
403 | ### Auto
404 |
405 | **auto**
406 |
407 | Slides will automatically transition
408 | ```
409 | default: false
410 | options: boolean (true / false)
411 | ```
412 | **stopAutoOnClick**
413 |
414 | Auto will stop on interaction with controls
415 | ```
416 | default: false
417 | options: boolean (true / false)
418 | ```
419 |
420 | **pause**
421 |
422 | The amount of time (in ms) between each auto transition
423 | ```
424 | default: 4000
425 | options: integer
426 | ```
427 |
428 | **autoStart**
429 |
430 | Auto show starts playing on load. If false, slideshow will start when the "Start" control is clicked
431 | ```
432 | default: true
433 | options: boolean (true / false)
434 | ```
435 |
436 | **autoDirection**
437 |
438 | The direction of auto show slide transitions
439 | ```
440 | default: 'next'
441 | options: 'next', 'prev'
442 | ```
443 |
444 | **autoHover**
445 |
446 | Auto show will pause when mouse hovers over slider
447 | ```
448 | default: false
449 | options: boolean (true / false)
450 | ```
451 |
452 | **autoDelay**
453 |
454 | Time (in ms) auto show should wait before starting
455 | ```
456 | default: 0
457 | options: integer
458 | ```
459 |
460 | ### Carousel
461 |
462 | **minSlides**
463 |
464 | The minimum number of slides to be shown. Slides will be sized down if carousel becomes smaller than the original size.
465 | ```
466 | default: 1
467 | options: integer
468 | ```
469 |
470 | **maxSlides**
471 |
472 | The maximum number of slides to be shown. Slides will be sized up if carousel becomes larger than the original size.
473 | ```
474 | default: 1
475 | options: integer
476 | ```
477 |
478 | **moveSlides**
479 |
480 | The number of slides to move on transition. This value must be `>= minSlides`, and `<= maxSlides`. If zero (default), the number of fully-visible slides will be used.
481 | ```
482 | default: 0
483 | options: integer
484 | ```
485 |
486 | **slideWidth**
487 |
488 | The width of each slide. This setting is required for all horizontal carousels!
489 | ```
490 | default: 0
491 | options: integer
492 | ```
493 |
494 | **shrinkItems**
495 |
496 | The Carousel will only show whole items and shrink the images to fit the viewport based on maxSlides/MinSlides.
497 | ```
498 | default: false
499 | options: boolean (true / false)
500 | ```
501 |
502 | ### Keyboard
503 |
504 | **keyboardEnabled**
505 |
506 | Allows for keyboard control of visible slider. Keypress ignored if slider not visible.
507 | ```
508 | default: false
509 | options: boolean (true / false)
510 | ```
511 |
512 | ### Accessibility
513 |
514 | **ariaLive**
515 |
516 | Adds Aria Live attribute to slider.
517 | ```
518 | default: true
519 | options: boolean (true / false)
520 | ```
521 |
522 | **ariaHidden**
523 |
524 | Adds Aria Hidden attribute to any nonvisible slides.
525 | ```
526 | default: true
527 | options: boolean (true / false)
528 | ```
529 |
530 | ### Callbacks
531 |
532 | **onSliderLoad**
533 |
534 | Executes immediately after the slider is fully loaded
535 | ```
536 | default: function(){}
537 | options: function(currentIndex){ // your code here }
538 | arguments:
539 | currentIndex: element index of the current slide
540 | ```
541 |
542 | **onSliderResize**
543 |
544 | Executes immediately after the slider is resized
545 | ```
546 | default: function(){}
547 | options: function(currentIndex){ // your code here }
548 | arguments:
549 | currentIndex: element index of the current slide
550 | ```
551 |
552 | **onSlideBefore**
553 |
554 | Executes immediately before each slide transition.
555 | ```
556 | default: function(){}
557 | options: function($slideElement, oldIndex, newIndex){ // your code here }
558 | arguments:
559 | $slideElement: jQuery element of the destination element
560 | oldIndex: element index of the previous slide (before the transition)
561 | newIndex: element index of the destination slide (after the transition)
562 | ```
563 |
564 | **onSlideAfter**
565 |
566 | Executes immediately after each slide transition. Function argument is the current slide element (when transition completes).
567 | ```
568 | default: function(){}
569 | options: function($slideElement, oldIndex, newIndex){ // your code here }
570 | arguments:
571 | $slideElement: jQuery element of the destination element
572 | oldIndex: element index of the previous slide (before the transition)
573 | newIndex: element index of the destination slide (after the transition)
574 | ```
575 |
576 | **onSlideNext**
577 |
578 | Executes immediately before each "Next" slide transition. Function argument is the target (next) slide element.
579 | ```
580 | default: function(){}
581 | options: function($slideElement, oldIndex, newIndex){ // your code here }
582 | arguments:
583 | $slideElement: jQuery element of the destination element
584 | oldIndex: element index of the previous slide (before the transition)
585 | newIndex: element index of the destination slide (after the transition)
586 | ```
587 |
588 | **onSlidePrev**
589 |
590 | Executes immediately before each "Prev" slide transition. Function argument is the target (prev) slide element.
591 | ```
592 | default: function(){}
593 | options: function($slideElement, oldIndex, newIndex){ // your code here }
594 | arguments:
595 | $slideElement: jQuery element of the destination element
596 | oldIndex: element index of the previous slide (before the transition)
597 | newIndex: element index of the destination slide (after the transition)
598 | ```
599 |
600 | **onAutoChange**
601 |
602 | Executes immediately after auto transtion starts or stops.
603 | ```
604 | default: function(){}
605 | options: function(state){ // your code here }
606 | arguments:
607 | state: the new state of "auto": boolean (true / false)
608 | ```
609 |
610 | ### Public methods
611 |
612 | **goToSlide**
613 |
614 | Performs a slide transition to the supplied slide index (zero-based)
615 | ```
616 | example:
617 | slider = $('.bxslider').bxSlider();
618 | slider.goToSlide(3);
619 | ```
620 |
621 | **goToNextSlide**
622 |
623 | Performs a "Next" slide transition
624 | ```
625 | example:
626 | slider = $('.bxslider').bxSlider();
627 | slider.goToNextSlide();
628 | ```
629 |
630 | **goToPrevSlide**
631 |
632 | Performs a "Prev" slide transition
633 | ```
634 | example:
635 | slider = $('.bxslider').bxSlider();
636 | slider.goToPrevSlide();
637 | ```
638 |
639 | **startAuto**
640 | Starts the auto show. Provide an argument `false` to prevent the auto controls from being updated.
641 | ```
642 | example:
643 | slider = $('.bxslider').bxSlider();
644 | slider.startAuto();
645 | ```
646 |
647 | **stopAuto**
648 |
649 | Stops the auto show. Provide an argument `false` to prevent the auto controls from being updated.
650 | ```
651 | example:
652 | slider = $('.bxslider').bxSlider();
653 | slider.stopAuto();
654 | ```
655 |
656 | **getCurrentSlide**
657 |
658 | Returns the current active slide
659 | ```
660 | example:
661 | slider = $('.bxslider').bxSlider();
662 | var current = slider.getCurrentSlide();
663 | ```
664 |
665 | **getSlideCount**
666 |
667 | Returns the total number of slides in the slider
668 | ```
669 | example:
670 | slider = $('.bxslider').bxSlider();
671 | var slideQty = slider.getSlideCount();
672 | ```
673 |
674 | **redrawSlider**
675 |
676 | Redraw the slider. Useful when needing to redraw a hidden slider after it is unhidden.
677 | ```
678 | example:
679 | slider = $('.bxslider').bxSlider();
680 | slider.redrawSlider();
681 | ```
682 |
683 | **reloadSlider**
684 |
685 | Reload the slider. Useful when adding slides on the fly. Accepts an optional settings object.
686 | ```
687 | example:
688 | slider = $('.bxslider').bxSlider();
689 | slider.reloadSlider();
690 | ```
691 |
692 | **destroySlider**
693 |
694 | Destroy the slider. This reverts all slider elements back to their original state (before calling the slider).
695 | ```
696 | example:
697 | slider = $('.bxslider').bxSlider();
698 | slider.destroySlider();
699 | ```
700 |
701 | ### Local Development with Gulp
702 |
703 | **Unfamiliar with npm? Don't have node installed?** [Download and install node.js](http://nodejs.org/download/) before proceeding.
704 |
705 | From the command line:
706 |
707 | 1. Install the CLI: `npm install --global gulp-cli`
708 | 2. Run `npm install` to install local development tools
709 | 3. Run `gulp` which will build the project
710 |
711 | ## Contributing
712 |
713 | Everyone is welcome to help [contribute](CONTRIBUTING.md) and improve this project. There are several ways you can contribute:
714 |
715 | * Reporting issues (please read [issue guidelines](https://github.com/necolas/issue-guidelines))
716 | * Suggesting new features
717 | * Writing or refactoring code
718 | * Fixing [issues](https://github.com/roots/roots/issues)
719 |
720 | ## Changelog
721 |
722 | ### Version 4.2.14
723 | * Fixing flickering (on -webkit) when used background-image to instead of
724 | * FIX calling API method stopAuto()
725 | * InvalidPointerId on Android 6
726 | * Use jQuery.fn.on instead of jQuery.fn.bind #1126
727 | * InvalidPointerId on Android 6
728 |
729 | ### Version 4.2.13
730 | * Fix error pagerqty
731 | * Fix the problem #48 in the version 4.2.5 when using YUI Compressor
732 | * Fix division by 0
733 | * Ensure that slider.working is set to false at the end of goToSlide(), regardless of what happened with position.
734 | * Add Callback for when Auto changes...
735 | * Fix for Firefox59 and PointerEvent standard compatibility
736 | * Fix for middle mouse click
737 | * Fix typo
738 | * Format the license in package.json to match the SPDX standard
739 | * Code formatting
740 |
741 | ### Version 4.2.12
742 | * Fixes auto control theme
743 |
744 | ### Version 4.2.11
745 | * Removes auto-centering for sliders with no pager or controls
746 |
747 | ### Version 4.2.10
748 | * Bumps npm and bower versions
749 |
750 | ### Version 4.2.9
751 | * Removes node engine version requirement
752 |
753 | ### Version 4.2.8
754 | * Removes auto-centering from the theme file (`jquery.bxslider.css`)
755 |
756 | ### Version 4.2.7
757 | * Allows new version to be published to NPM
758 |
759 | ### Version 4.2.6
760 | * Fix: jQuery 3 support
761 | * Adds Gulp and removes Grunt (for easier local development)
762 |
763 | ### Version 4.2.5
764 | * Fix: Vertical carousel minSlides not working #840
765 | * Fix: slider breaks with css animations if settings.speed set to 0 #838
766 | * Fix: Slider runs into undefined state when reloadSlider is called before initialization was finished #833
767 |
768 | ### Version 4.2.4
769 |
770 | NOTICE: We have switched to a Grunt based build process in order to leverage [Assemble](http://assemble.io) for local documentation building. Please review the above notes about Grunt for the commands available.
771 |
772 | * Fix: Fixed transition from first to last slide during infinite loop #778
773 | * Fix: Reload on multiple sliders doesn't work? #755
774 | * Fix: bxSlider with text only #746
775 | * Fix: bower missing main and ignore entries #738
776 | * Fix: Tickermode transitionend event bubbling #737
777 | * Fix: Initializing before destroyed breaks slider #748
778 | * Enhancement: Added shrinkItems carousel setting #772
779 | * Enhancement: Maintain auto display of slides after a manual selection #594
780 | * Enhancement: Slider getter through jquery object #739
781 | * Enhancement: Add aria attributes #751
782 | * Enhancement: Slider element in every callback and a new method getSliderElement (#780)
783 | * Enhancement: Local Documentiation and examples. I have added buildable documentation to the repo. This will expand over time and allow for community corrections as needed. Please see above Grunt notes on how to build.
784 |
785 |
786 | ### Version 4.2.3
787 | * Minor bug fix
788 |
789 | ### Version 4.2.2
790 | * Fix: Remove unused plugin variable (#733)
791 | * Fix: `updateAfterSlideTransition` not being called (#704)
792 | * Fix: Slider stops auto advancing (#702)
793 | * Fix: Refresh page, slider show the last item at the first in mode: 'horizontal' (#694)
794 | * Fix: horizintal ticker stutters on loop (#669)
795 | * Fix: Wrong bx-wrapper bottom margin with controls=true and pager=false (#647)
796 | * Fix: add css tickerHover. (#629)
797 | * Fix: Slider refusing to scale down, only up (#611)
798 | * Fix: bxSlider freezes on touch devices (#540)
799 | * Fix: Multiple fixes and improvements for Windows Mobile Devices (#596)
800 | * Fix: Accessing bxslider's slider object inside its “onSliderLoad” callback returns undefined (#475)
801 | * Fix: infiniteLoop glitch when scrolling from first to last slide (#429)
802 | * Enhancement: Cancel transitions on callbacks by returning false. (#411)
803 | * Enhancement: Added Keyboard arrow left and right support (#239)
804 |
805 | ### Version 4.2.1
806 | * Fix: Merge Conflict in dist
807 | * Fix: modified bower.json
808 |
809 | ### Version 4.2.0
810 | * Fix: Reverse #714, fixes #722.
811 | * Fix: Repo Tag #729
812 | * Fix: #720 pagerCustom issues
813 |
814 | 4.2.0 Introduces a streamlined build process using [gulp](www.gulpjs.com). Along with this new build process the projects folder structure has been changed. You will find a `dist` folder with all assets ready to use, including both minified and unminified versions of the javascript. These assets should be ready to go. In `src` you will find the uncompiled assets, including a new less version of the css for bxslider. This is an important step for bxslider. It will help speed development up and keep work clean. It also paves the way for a big revamp we have planned in the future.
815 |
816 | **Unfamiliar with npm? Don't have node installed?** [Download and install node.js](http://nodejs.org/download/) before proceeding.
817 |
818 | From the command line:
819 |
820 | 1. Install [gulp](http://gulpjs.com) globally with `npm install -g gulp`
821 | 2. Navigate to the project directory, then run `npm install`
822 |
823 | You now have all the necessary dependencies to run the build process.
824 |
825 | ### Available gulp commands
826 |
827 | * `gulp` — Compile and optimize all files to `dist`
828 | * `gulp styles` — Compile css assets only to `dist`
829 | * `gulp scripts` — Compile js assets only to `dist`
830 | * `gulp images` - Run lossless compression on all the images and copy to `dist`
831 | * `gulp jshint` — Checks JS and JSON code for errors based on our .jshintrc settings
832 |
833 |
834 | ### Version 4.1.3
835 | * Fix: responsive issue for horizontal mode for issue #611, #714
836 | * Fix: extra space on the left when using fade mode. #715
837 | * Fix: wrongly removing custom pager in destroySlider #610
838 | * Fix: bug with reloading slider with custom pager #545
839 | * Fix: Issue with infinite scroll sometimes returning to 0 #481
840 | * Fix: When "infiniteLoop" is used, true is not passed to a clone method. #346
841 | * Fix: "pagerCustom" won't work when using reloadSlider #171
842 | * Fix: Remove vendor prefix for translateZ(0) #565
843 | * Fix: give styles on focus for accessibility #228
844 | * Fix: Minified Version out of sync.
845 | * Fix: Remove -5px left #517
846 | * Enhancement: Invert order call of appendControls() and appendPager() #226
847 | * Enhancement: Various Indentation and typos in docs fixed. #551, #578
848 | * Enhancement: Update jsDelivr with update.json for autoupdate of CDN
849 | * Enhancement: Tag Repo so it can be included in CDNJS
850 | * Created development branch to work from. Eventually will restructure entire repo to follow best practice setup.
851 |
852 |
853 | ### Version 4.1.2
854 | * Added `bower.json` configuration file. Manage bxSlider as a dependency using [bower](http://bower.io/).
855 |
856 | ### Version 4.1.1
857 | * Removed imagesLoaded library and added iframe preloading support
858 | * Added responsive option - setting to false will prevent $(window).resize binding
859 |
860 | ### Version 4.1
861 | * Carousel mode (minSlides / maxSlides) was re-written to be more intuitive.
862 | * SlideWidth now acts as it should (slides respect the width value).
863 | * SlideWidth now properly parsed: accepts string ("600px") or integer (600).
864 | * Slider now only needs to load visible slides (by default) in order to initialize which results in much faster loading. A "preloadImages" setting allows for configuration.
865 |
866 |
867 | Long live Zep.
868 |
--------------------------------------------------------------------------------
/dist/images/bx_loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevenwanderski/bxslider-4/ed3ac54d1d3c1ae823689f614235955f5ae54fe4/dist/images/bx_loader.gif
--------------------------------------------------------------------------------
/dist/images/controls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stevenwanderski/bxslider-4/ed3ac54d1d3c1ae823689f614235955f5ae54fe4/dist/images/controls.png
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
');
709 | // add the controls to the DOM
710 | slider.controls.autoEl = $('');
711 | // on click actions to the controls
712 | slider.controls.autoEl.on('click', '.bx-start', clickStartBind);
713 | slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);
714 | // if autoControlsCombine, insert only the "start" control
715 | if (slider.settings.autoControlsCombine) {
716 | slider.controls.autoEl.append(slider.controls.start);
717 | // if autoControlsCombine is false, insert both controls
718 | } else {
719 | slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
720 | }
721 | // if auto controls selector was supplied, populate it with the controls
722 | if (slider.settings.autoControlsSelector) {
723 | $(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
724 | // if auto controls selector was not supplied, add it after the wrapper
725 | } else {
726 | slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
727 | }
728 | // update the auto controls
729 | updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
730 | };
731 |
732 | /**
733 | * Appends image captions to the DOM
734 | */
735 | var appendCaptions = function() {
736 | // cycle through each child
737 | slider.children.each(function(index) {
738 | // get the image title attribute
739 | var title = $(this).find('img:first').attr('title');
740 | // append the caption
741 | if (title !== undefined && ('' + title).length) {
742 | $(this).append('
' + title + '
');
743 | }
744 | });
745 | };
746 |
747 | /**
748 | * Click next binding
749 | *
750 | * @param e (event)
751 | * - DOM event object
752 | */
753 | var clickNextBind = function(e) {
754 | e.preventDefault();
755 | if (slider.controls.el.hasClass('disabled')) { return; }
756 | // if auto show is running, stop it
757 | if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); }
758 | el.goToNextSlide();
759 | };
760 |
761 | /**
762 | * Click prev binding
763 | *
764 | * @param e (event)
765 | * - DOM event object
766 | */
767 | var clickPrevBind = function(e) {
768 | e.preventDefault();
769 | if (slider.controls.el.hasClass('disabled')) { return; }
770 | // if auto show is running, stop it
771 | if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); }
772 | el.goToPrevSlide();
773 | };
774 |
775 | /**
776 | * Click start binding
777 | *
778 | * @param e (event)
779 | * - DOM event object
780 | */
781 | var clickStartBind = function(e) {
782 | el.startAuto();
783 | e.preventDefault();
784 | };
785 |
786 | /**
787 | * Click stop binding
788 | *
789 | * @param e (event)
790 | * - DOM event object
791 | */
792 | var clickStopBind = function(e) {
793 | el.stopAuto();
794 | e.preventDefault();
795 | };
796 |
797 | /**
798 | * Click pager binding
799 | *
800 | * @param e (event)
801 | * - DOM event object
802 | */
803 | var clickPagerBind = function(e) {
804 | var pagerLink, pagerIndex;
805 | e.preventDefault();
806 | if (slider.controls.el.hasClass('disabled')) {
807 | return;
808 | }
809 | // if auto show is running, stop it
810 | if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); }
811 | pagerLink = $(e.currentTarget);
812 | if (pagerLink.attr('data-slide-index') !== undefined) {
813 | pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
814 | // if clicked pager link is not active, continue with the goToSlide call
815 | if (pagerIndex !== slider.active.index) { el.goToSlide(pagerIndex); }
816 | }
817 | };
818 |
819 | /**
820 | * Updates the pager links with an active class
821 | *
822 | * @param slideIndex (int)
823 | * - index of slide to make active
824 | */
825 | var updatePagerActive = function(slideIndex) {
826 | // if "short" pager type
827 | var len = slider.children.length; // nb of children
828 | if (slider.settings.pagerType === 'short') {
829 | if (slider.settings.maxSlides > 1) {
830 | len = Math.ceil(slider.children.length / slider.settings.maxSlides);
831 | }
832 | slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + len);
833 | return;
834 | }
835 | // remove all pager active classes
836 | slider.pagerEl.find('a').removeClass('active');
837 | // apply the active class for all pagers
838 | slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); });
839 | };
840 |
841 | /**
842 | * Performs needed actions after a slide transition
843 | */
844 | var updateAfterSlideTransition = function() {
845 | // if infinite loop is true
846 | if (slider.settings.infiniteLoop) {
847 | var position = '';
848 | // first slide
849 | if (slider.active.index === 0) {
850 | // set the new position
851 | position = slider.children.eq(0).position();
852 | // carousel, last slide
853 | } else if (slider.active.index === getPagerQty() - 1 && slider.carousel) {
854 | position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
855 | // last slide
856 | } else if (slider.active.index === slider.children.length - 1) {
857 | position = slider.children.eq(slider.children.length - 1).position();
858 | }
859 | if (position) {
860 | if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); }
861 | else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); }
862 | }
863 | }
864 | // declare that the transition is complete
865 | slider.working = false;
866 | // onSlideAfter callback
867 | slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
868 | };
869 |
870 | /**
871 | * Updates the auto controls state (either active, or combined switch)
872 | *
873 | * @param state (string) "start", "stop"
874 | * - the new state of the auto show
875 | */
876 | var updateAutoControls = function(state) {
877 | // if autoControlsCombine is true, replace the current control with the new state
878 | if (slider.settings.autoControlsCombine) {
879 | slider.controls.autoEl.html(slider.controls[state]);
880 | // if autoControlsCombine is false, apply the "active" class to the appropriate control
881 | } else {
882 | slider.controls.autoEl.find('a').removeClass('active');
883 | slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');
884 | }
885 | };
886 |
887 | /**
888 | * Updates the direction controls (checks if either should be hidden)
889 | */
890 | var updateDirectionControls = function() {
891 | if (getPagerQty() === 1) {
892 | slider.controls.prev.addClass('disabled');
893 | slider.controls.next.addClass('disabled');
894 | } else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) {
895 | // if first slide
896 | if (slider.active.index === 0) {
897 | slider.controls.prev.addClass('disabled');
898 | slider.controls.next.removeClass('disabled');
899 | // if last slide
900 | } else if (slider.active.index === getPagerQty() - 1) {
901 | slider.controls.next.addClass('disabled');
902 | slider.controls.prev.removeClass('disabled');
903 | // if any slide in the middle
904 | } else {
905 | slider.controls.prev.removeClass('disabled');
906 | slider.controls.next.removeClass('disabled');
907 | }
908 | }
909 | };
910 | /* auto start and stop functions */
911 | var windowFocusHandler = function() { el.startAuto(); };
912 | var windowBlurHandler = function() { el.stopAuto(); };
913 | /**
914 | * Initializes the auto process
915 | */
916 | var initAuto = function() {
917 | // if autoDelay was supplied, launch the auto show using a setTimeout() call
918 | if (slider.settings.autoDelay > 0) {
919 | setTimeout(el.startAuto, slider.settings.autoDelay);
920 | // if autoDelay was not supplied, start the auto show normally
921 | } else {
922 | el.startAuto();
923 |
924 | //add focus and blur events to ensure its running if timeout gets paused
925 | $(window).focus(windowFocusHandler).blur(windowBlurHandler);
926 | }
927 | // if autoHover is requested
928 | if (slider.settings.autoHover) {
929 | // on el hover
930 | el.hover(function() {
931 | // if the auto show is currently playing (has an active interval)
932 | if (slider.interval) {
933 | // stop the auto show and pass true argument which will prevent control update
934 | el.stopAuto(true);
935 | // create a new autoPaused value which will be used by the relative "mouseout" event
936 | slider.autoPaused = true;
937 | }
938 | }, function() {
939 | // if the autoPaused value was created be the prior "mouseover" event
940 | if (slider.autoPaused) {
941 | // start the auto show and pass true argument which will prevent control update
942 | el.startAuto(true);
943 | // reset the autoPaused value
944 | slider.autoPaused = null;
945 | }
946 | });
947 | }
948 | };
949 |
950 | /**
951 | * Initializes the ticker process
952 | */
953 | var initTicker = function() {
954 | var startPosition = 0,
955 | position, transform, value, idx, ratio, property, newSpeed, totalDimens;
956 | // if autoDirection is "next", append a clone of the entire slider
957 | if (slider.settings.autoDirection === 'next') {
958 | el.append(slider.children.clone().addClass('bx-clone'));
959 | // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
960 | } else {
961 | el.prepend(slider.children.clone().addClass('bx-clone'));
962 | position = slider.children.first().position();
963 | startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
964 | }
965 | setPositionProperty(startPosition, 'reset', 0);
966 | // do not allow controls in ticker mode
967 | slider.settings.pager = false;
968 | slider.settings.controls = false;
969 | slider.settings.autoControls = false;
970 | // if autoHover is requested
971 | if (slider.settings.tickerHover) {
972 | if (slider.usingCSS) {
973 | idx = slider.settings.mode === 'horizontal' ? 4 : 5;
974 | slider.viewport.hover(function() {
975 | transform = el.css('-' + slider.cssPrefix + '-transform');
976 | value = parseFloat(transform.split(',')[idx]);
977 | setPositionProperty(value, 'reset', 0);
978 | }, function() {
979 | totalDimens = 0;
980 | slider.children.each(function(index) {
981 | totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
982 | });
983 | // calculate the speed ratio (used to determine the new speed to finish the paused animation)
984 | ratio = slider.settings.speed / totalDimens;
985 | // determine which property to use
986 | property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
987 | // calculate the new speed
988 | newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value))));
989 | tickerLoop(newSpeed);
990 | });
991 | } else {
992 | // on el hover
993 | slider.viewport.hover(function() {
994 | el.stop();
995 | }, function() {
996 | // calculate the total width of children (used to calculate the speed ratio)
997 | totalDimens = 0;
998 | slider.children.each(function(index) {
999 | totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1000 | });
1001 | // calculate the speed ratio (used to determine the new speed to finish the paused animation)
1002 | ratio = slider.settings.speed / totalDimens;
1003 | // determine which property to use
1004 | property = slider.settings.mode === 'horizontal' ? 'left' : 'top';
1005 | // calculate the new speed
1006 | newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
1007 | tickerLoop(newSpeed);
1008 | });
1009 | }
1010 | }
1011 | // start the ticker loop
1012 | tickerLoop();
1013 | };
1014 |
1015 | /**
1016 | * Runs a continuous loop, news ticker-style
1017 | */
1018 | var tickerLoop = function(resumeSpeed) {
1019 | var speed = resumeSpeed ? resumeSpeed : slider.settings.speed,
1020 | position = {left: 0, top: 0},
1021 | reset = {left: 0, top: 0},
1022 | animateProperty, resetValue, params;
1023 |
1024 | // if "next" animate left position to last child, then reset left to 0
1025 | if (slider.settings.autoDirection === 'next') {
1026 | position = el.find('.bx-clone').first().position();
1027 | // if "prev" animate left position to 0, then reset left to first non-clone child
1028 | } else {
1029 | reset = slider.children.first().position();
1030 | }
1031 | animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
1032 | resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top;
1033 | params = {resetValue: resetValue};
1034 | setPositionProperty(animateProperty, 'ticker', speed, params);
1035 | };
1036 |
1037 | /**
1038 | * Check if el is on screen
1039 | */
1040 | var isOnScreen = function(el) {
1041 | var win = $(window),
1042 | viewport = {
1043 | top: win.scrollTop(),
1044 | left: win.scrollLeft()
1045 | },
1046 | bounds = el.offset();
1047 |
1048 | viewport.right = viewport.left + win.width();
1049 | viewport.bottom = viewport.top + win.height();
1050 | bounds.right = bounds.left + el.outerWidth();
1051 | bounds.bottom = bounds.top + el.outerHeight();
1052 |
1053 | return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
1054 | };
1055 |
1056 | /**
1057 | * Initializes keyboard events
1058 | */
1059 | var keyPress = function(e) {
1060 | var activeElementTag = document.activeElement.tagName.toLowerCase(),
1061 | tagFilters = 'input|textarea',
1062 | p = new RegExp(activeElementTag,['i']),
1063 | result = p.exec(tagFilters);
1064 |
1065 | if (result == null && isOnScreen(el)) {
1066 | if (e.keyCode === 39) {
1067 | clickNextBind(e);
1068 | return false;
1069 | } else if (e.keyCode === 37) {
1070 | clickPrevBind(e);
1071 | return false;
1072 | }
1073 | }
1074 | };
1075 |
1076 | /**
1077 | * Initializes touch events
1078 | */
1079 | var initTouch = function() {
1080 | // initialize object to contain all touch values
1081 | slider.touch = {
1082 | start: {x: 0, y: 0},
1083 | end: {x: 0, y: 0}
1084 | };
1085 | slider.viewport.on('touchstart MSPointerDown pointerdown', onTouchStart);
1086 |
1087 | //for browsers that have implemented pointer events and fire a click after
1088 | //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not
1089 | slider.viewport.on('click', '.bxslider a', function(e) {
1090 | if (slider.viewport.hasClass('click-disabled')) {
1091 | e.preventDefault();
1092 | slider.viewport.removeClass('click-disabled');
1093 | }
1094 | });
1095 | };
1096 |
1097 | /**
1098 | * Event handler for "touchstart"
1099 | *
1100 | * @param e (event)
1101 | * - DOM event object
1102 | */
1103 | var onTouchStart = function(e) {
1104 | // if the target is a link allow it to click through and
1105 | // follow the URL
1106 | if ($(e.target).is('a')) {
1107 | return;
1108 | }
1109 |
1110 | // watch only for left mouse, touch contact and pen contact
1111 | // touchstart event object doesn`t have button property
1112 | if (e.type !== 'touchstart' && e.button !== 0) {
1113 | return;
1114 | }
1115 | e.preventDefault();
1116 | //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
1117 | slider.controls.el.addClass('disabled');
1118 |
1119 | if (slider.working) {
1120 | slider.controls.el.removeClass('disabled');
1121 | } else {
1122 | // record the original position when touch starts
1123 | slider.touch.originalPos = el.position();
1124 | var orig = e.originalEvent,
1125 | touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig];
1126 | var chromePointerEvents = typeof PointerEvent === 'function';
1127 | if (chromePointerEvents) {
1128 | if (orig.pointerId === undefined) {
1129 | return;
1130 | }
1131 | }
1132 | // record the starting touch x, y coordinates
1133 | slider.touch.start.x = touchPoints[0].pageX;
1134 | slider.touch.start.y = touchPoints[0].pageY;
1135 |
1136 | if (slider.viewport.get(0).setPointerCapture) {
1137 | slider.pointerId = orig.pointerId;
1138 | slider.viewport.get(0).setPointerCapture(slider.pointerId);
1139 | }
1140 | // store original event data for click fixation
1141 | slider.originalClickTarget = orig.originalTarget || orig.target;
1142 | slider.originalClickButton = orig.button;
1143 | slider.originalClickButtons = orig.buttons;
1144 | slider.originalEventType = orig.type;
1145 | // at this moment we don`t know what it is click or swipe
1146 | slider.hasMove = false;
1147 | // on a "touchmove" event to the viewport
1148 | slider.viewport.on('touchmove MSPointerMove pointermove', onTouchMove);
1149 | // on a "touchend" event to the viewport
1150 | slider.viewport.on('touchend MSPointerUp pointerup', onTouchEnd);
1151 | slider.viewport.on('MSPointerCancel pointercancel', onPointerCancel);
1152 | }
1153 | };
1154 |
1155 | /**
1156 | * Cancel Pointer for Windows Phone
1157 | *
1158 | * @param e (event)
1159 | * - DOM event object
1160 | */
1161 | var onPointerCancel = function(e) {
1162 | e.preventDefault();
1163 | /* onPointerCancel handler is needed to deal with situations when a touchend
1164 | doesn't fire after a touchstart (this happens on windows phones only) */
1165 | setPositionProperty(slider.touch.originalPos.left, 'reset', 0);
1166 |
1167 | //remove handlers
1168 | slider.controls.el.removeClass('disabled');
1169 | slider.viewport.off('MSPointerCancel pointercancel', onPointerCancel);
1170 | slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove);
1171 | slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd);
1172 | if (slider.viewport.get(0).releasePointerCapture) {
1173 | slider.viewport.get(0).releasePointerCapture(slider.pointerId);
1174 | }
1175 | };
1176 |
1177 | /**
1178 | * Event handler for "touchmove"
1179 | *
1180 | * @param e (event)
1181 | * - DOM event object
1182 | */
1183 | var onTouchMove = function(e) {
1184 | var orig = e.originalEvent,
1185 | touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1186 | // if scrolling on y axis, do not prevent default
1187 | xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x),
1188 | yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y),
1189 | value = 0,
1190 | change = 0;
1191 | // this is swipe
1192 | slider.hasMove = true;
1193 |
1194 | // x axis swipe
1195 | if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) {
1196 | e.preventDefault();
1197 | // y axis swipe
1198 | } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) {
1199 | e.preventDefault();
1200 | }
1201 | if (e.type !== 'touchmove') {
1202 | e.preventDefault();
1203 | }
1204 |
1205 | if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) {
1206 | // if horizontal, drag along x axis
1207 | if (slider.settings.mode === 'horizontal') {
1208 | change = touchPoints[0].pageX - slider.touch.start.x;
1209 | value = slider.touch.originalPos.left + change;
1210 | // if vertical, drag along y axis
1211 | } else {
1212 | change = touchPoints[0].pageY - slider.touch.start.y;
1213 | value = slider.touch.originalPos.top + change;
1214 | }
1215 | setPositionProperty(value, 'reset', 0);
1216 | }
1217 | };
1218 |
1219 | /**
1220 | * Event handler for "touchend"
1221 | *
1222 | * @param e (event)
1223 | * - DOM event object
1224 | */
1225 | var onTouchEnd = function(e) {
1226 | e.preventDefault();
1227 | slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove);
1228 | //enable slider controls as soon as user stops interacing with slides
1229 | slider.controls.el.removeClass('disabled');
1230 | var orig = e.originalEvent,
1231 | touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig],
1232 | value = 0,
1233 | distance = 0;
1234 | // record end x, y positions
1235 | slider.touch.end.x = touchPoints[0].pageX;
1236 | slider.touch.end.y = touchPoints[0].pageY;
1237 | // if fade mode, check if absolute x distance clears the threshold
1238 | if (slider.settings.mode === 'fade') {
1239 | distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
1240 | if (distance >= slider.settings.swipeThreshold) {
1241 | if (slider.touch.start.x > slider.touch.end.x) {
1242 | el.goToNextSlide();
1243 | } else {
1244 | el.goToPrevSlide();
1245 | }
1246 | el.stopAuto();
1247 | }
1248 | // not fade mode
1249 | } else {
1250 | // calculate distance and el's animate property
1251 | if (slider.settings.mode === 'horizontal') {
1252 | distance = slider.touch.end.x - slider.touch.start.x;
1253 | value = slider.touch.originalPos.left;
1254 | } else {
1255 | distance = slider.touch.end.y - slider.touch.start.y;
1256 | value = slider.touch.originalPos.top;
1257 | }
1258 | // if not infinite loop and first / last slide, do not attempt a slide transition
1259 | if (!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))) {
1260 | setPositionProperty(value, 'reset', 200);
1261 | } else {
1262 | // check if distance clears threshold
1263 | if (Math.abs(distance) >= slider.settings.swipeThreshold) {
1264 | if (distance < 0) {
1265 | el.goToNextSlide();
1266 | } else {
1267 | el.goToPrevSlide();
1268 | }
1269 | el.stopAuto();
1270 | } else {
1271 | // el.animate(property, 200);
1272 | setPositionProperty(value, 'reset', 200);
1273 | }
1274 | }
1275 | }
1276 | slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd);
1277 |
1278 | if (slider.viewport.get(0).releasePointerCapture) {
1279 | slider.viewport.get(0).releasePointerCapture(slider.pointerId);
1280 | }
1281 | // if slider had swipe with left mouse, touch contact and pen contact
1282 | if (slider.hasMove === false && (slider.originalClickButton === 0 || slider.originalEventType === 'touchstart')) {
1283 | // trigger click event (fix for Firefox59 and PointerEvent standard compatibility)
1284 | $(slider.originalClickTarget).trigger({
1285 | type: 'click',
1286 | button: slider.originalClickButton,
1287 | buttons: slider.originalClickButtons
1288 | });
1289 | }
1290 | };
1291 |
1292 | /**
1293 | * Window resize event callback
1294 | */
1295 | var resizeWindow = function(e) {
1296 | // don't do anything if slider isn't initialized.
1297 | if (!slider.initialized) { return; }
1298 | // Delay if slider working.
1299 | if (slider.working) {
1300 | window.setTimeout(resizeWindow, 10);
1301 | } else {
1302 | // get the new window dimens (again, thank you IE)
1303 | var windowWidthNew = $(window).width(),
1304 | windowHeightNew = $(window).height();
1305 | // make sure that it is a true window resize
1306 | // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
1307 | // are resized. Can you just die already?*
1308 | if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) {
1309 | // set the new window dimens
1310 | windowWidth = windowWidthNew;
1311 | windowHeight = windowHeightNew;
1312 | // update all dynamic elements
1313 | el.redrawSlider();
1314 | // Call user resize handler
1315 | slider.settings.onSliderResize.call(el, slider.active.index);
1316 | }
1317 | }
1318 | };
1319 |
1320 | /**
1321 | * Adds an aria-hidden=true attribute to each element
1322 | *
1323 | * @param startVisibleIndex (int)
1324 | * - the first visible element's index
1325 | */
1326 | var applyAriaHiddenAttributes = function(startVisibleIndex) {
1327 | var numberOfSlidesShowing = getNumberSlidesShowing();
1328 | // only apply attributes if the setting is enabled and not in ticker mode
1329 | if (slider.settings.ariaHidden && !slider.settings.ticker) {
1330 | // add aria-hidden=true to all elements
1331 | slider.children.attr('aria-hidden', 'true');
1332 | // get the visible elements and change to aria-hidden=false
1333 | slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false');
1334 | }
1335 | };
1336 |
1337 | /**
1338 | * Returns index according to present page range
1339 | *
1340 | * @param slideOndex (int)
1341 | * - the desired slide index
1342 | */
1343 | var setSlideIndex = function(slideIndex) {
1344 | if (slideIndex < 0) {
1345 | if (slider.settings.infiniteLoop) {
1346 | return getPagerQty() - 1;
1347 | }else {
1348 | //we don't go to undefined slides
1349 | return slider.active.index;
1350 | }
1351 | // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
1352 | } else if (slideIndex >= getPagerQty()) {
1353 | if (slider.settings.infiniteLoop) {
1354 | return 0;
1355 | } else {
1356 | //we don't move to undefined pages
1357 | return slider.active.index;
1358 | }
1359 | // set active index to requested slide
1360 | } else {
1361 | return slideIndex;
1362 | }
1363 | };
1364 |
1365 | /**
1366 | * ===================================================================================
1367 | * = PUBLIC FUNCTIONS
1368 | * ===================================================================================
1369 | */
1370 |
1371 | /**
1372 | * Performs slide transition to the specified slide
1373 | *
1374 | * @param slideIndex (int)
1375 | * - the destination slide's index (zero-based)
1376 | *
1377 | * @param direction (string)
1378 | * - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
1379 | */
1380 | el.goToSlide = function(slideIndex, direction) {
1381 | // onSlideBefore, onSlideNext, onSlidePrev callbacks
1382 | // Allow transition canceling based on returned value
1383 | var performTransition = true,
1384 | moveBy = 0,
1385 | position = {left: 0, top: 0},
1386 | lastChild = null,
1387 | lastShowingIndex, eq, value, requestEl;
1388 | // store the old index
1389 | slider.oldIndex = slider.active.index;
1390 | //set new index
1391 | slider.active.index = setSlideIndex(slideIndex);
1392 |
1393 | // if plugin is currently in motion, ignore request
1394 | if (slider.working || slider.active.index === slider.oldIndex) { return; }
1395 | // declare that plugin is in motion
1396 | slider.working = true;
1397 |
1398 | performTransition = slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1399 |
1400 | // If transitions canceled, reset and return
1401 | if (typeof (performTransition) !== 'undefined' && !performTransition) {
1402 | slider.active.index = slider.oldIndex; // restore old index
1403 | slider.working = false; // is not in motion
1404 | return;
1405 | }
1406 |
1407 | if (direction === 'next') {
1408 | // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1409 | if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1410 | performTransition = false;
1411 | }
1412 | } else if (direction === 'prev') {
1413 | // Prevent canceling in future functions or lack there-of from negating previous commands to cancel
1414 | if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) {
1415 | performTransition = false;
1416 | }
1417 | }
1418 |
1419 | // check if last slide
1420 | slider.active.last = slider.active.index >= getPagerQty() - 1;
1421 | // update the pager with active class
1422 | if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); }
1423 | // // check for direction control update
1424 | if (slider.settings.controls) { updateDirectionControls(); }
1425 | // if slider is set to mode: "fade"
1426 | if (slider.settings.mode === 'fade') {
1427 | // if adaptiveHeight is true and next height is different from current height, animate to the new height
1428 | if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1429 | slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1430 | }
1431 | // fade out the visible child and reset its z-index value
1432 | slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
1433 | // fade in the newly requested slide
1434 | slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function() {
1435 | $(this).css('zIndex', slider.settings.slideZIndex);
1436 | updateAfterSlideTransition();
1437 | });
1438 | // slider mode is not "fade"
1439 | } else {
1440 | // if adaptiveHeight is true and next height is different from current height, animate to the new height
1441 | if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) {
1442 | slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1443 | }
1444 | // if carousel and not infinite loop
1445 | if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) {
1446 | if (slider.settings.mode === 'horizontal') {
1447 | // get the last child position
1448 | lastChild = slider.children.eq(slider.children.length - 1);
1449 | position = lastChild.position();
1450 | // calculate the position of the last slide
1451 | moveBy = slider.viewport.width() - lastChild.outerWidth();
1452 | } else {
1453 | // get last showing index position
1454 | lastShowingIndex = slider.children.length - slider.settings.minSlides;
1455 | position = slider.children.eq(lastShowingIndex).position();
1456 | }
1457 | // horizontal carousel, going previous while on first slide (infiniteLoop mode)
1458 | } else if (slider.carousel && slider.active.last && direction === 'prev') {
1459 | // get the last child position
1460 | eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
1461 | lastChild = el.children('.bx-clone').eq(eq);
1462 | position = lastChild.position();
1463 | // if infinite loop and "Next" is clicked on the last slide
1464 | } else if (direction === 'next' && slider.active.index === 0) {
1465 | // get the last clone position
1466 | position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
1467 | slider.active.last = false;
1468 | // normal non-zero requests
1469 | } else if (slideIndex >= 0) {
1470 | //parseInt is applied to allow floats for slides/page
1471 | requestEl = slideIndex * parseInt(getMoveBy());
1472 | position = slider.children.eq(requestEl).position();
1473 | }
1474 |
1475 | /* If the position doesn't exist
1476 | * (e.g. if you destroy the slider on a next click),
1477 | * it doesn't throw an error.
1478 | */
1479 | if (typeof (position) !== 'undefined') {
1480 | value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top;
1481 | // plugin values to be animated
1482 | setPositionProperty(value, 'slide', slider.settings.speed);
1483 | }
1484 | slider.working = false;
1485 | }
1486 | if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1487 | };
1488 |
1489 | /**
1490 | * Transitions to the next slide in the show
1491 | */
1492 | el.goToNextSlide = function() {
1493 | // if infiniteLoop is false and last page is showing, disregard call
1494 | if (!slider.settings.infiniteLoop && slider.active.last) { return; }
1495 | if (slider.working === true){ return ;}
1496 | var pagerIndex = parseInt(slider.active.index) + 1;
1497 | el.goToSlide(pagerIndex, 'next');
1498 | };
1499 |
1500 | /**
1501 | * Transitions to the prev slide in the show
1502 | */
1503 | el.goToPrevSlide = function() {
1504 | // if infiniteLoop is false and last page is showing, disregard call
1505 | if (!slider.settings.infiniteLoop && slider.active.index === 0) { return; }
1506 | if (slider.working === true){ return ;}
1507 | var pagerIndex = parseInt(slider.active.index) - 1;
1508 | el.goToSlide(pagerIndex, 'prev');
1509 | };
1510 |
1511 | /**
1512 | * Starts the auto show
1513 | *
1514 | * @param preventControlUpdate (boolean)
1515 | * - if true, auto controls state will not be updated
1516 | */
1517 | el.startAuto = function(preventControlUpdate) {
1518 | // if an interval already exists, disregard call
1519 | if (slider.interval) { return; }
1520 | // create an interval
1521 | slider.interval = setInterval(function() {
1522 | if (slider.settings.autoDirection === 'next') {
1523 | el.goToNextSlide();
1524 | } else {
1525 | el.goToPrevSlide();
1526 | }
1527 | }, slider.settings.pause);
1528 | //allback for when the auto rotate status changes
1529 | slider.settings.onAutoChange.call(el, true);
1530 | // if auto controls are displayed and preventControlUpdate is not true
1531 | if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('stop'); }
1532 | };
1533 |
1534 | /**
1535 | * Stops the auto show
1536 | *
1537 | * @param preventControlUpdate (boolean)
1538 | * - if true, auto controls state will not be updated
1539 | */
1540 | el.stopAuto = function(preventControlUpdate) {
1541 | // if slider is auto paused, just clear that state
1542 | if (slider.autoPaused) slider.autoPaused = false;
1543 | // if no interval exists, disregard call
1544 | if (!slider.interval) { return; }
1545 | // clear the interval
1546 | clearInterval(slider.interval);
1547 | slider.interval = null;
1548 | //allback for when the auto rotate status changes
1549 | slider.settings.onAutoChange.call(el, false);
1550 | // if auto controls are displayed and preventControlUpdate is not true
1551 | if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('start'); }
1552 | };
1553 |
1554 | /**
1555 | * Returns current slide index (zero-based)
1556 | */
1557 | el.getCurrentSlide = function() {
1558 | return slider.active.index;
1559 | };
1560 |
1561 | /**
1562 | * Returns current slide element
1563 | */
1564 | el.getCurrentSlideElement = function() {
1565 | return slider.children.eq(slider.active.index);
1566 | };
1567 |
1568 | /**
1569 | * Returns a slide element
1570 | * @param index (int)
1571 | * - The index (zero-based) of the element you want returned.
1572 | */
1573 | el.getSlideElement = function(index) {
1574 | return slider.children.eq(index);
1575 | };
1576 |
1577 | /**
1578 | * Returns number of slides in show
1579 | */
1580 | el.getSlideCount = function() {
1581 | return slider.children.length;
1582 | };
1583 |
1584 | /**
1585 | * Return slider.working variable
1586 | */
1587 | el.isWorking = function() {
1588 | return slider.working;
1589 | };
1590 |
1591 | /**
1592 | * Update all dynamic slider elements
1593 | */
1594 | el.redrawSlider = function() {
1595 | // resize all children in ratio to new screen size
1596 | slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth());
1597 | // adjust the height
1598 | slider.viewport.css('height', getViewportHeight());
1599 | // update the slide position
1600 | if (!slider.settings.ticker) { setSlidePosition(); }
1601 | // if active.last was true before the screen resize, we want
1602 | // to keep it last no matter what screen size we end on
1603 | if (slider.active.last) { slider.active.index = getPagerQty() - 1; }
1604 | // if the active index (page) no longer exists due to the resize, simply set the index as last
1605 | if (slider.active.index >= getPagerQty()) { slider.active.last = true; }
1606 | // if a pager is being displayed and a custom pager is not being used, update it
1607 | if (slider.settings.pager && !slider.settings.pagerCustom) {
1608 | populatePager();
1609 | updatePagerActive(slider.active.index);
1610 | }
1611 | if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
1612 | };
1613 |
1614 | /**
1615 | * Destroy the current instance of the slider (revert everything back to original state)
1616 | */
1617 | el.destroySlider = function() {
1618 | // don't do anything if slider has already been destroyed
1619 | if (!slider.initialized) { return; }
1620 | slider.initialized = false;
1621 | $('.bx-clone', this).remove();
1622 | slider.children.each(function() {
1623 | if ($(this).data('origStyle') !== undefined) {
1624 | $(this).attr('style', $(this).data('origStyle'));
1625 | } else {
1626 | $(this).removeAttr('style');
1627 | }
1628 | });
1629 | if ($(this).data('origStyle') !== undefined) {
1630 | this.attr('style', $(this).data('origStyle'));
1631 | } else {
1632 | $(this).removeAttr('style');
1633 | }
1634 | $(this).unwrap().unwrap();
1635 | if (slider.controls.el) { slider.controls.el.remove(); }
1636 | if (slider.controls.next) { slider.controls.next.remove(); }
1637 | if (slider.controls.prev) { slider.controls.prev.remove(); }
1638 | if (slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom) { slider.pagerEl.remove(); }
1639 | $('.bx-caption', this).remove();
1640 | if (slider.controls.autoEl) { slider.controls.autoEl.remove(); }
1641 | clearInterval(slider.interval);
1642 | if (slider.settings.responsive) { $(window).off('resize', resizeWindow); }
1643 | if (slider.settings.keyboardEnabled) { $(document).off('keydown', keyPress); }
1644 | //remove self reference in data
1645 | $(this).removeData('bxSlider');
1646 | // remove global window handlers
1647 | $(window).off('blur', windowBlurHandler).off('focus', windowFocusHandler);
1648 | };
1649 |
1650 | /**
1651 | * Reload the slider (revert all DOM changes, and re-initialize)
1652 | */
1653 | el.reloadSlider = function(settings) {
1654 | if (settings !== undefined) { options = settings; }
1655 | el.destroySlider();
1656 | init();
1657 | //store reference to self in order to access public functions later
1658 | $(el).data('bxSlider', this);
1659 | };
1660 |
1661 | init();
1662 |
1663 | $(el).data('bxSlider', this);
1664 |
1665 | // returns the current jQuery object
1666 | return this;
1667 | };
1668 |
1669 | })(jQuery);
1670 |
--------------------------------------------------------------------------------
/dist/jquery.bxslider.min.css:
--------------------------------------------------------------------------------
1 | .bx-wrapper{position:relative;margin-bottom:60px;padding:0;-ms-touch-action:pan-y;touch-action:pan-y;-moz-box-shadow:0 0 5px #ccc;-webkit-box-shadow:0 0 5px #ccc;box-shadow:0 0 5px #ccc;border:5px solid #fff;background:#fff}.bx-wrapper img{max-width:100%;display:block}.bxslider{margin:0;padding:0;-webkit-perspective:1000}ul.bxslider{list-style:none}.bx-viewport{-webkit-transform:translateZ(0)}.bx-wrapper .bx-controls-auto,.bx-wrapper .bx-pager{position:absolute;bottom:-30px;width:100%}.bx-wrapper .bx-loading{min-height:50px;background:url(images/bx_loader.gif) center center no-repeat #fff;height:100%;width:100%;position:absolute;top:0;left:0;z-index:2000}.bx-wrapper .bx-pager{text-align:center;font-size:.85em;font-family:Arial;font-weight:700;color:#666;padding-top:20px}.bx-wrapper .bx-pager.bx-default-pager a{background:#666;text-indent:-9999px;display:block;width:10px;height:10px;margin:0 5px;outline:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.bx-wrapper .bx-pager.bx-default-pager a.active,.bx-wrapper .bx-pager.bx-default-pager a:focus,.bx-wrapper .bx-pager.bx-default-pager a:hover{background:#000}.bx-wrapper .bx-controls-auto .bx-controls-auto-item,.bx-wrapper .bx-pager-item{display:inline-block;vertical-align:bottom}.bx-wrapper .bx-pager-item{font-size:0;line-height:0}.bx-wrapper .bx-prev{left:10px;background:url(images/controls.png) 0 -32px no-repeat}.bx-wrapper .bx-prev:focus,.bx-wrapper .bx-prev:hover{background-position:0 0}.bx-wrapper .bx-next{right:10px;background:url(images/controls.png) -43px -32px no-repeat}.bx-wrapper .bx-next:focus,.bx-wrapper .bx-next:hover{background-position:-43px 0}.bx-wrapper .bx-controls-direction a{position:absolute;top:50%;margin-top:-16px;outline:0;width:32px;height:32px;text-indent:-9999px;z-index:9999}.bx-wrapper .bx-controls-direction a.disabled{display:none}.bx-wrapper .bx-controls-auto{text-align:center}.bx-wrapper .bx-controls-auto .bx-start{display:block;text-indent:-9999px;width:10px;height:11px;outline:0;background:url(images/controls.png) -86px -11px no-repeat;margin:0 3px}.bx-wrapper .bx-controls-auto .bx-start.active,.bx-wrapper .bx-controls-auto .bx-start:focus,.bx-wrapper .bx-controls-auto .bx-start:hover{background-position:-86px 0}.bx-wrapper .bx-controls-auto .bx-stop{display:block;text-indent:-9999px;width:9px;height:11px;outline:0;background:url(images/controls.png) -86px -44px no-repeat;margin:0 3px}.bx-wrapper .bx-controls-auto .bx-stop.active,.bx-wrapper .bx-controls-auto .bx-stop:focus,.bx-wrapper .bx-controls-auto .bx-stop:hover{background-position:-86px -33px}.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-pager{text-align:left;width:80%}.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-controls-auto{right:0;width:35px}.bx-wrapper .bx-caption{position:absolute;bottom:0;left:0;background:#666;background:rgba(80,80,80,.75);width:100%}.bx-wrapper .bx-caption span{color:#fff;font-family:Arial;display:block;font-size:.85em;padding:10px}
--------------------------------------------------------------------------------
/dist/jquery.bxslider.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * bxSlider v4.2.17
3 | * Copyright 2013-2017 Steven Wanderski
4 | * Written while drinking Belgian ales and listening to jazz
5 | * Licensed under MIT (http://opensource.org/licenses/MIT)
6 | */
7 | !function(t){var e={mode:"horizontal",slideSelector:"",infiniteLoop:!0,hideControlOnEnd:!1,speed:500,easing:null,slideMargin:0,startSlide:0,randomStart:!1,captions:!1,ticker:!1,tickerHover:!1,adaptiveHeight:!1,adaptiveHeightSpeed:500,video:!1,useCSS:!0,preloadImages:"visible",responsive:!0,slideZIndex:50,wrapperClass:"bx-wrapper",touchEnabled:!0,swipeThreshold:50,oneToOneTouch:!0,preventDefaultSwipeX:!0,preventDefaultSwipeY:!1,ariaLive:!0,ariaHidden:!0,keyboardEnabled:!1,pager:!0,pagerType:"full",pagerShortSeparator:" / ",pagerSelector:null,buildPager:null,pagerCustom:null,controls:!0,nextText:"Next",prevText:"Prev",nextSelector:null,prevSelector:null,autoControls:!1,startText:"Start",stopText:"Stop",autoControlsCombine:!1,autoControlsSelector:null,auto:!1,pause:4e3,autoStart:!0,autoDirection:"next",stopAutoOnClick:!1,autoHover:!1,autoDelay:0,autoSlideForOnePage:!1,minSlides:1,maxSlides:1,moveSlides:0,slideWidth:0,shrinkItems:!1,onSliderLoad:function(){return!0},onSlideBefore:function(){return!0},onSlideAfter:function(){return!0},onSlideNext:function(){return!0},onSlidePrev:function(){return!0},onSliderResize:function(){return!0},onAutoChange:function(){return!0}};t.fn.bxSlider=function(n){if(0===this.length)return this;if(this.length>1)return this.each(function(){t(this).bxSlider(n)}),this;var s={},o=this,r=t(window).width(),a=t(window).height();if(!t(o).data("bxSlider")){var l=function(){t(o).data("bxSlider")||(s.settings=t.extend({},e,n),s.settings.slideWidth=parseInt(s.settings.slideWidth),s.children=o.children(s.settings.slideSelector),s.children.length1||s.settings.maxSlides>1,s.carousel&&(s.settings.preloadImages="all"),s.minThreshold=s.settings.minSlides*s.settings.slideWidth+(s.settings.minSlides-1)*s.settings.slideMargin,s.maxThreshold=s.settings.maxSlides*s.settings.slideWidth+(s.settings.maxSlides-1)*s.settings.slideMargin,s.working=!1,s.controls={},s.interval=null,s.animProp="vertical"===s.settings.mode?"top":"left",s.usingCSS=s.settings.useCSS&&"fade"!==s.settings.mode&&function(){for(var t=document.createElement("div"),e=["WebkitPerspective","MozPerspective","OPerspective","msPerspective"],i=0;i'),s.viewport=o.parent(),s.settings.ariaLive&&!s.settings.ticker&&s.viewport.attr("aria-live","polite"),s.loader=t(''),s.viewport.prepend(s.loader),o.css({width:"horizontal"===s.settings.mode?1e3*s.children.length+215+"%":"auto",position:"relative"}),s.usingCSS&&s.settings.easing?o.css("-"+s.cssPrefix+"-transition-timing-function",s.settings.easing):s.settings.easing||(s.settings.easing="swing"),s.viewport.css({width:"100%",overflow:"hidden",position:"relative"}),s.viewport.parent().css({maxWidth:u()}),s.children.css({float:"horizontal"===s.settings.mode?"left":"none",listStyle:"none",position:"relative"}),s.children.css("width",h()),"horizontal"===s.settings.mode&&s.settings.slideMargin>0&&s.children.css("marginRight",s.settings.slideMargin),"vertical"===s.settings.mode&&s.settings.slideMargin>0&&s.children.css("marginBottom",s.settings.slideMargin),"fade"===s.settings.mode&&(s.children.css({position:"absolute",zIndex:0,display:"none"}),s.children.eq(s.settings.startSlide).css({zIndex:s.settings.slideZIndex,display:"block"})),s.controls.el=t(''),s.settings.captions&&k(),s.active.last=s.settings.startSlide===f()-1,s.settings.video&&o.fitVids(),"none"===s.settings.preloadImages?e=null:("all"===s.settings.preloadImages||s.settings.ticker)&&(e=s.children),s.settings.ticker?s.settings.pager=!1:(s.settings.controls&&C(),s.settings.auto&&s.settings.autoControls&&T(),s.settings.pager&&b(),(s.settings.controls||s.settings.autoControls||s.settings.pager)&&s.viewport.after(s.controls.el)),null===e?g():c(e,g)},c=function(e,i){var n=e.find('img:not([src=""]), iframe').length,s=0;if(0===n)return void i();e.find('img:not([src=""]), iframe').each(function(){t(this).one("load error",function(){++s===n&&i()}).each(function(){(this.complete||""==this.src)&&t(this).trigger("load")})})},g=function(){if(s.settings.infiniteLoop&&"fade"!==s.settings.mode&&!s.settings.ticker){var e="vertical"===s.settings.mode?s.settings.minSlides:s.settings.maxSlides,i=s.children.slice(0,e).clone(!0).addClass("bx-clone"),n=s.children.slice(-e).clone(!0).addClass("bx-clone");s.settings.ariaHidden&&(i.attr("aria-hidden",!0),n.attr("aria-hidden",!0)),o.append(i).prepend(n)}s.loader.remove(),m(),"vertical"===s.settings.mode&&(s.settings.adaptiveHeight=!0),s.viewport.height(p()),o.redrawSlider(),s.settings.onSliderLoad.call(o,s.active.index),s.initialized=!0,s.settings.responsive&&t(window).on("resize",U),s.settings.auto&&s.settings.autoStart&&(f()>1||s.settings.autoSlideForOnePage)&&L(),s.settings.ticker&&O(),s.settings.pager&&z(s.settings.startSlide),s.settings.controls&&q(),s.settings.touchEnabled&&!s.settings.ticker&&X(),s.settings.keyboardEnabled&&!s.settings.ticker&&t(document).keydown(B)},p=function(){var e=0,n=t();if("vertical"===s.settings.mode||s.settings.adaptiveHeight)if(s.carousel){var o=1===s.settings.moveSlides?s.active.index:s.active.index*x();for(n=s.children.eq(o),i=1;i<=s.settings.maxSlides-1;i++)n=o+i>=s.children.length?n.add(s.children.eq(i-1)):n.add(s.children.eq(o+i))}else n=s.children.eq(s.active.index);else n=s.children;return"vertical"===s.settings.mode?(n.each(function(i){e+=t(this).outerHeight()}),s.settings.slideMargin>0&&(e+=s.settings.slideMargin*(s.settings.minSlides-1))):e=Math.max.apply(Math,n.map(function(){return t(this).outerHeight(!1)}).get()),"border-box"===s.viewport.css("box-sizing")?e+=parseFloat(s.viewport.css("padding-top"))+parseFloat(s.viewport.css("padding-bottom"))+parseFloat(s.viewport.css("border-top-width"))+parseFloat(s.viewport.css("border-bottom-width")):"padding-box"===s.viewport.css("box-sizing")&&(e+=parseFloat(s.viewport.css("padding-top"))+parseFloat(s.viewport.css("padding-bottom"))),e},u=function(){var t="100%";return s.settings.slideWidth>0&&(t="horizontal"===s.settings.mode?s.settings.maxSlides*s.settings.slideWidth+(s.settings.maxSlides-1)*s.settings.slideMargin:s.settings.slideWidth),t},h=function(){var t=s.settings.slideWidth,e=s.viewport.width();if(0===s.settings.slideWidth||s.settings.slideWidth>e&&!s.carousel||"vertical"===s.settings.mode)t=e;else if(s.settings.maxSlides>1&&"horizontal"===s.settings.mode){if(e>s.maxThreshold)return t;e0?s.viewport.width()s.maxThreshold?t=s.settings.maxSlides:(e=s.children.first().width()+s.settings.slideMargin,t=Math.floor((s.viewport.width()+s.settings.slideMargin)/e)||1):"vertical"===s.settings.mode&&(t=s.settings.minSlides),t},f=function(){var t=0,e=0,i=0;if(s.settings.moveSlides>0){if(!s.settings.infiniteLoop){for(;e0&&s.settings.moveSlides<=v()?s.settings.moveSlides:v()},m=function(){var t,e,i;s.children.length>s.settings.maxSlides&&s.active.last&&!s.settings.infiniteLoop?"horizontal"===s.settings.mode?(e=s.children.last(),t=e.position(),S(-(t.left-(s.viewport.width()-e.outerWidth())),"reset",0)):"vertical"===s.settings.mode&&(i=s.children.length-s.settings.minSlides,t=s.children.eq(i).position(),S(-t.top,"reset",0)):(t=s.children.eq(s.active.index*x()).position(),s.active.index===f()-1&&(s.active.last=!0),void 0!==t&&("horizontal"===s.settings.mode?S(-t.left,"reset",0):"vertical"===s.settings.mode&&S(-t.top,"reset",0)))},S=function(e,i,n,r){var a,l;s.usingCSS?(l="vertical"===s.settings.mode?"translate3d(0, "+e+"px, 0)":"translate3d("+e+"px, 0, 0)",o.css("-"+s.cssPrefix+"-transition-duration",n/1e3+"s"),"slide"===i?(o.css(s.animProp,l),0!==n?o.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(e){t(e.target).is(o)&&(o.off("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd"),A())}):A()):"reset"===i?o.css(s.animProp,l):"ticker"===i&&(o.css("-"+s.cssPrefix+"-transition-timing-function","linear"),o.css(s.animProp,l),0!==n?o.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(e){t(e.target).is(o)&&(o.off("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd"),S(r.resetValue,"reset",0),F())}):(S(r.resetValue,"reset",0),F()))):(a={},a[s.animProp]=e,"slide"===i?o.animate(a,n,s.settings.easing,function(){A()}):"reset"===i?o.css(s.animProp,e):"ticker"===i&&o.animate(a,n,"linear",function(){S(r.resetValue,"reset",0),F()}))},w=function(){for(var e="",i="",n=f(),o=0;o'+i+"";s.pagerEl.html(e)},b=function(){s.settings.pagerCustom?s.pagerEl=t(s.settings.pagerCustom):(s.pagerEl=t(''),s.settings.pagerSelector?t(s.settings.pagerSelector).html(s.pagerEl):s.controls.el.addClass("bx-has-pager").append(s.pagerEl),w()),s.pagerEl.on("click touchend","a",I)},C=function(){s.controls.next=t(''+s.settings.nextText+""),s.controls.prev=t(''+s.settings.prevText+""),s.controls.next.on("click touchend",P),s.controls.prev.on("click touchend",E),s.settings.nextSelector&&t(s.settings.nextSelector).append(s.controls.next),s.settings.prevSelector&&t(s.settings.prevSelector).append(s.controls.prev),s.settings.nextSelector||s.settings.prevSelector||(s.controls.directionEl=t(''),s.controls.directionEl.append(s.controls.prev).append(s.controls.next),s.controls.el.addClass("bx-has-controls-direction").append(s.controls.directionEl))},T=function(){s.controls.start=t('