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