PageSourceSearch

https://lencrenoir.com/wp-content/plugins/wp_auto_grid/plugin/components/Media%20Boxes/js/jquery.mediaBoxes.js

js lencrenoir.com collected 2026-09-27 20:57:58 UTC 91,206 bytes, 2,015 lines download raw bytes

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.