1/* Edited by Pixelwars - 10.02.2015 */ 2/** 3 * jquery.gridrotator.js v1.1.0 4 * http://www.codrops.com 5 * 6 * Licensed under the MIT license. 7 * http://www.opensource.org/licenses/mit-license.php 8 * 9 * Copyright 2012, Codrops 10 * http://www.codrops.com 11 */ 12;( function( $, window, undefined ) { 13 14 'use strict'; 15 16 /* 17 * debouncedresize: special jQuery event that happens once after a window resize 18 * 19 * latest version and complete README available on Github: 20 * https://github.com/louisremi/jquery-smartresize/blob/master/jquery.debouncedresize.js 21 * 22 * Copyright 2011 @louis_remi 23 * Licensed under the MIT license. 24 */ 25 var $event = $.event, 26 $special, 27 resizeTimeout; 28 29 $special = $event.special.debouncedresize = { 30 setup: function() { 31 $( this ).on( "resize", $special.handler ); 32 }, 33 teardown: function() { 34 $( this ).off( "resize", $special.handler ); 35 }, 36 handler: function( event, execAsap ) { 37 // Save the context 38 var context = this, 39 args = arguments, 40 dispatch = function() { 41 // set correct event type 42 event.type = "debouncedresize"; 43 $event.dispatch.apply( context, args ); 44 }; 45 46 if ( resizeTimeout ) { 47 clearTimeout( resizeTimeout ); 48 } 49 50 execAsap ? 51 dispatch() : 52 resizeTimeout = setTimeout( dispatch, $special.threshold ); 53 }, 54 threshold: 100 55 }; 56 57 // http://www.hardcode.nl/subcategory_1/article_317-array-shuffle-function 58 Array.prototype.shuffle = function() { 59 var i=this.length,p,t; 60 while (i--) { 61 p = Math.floor(Math.random()*i); 62 t = this[i]; 63 this[i]=this[p]; 64 this[p]=t; 65 } 66 return this; 67 }; 68 69 // HTML5 PageVisibility API 70 // http://www.html5rocks.com/en/tutorials/pagevisibility/intro/ 71 // by Joe Marini (@joemarini) 72 function getHiddenProp(){ 73 var prefixes = ['webkit','moz','ms','o']; 74 75 // if 'hidden' is natively supported just return it 76 if ('hidden' in document) return 'hidden'; 77 78 // otherwise loop over all the known prefixes until we find one 79 for (var i = 0; i < prefixes.length; i++){ 80 if ((prefixes[i] + 'Hidden') in document) 81 return prefixes[i] + 'Hidden'; 82 } 83 84 // otherwise it's not supported 85 return null; 86 } 87 function isHidden() { 88 var prop = getHiddenProp(); 89 if (!prop) return false; 90 91 return document[prop]; 92 } 93 94 function isEmpty( obj ) { 95 return Object.keys(obj).length === 0; 96 } 97 98 // global 99 var $window = $( window ), 100 Modernizr = window.Modernizr; 101 102 $.GridRotator = function( options, element ) { 103 104 this.$el = $( element ); 105 if( Modernizr.backgroundsize ) { 106 107 var self = this; 108 this.$el.addClass( 'ri-grid-loading' ); 109 this._init( options ); 110 111 } 112 113 }; 114 115 // the options 116 $.GridRotator.defaults = { 117 // number of rows 118 rows : 4, 119 // number of columns 120 columns : 10, 121 w1500 : { rows : 4, columns : 9 }, 122 w1200 : { rows : 3, columns : 8 }, 123 w1024 : { rows : 3, columns : 8 }, 124 w768 : {rows : 3,columns : 7 }, 125 w480 : {rows : 3,columns : 5 }, 126 w320 : {rows : 2,columns : 4 }, 127 w240 : {rows : 2,columns : 3 }, 128 // step: number of items that are replaced at the same time 129 // random || [some number] 130 // note: for performance issues, the number "can't" be > options.maxStep 131 step : 'random', 132 // change it as you wish.. 133 maxStep : 3, 134 // prevent user to click the items 135 preventClick : true, 136 // animation type 137 // showHide || fadeInOut || 138 // slideLeft || slideRight || slideTop || slideBottom || 139 // rotateBottom || rotateLeft || rotateRight || rotateTop || 140 // scale || 141 // rotate3d || 142 // rotateLeftScale || rotateRightScale || rotateTopScale || rotateBottomScale || 143 // random 144 animType : 'random', 145 // animation speed 146 animSpeed : 800, 147 // animation easings 148 animEasingOut : 'linear', 149 animEasingIn: 'linear', 150 // the item(s) will be replaced every 3 seconds 151 // note: for performance issues, the time "can't" be < 300 ms 152 interval : 3000, 153 // if false the animations will not start 154 // use false if onhover is true for example 155 slideshow : true, 156 // if true the items will switch when hovered 157 onhover : false, 158 // ids of elements that shouldn't change 159 nochange : [] 160 }; 161 162 $.GridRotator.prototype = { 163 164 _init : function( options ) { 165 166 // options 167 this.options = $.extend( true, {}, $.GridRotator.defaults, options ); 168 // cache some elements + variables 169 this._config(); 170 171 }, 172 _config : function() { 173 174 var self = this, 175 transEndEventNames = { 176 'WebkitTransition' : 'webkitTransitionEnd', 177 'MozTransition' : 'transitionend', 178 'OTransition' : 'oTransitionEnd', 179 'msTransition' : 'MSTransitionEnd', 180 'transition' : 'transitionend' 181 }; 182 183 // support CSS transitions and 3d transforms 184 this.supportTransitions = Modernizr.csstransitions; 185 this.supportTransforms3D = Modernizr.csstransforms3d; 186 187 this.transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ] + '.gridrotator'; 188 189 // all animation types for the random option 190 this.animTypes = this.supportTransforms3D ? [ 191 'fadeInOut', 192 'slideLeft', 193 'slideRight', 194 'slideTop', 195 'slideBottom', 196 'rotateLeft', 197 'rotateRight', 198 'rotateTop', 199 'rotateBottom', 200 'scale', 201 'rotate3d', 202 'rotateLeftScale', 203 'rotateRightScale', 204 'rotateTopScale', 205 'rotateBottomScale' ] : 206 [ 'fadeInOut', 'slideLeft', 'slideRight', 'slideTop', 'slideBottom' ]; 207 208 this.animType = this.options.animType; 209 210 if( this.animType !== 'random' && !this.supportTransforms3D && $.inArray( this.animType, this.animTypes ) === -1 && this.animType !== 'showHide' ) { 211 212 // fallback to 'fadeInOut' if user sets a type which is not supported 213 this.animType = 'fadeInOut'; 214 215 } 216 217 this.animTypesTotal = this.animTypes.length; 218 219 // the <ul> where the items are placed 220 this.$list = this.$el.children( 'ul' ); 221 // remove images and add background-image to anchors 222 // preload the images before 223 var loaded = 0,
224 $imgs = this.$list.find( 'img' ), 225 count = $imgs.length; 226 227 $imgs.each( function() { 228 229 var $img = $( this ), src = $img.attr( 'src' ); 230 231 $( '<img/>' ).load( function() { 232 233 ++loaded; 234 $img.parent().css( 'background-image', 'url(' + src + ')' ); 235 236 if( loaded === count ) { 237 238 $imgs.remove(); 239 self.$el.removeClass( 'ri-grid-loading' ); 240 // the items 241 self.$items = self.$list.children( 'li' ); 242 // make a copy of the items 243 self.$itemsCache = self.$items.clone(); 244 // total number of items 245 self.itemsTotal = self.$items.length; 246 // the items that will be out of the grid 247 // actually the item's child (anchor element) 248 self.outItems= []; 249 self._layout( function() { 250 self._initEvents(); 251 } ); 252 // replace [options.step] items after [options.interval] time 253 // the items that go out are randomly chosen, while the ones that get in 254 // follow a "First In First Out" logic 255 self._start(); 256 257 } 258 259 } ).attr( 'src', src ) 260 261 } ); 262 263 }, 264 _layout : function( callback ) { 265 266 var self = this; 267 268 // sets the grid dimentions based on the container's width 269 this._setGridDim(); 270 271 // reset 272 this.$list.empty(); 273 this.$items = this.$itemsCache.clone().appendTo( this.$list ); 274 275 var $outItems = this.$items.filter( ':gt(' + ( this.showTotal - 1 ) + ')' ), 276 $outAItems = $outItems.children( 'a' ); 277 278 this.outItems.length = 0; 279 280 $outAItems.each( function( i ) { 281 self.outItems.push( $( this ) ); 282 } ); 283 284 $outItems.remove(); 285 286 this._setContainerWidth(); 287 288 // pixelwars edit 289 // moved codes to _setContainerWidth : function() { } 290 // pixelwars edit 291 292 if( this.options.preventClick ) { 293 294 this.$items.children().css( 'cursor', 'default' ).on( 'click.gridrotator', false ); 295 296 } 297 298 if( callback ) { 299 callback.call(); 300 } 301 302 }, 303 // set the grid rows and columns 304 _setGridDim : function() { 305 306 // container's width 307 var c_w = this.$el.width(); 308 309 // we will choose the number of rows/columns according to the container's width and the values set in the plugin options 310 switch( true ) { 311 case ( c_w < 240 ) : this.rows = this.options.w240.rows; this.columns = this.options.w240.columns; break; 312 case ( c_w < 320 ) : this.rows = this.options.w320.rows; this.columns = this.options.w320.columns; break; 313 case ( c_w < 480 ) : this.rows = this.options.w480.rows; this.columns = this.options.w480.columns; break; 314 case ( c_w < 768 ) : this.rows = this.options.w768.rows; this.columns = this.options.w768.columns; break; 315 case ( c_w < 1024 ) : this.rows = this.options.w1024.rows; this.columns = this.options.w1024.columns; break; 316 case ( c_w < 1200 ) : this.rows = this.options.w1200.rows; this.columns = this.options.w1200.columns; break; 317 case ( c_w < 1500 ) : this.rows = this.options.w1500.rows; this.columns = this.options.w1500.columns; break; 318 default : this.rows = this.options.rows; this.columns = this.options.columns; break; 319 } 320 321 this.showTotal = this.rows * this.columns; 322 323 }, 324 325 326 // pixelwars edit 327 // set container width 328 _setContainerWidth : function() { 329 330 // container's width 331 var containerWidth = ( document.defaultView ) ? parseInt( document.defaultView.getComputedStyle( this.$el.get( 0 ), null ).width ) : this.$el.width(), 332 // item's width 333 itemWidth = Math.floor( containerWidth / this.columns ), 334 // calculate gap 335 gapWidth = containerWidth - ( this.columns * Math.floor( itemWidth ) ); 336 337 for( var i = 0; i < this.rows; ++i ) { 338 339 for( var j = 0; j < this.columns; ++j ) { 340 341 var idx = this.columns * i + j, 342 $item = this.$items.eq( idx ); 343 344 $item.css( { 345 width : j < Math.floor( gapWidth ) ? itemWidth + 1 : itemWidth, 346 height : itemWidth 347 } ); 348 349 if( $.inArray( idx, this.options.nochange ) !== -1 ) { 350 $item.addClass( 'ri-nochange' ).data( 'nochange', true ); 351 } 352 353 } 354 355 } 356 357 }, 358 // pixelwars edit 359 360 361 // init window resize event 362 _initEvents : function() { 363 364 var self = this; 365 366 $window.on( 'debouncedresize.gridrotator', function() { 367 self._layout(); 368 369 // pixelwars edit 370 setTimeout(function() { self._setContainerWidth(); },10); 371 // pixelwars edit 372 373 } ); 374 375 376 // pixelwars edit 377 $window.on( 'load', function() { 378 setTimeout(function() { self._setContainerWidth(); },10); 379 } ); 380 // pixelwars edit 381 382 383 // use the property name to generate the prefixed event name 384 var visProp = getHiddenProp(); 385 386 // HTML5 PageVisibility API 387 // http://www.html5rocks.com/en/tutorials/pagevisibility/intro/ 388 // by Joe Marini (@joemarini) 389 if (visProp) { 390 391 var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange'; 392 document.addEventListener(evtname, function() { self._visChange(); } ); 393 394 } 395 396 if( !Modernizr.touch && this.options.onhover ) { 397 398 self.$items.on( 'mouseenter.gridrotator', function() { 399 400 var $item = $( this ); 401 if( !$item.data( 'active' ) && !$item.data( 'hovered' ) && !$item.data( 'nochange' ) ) { 402 $item.data( 'hovered', true ); 403 self._replace( $item ); 404 } 405 406 } ).on( 'mouseleave.gridrotator', function() { 407 408 $( this ).data( 'hovered', false ); 409 410 } ); 411 412 } 413 414 }, 415 _visChange : function() { 416 417 isHidden() ? clearTimeout( this.playtimeout ) : this._start(); 418 419 }, 420 // start rotating elements 421 _start : function() { 422 423 if( this.showTotal < this.itemsTotal && this.options.slideshow ) { 424 this._showNext(); 425 } 426 427 }, 428 // get which type of animation 429 _getAnimType : function() { 430 431 return this.animType === 'random' ? this.animTypes[ Math.floor( Math.random() * this.animTypesTotal ) ] : this.animType; 432 433 }, 434 // get css properties for the transition effect 435 _getAnimProperties : function( $out ) { 436 437 var startInProp = {}, startOutProp = {}, endInProp = {}, endOutProp = {},
438 animType = this._getAnimType(), speed, delay = 0; 439 440 switch( animType ) { 441 442 case 'showHide' : 443 444 speed = 0; 445 endOutProp.opacity = 0; 446 break; 447 448 case 'fadeInOut' : 449 450 endOutProp.opacity = 0; 451 break; 452 453 case 'slideLeft' : 454 455 startInProp.left = $out.width(); 456 endInProp.left = 0; 457 endOutProp.left = -$out.width(); 458 break; 459 460 case 'slideRight' : 461 462 startInProp.left = -$out.width(); 463 endInProp.left = 0; 464 endOutProp.left = $out.width(); 465 break; 466 467 case 'slideTop' : 468 469 startInProp.top = $out.height(); 470 endInProp.top = 0; 471 endOutProp.top = -$out.height(); 472 break; 473 474 case 'slideBottom' : 475 476 startInProp.top = -$out.height(); 477 endInProp.top = 0; 478 endOutProp.top = $out.height(); 479 break; 480 481 case 'rotateLeft' : 482 483 speed = this.options.animSpeed / 2; 484 startInProp.transform = 'rotateY(90deg)'; 485 endInProp.transform = 'rotateY(0deg)'; 486 delay = speed; 487 endOutProp.transform = 'rotateY(-90deg)'; 488 break; 489 490 case 'rotateRight' : 491 492 speed = this.options.animSpeed / 2; 493 startInProp.transform = 'rotateY(-90deg)'; 494 endInProp.transform = 'rotateY(0deg)';
495 delay = speed; 496 endOutProp.transform = 'rotateY(90deg)'; 497 break; 498 499 case 'rotateTop' : 500 501 speed = this.options.animSpeed / 2; 502 startInProp.transform= 'rotateX(90deg)'; 503 endInProp.transform = 'rotateX(0deg)'; 504 delay = speed; 505 endOutProp.transform = 'rotateX(-90deg)'; 506 break; 507 508 case 'rotateBottom' : 509 510 speed = this.options.animSpeed / 2; 511 startInProp.transform = 'rotateX(-90deg)'; 512 endInProp.transform = 'rotateX(0deg)'; 513 delay = speed; 514 endOutProp.transform = 'rotateX(90deg)'; 515 break; 516 517 case 'scale' : 518 519 speed = this.options.animSpeed / 2; 520 startInProp.transform = 'scale(0)'; 521 startOutProp.transform = 'scale(1)'; 522 endInProp.transform = 'scale(1)'; 523 delay = speed; 524 endOutProp.transform = 'scale(0)'; 525 break; 526 527 case 'rotateLeftScale' : 528 529 startOutProp.transform = 'scale(1)'; 530 speed = this.options.animSpeed / 2; 531 startInProp.transform = 'scale(0.3) rotateY(90deg)'; 532 endInProp.transform = 'scale(1) rotateY(0deg)';
533 delay = speed; 534 endOutProp.transform = 'scale(0.3) rotateY(-90deg)'; 535 break; 536 537 case 'rotateRightScale' : 538 539 startOutProp.transform = 'scale(1)'; 540 speed = this.options.animSpeed / 2; 541 startInProp.transform = 'scale(0.3) rotateY(-90deg)'; 542 endInProp.transform = 'scale(1) rotateY(0deg)'; 543 delay = speed; 544 endOutProp.transform = 'scale(0.3) rotateY(90deg)'; 545 break; 546 547 case 'rotateTopScale' : 548 549 startOutProp.transform = 'scale(1)'; 550 speed = this.options.animSpeed / 2; 551 startInProp.transform = 'scale(0.3) rotateX(90deg)'; 552 endInProp.transform = 'scale(1) rotateX(0deg)'; 553 delay = speed; 554 endOutProp.transform = 'scale(0.3) rotateX(-90deg)'; 555 break; 556 557 case 'rotateBottomScale' : 558 559 startOutProp.transform = 'scale(1)'; 560 speed = this.options.animSpeed / 2; 561 startInProp.transform = 'scale(0.3) rotateX(-90deg)'; 562 endInProp.transform = 'scale(1) rotateX(0deg)'; 563 delay = speed; 564 endOutProp.transform = 'scale(0.3) rotateX(90deg)'; 565 break; 566 567 case 'rotate3d' : 568 569 speed = this.options.animSpeed / 2; 570 startInProp.transform = 'rotate3d( 1, 1, 0, 90deg )'; 571 endInProp.transform = 'rotate3d( 1, 1, 0, 0deg )';
572 delay = speed; 573 endOutProp.transform = 'rotate3d( 1, 1, 0, -90deg )'; 574 break; 575 576 } 577 578 return { 579 startInProp : startInProp, 580 startOutProp : startOutProp, 581 endInProp : endInProp, 582 endOutProp : endOutProp, 583 delay : delay, 584 animSpeed : speed != undefined ? speed : this.options.animSpeed 585 }; 586 587 }, 588 // show next [option.step] elements 589 _showNext : function( time ) { 590 591 var self = this; 592 593 clearTimeout( this.playtimeout ); 594 595 this.playtimeout = setTimeout( function() { 596 597 var step = self.options.step, max= self.options.maxStep, min = 1; 598 599 if( max > self.showTotal ) { 600 max = self.showTotal; 601 } 602 603 // number of items to swith at this point of time 604 var nmbOut = step === 'random' ? Math.floor( Math.random() * max + min ) : Math.min( Math.abs( step ) , max ) , 605 // array with random indexes. These will be the indexes of the items we will replace 606 randArr = self._getRandom( nmbOut, self.showTotal ); 607 608 for( var i = 0; i < nmbOut; ++i ) { 609 610 // element to go out 611 var $out = self.$items.eq( randArr[ i ] ); 612 613 // if element is active, which means it is currently animating, 614 // then we need to get different positions.. 615 if( $out.data( 'active' ) || $out.data( 'nochange' ) ) { 616 617 // one of the items is active, call again.. 618 self._showNext( 1 ); 619 return false; 620 621 } 622 623 self._replace( $out ); 624 625 } 626 627 // again and again.. 628 self._showNext(); 629 630 }, time || Math.max( Math.abs( this.options.interval ) , 300 ) ); 631 632 }, 633 _replace : function( $out ) { 634 635 $out.data( 'active', true ); 636 637 var self = this, 638 $outA = $out.children( 'a:last' ), 639 newElProp = { 640 width : $outA.width(), 641 height : $outA.height() 642 }; 643 644 // element stays active 645 $out.data( 'active', true ); 646 647 // get the element (anchor) that will go in (first one inserted in this.outItems) 648 var $inA = this.outItems.shift(); 649 650 // save element that went out 651 this.outItems.push( $outA.clone().css( 'transition', 'none' ) ); 652 653 // prepend in element 654 $inA.css( newElProp ).prependTo( $out ); 655 656 var animProp = this._getAnimProperties( $outA ); 657 658 $inA.css( animProp.startInProp ); 659 $outA.css( animProp.startOutProp ); 660 661 this._setTransition( $inA, 'all', animProp.animSpeed, animProp.delay, this.options.animEasingIn ); 662 this._setTransition( $outA, 'all', animProp.animSpeed, 0, this.options.animEasingOut ); 663 664 this._applyTransition( $inA, animProp.endInProp, animProp.animSpeed, function() { 665 666 var $el = $( this ), 667 t = animProp.animSpeed === self.options.animSpeed && isEmpty( animProp.endInProp ) ? animProp.animSpeed : 0; 668 669 setTimeout( function() { 670 671 if( self.supportTransitions ) { 672 $el.off( self.transEndEventName ); 673 } 674 675 $el.next().remove(); 676 $el.parent().data( 'active', false ); 677 678 }, t ); 679 680 }, animProp.animSpeed === 0 || isEmpty( animProp.endInProp ) ); 681 this._applyTransition( $outA, animProp.endOutProp, animProp.animSpeed ); 682 683 }, 684 _getRandom : function( cnt, limit ) { 685 686 var randArray = []; 687 688 for( var i = 0; i < limit; ++i ) { 689 randArray.push( i ) 690 } 691 692 return randArray.shuffle().slice( 0, cnt ); 693 694 }, 695 _setTransition : function( el, prop, speed, delay, easing ) { 696 697 setTimeout( function() { 698 el.css( 'transition', prop + ' ' + speed + 'ms ' + delay + 'ms ' + easing ); 699 }, 25 ); 700 701 }, 702 _applyTransition : function( el, styleCSS, speed, fncomplete, force ) { 703 704 var self = this; 705 setTimeout( function() { 706 $.fn.applyStyle = self.supportTransitions ? $.fn.css : $.fn.animate; 707 708 if( fncomplete && self.supportTransitions ) { 709 710 el.on( self.transEndEventName, fncomplete ); 711 712 if( force ) { 713 fncomplete.call( el ); 714 } 715 716 } 717 718 fncomplete = fncomplete || function() { return false; }; 719 720 el.stop().applyStyle( styleCSS, $.extend( true, [], { duration : speed + 'ms', complete : fncomplete } ) ); 721 }, 25 ); 722 723 } 724 725 }; 726 727 var logError = function( message ) { 728 729 if ( window.console ) { 730 731 window.console.error( message ); 732 733 } 734 735 }; 736 737 $.fn.gridrotator = function( options ) { 738 739 var instance = $.data( this, 'gridrotator' ); 740 741 if ( typeof options === 'string' ) { 742 743 var args = Array.prototype.slice.call( arguments, 1 ); 744 745 this.each(function() { 746 747 if ( !instance ) { 748 749 logError( "cannot call methods on gridrotator prior to initialization; " + 750 "attempted to call method '" + options + "'" ); 751 return; 752 753 } 754 755 if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { 756 757 logError( "no such method '" + options + "' for gridrotator instance" ); 758 return; 759 760 } 761 762 instance[ options ].apply( instance, args ); 763 764 }); 765 766 } 767 else { 768 769 this.each(function() { 770 771 if ( instance ) { 772 773 instance._init(); 774 775 } 776 else { 777 778 instance = $.data( this, 'gridrotator', new $.GridRotator( options, this ) ); 779 780 } 781 782 }); 783 784 } 785 786 return instance; 787 788 }; 789 790} )( 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.