1 2/* ======================================================= 3 * 4 * Media Boxes 5 * Version: 3.7.4 6 * By castlecode 7 * 8 * Contact: http://codecanyon.net/user/castlecode 9 * Created: March 11, 2014 10 * 11 * Copyright (c) 2013, castlecode. All rights reserved. 12 * Available only in http://codecanyon.net/ 13 * 14 * --------------------------------- 15 * CONTENTS 16 * --------------------------------- 17 * 18 * [A] MEDIA BOXES CLASS 19 * [B] DEFAULTS 20 * [C] INIT 21 * [1] SETUP 22 * [2] GRID METHODS 23 * [3] EXTENDING ISOTOPE 24 * [4] FILTERING ISOTOPE 25 * [5] LOAD MORE BOXES 26 * [6] FILTER 27 * [7] SEARCH 28 * [8] SORTING 29 * [9] THUMBNAIL OVERLAY EFFECT 30 * [10] IFRAME ON GRID 31 * [11] INIT POPUP 32 * [12] FANCYBOX 33 * [13] MAGNIFIC POPUP 34 * [14] DEEP LINKING 35 * [15] SOCIAL IN MAGNIFIC POPUP 36 * [D] DESTROY 37 * [E] INSERT 38 * [F] INSERT IN FLOW 39 * [G] REFRESH 40 * [H] RESIZE 41 * [I] MEDIA BOXES PLUGIN 42 * 43 * ======================================================= */ 44 45(function( window, $, undefined ){ 46 47 "use strict"; 48 49/* ====================================================================== * 50 [A] MEDIA BOXES CLASS 51 * ====================================================================== */ 52 53 var MediaBoxes = function(container, options){ 54 this.init(container, options); 55 } 56 57/* ====================================================================== * 58 [B] DEFAULTS 59 * ====================================================================== */ 60 61 MediaBoxes.DEFAULTS = { 62 boxesToLoadStart : 8, 63 boxesToLoad : 4, 64 minBoxesPerFilter : 0, 65 lazyLoad : true, 66 horizontalSpaceBetweenBoxes : 15, 67 verticalSpaceBetweenBoxes : 15, 68 columnWidth : 'auto', 69 columns : 4, 70 resolutions : [ 71 { 72 maxWidth: 960, 73 columnWidth: 'auto', 74 columns: 3, 75 }, 76 { 77 maxWidth: 650, 78 columnWidth: 'auto', 79 columns: 2, 80 horizontalSpaceBetweenBoxes: 10, 81 verticalSpaceBetweenBoxes: 10, 82 }, 83 { 84 maxWidth: 450, 85 columnWidth: 'auto', 86 columns: 1, 87 horizontalSpaceBetweenBoxes: 10, 88 verticalSpaceBetweenBoxes: 10, 89 }, 90 ], 91 multipleFilterLogic : 'AND', 92 filterContainer : '#filter', 93 search : '', // i.e. #search 94 searchTarget : '.media-box-title', 95 sortContainer : '', // i.e. #sort 96 getSortData : { 97 title: '.media-box-title', 98 text: '.media-box-text', 99 }, 100 waitUntilThumbWithRatioLoads : true, // When they have dimensions specified 101 waitForAllThumbsNoMatterWhat : false, // Wait for all the thumbnails to load even if they got dimensions specified 102 noEmptySpaceOnThumbWithRatio : true, // Make thumbnail automatically adapt to the 100% of its container (so no black space) 103 thumbnailOverlay : true, //Show the overlay on mouse over 104 overlayEffect : 'fade', // 'push-up', 'push-down', 'push-up-100%', 'push-down-100%', 'reveal-top', 'reveal-bottom', 'reveal-top-100%', 'reveal-bottom-100%', 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom', 'fade' 105 overlaySpeed : 200, 106 overlayEasing : 'default', 107 showOnlyVisibleBoxesInPopup : false, 108 considerFilteringInPopup : true, 109 deepLinkingOnPopup : true, 110 deepLinkingOnFilter : true, 111 deepLinkingOnSearch : false, 112 LoadingWord : 'Loading...',
113 loadMoreWord : 'Load More', 114 noMoreEntriesWord : 'No More Entries', 115 percentage : false, 116 117 popup : 'magnificpopup', // fancybox, magnificpopup, none 118 magnificpopup : { 119 gallery: false, 120 alignTop: false, 121 preload: [0,2], 122 }, 123 fancybox : { 124 loop : false, // Enable infinite gallery navigation 125 margin : [44, 0], // Space around image, ignored if zoomed-in or viewport smaller than 800px 126 keyboard : true, // Enable keyboard navigation 127 arrows : true, // Should display navigation arrows at the screen edges 128 infobar : false, // Should display infobar (counter and arrows at the top) 129 toolbar : true, // Should display toolbar (buttons at the top) 130 buttons : [ // What buttons should appear in the top right corner. 131 'slideShow', 132 'fullScreen', 133 'thumbs', 134 'close' 135 ], 136 idleTime : 999999999, // Detect "idle" time in seconds 137 protect : false, // Disable right-click and use simple image protection for images 138 animationEffect : 'zoom', // Open/close animation type, it could be: false, 'zoom', 'fade', 'zoom-in-out' 139 animationDuration : 330, // Duration in ms for open/close animation 140 transitionEffect : 'fade', // ransition effect between slides, it could be: false, 'fade', 'slide', 'circular', 'tube', 'zoom-in-out', 'rotate' 141 transitionDuration : 330, // Duration in ms for transition animation 142 slideShow : { autoStart : false, speed : 4000 }, // slideshow settings 143 fullScreen : { autoStart : false, }, // activate or deactivate fullscreen when open 144 thumbs : { autoStart : false, hideOnClose : true }, // Display thumbnails on opening/closing 145 touch : { vertical : true, momentum : true }, // Allow to drag content 146 compensateScrollbar : '.fancybox-compensate-for-scrollbar', 147 }, 148 149 animation_on_thumbnail_overlay_hover : [ 150 // { item : '.fa', animation : 'zoom-out' } // zoom-out, zoom-in, from-top, from-bottom, from-left, from-right 151 ], 152 153 //some sharing hidden options (for magnific popup only) :D 154 /* 155 facebook : true, 156 twitter : true, 157 googleplus : true, 158 pinterest : true, 159 */ 160 161 /* Events */ 162 onLayoutFinish : function(){}, 163 onPopupStart : function(){}, 164 onPopupClose : function(){}, 165 }; 166 167/* ====================================================================== * 168 [C] INIT 169 * ====================================================================== */ 170 171 MediaBoxes.prototype.init = function(container, options){ 172 173 /* ====================================================================== * 174 [1] SETUP 175 * ====================================================================== */ 176 177 /* SETTINGS */ 178 var settings = $.extend(true, {}, MediaBoxes.DEFAULTS, options); 179 180 if(options!=undefined && options.resolutions!=undefined){ // the extend propety do not replace arrays it merges them 181 settings.resolutions = options.resolutions; 182 } 183 184 /* VARS */ 185 var $container = $(container).addClass('media-boxes-container'); 186 var itemSelector = '.media-box'; 187 var boxImageSelector = '.media-box-image'; 188 var itemClass = 'media-box'; /* same as itemSelector but without the '.' */ 189 var itemHiddenClass = 'media-box-hidden'; 190 var animation = Modernizr.csstransitions?'transition':'animate'; /* CSS3 transition or jQuery animate depending on the browser support */ 191 var filters = {}; 192 var loadingsCounter = 0; /* When there's more than one loading at the same time */ 193 var filtersContainers = $(settings.filterContainer); 194 195 if( settings.overlayEasing == 'default' ){ 196 settings.overlayEasing = (animation=='transition')?'_default':'swing'; /* 'default' is for CSS3 and 'swing' for jQuery animate */ 197 } 198 199 /* SET GLOBAL VARS, USED FOR "OUTSIDE" METHODS */ 200 this.container = $container;
201 this.container_clone = $container.clone().removeClass('media-boxes-container'); 202 203 /* Load more button */ 204 var loadMoreButton = $('<div class="media-boxes-load-more media-boxes-load-more-button"></div>').insertAfter($container); 205 206 /* Sort the resolutions from lower to higher */ 207 settings.resolutions.sort(function(a,b){ return a.maxWidth - b.maxWidth; }); 208 209 /* Save the settings in the container */ 210 $container.data('settings', settings); 211 212 /* Fix the margins for the container (for horizontal and vertical space) */ 213 //$container.css('margin-left', -settings.horizontalSpaceBetweenBoxes); 214 215 /* Hide all boxes */ 216 $container.find(itemSelector).removeClass(itemClass).addClass(itemHiddenClass); 217 218 /* default sort selected */ 219 var defSortElem = $(settings.sortContainer).find('*[data-sort-by]').filter('.selected'); 220 var defSort = defSortElem.attr('data-sort-by'); 221 var defAsc = getSortDirection(defSortElem); 222 223 /* Add the sizer for defining the width of isotope */ 224 $container.append('<div class="media-boxes-grid-sizer"></div>'); 225 226 /* Initialize isotope plugin */ 227 $container.isotopeMB({ 228 itemSelector : itemSelector, 229 transitionDuration: '0.5s', 230 hiddenStyle: { opacity: 0, transform: 'scale(0.7)' }, 231 visibleStyle: { opacity: 1, transform: 'scale(1)' }, 232 masonry: { 233 columnWidth: '.media-boxes-grid-sizer' 234 }, 235 getSortData: settings.getSortData, 236 sortBy: defSort, 237 sortAscending: defAsc, 238 }); 239 240 /* If the filter item is hidden AND if its was marked as "selected by default" then fallback to "all" */ 241 filtersContainers.find('[data-filter]').addBack('[data-filter]').each(function(){ 242 var $this = $(this); 243 244 if($this.attr('data-visible-only-if') != undefined){ // if the filter item visibility is based on another item 245 var $visible = $($this.attr('data-visible-only-if')); 246 247 // if it is a checkbox 248 if($visible.is(':checkbox')){ 249 if($visible.is(':checked') == false){ // If the element is unchecked, then uncheck the item 250 $this.prop('checked', false); 251 } 252 } 253 254 // if it is a dropdown or inline 255 if(!$visible.is(':checkbox') && !$visible.is('select')){ 256 if($visible.hasClass('selected') == false){ // if the element is not selected, then unselect the item (and select the "all" item) 257 $this.removeClass('selected'); 258 $this.parents(settings.filterContainer).find('[data-filter="*"]').addClass('selected'); 259 } 260 } 261 262 } 263 }); 264 265 /* default filters */ 266 filtersContainers.each(function(){ 267 /* current items */ 268 var current_filterContainer = $(this); 269 var filterValue = ''; 270 271 /* if its a checkbox */ 272 if(current_filterContainer.is(':checkbox')){ 273 filterValue = current_filterContainer.is(':checked') ? current_filterContainer.attr('data-filter') : '*'; 274 }else{ 275 var current_filter = current_filterContainer.find('*[data-filter]').filter('.selected'); 276 filterValue = current_filter[0] !== undefined ? current_filter.attr('data-filter') : '*'; 277 } 278 279 show_hide_filters(); 280 281 /* Filter isotope */ 282 var filterGroup = current_filterContainer.data("id") != undefined ? current_filterContainer.data("id") : "filter"; // take the id of the filter container if exists, if not just a string 283 filters[ filterGroup ] = filterValue; 284 285 $container.isotopeMB({ filter: combineFilters(filters) }); 286 287 updateFilterClasses(); 288 }); 289 290 /* ====================================================================== * 291 [2] GRID METHODS 292 * ====================================================================== */ 293 294 /* ****** Add div with margins (for horizontal and vertical space) ****** */ 295 function addWrapperForMargins(container){
296 /*var wrapper = $('<div class="media-box-container"></div').css({ 297 'margin-left' : container.data('settings').horizontalSpaceBetweenBoxes, 298 'margin-bottom' : container.data('settings').verticalSpaceBetweenBoxes 299 });*/ 300 301 var wrapper = $('<div class="media-box-container"></div'); 302 container.find(itemSelector+':not([data-wrapper-added])').attr('data-wrapper-added', 'yes').wrapInner( wrapper ); 303 } 304 305 /* ****** FadeIn the thumbnail or show broken thumbnail only for the ones with ratio specified ****** */ 306 function fadeInOrBroken(container, imageObj){ 307 var image = $(imageObj.img); 308 var thumbnailDiv = image.parents('.image-with-dimensions'); 309 310 /* it has already been loaded or broken so skip it */ 311 312 if(image.hasClass('done')){ 313 return; 314 } 315 image.addClass('done'); 316 317 /* if the media-box is fully scaled (100%) then no need for the delay, fadeIn right away */ 318 319 var delay = 200; 320 var media_box = image.parents(itemSelector); 321 var transform_matrix = media_box.css("-webkit-transform") || media_box.css("-moz-transform") || media_box.css("-ms-transform") || media_box.css("-o-transform") || media_box.css("transform"); 322 if(transform_matrix == 'none'){ 323 delay = 0; 324 } 325 326 /* Load or broken */ 327 328 //return; // HEREE 329 330 setTimeout(function(){ 331 332 if( imageObj.isLoaded ){ 333 334 noEmptySpaceOnThumbnails(container); 335 336 thumbnailDiv.find('.media-boxes-loading-animation').fadeOut(700); 337 image.fadeIn(500, function(){ /* This will only be trigger if you hide the image above (if the "waitUntilThumbWithRatioLoads" settings is true) */ 338 thumbnailDiv.removeClass('image-with-dimensions'); 339 }); 340 341 }else{ 342 thumbnailDiv.find('.media-boxes-loading-animation').fadeOut(500); 343 thumbnailDiv.removeClass('image-with-dimensions'); 344 image.hide(); /* hide image since you are going to show a broken logo */ 345 thumbnailDiv.addClass('broken-image-here'); 346 } 347 348 }, delay); 349 } 350 351 /* ****** No empty space on thumbnails (fill height or width) ****** */ 352 function noEmptySpaceOnThumbnails(container){ 353 if(container.data('settings') && container.data('settings').noEmptySpaceOnThumbWithRatio){ 354 355 container.find(itemSelector+', .'+itemHiddenClass).each(function(){ 356 var $this = $(this); 357 var thumbnailDiv = $this.find('div[data-width][data-height]'); 358 var image = thumbnailDiv.find('img'); 359 360 if(thumbnailDiv[0]!= undefined){ 361 362 var thumbnailDiv_ratio = parseFloat(thumbnailDiv.data('width')) / parseFloat(thumbnailDiv.data('height')); 363 var image_ratio = parseFloat(image.width()) / parseFloat(image.height()); 364 365 //thumbnailDiv_ratio = Math.floor(thumbnailDiv_ratio*100)/100; 366 //image_ratio = Math.floor(image_ratio*100)/100; 367 368 thumbnailDiv_ratio = thumbnailDiv_ratio.toFixed(2); 369 image_ratio = image_ratio.toFixed(2); 370 371 if(thumbnailDiv_ratio < image_ratio){ 372 thumbnailDiv.addClass('media-box-fill-height'); 373 //console.log(thumbnailDiv_ratio +" < "+ image_ratio); 374 }else{ 375 thumbnailDiv.removeClass('media-box-fill-height'); 376 } 377 378 } 379 }); 380 381 } 382 } 383 384 /* ****** Load images with dimensions ****** */ 385 function loadImagesWithDimensions(container){ 386 /* FadeIn thumbnails that have dimensions specified if you want to show them after they have been loaded */ 387 container.find('.image-with-dimensions').imagesLoadedMB() 388 .always(function(instance){ 389 /* In case the progress event don't get to show the images (this happens sometimes when you refresh the page) */ 390 for(var index in instance.images){ 391 var imageObj = instance.images[index]; 392 fadeInOrBroken(container, imageObj); 393 } 394 }) 395 .progress(function(instance, imageObj) { 396 fadeInOrBroken(container, imageObj); 397 }); 398 } 399 400 /* ****** Convert the divs with the URL specified to real images ****** */ 401 function convertDivsIntoImages(container, imagesWithDimensions){ 402 container.find(itemSelector).find(boxImageSelector+':not([data-imageconverted])').each(function(){ 403 var boxImage = $(this); 404 var thumbnailDiv = boxImage.find('div[data-thumbnail]').eq(0); /* only one thumb allowed */ 405 var thumbnailSrc = thumbnailDiv.attr('data-thumbnail'); 406 var thumbnailTitle = thumbnailDiv.attr('data-title') != undefined ? thumbnailDiv.attr('data-title') : ""; 407 var thumbnailAlt = thumbnailDiv.attr('data-alt') != undefined ? thumbnailDiv.attr('data-alt') : ""; 408 var gotDimensions = thumbnailDiv.attr('data-width') != undefined && thumbnailDiv.attr('data-height') != undefined; 409 var waitForAll = container.data('settings').waitForAllThumbsNoMatterWhat; 410 411 if(thumbnailSrc == 'none'){ // if there's no URL then don't load an image 412 return true; // same as "continue" 413 } 414 415 if(imagesWithDimensions == false && gotDimensions == true && waitForAll == false){ 416 /* when the plugin wants the images WITHOUT dimensions, only ignore the images WITH dimensions if option "waitForAll..." is false */ 417 return; 418 } 419 420 var imgHTML = $('<img alt="'+thumbnailAlt+'" title="'+thumbnailTitle+'" src="'+thumbnailSrc+'" />'); 421 422 if(imagesWithDimensions == true){ 423 /* If the dimensions are specified in the images then ignore them in the imagesLoaded plugin when you insert new items */ 424 imgHTML.attr('data-dont-wait-for-me', 'yes'); 425 thumbnailDiv.addClass('image-with-dimensions'); 426 thumbnailDiv.prepend('<div class="media-boxes-loading-animation"></div>'); 427 428 if( container.data('settings').waitUntilThumbWithRatioLoads ){ 429 imgHTML.hide(); 430 } 431 } 432 433 boxImage.attr('data-imageconverted', 'yes');
434 thumbnailDiv.addClass('media-box-thumbnail-container').prepend(imgHTML); 435 }); 436 437 loadImagesWithDimensions(container); 438 } 439 440 /* ****** Set the width and height for the media-box-image div, this is helpful for some overlay effects ****** */ 441 function setDimensionsToImageContainer(container){ 442 container.find(itemSelector).find(boxImageSelector).each(function(){ 443 var boxImage = $(this); 444 var box = boxImage.parents(itemSelector); 445 var hiddenBox = box.css('display') == 'none'; 446 var thumbnailDiv = boxImage.find('div[data-thumbnail]').eq(0); // only one thumb allowed 447 448 if(thumbnailDiv[0] != undefined){ // if you haven't specified a thumbnail then ignore 449 if(hiddenBox){// If it is hidden, display 'none' wont give you the right height so you need to do this trick 450 box.css('margin-top', 99999999999999).show(); 451 } 452 453 boxImage.width( thumbnailDiv[0].offsetWidth ); // now using offsetWidth, since jQuery3.width() changed to getBoundingClientRect() 454 boxImage.height( thumbnailDiv[0].offsetHeight ); 455 456 if(hiddenBox){ 457 box.css('margin-top', 0).hide(); 458 } 459 } 460 }); 461 } 462 463 /* ****** Calculate the right dimensions for the thumbnails ****** */ 464 function setStaticDimensionsOfThumbnails(container){ 465 container.find(itemSelector).find(boxImageSelector).each(function(){ 466 var boxImage = $(this); 467 var box = boxImage.parents(itemSelector); 468 var hiddenBox = box.css('display') == 'none'; 469 var thumbnailDiv = boxImage.find('div[data-thumbnail]').eq(0); /* only one thumb allowed */ 470 var gotDimensions = thumbnailDiv.attr('data-width') != undefined && thumbnailDiv.attr('data-height') != undefined; 471 472 var imgWidth = parseFloat( thumbnailDiv.data('width') ); 473 var imgHeight = parseFloat( thumbnailDiv.data('height') ); 474 475 if(hiddenBox){// If it is hidden, display 'none' wont give you the right height so you need to do this trick 476 box.css('margin-top', 99999999999999).show(); 477 } 478 479 var newWidth = box[0].offsetWidth - container.data('current_horizontalSpaceBetweenBoxes'); // now using offsetWidth, since jQuery3.width() changed to getBoundingClientRect() 480 var newHeight = (imgHeight * newWidth)/imgWidth; 481 482 if(hiddenBox){ 483 box.css('margin-top', 0).hide(); 484 } 485 486 thumbnailDiv.css('width', newWidth); 487 488 /* Set the height only to those thumbs with width and height specified */ 489 if( gotDimensions ){ 490 if(box.attr('data-current-columns')>1 && box.attr('data-extra-height')){ 491 newHeight = newHeight + parseFloat(box.attr('data-extra-height')); 492 } 493 thumbnailDiv.css('height', Math.floor(newHeight)); 494 } 495 }); 496 } 497 498 /* ****** Set the width of the columns according to the settings specified ****** */ 499 function setColumnWidth(container, columnWidth, columns){ 500 var newWidth = 0; 501 var percentage = container.data('settings').percentage; 502 var symbol = ''; 503 504 if( columnWidth == 'auto' ){ 505 if(percentage){ 506 newWidth = 100/columns; 507 symbol = '%'; 508 }else{ 509 newWidth = Math.floor( Math.floor(container.width())/columns ); // minus 1px because some resolutions don't fit perfectly 510 } 511 }else{ 512 newWidth = columnWidth; 513 } 514 515 /* the width that the isotope logic will use for each column of the grid */ 516 container.find('.media-boxes-grid-sizer').css( 'width' , newWidth + symbol ); 517 518 container.find(itemSelector).each(function(index){ 519 var box = $(this); 520 var boxColumns = box.data('columns'); 521 522 /* if the box has columns asigned, check that it doesn't have more than the number of columns in the grid */ 523 if(boxColumns != undefined && parseInt(boxColumns)>parseInt(columns)){ 524 boxColumns = columns; 525 } 526 527 /* for columns that don't have data-columns specified */ 528 if(boxColumns == undefined){ 529 boxColumns = 1; 530 } 531 532 /* number of columns for this item */ 533 box.attr('data-current-columns', boxColumns); 534 535 /* Adjust the width */
536 box.css( 'width' , (parseFloat(newWidth)*parseInt(boxColumns)) + symbol ); 537 }); 538 } 539 540 /* ****** Get viewport dimensions ****** */ 541 function viewport() { 542 var e = window, a = 'inner'; 543 if (!('innerWidth' in window )) { 544 a = 'client'; 545 e = document.documentElement || document.body; 546 } 547 return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }; 548 } 549 550 /* ****** Set new horizontal and vertical space between boxes ****** */ 551 function setSpaceBetweenBoxes(container, horizontal, vertical){ 552 container.data('current_horizontalSpaceBetweenBoxes', horizontal); 553 container.data('current_verticalSpaceBetweenBoxes', vertical); 554 555 container.css('margin-left', -horizontal); 556 /*container.find('.media-box-container').css({ 557 'margin-left' : horizontal, 558 'margin-bottom' : vertical 559 });*/ 560 container.find('.media-box-container').each(function(){ 561 this.style.setProperty( 'margin-left', horizontal+"px", 'important' ); 562 this.style.setProperty( 'margin-bottom', vertical+"px", 'important' ); 563 }); 564 565 566 } 567 568 /* ****** Get and set the correct columnWidth for the current resolution ****** */ 569 function getAndSetColumnWidth(container){ 570 var resolutionFound = false; 571 for (var key in container.data('settings').resolutions) { 572 var value = container.data('settings').resolutions[key]; 573 574 if( value.maxWidth >= viewport().width ){ 575 if(value.horizontalSpaceBetweenBoxes != undefined && value.verticalSpaceBetweenBoxes != undefined){ 576 setSpaceBetweenBoxes(container, value.horizontalSpaceBetweenBoxes, value.verticalSpaceBetweenBoxes); 577 }else{ 578 setSpaceBetweenBoxes(container, container.data('settings').horizontalSpaceBetweenBoxes, container.data('settings').verticalSpaceBetweenBoxes); 579 } 580 setColumnWidth(container, value.columnWidth, value.columns); 581 resolutionFound = true; 582 break; 583 } 584 } 585 586 /* If there wasn't a match then use the default one */ 587 if( resolutionFound == false ){ 588 setSpaceBetweenBoxes(container, container.data('settings').horizontalSpaceBetweenBoxes, container.data('settings').verticalSpaceBetweenBoxes); 589 setColumnWidth(container, container.data('settings').columnWidth, container.data('settings').columns); 590 } 591 } 592 593 /* ****** Hide overlays when resizing ****** */ 594 function hideOverlaysOnResize(container){ 595 var boxes = container.find(itemSelector); 596 597 boxes.each(function(){ 598 var box = $(this); 599 var boxImage = box.find(boxImageSelector); 600 var effect = container.data('settings').overlayEffect; 601 if(effect.indexOf('100') >= 0 && effect.indexOf('100%') == -1){ // if its missing the % sign at the end then just add it 602 effect = effect.split('100').join('100%'); 603 } 604 605 if( effect.substr(0, 9) == 'direction' ){ 606 boxImage.find('.thumbnail-overlay').hide(); 607 } 608 }); 609 610 /* reload isotope for the new width */ 611 container.isotopeMB('layout'); 612 } 613 614 /* ====================================================================== * 615 [3] EXTENDING ISOTOPE 616 * ====================================================================== */ 617 618 /* ****** Extending Isotope on resize event ****** */ 619 $.extend( IsotopeMB.prototype, { 620 resize : function() { 621 /* Hack for seting the grid */ 622 var container = $(this.element); 623 getAndSetColumnWidth(container); 624 setStaticDimensionsOfThumbnails(container); 625 setDimensionsToImageContainer(container); 626 hideOverlaysOnResize(container); 627 /* End hack */ 628
629 // don't trigger if size did not change 630 // or if resize was unbound. See #9 631 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 632 return; 633 } 634 635 this.layout(); 636 } 637 }); 638 639 /* ****** Extending Isotope so when it does set the container width the plugin can refresh the lazy load feature ****** */ 640 $.extend( IsotopeMB.prototype, { 641 _setContainerMeasure : function( measure, isWidth ) { 642 if ( measure === undefined ) { 643 return; 644 } 645 646 var elemSize = this.size; 647 // add padding and border width if border box 648 if ( elemSize.isBorderBox ) { 649 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 650 elemSize.borderLeftWidth + elemSize.borderRightWidth : 651 elemSize.paddingBottom + elemSize.paddingTop + 652 elemSize.borderTopWidth + elemSize.borderBottomWidth; 653 } 654 655 measure = Math.max( measure, 0 ); 656 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 657 658 /* Hack to refresh the lazy load */ 659 var container = $(this.element); 660 setTimeout(function(){ container.addClass('lazy-load-ready'); }, 10); // delay 10 ms 661 /* End hack */ 662 663 /* Remove this class since the grid has been resized due to the filtering system */ 664 container.removeClass('filtering-isotope'); 665 /* End Remove this class */ 666 } 667 }); 668 669 /* ****** Extending Isotope so when you insert items they got the right settings (like columnWidth, staticDimensions, convertDivsIntoImages, etc.) ****** */ 670 $.extend( IsotopeMB.prototype, { 671 insert : function( elems, callback ) { 672 673 var container = $(this.element); 674 675 if(!container.hasClass('first_time')){ 676 container.addClass('first_time'); 677 this._isLayoutInited = false; // if a filter othan than all is selected, this will remove an "effect" of hidding boxes that doesn't belong to the current filter, only the first time it loads 678 } 679 680 /* Make sure the new boxes got all the sorting targets, this must be before the items are passed to isotope */ 681 container.find(itemSelector).each(function(){ 682 var mb = $(this); 683 for (var key in container.data('settings').getSortData) { 684 var obj = container.data('settings').getSortData[key]; 685 if(typeof obj === 'string' && mb.find(obj)[0] == undefined){ 686 mb.append($('<div class="'+obj.substring(1)+'" style="display:none !important;" data-comment="This is added in JS because it needs it for sorting">ZZ</div>')); 687 } 688 } 689 }); 690 691 var items = this.addItems( elems ); 692 if ( !items.length ) { 693 /* Callback for inserting items, I added this 3 lines */ 694 if (typeof callback === 'function'){ 695 callback(); 696 } 697 return; 698 } 699 700 // append item elements 701 var i, item, firstHiddenBox = container.find('.'+itemHiddenClass)[0]; 702 var len = items.length; 703 for ( i=0; i < len; i++ ) { 704 item = items[i]; 705 if(firstHiddenBox != undefined){ 706 this.element.insertBefore( item.element, firstHiddenBox ); 707 }else{ 708 this.element.appendChild( item.element ); 709 } 710 } 711 712 var isotopeDefaultLogic = function(){ 713 714 // filter new stuff 715 var filteredInsertItems = this._filter( items ).matches; 716 // hide all newitems 717 this._noTransition( function() { 718 this.hide( filteredInsertItems ); 719 }); 720 // set flag 721 for ( i=0; i < len; i++ ) { 722 items[i].isLayoutInstant = true; 723 } 724 this.arrange(); 725 // reset flag 726 for ( i=0; i < len; i++ ) { 727 delete items[i].isLayoutInstant; 728 } 729 this.reveal( filteredInsertItems ); 730 731 } 732 733 /* ======== Hack when inserting new boxes so they are properly converted ======== */ 734 var checkForBrokenImages = function(image){ 735 var $image = $(image.img); 736 var thumbnailDiv = $image.parents('div[data-thumbnail], div[data-popup]'); 737 738 if( image.isLoaded == false ){ 739 $image.hide(); 740 thumbnailDiv.addClass('broken-image-here'); 741 } 742 } 743 744 var instance = this; 745 746 747 addPopupTrigger(container); /* Add popup trigger */ 748 addWrapperForMargins(container); /* Set the vertical and horizontal space between boxes */ 749 getAndSetColumnWidth(container); /* Set the column width */ 750 setStaticDimensionsOfThumbnails(container);
750 /* Set the static ratio to the thumbnailDiv */ 751 convertDivsIntoImages(container, false); /* Only the ones that have NO width and height */ 752 753 container.find('img:not([data-dont-wait-for-me])').imagesLoadedMB() 754 .always(function(){ 755 if( container.data('settings').waitForAllThumbsNoMatterWhat == false ){ 756 convertDivsIntoImages(container, true); /* the ones left that have width and height */ 757 }else{ 758 setTimeout(function(){ 759 noEmptySpaceOnThumbnails(container); 760 }, 0); 761 } 762 763 container.find(itemSelector).addClass('media-box-loaded'); /* Add the class to show the box */ 764 $(container.data('settings').search).trigger('keyup'); /* Show or hide according to the searching criteria */ 765 isotopeDefaultLogic.call(instance); /* Now you can call the default logic of the insert method from Isotope */ 766 setDimensionsToImageContainer(container); /* Set the same dimensions of the thumbnail to the container (for caption purposes) */ 767 setupOverlayForHoverEffect(container); /* Get ready for the overlay effect */ 768 769 /* Callback for inserting items */ 770 if (typeof callback === 'function'){ 771 callback(); 772 773 setTimeout(function(){ 774 container.data('settings').onLayoutFinish(); 775 }, 501); 776 } 777 778 /* In case the progress event don't get to check for broken images (this happens sometimes when you refresh the page) */ 779 for(index in instance.images){ 780 var image = instance.images[index]; 781 checkForBrokenImages(image); 782 } 783 }) 784 .progress(function( instance, image ) { 785 /* For broken images */ 786 checkForBrokenImages(image); 787 }); 788 789 /* ======== End Hack ======== */ 790 } 791 }); 792 793 /* ====================================================================== * 794 [4] FILTERING ISOTOPE 795 * ====================================================================== */ 796 797 function updateFilterClasses(){ 798 var boxes = $container.find(itemSelector+', .'+itemHiddenClass); 799 800 var filter = getCurrentFilter(); 801 boxes.filter( filter ).removeClass('hidden-media-boxes-by-filter').addClass('visible-media-boxes-by-filter'); 802 boxes.not( filter ).addClass('hidden-media-boxes-by-filter').removeClass('visible-media-boxes-by-filter'); 803 } 804 805 function filterTheBoxes(filterValue, filterGroup){ 806 807 /* Add a class until it resizes the grid */ 808 $container.addClass('filtering-isotope'); 809 810 // Combined the filters and filter isotope 811 goAndFilterIsotope(filterValue, filterGroup); 812 813 // update some CSS classes 814 updateFilterClasses(); 815 816 // Fix some details, like the loading button, the minBoxesPerFilter 817 seeItFiltered(); 818 } 819 820 function seeItFiltered(){ 821 // fix load more button 822 if( getLoadingBoxesInCurrentFilter().length > 0 ){ 823 loading(); 824 }else{ 825 fixLoadMoreButton(); 826 } 827 828 // load more boxes if neccessary 829 checkMinBoxesPerFilter(); 830 } 831 832 function goAndFilterIsotope(filterValue, filterGroup){ 833 // set filter for group 834 filters[ filterGroup ] = filterValue; 835 836 // set filters for Isotope 837 $container.isotopeMB({ filter: combineFilters(filters) }); 838 } 839 840 function combineFilters( filters ) { 841 842 var output = []; 843 844 for ( var prop in filters ) { 845 var selector = filters[prop]; 846 var selector_clean = selector.split(" ").join(""); // Remove empty spaces, so if we have this: .red, .blue it should be: .red,.blue 847 var selector_split = selector_clean.split(",") 848 849 /* ###### AND ###### */ 850 if(settings.multipleFilterLogic == 'AND'){ 851 852 if(selector_clean != '*'){ 853 if(output.length == 0){ 854 output = selector_split; 855 }else{ 856 output = allPossibleCases([ output, selector_split ]); 857 } 858 } 859 860 } 861 862 /* ###### OR ###### */ 863 else if(settings.multipleFilterLogic == 'OR'){ 864 if(selector_clean != '*' && selector_clean != '.search-match'){ 865 if('search' in filters){ // if the search f
865ilter is enable, then combine it with the current selector 866 var mixed = allPossibleCases([ ['.search-match'], selector_split ]); 867 output.push( mixed.join(',') ); 868 }else{ 869 output.push( selector_split.join(',') ); 870 } 871 } 872 } 873 874 } 875 876 var combined = output.length > 0 ? output.join(',') : '*'; // if output is empty, is probably because all filters were '*' 877 878 /* [start] when using OR if all filters where set to ALL and you type something in the search field, it was NOT filtering anything */ 879 if(combined == '*' && settings.multipleFilterLogic == 'OR'){ // if the logic is OR and all filters were '*' 880 if('search' in filters){ // if the search filter is enable, then only filter by the "search-filter" 881 combined = '.search-match'; 882 } 883 } 884 /* [end] when using OR if all filters where set to ALL and you type something in the search field, it was NOT filtering anything */ 885 886 return combined; 887 } 888 889 function allPossibleCases(arr) { 890 if (arr.length == 1) { 891 return arr[0]; 892 } else { 893 var result = []; 894 var allCasesOfRest = allPossibleCases(arr.slice(1)); // recur with the rest of array 895 for (var i = 0; i < allCasesOfRest.length; i++) { 896 for (var j = 0; j < arr[0].length; j++) { 897 result.push(arr[0][j] + allCasesOfRest[i]); 898 } 899 } 900 return result; 901 } 902 } 903 904 /* ====================================================================== * 905 [5] LOAD MORE BOXES 906 * ====================================================================== */ 907 908 function checkMinBoxesPerFilter(){ 909 910 var filter = getCurrentFilter(); 911 var in_all = false; 912 if( filter == '*' || (filter == '.search-match' && $(settings.search).val() == '') ){ 913 in_all = true; 914 } 915 916 if(in_all == false){//only execute the minBoxesPerFilter when is not showing all the boxes 917 918 var boxesInCurrentCategory = getBoxesInCurrentFilter().length; 919 920 /* Also check if there's boxes waiting to get load from that category, because maybe there isn't and there's no case to try to load them */ 921 if( boxesInCurrentCategory < settings.minBoxesPerFilter && hiddenBoxesWaitingToLoad().length > 0 ){ 922 /* Load the boxes that are missing */ 923 loadMore( settings.minBoxesPerFilter - boxesInCurrentCategory ); 924 925 return true; 926 } 927 928 } 929 930 return false; 931 } 932 933 function getBoxesInCurrentFilter(){ 934 var boxes = $container.find(itemSelector); 935 var filter = getCurrentFilter(); 936 if( filter != '*' ){ 937 boxes = boxes.filter( filter ); 938 } 939 940 return boxes; 941 } 942 943 function getLoadingBoxesInCurrentFilter(){ 944 var boxes = getBoxesInCurrentFilter().not('.media-box-loaded'); 945 946 return boxes; 947 } 948 949 function getCurrentFilter(){ 950 var filter = $container.data('isotopeMB').options.filter; 951 if( filter == '' || filter == undefined ){ 952 filter = '*'; 953 } 954 955 return filter; 956 } 957 958 function hiddenBoxesWaitingToLoad(ignoreFilter){ /* Number of hidden boxes waiting to get load, depending on the filter */ 959 var boxes = $container.find('.'+itemHiddenClass); 960 961 var filter = getCurrentFilter(); 962 if( filter != '*' && ignoreFilter == undefined){ 963 boxes = boxes.filter( filter ); 964 } 965 966 return boxes; 967 } 968 969 function loading(){ 970 loadMoreButton.html(settings.LoadingWord);
971 loadMoreButton.removeClass('media-boxes-load-more'); 972 loadMoreButton.addClass('media-boxes-loading'); 973 } 974 975 function startLoading(){ 976 loadingsCounter++; 977 loading(); 978 } 979 980 function finishLoading(){ 981 loadingsCounter--; 982 if(loadingsCounter == 0){ 983 fixLoadMoreButton(); 984 } 985 } 986 987 function fixLoadMoreButton(){ 988 loadMoreButton.removeClass('media-boxes-load-more'); 989 loadMoreButton.removeClass('media-boxes-loading'); 990 loadMoreButton.removeClass('media-boxes-no-more-entries'); 991 992 if( hiddenBoxesWaitingToLoad().length > 0 ){ 993 loadMoreButton.html(settings.loadMoreWord); 994 loadMoreButton.addClass('media-boxes-load-more'); 995 }else{ 996 loadMoreButton.html(settings.noMoreEntriesWord); 997 loadMoreButton.addClass('media-boxes-no-more-entries'); 998 } 999 } 1000 1001 function loadMore( boxesToLoad, ignoreFilter){ 1002 if( loadMoreButton.hasClass('media-boxes-no-more-entries') == true ){ /* Only if it is the "load more" button or the "loading...", no the "no more entries" button */ 1003 return; 1004 } 1005 1006 /* Loading... */ 1007 startLoading(); 1008 1009 /* The new boxes */ 1010 var newBoxes = []; 1011 1012 /* Boxes that will be loaded as part of isotope */ 1013 hiddenBoxesWaitingToLoad(ignoreFilter).each(function(index){ 1014 var $this = $(this); 1015 if( (index+1) <= boxesToLoad){ 1016 $this.removeClass(itemHiddenClass).addClass(itemClass); 1017 $this.hide(); 1018 newBoxes.push(this); 1019 } 1020 }); 1021 1022 $container.isotopeMB( 'insert', $(newBoxes), function(){ 1023 /* Fix Load More Button */ 1024 finishLoading(); 1025 1026 /* Force a relayout of Isotope */ 1027 $container.isotopeMB('layout'); 1028 }); 1029 } 1030 loadMore( settings.boxesToLoadStart, true ); 1031 checkMinBoxesPerFilter(); 1032 1033 /* Load more boxes when you click the button */ 1034 loadMoreButton.on('click', function(){ 1035 loadMore( settings.boxesToLoad ); 1036 }); 1037 1038 function loadMoreIfButtonIsVisible(){ 1039 if(loadMoreButton.filter(':visible')[0] !== undefined && loadMoreButton.filter(':visible').visible( true )){ 1040 if( $container.hasClass('lazy-load-ready') ){ 1041 if( $container.hasClass('filtering-isotope') == false){ 1042 $container.removeClass('lazy-load-ready'); 1043 loadMore( settings.boxesToLoad ); 1044 } 1045 } 1046 } 1047 } 1048 1049 if( settings.lazyLoad ){ 1050 $(window).scroll(function(){ 1051 loadMoreIfButtonIsVisible(); 1052 }); 1053 } 1054 1055 /* ====================================================================== * 1056 [6] FILTER 1057 * ====================================================================== */ 1058 1059 /* DEFAULT FILTERS SELECTED (SAVE ORIGINAL SELECTED FILTER) */ 1060 1061 filtersContainers.each(function(){ 1062 var $this = $(this); 1063 1064 if($this.is(':checkbox')){ 1065 $this.attr('default-value', $this.is(':checked') ? $this.attr('data-filter') : '*' ); // set default value 1066 }else{ 1067 $this.attr('default-value', $this.find('*[data-filter]').filter('.selected').attr('data-filter')); // set default value 1068 } 1069 }); 1070 1071 /* INIT DEFAULT FILTERING */ 1072 1073 setTimeout(function(){ 1074 1075 // filtersContainers.each(function(){ 1076 // /* current items */ 1077 // var current_filterContainer = $(this); 1078 // var filterValue = ''; 1079 1080 // /* if its a checkbox */ 1081 // if(current_filterContainer.is(':checkbox')){ 1082 // filterValue = current_filterContainer.is(':checked') ? current_filterContainer.attr('data-filter') : '*'; 1083 // }else{ 1084 // var current_filter = current_filterContainer.find('*[data-filter]').filter('.selected'); 1085 // filterValue = current_filter[0] !== undefined ? current_filter.attr('data-filter') : '*'; 1086 // } 1087 1088 // /* initialize the filtering */ 1089 // init_filtering(filterValue, current_filterContainer, 'default'); 1090 // }); 1091 1092 }, 1); // this to fixes the following: when a selected filter is other than all when the page loads, the thumbnail-overlay of the first item in the grid was not working correctly, because some hidden boxes were on top of it, as if they were not fully hidden 1093 1094 /* EVENT IF THE FILTER IS A SELECT */ 1095 1096 filtersContainers.on('change', function(){ 1097 if($(this).is('select')){ // check if its a select element 1098 /* current items */ 1099 var current_filterContainer = $(this); 1100 1101 /* initialize the filtering */ 1102 init_filtering(current_filterContainer.val(), current_filterContainer); 1103 } 1104 }); 1105 1106 /* EVENT FOR WHEN CLICKING A FILTER NAVIGATION BAR OR A DROPDOWN MENU */ 1107 1108 filtersContainers.on('click', '*[data-filter]', function(e){ 1109 if(!$(this).is('option') && !$(this).is(':checkbox')){ // check if its not an option from a select element or if its not a checkbox 1110 /* current items */ 1111 var current_filter = $(this); 1112 var current_filterContainer = $(this).parents(settings.filterContainer); 1113 1114 /* Remove selected class from others and add selected to current */ 1115 current_filterContainer.find('*[data-filter]').removeClass('selected'); 1116 current_filter.addClass('selected'); 1117 1118 /* initialize the filtering */ 1119 init_filtering(current_filter.attr('data-filter'), current_filterContainer); 1120 1121 e.preventDefault(); 1122 } 1123 }); 1124 1125 /* EVENT FOR WHEN CLICKING A CHECKBOX */ 1126 1127 $('body').on('change', settings.filterContainer, function(){ 1128 if($(this).is(':checkbox')){ 1129 /* current items */ 1130 var current_filterContainer = $(this); 1131 1132 /* initialize the filtering */ 1133 init_filtering(current_filterContainer.is(':checked') ? current_filterContainer.attr('data-filter') : '*', current_filterContainer); 1134 } 1135 }); 1136 1137 /* FILTERING */ 1138 1139 function init_filtering(filterValue, current_filterContainer){ 1140 show_hide_filters(); 1141 1142 /* Filter isotope */ 1143 var filterGroup = current_filterContainer.data("id") != undefined ? current_filterContainer.data("id") : "filter"; // take the id of the filter container if exists, if not just a string 1144 var is_default = current_filterContainer.attr('default-value') == filterValue; 1145 1146 /* Hash on filter change (this is not executed when the plugin first load with a default filter) */ 1147 set_hash_on_filter_change(filterValue, filterGroup, is_default); 1148 1149 /* Filter the boxes */ 1150 filterTheBoxes( filterValue , filterGroup); 1151 } 1152 1153 /* SHOW-HIDE FILTERS (WHEN THE VISIBILITY OF A FILTER DEPENDS O
1153N ANOTHER) */ 1154 1155 function show_hide_filters(){ 1156 filtersContainers.find('[data-filter]').addBack('[data-filter]').each(function(){ 1157 var $this = $(this); 1158 1159 if($this.attr('data-visible-only-if') != undefined){ 1160 var $visible = $($this.attr('data-visible-only-if')); 1161 1162 // If its a checkbox 1163 if($visible.is(':checkbox')){ 1164 if($visible.is(':checked')){ // show item 1165 $this.removeClass('visibility_hidden'); 1166 $this.parents('.media-boxes-checkboxes-label').show(); 1167 }else{ // hide item 1168 $this.addClass('visibility_hidden'); 1169 $this.parents('.media-boxes-checkboxes-label').hide(); 1170 1171 if($this.is(':checked')){ // if when hidding, the checkbox was "checked" then go back to "all" 1172 setTimeout(function(){ 1173 $this.prop('checked', false).trigger('change'); // uncheck if its checked 1174 }, 1); 1175 } 1176 } 1177 } 1178 1179 // If its a dropdown or inline 1180 if(!$visible.is(':checkbox') && !$visible.is('select')){ 1181 if($visible.hasClass('selected')){ // show item 1182 $this.show().removeClass('visibility_hidden'); 1183 }else{ // hide item 1184 $this.hide().addClass('visibility_hidden'); 1185 1186 if($this.hasClass('selected')){ // if when hidding, the item was "selected" then go back to all 1187 $this.parents(settings.filterContainer).find('[data-filter="*"]').trigger('click'); 1188 } 1189 } 1190 } 1191 1192 } 1193 }); 1194 1195 show_hide_filter_container(); 1196 } 1197 1198 function show_hide_filter_container(){ 1199 $('.media-boxes-drop-down, .media-boxes-filter, .media-boxes-checkboxes').each(function(){ 1200 var $this = $(this); 1201 var items = $this.find('[data-filter]').not('.visibility_hidden'); 1202 1203 if($this.find('[data-filter]')[0] == undefined) return; // only do this if there are filters 1204 1205 if(!$this.hasClass('media-boxes-checkboxes')){ 1206 items = items.not('[data-filter="*"]'); 1207 } 1208 1209 if(items.length <= 0){ 1210 $this.hide(); 1211 }else{ 1212 $this.show(); 1213 } 1214 }) 1215 } 1216 1217 /* ====================================================================== * 1218 [7] SEARCH 1219 * ====================================================================== */ 1220 1221 function search(value){ 1222 if(value == undefined) return; 1223 1224 var allBoxes = $container.find('.'+itemClass+', .'+itemHiddenClass); 1225 if(value == ''){ 1226 /* If there's nothing in the input text field then show all the boxes */ 1227 allBoxes.addClass('search-match'); 1228 }else{ 1229 allBoxes.removeClass('search-match'); 1230 1231 $container.find(settings.searchTarget).each(function(){ 1232 var $this = $(this); 1233 var box = $this.parents('.'+itemClass+', .'+itemHiddenClass); 1234 if( $this.text().toLowerCase().indexOf(value.toLowerCase()) !== -1 ){ 1235 box.addClass('search-match'); 1236 } 1237 }); 1238 } 1239 1240 var is_default = $(settings.search).attr('default-value') == value; 1241 1242 setTimeout( function() { 1243 // Hash on filter change 1244 set_hash_on_filter_change(value, 'search', is_default); 1245 1246 // Filter the boxes 1247 filterTheBoxes('.search-match', 'search'); 1248 }, 100 ); 1249 } 1250 1251 $(settings.search).on('keyup', function(){ 1252 search( $(this).val() ); 1253 }); 1254 1255 /* set default value */ 1256 $(settings.search).attr('default-value', $(settings.search).attr('value') === undefined ? "" : $(settings.search).attr('value')); 1257 1258 /* default search selected */ 1259 search( $(settings.search).val() ); 1260 1261 $('body').on('click', '.media-boxes-clear', function(){ 1262 $(this).parents('.media-boxes-search').find('input').val('').trigger('keyup').focus(); 1263 }); 1264 1265 /* ====================================================================== * 1266 [8] SORTING 1267 * ====================================================================== */ 1268 1269 function getSortDirection($this){ 1270 var direction = $this.data('sort-ascending'); 1271 if(direction == undefined){ 1272 direction = true; 1273 } 1274 1275 if($this.data('sort-toggle') && $this.data('sort-toggle') == true){ 1276 $this.data('sort-ascending', !direction); 1277 } 1278 1279 /* if there's a sort order button then use the value from there */ 1280 var sort_order = $this.parents('.media-boxes-sort').find('.media-boxes-sort-order').find('.selected'); 1281 if(sort_order[0] !== undefined){ 1282 direction = sort_order.data('sort-ascending'); 1283 } 1284 1285 /* if the sort option is "original-order" then always true (ascending) */ 1286 if($this.attr('data-sort-by') == 'original-order'){ 1287 direction = true; 1288 } 1289 1290 return direction; 1291 } 1292 1293 /* Clicking on the different sort options */ 1294 1295 $(settings.sortContainer).find('*[data-sort-by]').on('click', function(e){ 1296 var $this = $(this); 1297 1298 /* Remove selected class from others */ 1299 $this.parents(settings.sortContainer).find('*[data-sort-by]').removeClass('selected'); 1300 1301 /* Add class of selected */ 1302 $this.addClass('selected'); 1303 1304 /* Sort isotope */ 1305 var sortValue = $this.attr('data-sort-by'); 1306 $container.isotopeMB({ sortBy: sortValue, sortAscending: getSortDirection($this) }); 1307 1308 e.preventDefault(); 1309 }); 1310 1311 /* Clicking on the sort order button */ 1312 1313 $(settings.sortContainer).parents('.media-boxes-sort').find('.media-boxes-sort-order').on('click', function(e){ 1314 var $this = $(this); 1315 1316 /* change sort order */ 1317 $this.find('.selected').removeClass('selected').siblings('span').addClass('selected'); 1318 1319 /* selected sort-by option */ 1320 var sort_by = $this.parents('.media-boxes-sort').find('.selected[data-sort-by]'); 1321 1322 /* apply new sort order to isotope */ 1323 $container.isotopeMB({ sortAscending: getSortDirection(sort_by) }); 1324 }); 1325 1326 /* ====================================================================== * 1327 [9] THUMBNAIL OVERLAY EFFECT 1328 * ====================================================================== */ 1329 1330 /* ****** Set the overlay depending on the overlay effect before the hover event is trigger ****** */ 1331 function setupOverlayForHoverEffect(container){ 1332 if( container.data('settings').thumbnailOverlay == false ) return; 1333 1334 var boxes = container.find(itemSelector+':not([data-set-overlay-for-hover-effect])').attr('data-set-overlay-for-hover-effect', 'yes'); 1335 1336 /* Add extra divs for vertical alignment */ 1337 boxes.find('.thumbnail-overlay').wrapInner( "<div class='aligment'><div class='aligment'></div></div>" ); 1338 1339 boxes.each(function(){ 1340 1341 var box = $(this); 1342 var boxImage = box.find(boxImageSelector); 1343 var effect = container.data('settings').overlayEffect; 1344 if(boxImage.data('overlay-effect') != undefined){ 1345 effect = boxImage.data('overlay-effect'); 1346 1347 if(effect.indexOf('100') >= 0 && effect.indexOf('100%') == -1){ 1348 effect = effect.split('100').join('100%'); 1349 } 1350 } 1351 1352 /* Add wrapper for some effects */ 1353 if( effect == 'push-up' || effect == 'push-down' || effect == 'push-up-100%' || effect == 'push-down-100%' ){ 1354 1355 var thumbnailDiv = boxImage.find('.media-box-thumbn
1355ail-container'); 1356 var thumbnailOverlay = boxImage.find('.thumbnail-overlay').css('position', 'relative'); 1357 if( effect == 'push-up-100%' || effect == 'push-down-100%' ){/* set the height of the overlay to the same of the thumbnail */ 1358 thumbnailOverlay.outerHeight( thumbnailDiv.outerHeight(false) ); 1359 } 1360 var heightOverlay = thumbnailOverlay.outerHeight(false); 1361 1362 var wrapper = $('<div class="wrapper-for-some-effects"></div'); 1363 1364 if( effect == 'push-up' || effect == 'push-up-100%' ){ 1365 thumbnailOverlay.appendTo(boxImage); 1366 }else if( effect == 'push-down' || effect == 'push-down-100%' ){ 1367 thumbnailOverlay.prependTo(boxImage); 1368 wrapper.css('margin-top', -heightOverlay); 1369 } 1370 1371 boxImage.wrapInner( wrapper ); 1372 1373 } 1374 /* Set some CSS style for this effects */ 1375 else if( effect == 'reveal-top' || effect == 'reveal-top-100%' ){ 1376 1377 box.addClass('position-reveal-effect'); 1378 1379 var overlay = box.find('.thumbnail-overlay').css('top', 0); 1380 if( effect == 'reveal-top-100%' ){ 1381 overlay.css('height', '100%'); 1382 } 1383 1384 }else if( effect == 'reveal-bottom' || effect == 'reveal-bottom-100%' ){ 1385 1386 box.addClass('position-reveal-effect').addClass('position-bottom-reveal-effect'); 1387 1388 var overlay = box.find('.thumbnail-overlay').css('bottom', 0); 1389 if( effect == 'reveal-bottom-100%' ){ 1390 overlay.css('height', '100%'); 1391 } 1392 1393 }else if( effect.substr(0, 9) == 'direction'){ // 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom' 1394 1395 /* Set the height to 100% if not it would be just the default height of the overlay */ 1396 box.find('.thumbnail-overlay').css('height', '100%'); 1397 1398 }else if( effect == 'fade' ){ 1399 1400 var thumbOverlay = box.find('.thumbnail-overlay').hide(); 1401 thumbOverlay.css({ 1402 'height' : '100%', 1403 'top' : '0', 1404 'left' : '0', 1405 }); 1406 //thumbOverlay.find("[class^='fa-'],div[class*=' fa-']").css({ scale : 1.4 }); 1407 1408 } 1409 1410 /* Init effect on overlay-thumbnail hover */ 1411 container.data('settings').animation_on_thumbnail_overlay_hover.forEach(function(row){ 1412 var item = box.find('.thumbnail-overlay').find(row.item); 1413 1414 if(row.animation == 'zoom-out'){ 1415 item.css({ scale: 1.4 }); 1416 }else if(row.animation == 'zoom-in'){ 1417 item.css({ scale : 0.6 }); 1418 }else if(row.animation == 'from-top'){ 1419 item.transition({ y : '-30px' }, 0); 1420 }else if(row.animation == 'from-bottom'){ 1421 item.transition({ y : '30px' }, 0); 1422 }else if(row.animation == 'from-left'){ 1423 item.transition({ x : '-30px' }, 0); 1424 }else if(row.animation == 'from-right'){ 1425 item.transition({ x : '30px' }, 0); 1426 } 1427 1428 }); 1429 1430 }); 1431 1432 } 1433 1434 /* ****** Hide element when done ****** */ 1435 function hideWhenDone(element){ 1436 if( element.attr('data-stop') != undefined ){ 1437 element.hide(); 1438 element.removeAttr('data-stop'); 1439 } 1440 } 1441 1442 /* ****** Trigger the overlay effect ****** */ 1443 $container.on( 'mouseenter.hoverdir, mouseleave.hoverdir', boxImageSelector, function(event){ 1444 if( settings.thumbnailOverlay == false ) return; 1445 1446 var boxImage = $(this); 1447 var effect = settings.overlayEffect; 1448 if(boxImage.data('overlay-effect') != undefined){ 1449 effect = boxImage.data('overlay-effect'); 1450 1451 if(effect.indexOf('100') >= 0 && effect.indexOf('100%') == -1){ // if its missing the % sign at the end then just add it 1452 effect = effect.split('100').join('100%'); 1453 } 1454 } 1455 1456 var eventType = event.type; 1457 var thumbnailDiv = boxImage.find('.media-box-thumbn
1457ail-container'); 1458 var thumbnailOverlay = boxImage.find('.thumbnail-overlay') ; 1459 var heightOverlay = thumbnailOverlay.outerHeight(false); 1460 1461 /* The effects */ 1462 if( effect == 'push-up' || effect == 'push-up-100%' ){ 1463 var wrapper = boxImage.find('div.wrapper-for-some-effects'); 1464 1465 if( eventType === 'mouseenter' ) { 1466 wrapper.stop().show()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 1467 }else{ 1468 wrapper.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 1469 } 1470 } 1471 1472 else if( effect == 'push-down' || effect == 'push-down-100%' ){ 1473 var wrapper = boxImage.find('div.wrapper-for-some-effects'); 1474 1475 if( eventType === 'mouseenter' ) { 1476 wrapper.stop().show()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 1477 }else{ 1478 wrapper.stop()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 1479 } 1480 } 1481 1482 else if( effect == 'reveal-top' || effect == 'reveal-top-100%' ){ 1483 if( eventType === 'mouseenter' ) { 1484 thumbnailDiv.stop().show()[animation]({ 'margin-top': heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 1485 }else{ 1486 thumbnailDiv.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 1487 } 1488 } 1489 1490 else if( effect == 'reveal-bottom' || effect == 'reveal-bottom-100%' ){ 1491 if( eventType === 'mouseenter' ) { 1492 thumbnailDiv.stop().show()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 1493 }else{ 1494 thumbnailDiv.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 1495 } 1496 } 1497 1498 else if( effect.substr(0, 9) == 'direction' ){ // 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom' 1499 var direction = _getDir( boxImage, { x : event.pageX, y : event.pageY } ); 1500 1501 if( effect == 'direction-top' ){ 1502 direction = 0; 1503 }else if( effect == 'direction-bottom' ){ 1504 direction = 2; 1505 }else if( effect == 'direction-right' ){ 1506 direction = 1; 1507 }else if( effect == 'direction-left' ){ 1508 direction = 3 1509 } 1510 1511 var cssPos = _getPosition( direction, boxImage ); 1512 1513 if( eventType == 'mouseenter' ){ 1514 thumbnailOverlay.css( { 'left' : cssPos.from, 'top' : cssPos.to } ); 1515 1516 thumbnailOverlay.stop().show().fadeTo(0, 1, function(){ 1517 $(this).stop()[animation]({ 'left' : 0, 'top' : 0 }, settings.overlaySpeed, settings.overlayEasing); 1518 }); 1519 }else{ 1520 if( effect == 'direction-aware-fade' ){ 1521 thumbnailOverlay.fadeOut(700); 1522 }else{ 1523 thumbnailOverlay.stop()[animation]({ 'left' : cssPos.from, 'top' : cssPos.to }, settings.overlaySpeed, settings.overlayEasing ); 1524 } 1525 } 1526 } 1527 1528 else if( effect == 'fade' ){ 1529 1530 if( eventType == 'mouseenter' ){ 1531 thumbnailOverlay.stop().fadeOut(0); 1532 thumbnailOverlay.fadeIn( settings.overlaySpeed ); 1533 }else{ 1534 thumbnailOverlay.stop().fadeIn(0); 1535 thumbnailOverlay.fadeOut( settings.overlaySpeed ); 1536 } 1537 1538 } 1539 1540 /* Init effect on overlay-thumbnail hover */ 1541 settings.animation_on_thumbnail_overlay_hover.forEach(function(row){ 1542 var item = thumbnailOverlay.find(row.item); 1543 1544 if( eventType == 'mouseenter' ){ 1545 1546 if(row.animation == 'zoom-out'){ 1547 item.css({ scale : 1.4 }); 1548 item[animation]({ scale: 1 }, 200); 1549 }else if(row.animation == 'zoom-in'){ 1550 item.css({ scale: 0.6 }); 1551 item[animation]({ scale: 1 }, 200); 1552 }else if(row.animation == 'from-top'){ 1553 item.transition({ y : '-30px' }, 0); 1554 item.transition({ y : '0px' }, 200); 1555 }else if(row.animation == 'from-bottom'){ 1556 item.transition({ y : '30px' }, 0); 1557 item.transition({ y : '0px' }, 200); 1558 }else if(row.animation == 'from-left'){ 1559 item.transition({ x : '-30px' }, 0); 1560 item.transition({ x : '0px' }, 200); 1561 }else if(row.animation == 'from-right'){ 1562 item.transition({ x : '30px' }, 0); 1563 item.transition({ x : '0px' }, 200); 1564 } 1565 1566 }else{ 1567 1568 if(row.animation == 'zoom-out'){ 1569 item.css({ scale: 1 }); 1570 item[animation]({ scale: 1.4 }, 200); 1571 }else if(row.animation == 'zoom-in'){ 1572 item.css({ scale : 1 }); 1573 item[animation]({ scale: 0.6 }, 200); 1574 }else if(row.animation == 'from-top'){ 1575 item.transition({ y : '0px' }, 0); 1576 item.transition({ y: '-30px' }, 200); 1577 }else if(row.animation == 'from-bottom'){ 1578 item.transition({ y : '0px' }, 0); 1579 item.transition({ y: '30px' }, 200); 1580 }else if(row.animation == 'from-left'){ 1581 item.transition({ x : '0px' }, 0); 1582 item.transition({ x : '-30px' }, 200); 1583 }else if(row.animation == 'from-right'){ 1584 item.transition({ x : '0px' }, 0); 1585 item.transition({ x : '30px' }, 200); 1586 } 1587 1588 } 1589 1590 }); 1591 1592 }); 1593 1594 /* ****** Methods for the direction-aware hover effect ****** */ 1595 var _getDir = function( $el, coordinates ) { 1596 /** the width and height of the current div **/ 1597 var w = $el.width(), 1598 h = $el.height(), 1599 1600 /** calculate the x and y to get an angle to the center of the div from that x and y. **/ 1601 /** gets the x value relative to the center of the DIV and "normalize" it **/ 1602 x = ( coordinates.x - $el.offset().left - ( w/2 )) * ( w > h ? ( h/w ) : 1 ), 1603 y = ( coordinates.y - $el.offset().top - ( h/2 )) * ( h > w ? ( w/h ) : 1 ), 1604 1605 /** the angle and the direction from where the mouse
1605came in/went out clockwise (TRBL=0123);**/ 1606 /** first calculate the angle of the point, 1607 add 180 deg to get rid of the negative values 1608 divide by 90 to get the quadrant 1609 add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/ 1610 direction = Math.round( ( ( ( Math.atan2(y, x) * (180 / Math.PI) ) + 180 ) / 90 ) + 3 ) % 4; 1611 1612 return direction; 1613 1614 }; 1615 1616 var _getPosition = function( direction, $el ) { 1617 var fromLeft, fromTop; 1618 switch( direction ) { 1619 case 0: 1620 // from top 1621 if ( !settings.reverse ) { 1622 fromLeft = 0, fromTop = - $el.height() 1623 }else { 1624 fromLeft = 0, fromTop = - $el.height() 1625 } 1626 break; 1627 case 1: 1628 // from right 1629 if ( !settings.reverse ) { 1630 fromLeft = $el.width() , fromTop = 0 1631 }else { 1632 fromLeft = - $el.width() , fromTop = 0 1633 } 1634 break; 1635 case 2: 1636 // from bottom 1637 if ( !settings.reverse ) { 1638 fromLeft = 0 , fromTop = $el.height() 1639 } 1640 else { 1641 fromLeft = 0, fromTop = - $el.height() 1642 } 1643 break; 1644 case 3: 1645 // from left 1646 if ( !settings.reverse ) { 1647 fromLeft = -$el.width() , fromTop = 0 1648 } 1649 else { 1650 fromLeft = $el.width(), fromTop = 0 1651 } 1652 break; 1653 }; 1654 return { from : fromLeft, to: fromTop }; 1655 }; 1656 1657 /* ====================================================================== * 1658 [10] IFRAME ON GRID 1659 * ====================================================================== */ 1660 1661 /* Instead of openning the youtube/vimeo video in the popup open it in the grid */ 1662 $container.on('click', '.iframe-on-grid', function(){ 1663 var $this = $(this); 1664 var mbImage = $this.parents(itemSelector).find(boxImageSelector); 1665 1666 show_video_on_grid(mbImage, $this.attr('data-src')); 1667 }); 1668 1669 function show_video_on_grid(mbImage, src){ 1670 var iframeContainer = ""; 1671 1672 if(mbImage.find('.iframe-on-grid-container')[0] != undefined){ 1673 iframeContainer = mbImage.find('.iframe-on-grid-container'); 1674 }else{ 1675 1676 if(src.indexOf('vimeo.com/') > -1){ 1677 src = src.split('vimeo.com/').pop(); 1678 src = 'https://player.vimeo.com/video/'+src+'?autoplay=1'; 1679 }else if(src.indexOf('youtube.com/') > -1){ 1680 src = src.split('?v=').pop(); 1681 src = 'https://www.youtube.com/embed/'+src+'?autoplay=1'; 1682 } 1683
1684 iframeContainer = $('<div class="iframe-on-grid-container"><iframe src="'+src+'" allowfullscreen></iframe></div>').appendTo(mbImage); 1685 1686 iframeContainer.find('iframe').load(function(){ 1687 $(this).fadeIn(100); 1688 }); 1689 } 1690 1691 iframeContainer.fadeIn(300); 1692 } 1693 1694 /* ====================================================================== * 1695 [11] INIT POPUP 1696 * ====================================================================== */ 1697 1698 function addPopupTrigger(container){ 1699 1700 container.find(itemSelector+', .'+itemHiddenClass).find('.mb-open-popup:not(.popup-trigger-added)').each(function(){ 1701 1702 var $this = $(this).addClass('popup-trigger-added'); 1703 var attr_src = $this.attr('data-src'); 1704 var attr_type = $this.attr('data-type'); // image, iframe, inline, and ajax 1705 var attr_title = $this.attr('data-title') != undefined ? $this.attr('data-title') : ""; 1706 var attr_alt = $this.attr('data-alt') != undefined ? $this.attr('data-alt') : ""; 1707 1708 // Add data-thumb if is not specified (fancybox needs this for creating the thumbnails/small-gallery in the popup, sometimes it worked, because it was autodetecting the thumbnails if the thumbnails were inside the mb-open-popup) 1709 1710 if($this.attr('data-thumb') === undefined){ 1711 var box = $(this).parents(itemSelector); 1712 var thumbnailDiv = box.find('div[data-thumbnail]').eq(0); // only one thumb allowed 1713 1714 $this.attr('data-thumb', thumbnailDiv.attr('data-thumbnail')); 1715 } 1716 1717 // Instead of openning the iframe in the popup open it in the grid 1718 1719 if( $this.hasClass('iframe-on-grid') && attr_type == 'iframe' ){ 1720 return; 1721 } 1722 1723 // If the data-src is not specified, then ignore 1724 1725 if(attr_src == undefined){ 1726 return; 1727 } 1728 1729 if(attr_src == ''){ 1730 $this.removeClass('mb-open-popup'); 1731 $this.removeAttr('data-src'); 1732 $this.removeAttr('data-type'); 1733 $this.removeAttr('data-title'); 1734 $this.removeAttr('data-alt'); 1735 } 1736 1737 // Check if type is valid 1738 1739 if(attr_type == 'iframe' || attr_type == 'inline' || attr_type == 'ajax'){ 1740 // all good 1741 }else{ 1742 $this.removeAttr('data-type'); // remove invalid type 1743 } 1744 1745 // Fancybox Attribures 1746 1747 if(settings.popup == 'fancybox'){ 1748 1749 $this.attr('data-caption', attr_title); 1750 if(attr_src.indexOf('youtube') >= 0 || attr_src.indexOf('vimeo') >= 0){ 1751 $this.removeAttr('data-type'); 1752 } 1753 1754 } 1755 1756 // Magnific Popup Attributes 1757 1758 if(settings.popup == 'magnificpopup'){ 1759 1760 var type = 'mfp-image'; 1761 if(attr_type == 'iframe'){ 1762 type = 'mfp-iframe'; 1763 }else if(attr_type == 'inline'){ 1764 type = 'mfp-inline'; 1765 }else if(attr_type == 'ajax'){ 1766 type = 'mfp-ajax'; 1767 } 1768 1769 $this.attr('data-mfp-src', attr_src); 1770 $this.addClass(type); 1771 $this.attr('mfp-title', attr_title); 1772 $this.attr('mfp-alt', attr_alt); 1773 1774 } 1775 1776 }); 1777 1778 } 1779 1780 if(settings.popup == 'fancybox' || settings.popup == 'magnificpopup'){ 1781 var selector = '.mb-open-popup[data-src]'; 1782 if(settings.considerFilteringInPopup){ 1783 selector = itemSelector+':not(.hidden-media-boxes-by-filter) .mb-open-popup[data-src], .'+itemHiddenClass+':not(.hidden-media-boxes-by-filter) .mb-open-popup[data-src]'; 1784 } 1785 if(settings.showOnlyVisibleBoxesInPopup){ 1786 selector = itemSelector+':visible .mb-open-popup[data-src]'; 1787 } 1788 1789 if(settings.popup == 'fancybox'){ 1790 /* 1791 Example on how to have a gallery popup per media-box
1792 Add these in a media-box for extra popup items: 1793 <div class="mb-open-popup" data-src="gallery/img-37.jpg"></div> 1794 <div class="mb-open-popup" data-src="gallery/img-38.jpg"></div> 1795 */ 1796 /* 1797 $container.find('.media-box, .media-box-hidden').each(function(){ 1798 selector = ".mb-open-popup[data-src]"; 1799 startFancybox($(this), selector); 1800 }); 1801 */ 1802 startFancybox($container, selector); 1803 } 1804 if(settings.popup == 'magnificpopup'){ 1805 startMagnificpopup($container, selector); 1806 } 1807 1808 } 1809 1810 /* ====================================================================== * 1811 [12] FANCYBOX 1812 * ====================================================================== */ 1813 1814 function startFancybox(container, selector){ 1815 1816 container.on('click', '.mb-open-popup', function(){ 1817 var visibleLinks = container.find(selector); 1818 1819 $.fancyboxMB.open( 1820 visibleLinks, 1821 { 1822 loop : settings.fancybox.loop, 1823 margin : settings.fancybox.margin, 1824 keyboard : settings.fancybox.keyboard, 1825 arrows : settings.fancybox.arrows, 1826 infobar : settings.fancybox.infobar, 1827 toolbar : settings.fancybox.toolbar, 1828 buttons : settings.fancybox.buttons, 1829 share : settings.fancybox.share, 1830 idleTime : settings.fancybox.idleTime, 1831 protect : settings.fancybox.protect, 1832 animationEffect : settings.fancybox.animationEffect, 1833 animationDuration : settings.fancybox.animationDuration, 1834 transitionEffect : settings.fancybox.transitionEffect, 1835 transitionDuration : settings.fancybox.transitionDuration, 1836 1837 // ====== MODULES =====> 1838 1839 slideShow : settings.fancybox.slideShow, 1840 fullScreen : settings.fancybox.fullScreen, 1841 thumbs : settings.fancybox.thumbs, 1842 touch : settings.fancybox.touch, 1843 1844 // ====== EVENTS =====> 1845 1846 afterShow : function(instance, slide){ 1847 1848 // Add alt attribute to lightbox image 1849 1850 if(slide.opts.$orig.attr('data-alt') != undefined){ 1851 slide.$image.attr('alt', slide.opts.$orig.attr('data-alt')); 1852 } 1853 1854 // Add hash to URL 1855 1856 set_hash_on_popup_change(slide.opts.$orig.attr('data-src')); 1857 1858 }, 1859 1860 beforeClose : function(instance, slide){ 1861 1862 // Remove hash from URL 1863 1864 if(settings.deepLinkingOnPopup){ 1865 remove_from_hash('('+slide.opts.$orig.parents('.media-boxes-container').attr('id')+'|popup)='); 1866 } 1867 1868 }, 1869 1870 onInit : function(){ 1871 1872 settings.onPopupStart(); 1873 1874 $(settings.fancybox.compensateScrollbar).each(function(){ 1875 $(this).css('padding-right', '+='+$('body').css('margin-right')); 1876 }); 1877 1878 }, 1879 1880 afterClose : function(){ 1881 1882 settings.onPopupClose(); 1883 1884 $(settings.fancybox.compensateScrollbar).each(function(){ 1885 $(this).css('padding-right', '-='+$('body').css('margin-right')); 1886 }); 1887 1888 }, 1889 1890 }, 1891 visibleLinks.index( this ) 1892 ); 1893 1894 return false;
1895 }); 1896 1897 $.fancyboxMB.defaults.hash = false; 1898 1899 } 1900 1901 /* ====================================================================== * 1902 [13] MAGNIFIC POPUP 1903 * ====================================================================== */ 1904 1905 function startMagnificpopup(container, selector){ 1906 1907 container.magnificPopup({ 1908 delegate : selector, // child items selector, by clicking on it popup will open 1909 type : 'image', 1910 removalDelay : 200, 1911 closeOnContentClick : false, 1912 alignTop : settings.magnificpopup.alignTop, 1913 preload : settings.magnificpopup.preload, 1914 tLoading : 'loading...', 1915 mainClass : 'my-mfp-slide-bottom', 1916 gallery : { enabled : settings.magnificpopup.gallery }, 1917 closeMarkup : '<button title="%title%" class="mfp-close"></button>', 1918 titleSrc : 'title', 1919 autoFocusLast : false, // in the new version of Magnific Popup on IE it jumps to the element that triggered the popup, which looks odd, so we better disable it 1920 iframe : { 1921 patterns : { 1922 youtube: { 1923 index: 'youtube.com/', // String that detects type of video (in this case YouTube). Simply via url.indexOf(index). 1924 id: 'v=', // String that splits URL in a two parts, second part should be %id% 1925 src: 'https://www.youtube.com/embed/%id%?autoplay=1' // URL that will be set as a source for iframe. 1926 }, 1927 vimeo: { 1928 index: 'vimeo.com/', 1929 id: '/', 1930 src: 'https://player.vimeo.com/video/%id%?autoplay=1' 1931 }, 1932 }, 1933 markup : '<div class="mfp-iframe-scaler">'+ 1934 '<div class="mfp-close"></div>'+ 1935 '<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+ 1936 '<div class="mfp-bottom-bar" style="margin-top:4px;"><div class="mfp-title"></div><div class="mfp-counter"></div></div>'+ 1937 '</div>' 1938 }, 1939 callbacks : { 1940 change : function() { 1941 var item = $(this.currItem.el); 1942 1943 setTimeout(function(){ 1944 $('.mfp-title').html(item.attr('mfp-title')); 1945 $('.mfp-img').attr('alt', item.attr('mfp-alt')); 1946 1947 addSocialButtons(item) 1948 }, 5); 1949 1950 set_hash_on_popup_change(item.attr('data-src')); 1951 }, 1952 close: function () { 1953 if(settings.deepLinkingOnPopup){ 1954 var item = $(this.currItem.el); 1955 remove_from_hash('('+item.parents('.media-boxes-container').attr('id')+'|popup)='); 1956 } 1957 }, 1958 // FIX SO THE BACKGROUND DOESN'T MOVE 1959 beforeOpen: function() { 1960 this.container.data('scrollTop', parseInt($(window).scrollTop())); 1961 }, 1962 open: function(){ 1963 $('html, body').scrollTop( this.container.data('scrollTop') ); 1964 }, 1965 }, 1966 }); 1967 1968 } 1969 1970 /* ====================================================================== * 1971 [14] DEEP LINKING 1972 * ====================================================================== */ 1973 1974 /* ### SET HAS WHEN FILTER, SEARCH OR POPUP CHANGE ### */ 1975 1976 function set_hash_on_filter_change(filterValue, filterGroup, is_default){ 1977 if( (filterGroup=='search' && settings.deepLinkingOnSearch) || (filterGroup!='search' && settings.deepLinkingOnFilter) ){ 1978 if(is_default === true){ 1979 remove_from_hash('('+$container.attr('id')+'|'+filterGroup+')='); 1980 }else{ 1981 set_key_and_value_in_hash('('+$container.attr('id')+'|'+filterGroup+')=', filterValue); 1982 } 1983 } 1984 } 1985 1986 function set_hash_on_popup_change(value){ 1987 if(settings.deepLinkingOnPopup){ 1988 set_key_and_value_in_hash('('+$container.attr('id')+'|popup)=', value); /* with the "src" of the image and the "id" of the container */ 1989 } 1990 } 1991 1992 /* ### INIT SEARCH, FILTER AND POPUP ### */ 1993 1994 function trigger_search(){ 1995 if(settings.deepLinkingOnSearch){ 1996 var key = '('+$container.attr('id')+'|search)='; 1997 var hash_value = get_value_from_hash(key); 1998 1999 if(hash_value != ''){ 2000 $(settings.search).val(hash_value).trigger('keyup'); 2001 } 2002 } 2003 } 2004 2005 trigger_search(); 2006 2007 function trigger_filter(){ 2008 if(settings.deepLinkingOnFilter){ 2009 $(settings.filterContainer).each(function(){ 2010 var current_filterContainer = $(this); 2011 var filterGroup = current_filterContainer.data("id") != undefined ? current_filterContainer.data("id") : "filter"; // take the id of the filter container if exists, if not just a string 2012 var key = '('+$container.attr('id')+'|'+filterGroup+')='; 2013 var hash_value = get_value_from_hash(key); 2014 2015 if(hash_value != ''){ 2016 if(current_filterContainer.is("select")){ // check if its a select element 2017 var val = current_filterContainer.find('*[data-filter="'+hash_value+'"]').val(); 2018 current_filterContainer.val(val).trigger('change'); 2019 }else if(current_filterContainer.is(":checkbox")){ // checkbox 2020 if(hash_value == '*'){ 2021 current_filterContainer.prop('checked', false).trigger('change'); 2022 }else{ 2023 current_filterContainer.prop('checked', true).trigger('change'); 2024 } 2025 //current_filterContainer.attr('data-filter', hash_value).trigger('click'); 2026 }else{ // dropdown menu or inline menu 2027 current_filterContainer.find('*[data-filter="'+hash_value+'"]').trigger('click'); 2028 } 2029 } 2030 }); 2031 } 2032 } 2033 2034 trigger_filter(); 2035 2036 function trigger_popup(){ 2037 if(settings.deepLinkingOnPopup){ 2038 var key = '('+$container.attr('id')+'|popup)='; 2039 var hash_value = get_value_from_hash(key); 2040 2041 if(hash_value != ''){ 2042 setTimeout(function(){ 2043 $container.find('.mb-open-popup[data-src="'+ hash_value +'"]').trigger('click'); 2044 }, 50); 2045 } 2046 } 2047 } 2048 2049 trigger_popup(); 2050 2051 /* ### HELPFUL METHODS ### */ 2052 2053 function set_hash(new_hash){ 2054 if(new_hash === '' || new_hash === '#' || new_hash === '!'){ 2055 /* if the hash will be empty then use this following peace of code, otherwise it will jump back to the top of the page if you set an empty result for the hash */ 2056 if(history.pushState) { 2057 history.pushState(null, null, ' '); 2058 }else{ 2059 location.hash = '#!'; 2060 } 2061 }else{ 2062 location.hash = '#' + new_hash; 2063 2064 /* This may be helpful later on (I found in a site it jumps to the beginning of the page the first time you change the hash, but in the examples is working like a charm) 2065 if(history.pushState) { 2066 history.pushState(null, null, '#'+ new_hash); 2067 }else{ 2068 location.hash = '#!'+ new_hash; 2069 } 2070 */ 2071 } 2072 } 2073 2074 function replace_in_hash(old_value, new_value){ 2075 var hash = get_hash(); 2076 2077 if(hash.indexOf(old_value) > -1 && old_value != ""){ // if the old value exists, then just replace it 2078 set_hash( hash.split(old_value).join(new_value) ); 2079 }else{ // if the old value doesn't exists then just add the new one 2080 set_hash( hash+new_value ); 2081 } 2082 } 2083 2084 function get_hash(){ 2085 if(location.href.indexOf("#") != -1){ 2086 //return decodeURI( location.href.split("#")[1] ); // this wouldn't work if there are more # in the hash 2087 return decodeURI( location.href.substring(location.href.indexOf('#')+1) ); 2088 }else{ 2089 return ''; 2090 } 2091 } 2092 2093 function get_value_and_key_from_hash(start){ 2094 var hash = get_hash(); 2095 var output = ''; 2096 var index_start = hash.indexOf(start); 2097 2098 if(index_start > -1 && hash.indexOf(';', index_start) > -1){ 2099 output = hash.substring(index_start, hash.indexOf(';', index_start)+1); 2100 } 2101 2102 return output; 2103 } 2104 2105 function get_value_from_hash(start){ 2106 var hash = get_hash(); 2107 var output = ''; 2108 var index_start = hash.indexOf(start); 2109 2110 if(index_start > -1 && hash.indexOf(';', index_start) > -1){ 2111 output = hash.substring(index_start+(start.length), hash.indexOf(';', index_start)) 2112 } 2113 2114 return output; 2115 } 2116 2117 function remove_from_hash(start){ 2118 var new_hash = get_hash().split( get_value_and_key_from_hash(start) ).join(''); 2119 set_hash(new_hash); 2120 } 2121 2122 function set_key_and_value_in_hash(start, value){ 2123 if(get_value_from_hash(start) == value){ 2124 // do nothing, since there's no change in the hash 2125 }else{ 2126 var old_value = get_value_and_key_from_hash(start); 2127 var new_value = start + value + ';'; // i.e. // (grid|popup)=some_image.png; 2128 replace_in_hash(old_value, new_value); 2129 } 2130 } 2131 2132 /* ====================================================================== * 2133 [15] SOCIAL IN MAGNIFIC POPUP 2134 * ====================================================================== */ 2135 2136 function addSocialButtons(item){ 2137 var FullURL = location.href; // the url of your page 2138 var URLWithoutHash = location.href.replace(location.hash,""); // the url of your page without the hashtag 2139 var imageURL = item.attr('data-src'); // the image URL 2140 2141 // which URL do you want to share of the 3 options above? 2142 // var sharingURL = URLWithoutHash+"/"+imageURL; 2143 var sharingURL = FullURL; 2144 2145 var social = "<div class='media-boxes-social-container'>"; 2146 if(settings.facebook != undefined){//FB 2147 social+="<div class='media-boxes-facebook fa fa-facebook-square' data-url='"+sharingURL+"'></div>"; 2148 } 2149 if(settings.twitter != undefined){//Twitter 2150 social+="<div class='media-boxes-twitter fa fa-twitter-square' data-url='"+sharingURL+"'></div>"; 2151 } 2152 if(settings.googleplus != undefined){//Google+ 2153 social+="<div class='media-boxes-googleplus fa fa-google-plus-square' data-url='"+sharingURL+"'></div>"; 2154 } 2155 if(settings.pinterest != undefined){//Pintrest 2156 social+="<div class='media-boxes-pinterest fa fa-pinterest-square' data-url='"+sharingURL+"'></div>"; 2157 } 2158 social+="</div>"; 2159 2160 var oldHTML = $('.mfp-title').html(); 2161 $('.mfp-title').html(oldHTML+social); 2162 } 2163 2164 // OPEN WINDOWS FOR SHARING :D 2165 var openWindow = function(url){ 2166 var w = window.open(url, "ftgw", "location=1,status=1,scrollbars=1,width=600,height=400"); 2167 w.moveTo((screen.width / 2) - (300), (screen.height / 2) - (200)); 2168 } 2169 2170 //FACEBOOK SHARE 2171 $('body').on('click', 'div.media-boxes-facebook', function(){ 2172 var $this = $(this); 2173 var url = encodeURIComponent($this.data('url')); 2174 url = 'https://www.facebook.com/sharer/sharer.php?u=' + url; 2175 openWindow(url); 2176 }); 2177 //TWITTER SHARE 2178 $('body').on('click', 'div.media-boxes-twitter', function(){ 2179 var $this = $(this); 2180 var url = encodeURIComponent($this.data('url')); 2181 url = "https://twitter.com/intent/tweet?url=&text=" + url; 2182 openWindow(url); 2183 }); 2184 //GOOGLE PLUS 2185 $('body').on('click', 'div.media-boxes-googleplus', function(){ 2186 var $this = $(this); 2187 var url = encodeURIComponent($this.data('url')); 2188 url = 'https://plus.google.com/share?url=' + url 2189 openWindow(url); 2190 }); 2191 //PINTREST 2192 $('body').on('click', 'div.media-boxes-pinterest', function(){ 2193 var $this = $(this); 2194 var url = encodeURIComponent($this.data('url')); 2195 url = 'http://pinterest.com/pin/create/button/?url=' + url + '&media=' + url; 2196 openWindow(url); 2197 }); 2198 2199 /* ====================================================================== * 2200 [D] DESTROY 2201 * ====================================================================== */ 2202 2203 this.destroy = function () { // Destroy grid and put it back as it were before being initialized 2204
2205 this.container_clone.insertBefore(this.container).removeData('mediaBoxes'); 2206 2207 this.container.removeClass(); // remove all classes! (if I don't the lazy load gets triggered) 2208 this.container.next('.media-boxes-load-more-button').remove(); 2209 this.container.isotopeMB('destroy'); 2210 this.container.remove(); 2211 2212 } 2213 2214 /* ====================================================================== * 2215 [E] INSERT 2216 * ====================================================================== */ 2217 2218 this.insert = function (content, callback) { // insert and load all content into the grid 2219 2220 var $container = this.container; 2221 2222 $container.isotopeMB( 'insert', $(content), function(){ 2223 callback(); 2224 $container.isotopeMB('layout'); 2225 }); 2226 2227 } 2228 2229 /* ====================================================================== * 2230 [F] INSERT IN FLOW 2231 * ====================================================================== */ 2232 2233 this.insert_in_flow = function (content, callback) { // insert more boxes and continue with the loadMore/lazyLoad effect 2234 2235 var $container = this.container; 2236 2237 $container.append( $(content).removeClass(itemClass).addClass(itemHiddenClass) ); 2238 2239 loadMoreButton.removeClass('media-boxes-no-more-entries'); 2240 2241 loadMore( settings.boxesToLoadStart, true ); 2242 2243 callback(); 2244 2245 } 2246 2247 /* ====================================================================== * 2248 [G] REFRESH 2249 * ====================================================================== */ 2250 2251 this.refresh = function () { // refresh layout grid only 2252 2253 this.container.isotopeMB('layout'); 2254 2255 } 2256 2257 /* ====================================================================== * 2258 [H] RESIZE 2259 * ====================================================================== */ 2260 2261 this.resize = function () { // refresh all the variables and things, its like resizing the browser width 2262 2263 this.container.isotopeMB('resize'); 2264 2265 } 2266 2267 };//END OF INIT 2268 2269/* ====================================================================== * 2270 [I] MEDIA BOXES PLUGIN 2271 * ====================================================================== */ 2272 2273 $.fn.mediaBoxes = function(options, content, callback) { 2274 2275 return this.each(function(key, value){ 2276 var $this = $(this); 2277 var data = $this.data('mediaBoxes') 2278 2279 // Initialize plugin 2280 if (!data && typeof options != 'string'){ 2281 $this.data('mediaBoxes', new MediaBoxes(this, options)); 2282 } 2283 2284 // Call method 2285 if (data && typeof options == 'string'){ 2286 data[options](content, callback); 2287 } 2288 }); 2289 2290 }; 2291 2292})( window, jQuery );
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.