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.