1/*! carousel transition plugin for Cycle2; version: 20130528 */ 2(function($) { 3"use strict"; 4 5$( document ).on('cycle-bootstrap', function( e, opts, API ) { 6 if ( opts.fx !== 'carousel' ) 7 return; 8 9 API.getSlideIndex = function( el ) { 10 var slides = this.opts()._carouselWrap.children(); 11 var i = slides.index( el ); 12 return i % slides.length; 13 }; 14 15 // override default 'next' function 16 API.next = function() { 17 var count = opts.reverse ? -1 : 1; 18 if ( opts.allowWrap === false && ( opts.currSlide + count ) > opts.slideCount - opts.carouselVisible ) 19 return; 20 opts.API.advanceSlide( count ); 21 opts.API.trigger('cycle-next', [ opts ]).log('cycle-next'); 22 }; 23}); 24 25$( document ).on('cycle-paused', function( e, opts ) { 26 if ( opts.fx !== 'carousel' ) 27 return; 28 29 opts._carouselWrap.pause(); 30}); 31 32$( document ).on('cycle-resumed', function( e, opts ) { 33 if ( opts.fx !== 'carousel' ) 34 return; 35 36 opts._carouselWrap.resume(); 37}); 38 39 40$.fn.cycle.transitions.carousel = { 41 // transition API impl 42 preInit: function( opts ) { 43 opts.hideNonActive = false; 44 45 opts.container.on('cycle-destroyed', $.proxy(this.onDestroy, opts.API)); 46 // override default API implementation 47 opts.API.stopTransition = this.stopTransition; 48 49 // issue #10 50 for (var i=0; i < opts.startingSlide; i++) { 51 opts.container.append( opts.slides[0] ); 52 } 53 }, 54 55 // transition API impl 56 postInit: function( opts ) { 57 var i, j, slide, pagerCutoffIndex, wrap; 58 var vert = opts.carouselVertical; 59 if (opts.carouselVisible && opts.carouselVisible > opts.slideCount) 60 opts.carouselVisible = opts.slideCount - 1; 61 var visCount = opts.carouselVisible || opts.slides.length; 62 var slideCSS = { display: vert ? 'block' : 'inline-block', position: 'static' }; 63 64 // required styles 65 opts.container.css({ position: 'relative', overflow: 'hidden' }); 66 opts.slides.css( slideCSS ); 67 68 opts._currSlide = opts.currSlide; 69 70 // wrap slides in a div; this div is what is animated 71 wrap = $('<div class="cycle-carousel-wrap"></div>') 72 .prependTo( opts.container ) 73 .css({ margin: 0, padding: 0, top: 0, left: 0, position: 'absolute' }) 74 .append( opts.slides ); 75 76 opts._carouselWrap = wrap; 77 78 if ( !vert ) 79 wrap.css('white-space', 'nowrap'); 80 81 if ( opts.allowWrap !== false ) { 82 // prepend and append extra slides so we don't see any empty space when we 83 // near the end of the carousel. for fluid containers, add even more clones 84 // so there is plenty to fill the screen 85 // @todo: optimzie this based on slide sizes 86 87 for ( j=0; j < (opts.carouselVisible === undefined ? 2 : 1); j++ ) { 88 for ( i=0; i < opts.slideCount; i++ ) { 89 wrap.append( opts.slides[i].cloneNode(true) ); 90 } 91 i = opts.slideCount; 92 while ( i-- ) { // #160, #209 93 wrap.prepend( opts.slides[i].cloneNode(true) ); 94 } 95 } 96 97 wrap.find('.cycle-slide-active').removeClass('cycle-slide-active'); 98 opts.slides.eq(opts.startingSlide).addClass('cycle-slide-active'); 99 } 100 101 if ( opts.pager && opts.allowWrap === false ) { 102 // hide "extra" pagers 103 pagerCutoffIndex = opts.slideCount - visCount; 104 $( opts.pager ).children().filter( ':gt('+pagerCutoffIndex+')' ).hide(); 105 } 106 107 opts._nextBoundry = opts.slideCount - opts.carouselVisible; 108 109 this.prepareDimensions( opts ); 110 }, 111 112 prepareDimensions: function( opts ) { 113 var dim, offset, pagerCutoffIndex, tmp, j; 114 var vert = opts.carouselVertical; 115 var visCount = opts.carouselVisible || opts.slides.length; 116 117 if ( opts.carouselFluid && opts.carouselVisible ) { 118 if ( ! opts._carouselResizeThrottle ) { 119 // fluid container AND fluid slides; slides need to be resized to fit container 120 this.fluidSlides( opts ); 121 } 122 } 123 else if ( opts.carouselVisible && opts.carouselSlideDimension ) { 124 dim = visCount * opts.carouselSlideDimension; 125 opts.container[ vert ? 'height' : 'width' ]( dim ); 126 } 127 else if ( opts.carouselVisible ) { 128 dim = visCount * $(opts.slides[0])[vert ? 'outerHeight' : 'outerWidth'](true); 129 opts.container[ vert ? 'height' : 'width' ]( dim ); 130 } 131 // else { 132 // // fluid; don't size the container 133 // } 134
135 offset = ( opts.carouselOffset || 0 ); 136 if ( opts.allowWrap !== false ) { 137 if ( opts.carouselSlideDimension ) { 138 offset -= ( (opts.slideCount + opts.currSlide) * opts.carouselSlideDimension ); 139 } 140 else { 141 // calculate offset based on actual slide dimensions 142 tmp = opts._carouselWrap.children(); 143 for (j=0; j < (opts.slideCount + opts.currSlide); j++) { 144 offset -= $(tmp[j])[vert?'outerHeight':'outerWidth'](true); 145 } 146 } 147 } 148 149 opts._carouselWrap.css( vert ? 'top' : 'left', offset ); 150 }, 151 152 fluidSlides: function( opts ) { 153 var timeout; 154 var slide = opts.slides.eq(0); 155 var adjustment = slide.outerWidth() - slide.width(); 156 var prepareDimensions = this.prepareDimensions; 157 158 // throttle resize event 159 $(window).on( 'resize', resizeThrottle); 160 161 opts._carouselResizeThrottle = resizeThrottle; 162 onResize(); 163 164 function resizeThrottle() { 165 clearTimeout( timeout ); 166 timeout = setTimeout( onResize, 20 ); 167 } 168 169 function onResize() { 170 opts._carouselWrap.stop( false, true ); 171 var slideWidth = opts.container.width() / opts.carouselVisible; 172 slideWidth = Math.ceil( slideWidth - adjustment ); 173 opts._carouselWrap.children().width( slideWidth ); 174 if ( opts._sentinel ) 175 opts._sentinel.width( slideWidth ); 176 prepareDimensions( opts ); 177 } 178 }, 179 180 // transition API impl 181 transition: function( opts, curr, next, fwd, callback ) { 182 var moveBy, props = {}; 183 var hops = opts.nextSlide - opts.currSlide; 184 var vert = opts.carouselVertical; 185 var speed = opts.speed; 186 187 // handle all the edge cases for wrapping & non-wrapping 188 if ( opts.allowWrap === false ) { 189 fwd = hops > 0; 190 var currSlide = opts._currSlide; 191 var maxCurr = opts.slideCount - opts.carouselVisible; 192 if ( hops > 0 && opts.nextSlide > maxCurr && currSlide == maxCurr ) { 193 hops = 0; 194 } 195 else if ( hops > 0 && opts.nextSlide > maxCurr ) { 196 hops = opts.nextSlide - currSlide - (opts.nextSlide - maxCurr); 197 } 198 else if ( hops < 0 && opts.currSlide > maxCurr && opts.nextSlide > maxCurr ) { 199 hops = 0; 200 } 201 else if ( hops < 0 && opts.currSlide > maxCurr ) { 202 hops += opts.currSlide - maxCurr; 203 } 204 else 205 currSlide = opts.currSlide; 206 207 moveBy = this.getScroll( opts, vert, currSlide, hops ); 208 opts.API.opts()._currSlide = opts.nextSlide > maxCurr ? maxCurr : opts.nextSlide; 209 } 210 else { 211 if ( fwd && opts.nextSlide === 0 ) { 212 // moving from last slide to first 213 moveBy = this.getDim( opts, opts.currSlide, vert ); 214 callback = this.genCallback( opts, fwd, vert, callback ); 215 } 216 else if ( !fwd && opts.nextSlide == opts.slideCount - 1 ) { 217 // moving from first slide to last 218 moveBy = this.getDim( opts, opts.currSlide, vert ); 219 callback = this.genCallback( opts, fwd, vert, callback ); 220 } 221 else { 222 moveBy = this.getScroll( opts, vert, opts.currSlide, hops ); 223 } 224 } 225 226 var pos = opts._carouselWrap.position(); 227 props[ vert ? 'top' : 'left' ] = pos[ vert ? 'top' : 'left' ] + (fwd ? -moveBy : moveBy ); 228 229 // throttleSpeed means to scroll slides at a constant rate, rather than 230 // a constant speed 231 if ( opts.throttleSpeed ) 232 speed = (moveBy / $(opts.slides[0])[vert ? 'height' : 'width']() ) * opts.speed; 233 234 opts._carouselWrap.animate( props, speed, opts.easing, callback ); 235 }, 236 237 getDim: function( opts, index, vert ) { 238 var slide = $( opts.slides[index] ); 239 return slide[ vert ? 'outerHeight' : 'outerWidth'](true); 240 }, 241 242 getScroll: function( opts, vert, currSlide, hops ) { 243 var i, moveBy = 0; 244 245 if (hops > 0) { 246 for (i=currSlide; i < currSlide+hops; i++) 247 moveBy += this.getDim( opts, i, vert); 248 } 249 else { 250 for (i=currSlide; i > currSlide+hops; i--) 251 moveBy += this.getDim( opts, i, vert); 252 } 253 return moveBy; 254 }, 255 256 genCallback: function( opts, fwd, vert, callback ) { 257 // returns callback fn that resets the left/top wrap position to the "real" slides 258 return function() { 259 var pos = $(opts.slides[opts.nextSlide]).position(); 260 var offset = 0 - pos[vert?'top':'left'] + (opts.carouselOff
260set || 0); 261 opts._carouselWrap.css( opts.carouselVertical ? 'top' : 'left', offset ); 262 callback(); 263 }; 264 }, 265 266 // core API override 267 stopTransition: function() { 268 var opts = this.opts(); 269 opts.slides.stop( false, true ); 270 opts._carouselWrap.stop( false, true ); 271 }, 272 273 // core API supplement 274 onDestroy: function( e ) { 275 var opts = this.opts(); 276 if ( opts._carouselResizeThrottle ) 277 $( window ).off( 'resize', opts._carouselResizeThrottle ); 278 opts.slides.prependTo( opts.container ); 279 opts._carouselWrap.remove(); 280 } 281}; 282 283})(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.