PageSourceSearch

https://bibnat.ro/wp-content/themes/scientia/js/theme-gallery/theme-gallery.js

js bibnat.ro collected 2026-10-02 06:21:47 UTC 17,833 bytes, 518 lines download raw bytes

1;// GalleryFx - animated gallery items with preview mode
2(function(window) {
3
4	'use strict';
5
6	if ( ! window.Modernizr) {
7		return;
8	}
9
10	var support = { transitions: Modernizr.csstransitions },
11		// transition end event name
12		transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' },
13		transEndEventName  = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
14		onEndTransition    = function( el, callback ) {
15			var onEndCallbackFn = function( e ) {
16				if ( support.transitions ) {
17					if ( e.target != this ) {
18						return;
19					}
20					this.removeEventListener( transEndEventName, onEndCallbackFn );
21				}
22				if ( callback && typeof callback === 'function' ) {
23					callback.call( this ); }
24			};
25			if ( support.transitions ) {
26				el.addEventListener( transEndEventName, onEndCallbackFn );
27			} else {
28				onEndCallbackFn();
29			}
30		};
31
32	// some helper functions
33	function throttle(fn, delay) {
34		var allowSample = true;
35		return function(e) {
36			if (allowSample) {
37				allowSample = false;
38				setTimeout( function() { allowSample = true; }, delay );
39				fn( e );
40			}
41		};
42	}
43	function nextSibling(el) {
44		var nextSibling = el.nextSibling;
45		while (nextSibling && nextSibling.nodeType != 1) {
46			nextSibling = nextSibling.nextSibling
47		}
48		return nextSibling;
49	}
50	function extend( a, b ) {
51		for ( var key in b ) {
52			if ( b.hasOwnProperty( key ) ) {
53				a[key] = b[key];
54			}
55		}
56		return a;
57	}
58
59	// GalleryFx obj
60	function GalleryFx(el, options) {
61		this.galleryEl = el;
62		this.options   = extend( {}, this.options );
63		extend( this.options, options );
64
65		this.items = [].slice.call( this.galleryEl.querySelectorAll( '.post_layout_gallery' ) );
66
67		if (jQuery( this.galleryEl ).next( '.gallery_preview' ).length == 0) {
68			jQuery( this.galleryEl ).after(
69				'<div class="gallery_preview' + (this.options.previewClass ? ' ' + this.options.previewClass : '') + '">\
70				<a href="#" class="gallery_preview_close icon-cancel"></a>\
71				<div class="gallery_preview_description"></div>\
72			</div>'
73			);
74		}
75		this.previewEl            = nextSibling( this.galleryEl );
76		this.isExpanded           = false;
77		this.isAnimating          = false;
78		this.closeCtrl            = this.previewEl.querySelector( '.gallery_preview_close' );
79		this.previewDescriptionEl = this.previewEl.querySelector( '.gallery_preview_description' );
80
81		this._init();
82	}
83
84	// options
85	GalleryFx.prototype.options = {
86		pagemargin : 0,						// Additional margins for the preview window
87		imgPosition : { x : 1, y : 1 },		// Preview window size
88											// x and y can have values from 0 to 1 (percentage).
89											// If negative then it means the alignment is left and/or top rather than right and/or bottom
90											// So, as an example, if we want our large image to be positioned vertically on 25% of the screen and centered horizontally the values would be x:1,y:-0.25
91		previewClass : '',					// Extra class for the preview block
92		onInit : function(instance) { return false; },
93		onResize : function(instance) {	return false; },
94		onOpenItem : function(instance, item) { return false; },
95		onCloseItem : function(instance, item) { return false; },
96		onExpand : function() { return false; }
97	}
98
99	GalleryFx.prototype._init = function() {
100		// callback
101		this.options.onInit( this );
102
103		var self = this;
104		// init masonry after all images are loaded
105		//imagesLoaded( this.galleryEl, function() {
106		scientia_when_images_loaded(
107			jQuery( this.galleryEl ), function() {
108				// init/bind events
109				self._initEvents();
110				// create the large image and append it to the DOM
111				self._setOriginal();
112				// create the clone image and append it to the DOM
113				self._setClone();
114			}
115		);
116	};
117
118	GalleryFx.prototype.appendItems = function() {
119		// init/bind events
120		this.items = [].slice.call( this.galleryEl.querySelectorAll( '.post_layout_gallery' ) );
121		this._initEvents();
122	};
123
124	// initialize/bind events
125	GalleryFx.prototype._initEvents = function () {
126		var self       = this,
127			clickEvent = (document.ontouchstart !== null ? 'click' : 'touchstart');
128
129		this.items.forEach(
130			function(item) {
131				if (classie.has( item, 'inited' )) {
132					return;
133				}
134				classie.add( item, 'inited' );
135
136				var touchend = function(e) {
137					e.preventDefault();
138					self._openItem( e, item );
139					item.removeEventListener( 'touchend', touchend );
140				},
141				touchmove    = function(e) {
142					item.removeEventListener( 'touchend', touchend );
143				},
144				manageTouch  = function() {
145					item.addEventListener( 'touchend', touchend );
146					item.addEventListener( 'touchmove', touchmove );
147				};
148
149				item.addEventListener(
150					clickEvent, function(e) {
151						if (clickEvent === 'click') {
152							e.preventDefault();
153							self._openItem( e, item );
154						} else {
155							manageTouch();
156						}
157					}
158				);
159			}
160		);
161
162		// close expanded image
163		this.closeCtrl.addEventListener(
164			'click', function(e) {
165				self._closeItem();
166				e.preventDefault();
167				return false;
168			}
169		);
170
171		window.addEventListener(
172			'resize', throttle(
173				function(e) {
174					// callback
175					self.options.onResize( self );
176				}, 10
177			)
178		);
179	}
180
181	// open a gallery item
182	GalleryFx.prototype._openItem = function(ev, item) {
183		if ( this.isAnimating || this.isExpanded ) {
184			return;
185		}
186		this.isAnimating = true;
187		this.isExpanded  = true;
188
189		// item's image
190		var galleryImg       = item.querySelector( 'img' ),
191			galleryImgOffset = galleryImg.getBoundingClientRect();
192
193		// index of current item
194		this.current = this.items.indexOf( item );
195
196		// set the src of the original image element (large image)
197		this._setOriginal( item.getAttribute( 'data-src' ) );
198
199		// callback
200		this.options.onOpenItem( this, item );
201
202		// set the clone image
203		this._setClone(
204			galleryImg.src, {
205				width : galleryImg.offsetWidth,
206				height : galleryImg.offsetHeight,
207				left : galleryImgOffset.left,
208				top : galleryImgOffset.top
209			}
210		);
211
212		// hide original gallery item
213		classie.add( item, 'gallery_item_current' );
214
215		// calculate the transform value for the clone to animate to the full image view
216		var win             = this._getWinSize(),
217			originalSizeArr = item.getAttribute( 'data-size' ).split( 'x' ),
218			originalSize    = {width: originalSizeArr[0], height: originalSizeArr[1]},
219			dx              = ((this.options.imgPosition.x > 0 ? 1 - Math.abs( this.options.imgPosition.x ) : Math.abs( this.options.imgPosition.x )) * win.width + this.options.imgPosition.x * win.width / 2) - galleryImgOffset.left - 0.5 * galleryImg.offsetWidth,
220			dy              = ((this.options.imgPosition.y > 0 ? 1 - Math.abs( this.options.imgPosition.y ) : Math.abs( this.options.imgPosition.y )) * win.height + this.options.imgPosition.y * win.height / 2) - galleryImgOffset.top - 0.5 * galleryImg.offsetHeight,
221			z               = Math.min( Math.min( win.width * Math.abs( this.options.imgPosition.x ) - this.options.pagemargin, originalSize.width - this.options.pagemargin ) / galleryImg.offsetWidth, Math.min( win.height * Math.abs( this.options.imgPosition.y ) - this.options.pagemargin, originalSize.height - this.options.pagemargin ) / galleryImg.offsetHeight );
222
223		// apply transform to the clone
224		this.cloneImg.style.WebkitTransform = 'translate3d(' + dx + 'px, ' + dy + 'px, 0) scale3d(' + z + ', ' + z + ', 1)';
225		this.cloneImg.style.transform       = 'translate3d(' + dx + 'px, ' + dy + 'px, 0) scale3d(' + z + ', ' + z + ', 1)';
226
227		// add the description if any
228		var descriptionEl = item.querySelector( '.post_details' );
229		if ( descriptionEl ) {
230			this.previewDescriptionEl.innerHTML = descriptionEl.innerHTML;
231		}
232
233		var self = this;
234		setTimeout(
235			function() {
236				// controls the elements inside the expanded view
237				classie.add( self.previewEl, 'gallery_preview_show' );
238				// callback
239				self.options.onExpand();
240			}, 0
241		);
242
243		// after the clone animates..
244		onEndTransition(
245			this.cloneImg, function() {
246				// when the original/large image is loaded..
247				imagesLoaded(
248					self.originalImg, function() {
249						// close button just gets shown after the large image gets loaded
250						classie.add( self.previewEl, 'gallery_preview_image_loaded' );
251						// animate the opacity to 1
252						self.originalImg.style.opacity = 1;
253						// and once that's done..
254						onEndTransition(
255							self.originalImg, function() {
256								// reset cloneImg
257								self.cloneImg.style.opacity         = 0;
258								self.cloneImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
259								self.cloneImg.style.transform       = 'translate3d(0,0,0) scale3d(1,1,1)';
260								// end animating
261								self.isAnimating = false;
262							}
263						);
264					}
265				);
266			}
267		);
268	};
269
270	// create/set the original/large image element
271	GalleryFx.prototype._setOriginal = function(src) {
272		if ( ! src) {
273			this.originalImg                 = document.createElement( 'img' );
274			this.originalImg.className       = 'gallery_preview_image_original';
275			this.originalImg.style.opacity   = 0;
276			this.originalImg.style.maxWidth  = 'calc(' + parseInt( Math.abs( this.options.imgPosition.x ) * 100 ) + 'vw - ' + this.options.pagemargin + 'px)';
277			this.originalImg.style.maxHeight = 'calc(' + parseInt( Math.abs( this.options.imgPosition.y ) * 100 ) + 'vh - ' + this.options.pagemargin + 'px)';
278			// need it because of firefox
279			this.originalImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
280			this.originalImg.style.transform       = 'translate3d(0,0,0) scale3d(1,1,1)';
281			src                                    = '';
282			this.previewEl.appendChild( this.originalImg );
283		}
284
285		this.originalImg.setAttribute( 'src', src );
286	};
287
288	// create/set the clone image element
289	GalleryFx.prototype._setClone = function(src, settings) {
290		if ( ! src) {
291			this.cloneImg               = document.createElement( 'img' );
292			this.cloneImg.className     = 'gallery_preview_image_clone';
293			src                         = '';
294			this.cloneImg.style.opacity = 0;
295			this.previewEl.appendChild( this.cloneImg );
296		} else {
297			this.cloneImg.style.opacity = 1;
298			// set top/left/width/height of gallery item's image to the clone
299			this.cloneImg.style.width  = settings.width + 'px';
300			this.cloneImg.style.height = settings.height + 'px';
301			this.cloneImg.style.top    = settings.top + 'px';
302			this.cloneImg.style.left   = settings.left + 'px';
303		}
304
305		this.cloneImg.setAttribute( 'src', src );
306	};
307
308	// close the original/large image view
309	GalleryFx.prototype._closeItem = function() {
310
311		if ( ! this.isExpanded || this.isAnimating ) {
312			return;
313		}
314		this.isExpanded  = false;
315		this.isAnimating = true;
316
317		// the gallery item's image and its offset
318		var galleryItem      = this.items[this.current],
319			galleryImg       = galleryItem.querySelector( 'img' ),
320			galleryImgOffset = galleryImg.getBoundingClientRect(),
321			self             = this;
322
323		classie.remove( this.previewEl, 'gallery_preview_show' );
324		classie.remove( this.previewEl, 'gallery_preview_image_loaded' );
325
326		// callback
327		this.options.onCloseItem( this, galleryItem );
328
329		// large image will animate back to the position of its gallery's item
330		classie.add( this.originalImg, 'gallery_preview_image_animate' );
331
332		// set the transform to the original/large image
333		var win = this._getWinSize(),
334			dx  = galleryImgOffset.left + galleryImg.offsetWidth / 2 - ((this.options.imgPosition.x > 0 ? 1 - Math.abs( this.options.imgPosition.x ) : Math.abs( this.options.imgPosition.x )) * win.width + this.options.imgPosition.x * win.width / 2),
335			dy  = galleryImgOffset.top + galleryImg.offsetHeight / 2 - ((this.options.imgPosition.y > 0 ? 1 - Math.abs( this.options.imgPosition.y ) : Math.abs( this.options.imgPosition.y )) * win.height + this.options.imgPosition.y * win.height / 2),
336			z   = galleryImg.offsetWidth / this.originalImg.offsetWidth;
337
338		this.originalImg.style.WebkitTransform = 'translate3d(' + dx + 'px, ' + dy + 'px, 0) scale3d(' + z + ', ' + z + ', 1)';
339		this.originalImg.style.transform       = 'translate3d(' + dx + 'px, ' + dy + 'px, 0) scale3d(' + z + ', ' + z + ', 1)';
340
341		// once that's done..
342		onEndTransition(
343			this.originalImg, function() {
344				// clear description
345				self.previewDescriptionEl.innerHTML = '';
346				// show original gallery item
347				classie.remove( galleryItem, 'gallery_item_current' );
348				// fade out the original image
349				setTimeout( function() { self.originalImg.style.opacity = 0;	}, 60 );
350				// and after that
351				onEndTransition(
352					self.originalImg, function() {
353						// reset original/large image
354						classie.remove( self.originalImg, 'animate' );
355						self.originalImg.style.WebkitTransform = 'translate3d(0,0,0) scale3d(1,1,1)';
356						self.originalImg.style.transform       = 'translate3d(0,0,0) scale3d(1,1,1)';
357						// end animating
358						self.isAnimating = false;
359					}
360				);
361			}
362		);
363	};
364
365	// gets the window sizes
366	GalleryFx.prototype._getWinSize = function() {
367		return {
368			width: document.documentElement.clientWidth,
369			height: window.innerHeight
370		};
371	};
372
373	window.GalleryFx = GalleryFx;
374
375	/*
376	// Relayout masonry elements on resize
377	jQuery(window).on('resize', throttle(
378											function(e) {
379												jQuery('.masonry_wrap.inited,.post_format_gallery .gallery.inited' ).masonry();
380											}, 10
381										)
382					);
383	*/
384
385	// Create and init GalleryFx object
386	jQuery( document ).on(
387		'action.init_hidden_elements', function(e, cont) {
388
389			if (cont === undefined) cont = jQuery( 'body' );
390
391			cont.find( '.masonry_wrap,.post_format_gallery .gallery' ).each(
392				function() {
393
394					var portfolio = jQuery( this );
395					if (portfolio.parents( 'div:hidden,article:hidden' ).length > 0) {
396						return;
397					}
398					if ( ! portfolio.hasClass( 'inited' )) {
399						if ( ! portfolio.hasClass( 'gallery_wrap' )) {
400							portfolio.addClass( 'inited' );
401						}
402						var portfolio_dom = portfolio.get( 0 );
403						// init masonry after all images are loaded
404						//imagesLoaded( portfolio_dom, function() {
405						scientia_when_images_loaded(
406							portfolio, function() {
407								// item selector
408								var selector = portfolio.hasClass( 'gallery' ) ? '.gallery-item' : '.masonry_item';
409								// initialize masonry
410								portfolio.masonry(
411									{
412										itemSelector: selector,
413										columnWidth: selector,
414										percentPosition: true
415									}
416								);
417								jQuery( window ).trigger( 'resize' );
418							}
419						);
420					} else {
421						// Relayout after
422						setTimeout( function() { portfolio.masonry(); }, 310 );
423					}
424				}
425			);
426
427			var support = { transitions: Modernizr.csstransitions },
428			// transition end event name
429			transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' },
430			transEndEventName  = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
431			onEndTransition    = function( el, callback ) {
432				var onEndCallbackFn = function( e ) {
433					if ( support.transitions ) {
434						if ( e.target != this ) {
435							return;
436						}
437						this.removeEventListener( transEndEventName, onEndCallbackFn );
438					}
439					if ( callback && typeof callback === 'function' ) {
440						callback.call( this ); }
441				};
442				if ( support.transitions ) {
443					el.addEventListener( transEndEventName, onEndCallbackFn );
444				} else {
445					onEndCallbackFn();
446				}
447			};
448
449			cont.find( '.gallery_wrap:not(.inited)' ).each(
450				function(idx) {
451					if (jQuery( this ).parents( 'div:hidden,article:hidden' ).length > 0) {
452						return;
453					}
454					if ( ! SCIENTIA_STORAGE['GalleryFx']) {
455						SCIENTIA_STORAGE['GalleryFx'] = {};
456					}
457					var id = jQuery( this ).addClass( 'inited' ).attr( 'id' );
458					if (id == undefined) {
459						id = 'gallery_fx_' + Math.random();
460						id = id.replace( '.', '' );
461						jQuery( this ).attr( 'id', id );
462					}
463					SCIENTIA_STORAGE['GalleryFx'][id] = new GalleryFx(
464						this, {
465							previewClass: 'scheme_dark',
466							imgPosition: {
467								x: -0.5,
468								y: 1
469							},
470							onOpenItem: function(instance, item) {
471								instance.items.forEach(
472									function(el) {
473										if (item != el) {
474											var delay                 = Math.floor( Math.random() * 50 );
475											el.style.WebkitTransition = 'opacity .5s ' + delay + 'ms cubic-bezier(.7,0,.3,1), -webkit-transform .5s ' + delay + 'ms cubic-bezier(.7,0,.3,1)';
476											el.style.transition       = 'opacity .5s ' + delay + 'ms cubic-bezier(.7,0,.3,1), transform .5s ' + delay + 'ms cubic-bezier(.7,0,.3,1)';
477											el.style.WebkitTransform  = 'scale3d(0.1,0.1,1)';
478											el.style.transform        = 'scale3d(0.1,0.1,1)';
479											el.style.opacity          = 0;
480										}
481									}
482								);
483							},
484							onCloseItem: function(instance, item) {
485								instance.items.forEach(
486									function(el) {
487										if (item != el) {
488											el.style.WebkitTransition = 'opacity .4s, -webkit-transform .4s';
489											el.style.transition       = 'opacity .4s, transform .4s';
490											el.style.WebkitTransform  = 'scale3d(1,1,1)';
491											el.style.transform        = 'scale3d(1,1,1)';
492											el.style.opacity          = 1;
493
494											onEndTransition(
495												el, function() {
496													el.style.transition      = 'none';
497													el.style.WebkitTransform = 'none';
498												}
499											);
500										}
501									}
502								);
503							},
504							onExpand: function() {
505								var content = jQuery( '.gallery_preview' );
506								if (content.length > 0) {
507									content.find( '.inited' ).removeClass( 'inited' );
508									jQuery( document ).trigger( 'action.init_hidden_elements', [content] );
509								}
510							}
511						}
512					);
513				}
514			);
515		}
516	);
517
518})( 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.