1/** 2 * jquery.windy.js v1.0.0 3 * http://www.codrops.com 4 * 5 * Licensed under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7 * 8 * Copyright 2012, Codrops 9 * http://www.codrops.com 10 */ 11;( function( $, window, undefined ) { 12 13 'use strict'; 14 15 // global 16 var Modernizr = window.Modernizr; 17 18 $.Windy = function( options, element ) { 19 20 this.$el = $( element ); 21 this._init( options ); 22 23 }; 24 25 // the options 26 $.Windy.defaults = { 27 // if we want to specify a selector that triggers the next() function. example: '#wi-nav-next'. 28 nextEl : '', 29 // if we want to specify a selector that triggers the prev() function. 30 prevEl : '', 31 // rotation and translation boundaries for the items transitions 32 boundaries : { 33 rotateX : { min : 40 , max : 90 }, 34 rotateY : { min : -15 , max : 15 }, 35 rotateZ : { min : -10 , max : 10 }, 36 translateX : { min : -200 , max : 200 }, 37 translateY : { min : -400 , max : -200 }, 38 translateZ : { min : 250 , max : 550 } 39 }, 40 endBoundaries: { 41 rotateX : { min : 5 , max : 15 }, 42 rotateY : { min : -2 , max : 2 }, 43 rotateZ : { min : -2 , max : 2 }, 44 translateX : { min : -10 , max : -2 }, 45 translateY : { min : -20 , max : -2 }, 46 translateZ : { min : 5 , max : 15 } 47 }, 48 items: '.wi-item', 49 itemsContainer: '.wi-container', 50 controlNav: false, 51 directionNav: true 52 }; 53 54 $.Windy.prototype = { 55 $controlNavItems: [], 56 _init : function( options ) { 57 58 // options 59 this.options = $.extend( true, {}, $.Windy.defaults, options ); 60 if (this.$el.data('control-nav') !== undefined) this.options.controlNav = Boolean(this.$el.data('control-nav')); 61 if (this.$el.data('direction-nav') !== undefined) this.options.directionNav = Boolean(this.$el.data('direction-nav')); 62 if (this.options.directionNav === false) { 63 this.options.prevEl = ''; 64 this.options.nextEl = ''; 65 } 66 67 // itemsContainer 68 this.$itemsContainer = this.$el.find(this.options.itemsContainer); 69 70 // https://github.com/twitter/bootstrap/issues/2870 71 this.transEndEventNames = { 72 'WebkitTransition' : 'webkitTransitionEnd', 73 'MozTransition' : 'transitionend', 74 'OTransition' : 'oTransitionEnd', 75 'msTransition' : 'MSTransitionEnd', 76 'transition' : 'transitionend' 77 }; 78 this.transEndEventName = this.transEndEventNames[ Modernizr.prefixed( 'transition' ) ]; 79 80 this.$items = this.$itemsContainer.children(this.options.items); 81 82 // custom position setup 83 var _maxHeight = 0; 84 this.$items.each(function(i, ele){ 85 $(ele).css({ 86 float: 'left', 87 display: 'block', 88 visibility: 'hidden', 89 position: 'relative' 90 }); 91 92 if ($(ele).outerHeight() > _maxHeight) _maxHeight = $(ele).outerHeight(); 93 $(ele).css({ 94 float: 'none', 95 display: 'none', 96 visibility: 'visible' 97 }); 98 }); 99 // this.$itemsContainer.height(_maxHeight); 100 // this.$items.css({position: 'absolute'}); 101 // custom position setup end 102 103 this.itemsCount = this.$items.length; 104 105 this.resetTransformStr = 'translateX( 0px ) translateY( 0px ) translateZ( 0px ) rotateX( 0deg ) rotateY( 0deg ) rotateZ( 0deg )'; 106 107 this.supportTransitions = Modernizr.csstransitions; 108 this.support3d = Modernizr.csstransforms3d; 109 110 // show first item 111 this.current = 0; 112 this.$items.eq( this.current ).show(); 113 114 // init control navigation 115 var _self = this; 116 if (this.options.controlNav) { 117 this.$controlNavContainer = $('<ul class="slider-control-nav"></ul>'); 118 _self.$items.each(function(i, item){ 119 var controlItem = $('<li><a href="#"></a></li>'); 120 if (i == _self.current) controlItem.addClass('current'); 121 _self.$controlNavItems.push(controlItem); 122 _self.$controlNavContainer.append(controlItem); 123 }); 124 var $controlNavWrapper = $('<div class="bullets-wrap"></div>'); 125 $controlNavWrapper.append(_self.$controlNavContainer); 126 _self.$el.append($controlNavWrapper); 127 } 128 129 this._initEvents(); 130 131 },
132 _getRandTransform : function(boundaries) { 133 var boundaries = $.extend(true, {}, this.options.boundaries, boundaries); 134 135 return { 136 rx : Math.floor( Math.random() * ( boundaries.rotateX.max - boundaries.rotateX.min + 1 ) + boundaries.rotateX.min ), 137 ry : Math.floor( Math.random() * ( boundaries.rotateY.max - boundaries.rotateY.min + 1 ) + boundaries.rotateY.min ), 138 rz : Math.floor( Math.random() * ( boundaries.rotateZ.max - boundaries.rotateZ.min + 1 ) + boundaries.rotateZ.min ), 139 tx : Math.floor( Math.random() * ( boundaries.translateX.max - boundaries.translateX.min + 1 ) + boundaries.translateX.min ), 140 ty : Math.floor( Math.random() * ( boundaries.translateY.max - boundaries.translateY.min + 1 ) + boundaries.translateY.min ), 141 tz : Math.floor( Math.random() * ( boundaries.translateZ.max - boundaries.translateZ.min + 1 ) + boundaries.translateZ.min ) 142 }; 143 144 }, 145 _initEvents : function() { 146 147 var self = this; 148 149 this.$items.on( this.transEndEventName, function( event ) { 150 151 self._onTransEnd( $( this ) ); 152 153 } ); 154 155 156 if( this.options.nextEl !== '' ) { 157 this.options.nextEl = this.$el.find(this.options.nextEl); 158 $( this.options.nextEl ).on( 'click.windy', function() { 159 160 self.next(); 161 return false; 162 163 } ); 164 165 } 166 167 if( this.options.prevEl !== '' ) { 168 this.options.prevEl = this.$el.find(this.options.prevEl); 169 $( this.options.prevEl ).on( 'click.windy', function() { 170 171 self.prev(); 172 return false; 173 174 } ); 175 176 } 177 178 if ( this.options.controlNav ) { 179 this.$controlNavContainer.children().on('click', function(e){ 180 e.preventDefault(); 181 182 var indexDiff = self.current - $(this).index(); 183 var indexDiffAbs = Math.abs(indexDiff); 184 185 for (var i=0; i<indexDiffAbs; i++) { 186 var itemNumAppend = (indexDiff < 0) ? 1 : -1; 187 setTimeout(function(){ 188 self.navigate(self.current + itemNumAppend); 189 }, i*.4*150); 190 } 191 }); 192 } 193 194 $(window).resize(function(){ 195 // console.log(self.$items.eq(self.current).outerHeight()); 196 // self.$itemsContainer.height(self.$items.eq(self.current).children().children().outerHeight()); 197 }); 198 199 }, 200 _onTransEnd : function( el ) { 201 202 el.removeClass( 'wi-move' ); 203 204 if( el.data( 'dir' ) === 'right' ) { 205 206 var styleStart = { 207 zIndex : 1, 208 opacity : 1, 209 position: 'relative' 210 }; 211 212 if( this.support3d ) { 213 214 styleStart.transform = this.resetTransformStr; 215 216 } 217 else if( this.supportTransitions ) { 218 219 styleStart.left = 0; 220 styleStart.top = 0; 221 222 } 223 224 el.hide().css( styleStart ); 225 226 } else { 227 el.next().hide(); 228 } 229 230 }, 231 // public method: shows item with index idx 232 navigate : function( idx ) { 233 234 var self = this, 235 // current item 236 $current = this.$items.eq( this.current ), 237 // next item to be shown 238 $next = this.$items.eq( idx ), 239 // random transformation configuration 240 randTranform = this._getRandTransform(), 241 // the z-index is higher for the first items so that the ordering is correct if more items are moving at the same time 242 styleEnd = { 243 zIndex : this.itemsCount + 20 - idx, 244 opacity : 0 245 }, 246 styleStart = { 247 opacity : 1 248 }; 249 250 if( this.support3d ) { 251 252 styleStart.transform = self.resetTransformStr; 253 styleEnd.transform = 'translateX(' + randTranform.tx + 'px) translateY(' + randTranform.ty + 'px) translateZ(' + randTranform.tz + 'px) rotateX(' + randTranform.rx + 'deg) rotateY(' + randTranform.ry + 'deg) rotateZ(' + randTranform.rz + 'deg)'; 254 255 } 256 else if( this.supportTransitions ) { 257 258 styleStart.left = 0; 259 styleStart.top = 0; 260 styleEnd.left = randTranform.tx; 261 styleEnd.top = randTranform.ty; 262 263 } 264 265 // if navigating to the right.. 266 if( idx > this.current ) { 267 268 // if last step was to go to the left.. 269 if( this.dir === 'left') { 270 271 // reset all z-indexes and hide items except the current 272 this.$items.not( $current ).css( 'z-index', 1 ).hide(); 273 274 } 275 276 this.dir = 'right'; 277 278 $current.addClass( 'wi-move' ) 279 .data( 'dir', 'right' ) 280 .css( styleEnd ) 281 .css( 'position', 'absolute' ); 282 $next.css( 'position', 'relative' ); 283 284 if( $next.hasClass( 'wi-move' ) ) { 285 286 $next.removeClass( 'wi-move' ); 287 288 } 289 290 // apply styleStart just to make sure.. 291 $next.css( styleStart ).show(); 292 293 if( !this.supportTransitions ) { 294 295 this._onTransEnd( $current ); 296 297 } 298 299 } 300 else if( idx < this.current ) { 301 302 this.dir = 'left'; 303 304 $next.data( 'dir', 'left' ).css( styleEnd ).show().css({ 305 position: 'relative' 306 }); 307 $current.css({ 308 position: 'absolute' 309 }); 310 setTimeout( function() { 311 312 $next.addClass( 'wi-move' ) 313 .data( 'dir', 'left' ) 314 .css( styleStart ); 315 316 if( !self.supportTransitions ) { 317 318 self._onTransEnd( $next ); 319 320 } 321 322 }, 20 ); 323 324 } 325 326 this.current = idx; 327 328 if ( this.options.controlNav ) { 329 this.$controlNavContainer.children('.current').removeClass('current'); 330 this.$controlNavContainer.children().eq(idx).addClass('current'); 331 } 332 333 }, 334 // public method: returns total number of items 335 getItemsCount : function() { 336 337 return this.itemsCount; 338 339 }, 340 // public method: shows next item 341 next : function() { 342 343 if( this.current < this.itemsCount - 1 ) { 344 345 var idx = this.current + 1; 346 this.navigate( idx ); 347 348 } else { 349 var $current = this.$items.eq( this.current ); 350 var tr = {}; 351 var randTranform = this._getRandTransform(this.options.endBoundaries); 352 tr.transform = 'translateX(' + randTranform.tx + 'px) translateY(' + randTranform.ty + 'px) translateZ(' + randTranform.tz + 'px) rotateX(' + randTranform.rx + 'deg) rotateY(' + randTranform.ry + 'deg) rotateZ(' + randTranform.rz + 'deg)'; 353 354 $current.addClass( 'wi-move' ) 355 .css( tr ); 356 setTimeout(function(){ 357 tr.transform = 'translateX(' + 0 + 'px) translateY(' + 0 + 'px) translateZ(' + 0 + 'px) rotateX(' + 0 + 'deg) rotateY(' + 0 + 'deg) rotateZ(' + 0 + 'deg)'; 358 $current.addClass( 'wi-move' ) 359 .css( tr ); 360 }, 200); 361 } 362 363 }, 364 // public method: shows previous item 365 prev : function() { 366 367 if( this.current > 0 ) { 368 369 var idx = this.current - 1; 370 this.navigate( idx ); 371 372 } else { 373 var $current = this.$items.eq( this.current ); 374 var tr = {}; 375 var randTranform = this._getRandTransform(this.options.endBoundaries); 376 tr.transform = 'translateX(' + randTranform.tx + 'px) translateY(' + randTranform.ty + 'px) translateZ(' + randTranform.tz + 'px) rotateX(' + randTranform.rx + 'deg) rotateY(' + randTranform.ry + 'deg) rotateZ(' + randTranform.rz + 'deg)'; 377 378 $current.addClass( 'wi-move' ) 379 .css( tr ); 380 setTimeout(function(){ 381 tr.transform = 'translateX(' + 0 + 'px) translateY(' + 0 + 'px) translateZ(' + 0 + 'px) rotateX(' + 0 + 'deg) rotateY(' + 0 + 'deg) rotateZ(' + 0 + 'deg)'; 382 $current.addClass( 'wi-move' ) 383 .css( tr ); 384 }, 200); 385 } 386 387 } 388 389 }; 390 391 var logError = function( message ) { 392 393 if ( window.console ) { 394 395 window.console.error( message ); 396 397 } 398 399 }; 400 401 $.fn.windy = function( options ) { 402 403 var instance = $.data( this, 'windy' ); 404 405 if ( typeof options === 'string' ) { 406 407 var args = Array.prototype.slice.call( arguments, 1 ); 408 409 this.each(function() { 410 411 if ( !instance ) { 412 413 logError( "cannot call methods on windy prior to initialization; " + 414 "attempted to call method '" + options + "'" ); 415 return; 416 417 } 418 419 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { 420 421 logError( "no such method '" + options + "' for windy instance" ); 422 return; 423 424 } 425 426 instance[ options ].apply( instance, args ); 427 428 }); 429 430 } 431 else { 432 433 this.each(function() { 434 435 if ( instance ) { 436 437 instance._init(); 438 439 } 440 else { 441 442 instance = $.data( this, 'windy', new $.Windy( options, this ) ); 443 444 } 445 446 }); 447 448 } 449 450 return instance; 451 452 }; 453 454} )( jQuery, window );
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.