PageSourceSearch

https://markus-genesius.com/wp-content/themes/photographer-wp/js/jquery.gridrotator.js

js markus-genesius.com collected 2026-10-08 01:09:58 UTC 21,075 bytes, 790 lines download raw bytes

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.