PageSourceSearch

https://chinmayala.org/wp-content/plugins/wpeventplus/assets/scrip…/gridview/js/jquery.mediaBoxes.js?ver=1.0.0

js chinmayala.org collected 2026-10-07 15:19:58 UTC 68,992 bytes, 1,604 lines download raw bytes

1    
2/* ======================================================= 
3 *
4 *      Media Boxes     
5 *      Version: 2.6
6 *      By David Blanco
7 *
8 *      Contact: http://codecanyon.net/user/davidbo90
9 *      Created: March 11, 2014
10 *
11 *      Copyright (c) 2013, David Blanco. All rights reserved.
12 *      Available only in http://codecanyon.net/
13 *      
14 *      ---------------------------------
15 *      CONTENTS
16 *      ---------------------------------
17 *
18 *      [1] SETUP
19 *      [2] GRID METHODS
20 *      [3] EXTENGIN ISOTOPE
21 *      [4] FILTERING ISOTOPE
22 *      [5] LOAD MORE BOXES
23 *      [6] FILTER
24 *      [7] SEARCH
25 *      [8] SORT
26 *      [9] THUMBNAIL OVERLAY EFFECT
27 *      [10] MAGNIFIC POPUP
28 *      [11] DEEP LINKING
29 *      [12] SOCIAL IN MAGNIFIC POPUP
30 *      
31 * ======================================================= */
32
33
34// convert divs into images
35(function( window, $, undefined ){
36
37    var MediaBoxes = function(container, options){
38        
39    /* ====================================================================== *
40            [1] SETUP
41     * ====================================================================== */
42
43        /* SETTINGS */
44        var settings = $.extend({}, $.fn.mediaBoxes.defaults, options);
45
46        /* VARS */
47        var $container                  = $(container).addClass('media-boxes-container');        
48        var itemSelector                = '.media-box';
49        var boxImageSelector            = '.media-box-image';
50        var itemClass                   = 'media-box'; /* same as itemSelector but without the '.' */
51        var itemHiddenClass             = 'media-box-hidden';
52        var animation                   = Modernizr.csstransitions?'transition':'animate'; /* CSS3 transition or jQuery animate depending on the browser support */
53        var filters                     = {};
54        var loadingsCounter             = 0; /* When there's more than one loading at the same time */
55
56        if( settings.overlayEasing == 'default' ){
57            settings.overlayEasing = (animation=='transition')?'_default':'swing'; /* 'default' is for CSS3 and 'swing' for jQuery animate */
58        }
59        
60        /* LOAD MORE BUTTON */
61        var loadMoreButton              = $('<div class="media-boxes-load-more media-boxes-load-more-button"></div>').insertAfter($container);
62
63        /* Sort the resolutions from lower to higher */
64        settings.resolutions.sort(function(a,b){ return a.maxWidth - b.maxWidth; });
65
66        /* Save the settings in the container */
67        $container.data('settings', settings);
68        
69        /* Fix the margins for the container (for horizontal and vertical space)  */
70        $container
71            .css({
72                    'margin-left' : -settings.horizontalSpaceBetweenBoxes,
73                    //'margin-top'  : -settings.verticalSpaceBetweenBoxes,
74                });
75
76        /* Hide all boxes */
77        $container.find(itemSelector).removeClass(itemClass).addClass(itemHiddenClass);
78
79        /* default sort selected */
80        var defSortElem = $(settings.sortContainer).find(settings.sort).filter('.selected');
81        var defSort     = defSortElem.attr('data-sort-by');
82        var defAsc      = getSortDirection(defSortElem);
83
84        /* Add the sizer for defining the width of isotope */
85        $container.append('<div class="media-boxes-grid-sizer"></div>');
86
87        /* Initialize isotope plugin */
88        $container.isotopeMB({
89            itemSelector    : itemSelector,  
90            //transitionDuration: '0.3s',  
91            //filter: combineFilters(filters),     
92            masonry: {
93                columnWidth: '.media-boxes-grid-sizer'
94            },
95            getSortData: settings.getSortData,
96            sortBy: defSort, 
97            sortAscending: defAsc,     
98        }); 
99
100        //updateFilterClasses(); /* this is used for the popup, so it does show the images depending on the filter */
101
102    /* ====================================================================== *
103            [2] GRID METHODS
104     * ====================================================================== */
105
106        /* ****** Add the trigger for the magnific popup ****** */
107        function addPopupTrigger(container){
108
109            container.find(itemSelector+', .'+itemHiddenClass).find(boxImageSelector+':not([data-popupTrigger])').each(function(){
110                var boxImage        = $(this);
111                var popupDiv        = boxImage.find('div[data-popup]').eq(0); /* only one popup allowed */
112
113                boxImage.attr('data-popupTrigger', 'yes');
114                
115                var type = 'mfp-image';
116                if(popupDiv.data('type') == 'iframe'){
117                    type = 'mfp-iframe';
118                }else if(popupDiv.data('type') == 'inline'){
119                    type = 'mfp-inline';
120                }else if(popupDiv.data('type') == 'ajax'){
121                    type = 'mfp-ajax';
122                }
123
124                var popupTrigger = boxImage.find('.mb-open-popup').addBack('.mb-open-popup');
125                popupTrigger.attr('data-mfp-src', popupDiv.data('popup')).addClass(type);
126                if(popupDiv.attr('title') != undefined){
127                    popupTrigger.attr('mfp-title', popupDiv.attr('title'));
128                }
129            });
130
131        }
132
133        /* ****** Convert the divs with the URL specified to real images ****** */
134        function convertDivsIntoImages(container, imagesWithDimensions){
135            container.find(itemSelector).find(boxImageSelector+':not([data-imageconverted])').each(function(){
136                var boxImage        = $(this);
137                var thumbnailDiv    = boxImage.find('div[data-thumbnail]').eq(0); /* only one thumb allowed */
138                var popupDiv        = boxImage.find('div[data-popup]').eq(0); /* only one popup allowed */
139                var thumbSrc        = thumbnailDiv.data('thumbnail');
140
141                if(thumbnailDiv[0] == undefined){ /* if you haven't sepcified a thumbnail then take the image */
142                    thumbnailDiv   = popupDiv;
143                    thumbSrc    = popupDiv.data('popup');
144                }
145                
146                if( imagesWithDimensions == false && container.data('settings').waitForAllThumbsNoMatterWhat == false ){
147                    if( thumbnailDiv.data('width') == undefined && thumbnailDiv.data('height') == undefined ){
148                        /* Then we are good to go since we don't want images with dimenssions specified */
149                    }else{
150                        return;
151                        /* If you are here then nothing after this will be executed */
152                    }
153                }
154
155                boxImage.attr('data-imageconverted', 'yes');
156                
157                var thumbTitle = thumbnailDiv.attr('title');
158                if(thumbTitle == undefined){
159                    thumbTitle = thumbSrc;
160                }
161                var imgHTML   = $('<img title="'+ thumbTitle +'" src="'+ thumbSrc +'" />');
162
163                if(imagesWithDimensions == true){
164                    /* If the dmienssions are specified in the images then ignore them in the imagesLoaded plugin when you insert new items */
165                    imgHTML.attr('data-dont-wait-for-me', 'yes');
166
167                    thumbnailDiv.addClass('image-with-dimensions');
168
169                    if( container.data('settings').waitUntilThumbLoads ){
170                        imgHTML.hide();
171                    }
172                }
173
174                thumbnailDiv.addClass('media-box-thumbnail-container').prepend(imgHTML);
175            });
176
177            if(imagesWithDimensions == true){
178
179                    /* FadeIn the thumbnail or show broken thumbnail */
180                    function fadeInOrBroken(image){
181                        var $image          = $(image.img);
182                        var thumbnailDiv    = $image.parents('.image-with-dimensions');
183                        
184                        if(thumbnailDiv[0] == undefined){ /* If is undefined it means that it has already been loaded or broken so skip it */
185                            return;
186                        }
187
188                        if( image.isLoaded ){
189                            $image.fadeIn(400, function(){ /* This will only be trigger if you hide the image above (if the "waitUntilThumbLoads" settings is true) */
190                                thumbnailDiv.removeClass('image-with-dimensions'); 
191                            }); 
192                        }else{
193                            thumbnailDiv.removeClass('image-with-dimensions');
194                            $image.hide(); /* hide image since you are going to show a broken logo */
195                            thumbnailDiv.addClass('broken-image-here');
196                        }
197                    }
198
199                    /* FadeIn thumbnails that have dimensions specified if you want to show them after they have been loaded */
200                    container.find('.image-with-dimensions').imagesLoadedMB()
201                        .always(function(instance){
202                            
203                            /* In case the progress event don't get to show the images (this happens sometimes when you refresh the page) */
204                            for(index in instance.images){
205                                var image = instance.images[index];
206                                fadeInOrBroken(image);
207                            }
208
209                        })
210                        .progress(function(instance, image) {
211                            
212                            fadeInOrBroken(image);
213
214                        });
215
216            }
217
218        }
219
220        function setDimensionsToImageContainer(container){
221            container.find(itemSelector).each(function(){
222                var box             = $(this);
223
224                var boxImage        = box.find(boxImageSelector);
225                var thumbnailDiv    = boxImage.find('div[data-thumbnail]').eq(0); /* only one thumb allowed */
226                var popupDiv        = boxImage.find('div[data-popup]').eq(0); /* only one popup allowed */
227
228                if(thumbnailDiv[0] == undefined){ /* if you haven't sepcified a thumbnail then take the image */
229                    thumbnailDiv   = popupDiv;
230                }
231
232                var display = box.css('display');
233                if(display == 'none'){// If it is hidden, display to 'none' wont give you the right height so you need to do this trick
234                    box.css('margin-top', 99999999999999).show();
235                }
236
237                boxImage.width( thumbnailDiv.width() );
238                boxImage.height( thumbnailDiv.height() );
239
240                if(display == 'none'){
241                    box.css('margin-top', 0).hide();
242                }
243            });
244        }
245
246        /* ****** Calculate the right dimensions for the thumbnails ****** */
247        function setStaticDimensionsOfThumbnails(container){
248            
249            container.find(itemSelector).find(boxImageSelector).each(function(){
250                var boxImage        = $(this);
251                var thumbnailDiv    = boxImage.find('div[data-thumbnail]').eq(0); /* only one thumb allowed */
252                var popupDiv        = boxImage.find('div[data-popup]').eq(0); /* only one popup allowed */
253
254                if(thumbnailDiv[0] == undefined){ /* if you haven't sepcified a thumbnail then take the image */
255                    thumbnailDiv = popupDiv;
256                }
257                
258                var imgWidth    = parseFloat( thumbnailDiv.data('width') );
259                var imgHeight   = parseFloat( thumbnailDiv.data('height') );
260
261                var newWidth    = boxImage.parents(itemSelector).width() - container.data('settings').horizontalSpaceBetweenBoxes;
262                var newHeight   = (imgHeight * newWidth)/imgWidth;
263                
264                thumbnailDiv.css('width', newWidth);
265
266                /* Set the height only to those thumbs with width and height specified */ 
267                if( thumbnailDiv.data('width') != undefined || thumbnailDiv.data('height') != undefined ){
268                    thumbnailDiv.css('height', Math.floor(newHeight));
269                }
270            });
271
272        }
273        
274        /* ****** Set the width of the columns according to the settings specified ****** */
275        function setColumnWidth(container, columnWidth, columns){
276            var mediaBoxes = container.find(itemSelector);
277            var newWidth;
278            var percentage = false;
279
280            if( columnWidth == 'auto' ){
281                if(percentage){
282                    newWidth = 100/columns+'%';
283                }else{
284                   newWidth = Math.floor( (container.width()-1)/columns ); // minus 1px because some resolutions don't fit perfectly
285                }
286            }else{
287                newWidth = columnWidth;
288            }
289
290            /* the width that the isotope logic will use for each column of the grid */
291            container.find('.media-boxes-grid-sizer').css( 'width' , newWidth );
292            
293            mediaBoxes.each(function(index){
294                var $this       = $(this);
295                var boxColumns  = $this.data('columns');
296                
297                /* check for the number of columns on each box */
298                if(boxColumns != undefined && parseInt(columns)>=parseInt(boxColumns)){
299                    if(percentage){
300                        $this.css( 'width' , parseFloat(100/columns)*boxColumns+'%' );
301                    }else{
302                        $this.css( 'width' , newWidth*parseInt(boxColumns) );
303                    }
304                }else{
305                    if(percentage){
306                        $this.css( 'width' , 100/columns+'%' );
307                    }else{
308                        $this.css( 'width' , newWidth );
309                    }
310                }
311            });
312        }
313        
314        /* ****** Get viewport dimensions ****** */
315        function viewport() {
316            var e = window, a = 'inner';
317            if (!('innerWidth' in window )) {
318                a = 'client';
319                e = document.documentElement || document.body;
320            }
321            return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
322        }
323        
324        /* ****** Get and set the correct columnWidth for the current resolution ****** */
325        function getAndSetColumnWidth(container){
326            var resolutionFound = false;
327            for (var key in container.data('settings').resolutions) {
328                var value = container.data('settings').resolutions[key];
329                
330                if( value.maxWidth >= viewport().width ){
331                    setColumnWidth(container, value.columnWidth, value.columns);
332                    resolutionFound = true;
333                    break;
334                }
335            }
336            
337            /* If there wasn't a match then use the default one */
338            if( resolutionFound == false ){
339                setColumnWidth(container, container.data('settings').columnWidth, container.data('settings').columns);
340            }
341        }
342
343        /* ****** Add div with margins (for horizontal and vertical space) ****** */
344        function addWrapperForMargins(container){
345            var wrapper = $('<div class="media-box-container"></div')
346                            .css({
347                                    'margin-left' : container.data('settings').horizontalSpaceBetweenBoxes,
348                                    'margin-bottom'  : container.data('settings').verticalSpaceBetweenBoxes
349                                });
350
351            var boxes = container.find(itemSelector+':not([data-wrapper-added])').attr('data-wrapper-added', 'yes');
352            
353            boxes.wrapInner( wrapper );
354        }
355
356        /* ****** Set the overlay depending on the overlay effect before the hover event is trigger ****** */
357        function setupOverlayForHoverEffect(container){
358            if( container.data('settings').thumbnailOverlay == false ) return;
359
360            var boxes = container.find(itemSelector+':not([data-set-overlay-for-hover-effect])').attr('data-set-overlay-for-hover-effect', 'yes');
361
362            /* Add extra divs for vertical aliognment */
363            boxes.find('.thumbnail-overlay').wrapInner( "<div class='aligment'><div class='aligment'></div></div>" );
364
365            boxes.each(function(){
366
367                var box         = $(this);
368                var boxImage    = box.find(boxImageSelector);
369                var effect      = container.data('settings').overlayEffect;
370                if(boxImage.data('overlay-effect') != undefined){
371                    effect = boxImage.data('overlay-effect');
372                }
373
374                    /* Add wrapper for some effects */
375                    if( effect == 'push-up' || effect == 'push-down' || effect == 'push-up-100%' || effect == 'push-down-100%'  ){
376                        
377                            var thumbnailDiv        = boxImage.find('.media-box-thumbn
377ail-container');
378                            var thumbnailOverlay    = boxImage.find('.thumbnail-overlay').css('position', 'relative');
379                            if( effect == 'push-up-100%' || effect == 'push-down-100%' ){/* set the height of the overlay to the same of the thumbnail */
380                                thumbnailOverlay.outerHeight( thumbnailDiv.outerHeight(false) );
381                            }
382                            var heightOverlay       = thumbnailOverlay.outerHeight(false);
383                            
384
385
386                            var wrapper             = $('<div class="wrapper-for-some-effects"></div');
387
388                            if( effect == 'push-up' || effect == 'push-up-100%' ){
389                                thumbnailOverlay.appendTo(boxImage);    
390                            }else if( effect == 'push-down' || effect == 'push-down-100%'  ){
391                                thumbnailOverlay.prependTo(boxImage);    
392                                wrapper.css('margin-top', -heightOverlay);
393                            }
394                    
395                            boxImage.wrapInner( wrapper );
396
397                    }
398                    /* Set some CSS style for this effects */
399                    else if( effect == 'reveal-top' || effect == 'reveal-top-100%' ){
400                        
401                        box.addClass('position-reveal-effect');
402                        
403                        var overlay = box.find('.thumbnail-overlay').css('top', 0);
404                        if( effect == 'reveal-top-100%' ){
405                            overlay.css('height', '100%');
406                        }
407
408                    }else if( effect == 'reveal-bottom' || effect == 'reveal-bottom-100%' ){
409                        
410                        box.addClass('position-reveal-effect').addClass('position-bottom-reveal-effect');
411                        
412                        var overlay = box.find('.thumbnail-overlay').css('bottom', 0);
413                        if( effect == 'reveal-bottom-100%' ){
414                            overlay.css('height', '100%');
415                        }
416
417                    }else if( effect.substr(0, 9) == 'direction'){ // 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom'
418
419                        /* Set the height to 100% if not it would be just the default height of the overlay */
420                        box.find('.thumbnail-overlay').css('height', '100%');
421
422                    }else if( effect == 'fade' ){
423                        
424                        var thumbOverlay = box.find('.thumbnail-overlay').hide();
425                        thumbOverlay.css({
426                                            'height' : '100%',
427                                            'top'    : '0',
428                                            'left'   : '0',
429                                        });
430                        thumbOverlay.find('.fa').css({ scale : 1.4 });
431
432                    }
433
434            });
435
436        }
437
438        function hideOverlaysOnResize(container){
439            var boxes = container.find(itemSelector);
440
441            boxes.each(function(){
442                var box         = $(this);
443                var boxImage    = box.find(boxImageSelector);
444                var effect      = container.data('settings').overlayEffect;
445                if(boxImage.data('overlay-effect') != undefined){
446                    effect = boxImage.data('overlay-effect');
447                }
448
449                if( effect.substr(0, 9) == 'direction' ){
450                    boxImage.find('.thumbnail-overlay').hide();
451                }
452            });
453
454            /* reload isotope for the new width */
455            container.isotopeMB('layout');
456        }
457
458    /* ====================================================================== *
459            [3] EXTENDING ISOTOPE
460     * ====================================================================== */
461
462        /* ****** Extending Isotope on resize event ****** */
463        $.extend( IsotopeMB.prototype, {
464            resize : function() {
465                /* Hack for setting the right sizes of the column */
466                var container = $(this.element);
467                getAndSetColumnWidth(container);
468                setStaticDimensionsOfThumbnails(container);
469                setDimensionsToImageContainer(container);
470                hideOverlaysOnResize(container);
471                /* End hack */
472                
473                // don't trigger if size did not change
474                // or if resize was unbound. See #9
475                if ( !this.isResizeBound || !this.needsResizeLayout() ) {
476                    return;
477                }
478
479                this.layout();
480            }
481        });
482        
483        /* ****** Extending Isotope so when it does set the container width the plugin can refresh the lazy load feature ****** */
484        $.extend( IsotopeMB.prototype, {
485            _setContainerMeasure : function( measure, isWidth ) {
486                  if ( measure === undefined ) {
487                    return;
488                  }
489
490                  var elemSize = this.size;
491                  // add padding and border width if border box
492                  if ( elemSize.isBorderBox ) {
493                    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
494                      elemSize.borderLeftWidth + elemSize.borderRightWidth :
495                      elemSize.paddingBottom + elemSize.paddingTop +
496                      elemSize.borderTopWidth + elemSize.borderBottomWidth;
497                  }
498
499                  measure = Math.max( measure, 0 );
500                  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
501                  
502                  /* Hack to refresh the waypoint */
503                  var container = $(this.element);
504                  $.waypoints('refresh');
505                  container.addClass('lazy-load-ready');
506                  /* End hack */
507
508                  /* Remove this class since the grid has been resized due to the filtering system */
509                  container.removeClass('filtering-isotope');
510                  /* End Remove this class */
511            }
512        });
513
514        /* ****** Extending Isotope so when you insert items they got the right settings (like columnWidth, staticDimensions, convertDivsIntoImages, etc.) ****** */
515        $.extend( IsotopeMB.prototype, {
516            insert : function( elems, callback ) {
517                var items = this.addItems( elems );
518                if ( !items.length ) {
519                  return;
520                }   
521
522                /* Snippet (the insertBefore method so it is always ordered) */
523                var container   = $(this.element);
524                var firstHiddenBox = container.find('.'+itemHiddenClass)[0];
525                // append item elements
526                var i, item;
527                var len = items.length;
528                for ( i=0; i < len; i++ ) {
529                  item = items[i];
530                  if(firstHiddenBox != undefined){
531                    this.element.insertBefore( item.element, firstHiddenBox );
532                  }else{
533                    this.element.appendChild( item.element );
534                  }
535                } 
536                /* End Snippet */
537
538                var isotopeDefaultLogic = function(){
539                    // filter new stuff
540                    /*
541                    // this way adds hides new filtered items with NO transition
542                    // so user can't see if new hidden items have been inserted
543                    var filteredInsertItems;
544                    this._noTransition( function() {
545                      filteredInsertItems = this._filter( items );
546                      // hide all new items
547                      this.hide( filteredInsertItems );
548                    });
549                    // */
550                    // this way hides new filtered items with transition
551                    // so user at least sees that something has been added
552                    var filteredInsertItems = this._filter( items );
553                    // hide all newitems
554                    this._noTransition( function() {
555                      this.hide( filteredInsertItems );
556                    });
557                    // */
558                    // set flag
559                    for ( i=0; i < len; i++ ) {
560                      items[i].isLayoutInstant = true;
561                    }
562                    this.arrange();
563                    // reset flag
564                    for ( i=0; i < len; i++ ) {
565                      delete items[i].isLayoutInstant;
566                    }
567                    this.reveal( filteredInsertItems );
568                }
569
570                /* ======== Hack when inserting new boxes so they are properly converted ======== */
571                var checkForBrokenImages = function(image){
572                    var $image          = $(image.img);
573                    var thumbnailDiv    = $image.parents('div[data-thumbnail], div[data-popup]');
574
575                    if( image.isLoaded == false ){
576                        $image.hide();
577                        thumbnailDiv.addClass('broken-image-here');
578                    }
579                }
580
581
582
583                var instance    = this;
584                
585                /* Set the vertical and horizontal space between boxes */
586                addWrapperForMargins(container);
587                
588                /* Set the columnWidth and set the static dimensions of the images that have it specified */
589                getAndSetColumnWidth(container);
590                setStaticDimensionsOfThumbnails(container);
591
592                addPopupTrigger(container);
593                
594                convertDivsIntoImages(container, false); /* only the ones that have NO width and height */
595
596                container.find('img:not([data-dont-wait-for-me])').imagesLoadedMB()
597                    .always(function(){
598                        if( settings.waitForAllThumbsNoMatterWhat == false ){
599                            convertDivsIntoImages(container, true); /* the ones left that have width and height */                  
600                        }
601
602                        /* Add the class to show the box */
603                        container.find(itemSelector).addClass('media-box-loaded');
604
605                        /* Now you can call the default logic of the insert method from Isotope */
606                        isotopeDefaultLogic.call(instance);
607
608                        setDimensionsToImageContainer(container); /* set the same dimensions of the thumbnail to the container (for caption purposes) */
609
610                        setupOverlayForHoverEffect(container);
611
612                        /* Callback for inserting items */
613                        if (typeof callback === 'function'){
614                            callback();
615                        }
616
617                        /* In case the progress event don't get to check for broken images (this happens sometimes when you refresh the page) */
618                        for(index in instance.images){
619                            var image = instance.images[index];
620                            checkForBrokenImages(image);
621                        }
622                    })
623                    .progress(function( instance, image ) {
624                        /* For broken images */
625                        checkForBrokenImages(image);
626                    });
627                
628                /* ======== End Hack ======== */
629            }                  
630        });
631
632    /* ====================================================================== *
633            [4] FILTERING ISOTOPE
634     * ====================================================================== */
635
636        function updateFilterClasses(){
637            var boxes         = $container.find(itemSelector+', .'+itemHiddenClass);   
638            
639            var filter = getCurrentFilter();
640            boxes.filter( filter ).removeClass('hidden-media-boxes-by-filter').addClass('visible-media-boxes-by-filter');
641            boxes.not( filter ).addClass('hidden-media-boxes-by-filter').removeClass('visible-media-boxes-by-filter');
642        }
643
644        function filterTheBoxes( filterValue, filterGroup ){
645            /* Add a class until it resizes the grid */
646            $container.addClass('filtering-isotope');
647
648            // Combined the filters and filter isotope
649            goAndFilterIsotope(filterValue, filterGroup);
650
651            // update some CSS classes 
652            updateFilterClasses();
653
654            // Fix some details, like the loading button, the minBoxesPerFilter
655            seeItFiltered();
656        }
657
658        function seeItFiltered(){
659            // fix load more button
660            if( getLoadingBoxesInCurrentFilter().length > 0 ){
661                loading();
662            }else{
663                fixLoadMoreButton();
664            }
665
666            if( checkMinBoxesPerFilter() ){
667                /* it will load the missing boxes */
668            }
669        }
670
671        function goAndFilterIsotope(filterValue, filterGroup){
672            // set filter for group
673            filters[ filterGroup ] = filterValue;
674            
675            // set filters for Isotope
676            $container.isotopeMB({ filter: combineFilters(filters) });
677        }
678
679        function combineFilters( filters ) {
680            //Remove undefined values
681            for ( var prop in filters ) {
682                var filter = filters[ prop ];
683                if(filter == undefined){
684                    filters[ prop ] = '*';
685                }
686            }
687            
688            var longerFilter = ''; // i.e. navigation-bar 
689            for ( var prop in filters ) {
690                var filter = filters[ prop ];
691
692                if(longerFilter == ''){
693                    longerFilter = prop;
694                }else if( longerFilter.split(',').length < filter.split(',').length ){
695                    longerFilter = prop;
696                }
697            }
698
699            var combinedFilters = filters[longerFilter]; // i.e. .images, .sounds
700            for ( var prop in filters ) {
701                if(prop == longerFilter)continue;
702
703                var filterSplit = filters[ prop ].split(',');
704                for(var i=0; i<filterSplit.length; i++){
705
706                    var largerFilterSplit   = combinedFilters.split(',');
707                    var newFilter           = [];
708                    for(var j=0; j<largerFilterSplit.length; j++){
709                        if(largerFilterSplit[j] == '*' && filterSplit[i] == '*'){
710                            filterSplit[i] = '';
711                        }else{
712                            if(filterSplit[i] == '*'){
713                                filterSplit[i] = '';
714                            }   
715                            if(largerFilterSplit[j] == '*'){
716                                largerFilterSplit[j] = '';
717                            }
718                        }
719                        
720                        
721                        newFilter.push( largerFilterSplit[j]+filterSplit[i] );
722                    }
723                    combinedFilters = newFilter.join(',');
724                }
725            }
726
727            return combinedFilters;
728        }
729
730    /* ====================================================================== *
731            [5] LOAD MORE BOXES
732     * ====================================================================== */
733
734        function checkMinBoxesPerFilter(){
735
736            var boxesInCurrentCategory = getBoxesInCurrentFilter().length;
737
738            /* 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 */
739            if( boxesInCurrentCategory < settings.minBoxesPerFilter && hiddenBoxesWaitingToLoad().length > 0 ){
740                /* Load the boxes that are missing */
741                loadMore( settings.minBoxesPerFilter - boxesInCurrentCategory );
742
743                return true;
744            }
745
746            return false;
747        }
748
749        function getBoxesInCurrentFilter(){
750            var boxes = $container.find(itemSelector);   
751            var filter = getCurrentFilter();
752            if( filter != '*' ){
753                boxes = boxes.filter( filter );
754            }
755
756            return boxes;
757        }
758
759        function getLoadingBoxesInCurrentFilter(){
760            var boxes = getBoxesInCurrentFilter().not('.media-box-loaded');   
761
762            return boxes;
763        }
764
765        function getCurrentFilter(){
766            var filter = $container.data('isotopeMB').options.filter;
767            if( filter == '' || filter == undefined ){
768                filter = '*';
769            }
770
771            return filter;
772        }
773
774        function hiddenBoxesWaitingToLoad(ignoreFilter){ /* Number of hidden boxes waiting to get load, depending on the filter */
775            var boxes = $container.find('.'+itemHiddenClass);   
776
777            var filter = getCurrentFilter();
778            if( filter != '*' && ignoreFilter == undefined){
779                boxes = boxes.filter( filter );
780            }
781
782            return boxes;
783        }
784
785        function loading(){
786            loadMoreButton.html(settings.LoadingWord);
787            loadMoreButton.removeClass('media-boxes-load-more');
788            loadMoreButton.addClass('media-boxes-loading');
789        }
790
791        function startLoading(){
792            loadingsCounter++;
793
794            loading();
795        }
796
797        function finishLoading(){
798            loadingsCounter--;
799            if(loadingsCounter == 0){
800                fixLoadMoreButton();
801            }
802        }
803
804        function fixLoadMoreButton(){
805            loadMoreButton.removeClass('media-boxes-load-more');
806            loadMoreButton.removeClass('media-boxes-loading');
807            loadMoreButton.removeClass('media-boxes-no-more-entries');
808
809            if( hiddenBoxesWaitingToLoad().length > 0 ){
810                loadMoreButton.html(settings.loadMoreWord);
811                loadMoreButton.addClass('media-boxes-load-more'); 
812            }else{
813                loadMoreButton.html(settings.noMoreEntriesWord); 
814                loadMoreButton.addClass('media-boxes-no-more-entries');
815            }
816        }
817
818        function loadMore( boxesToLoad, ignoreFilter){
819            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 */
820                return;
821            }
822
823            /* Loading... */
824            startLoading();
825
826            /* The new boxes */
827            var newBoxes = [];
828
829            /* Boxes that will be loaded as part of isotope */
830            hiddenBoxesWaitingToLoad(ignoreFilter).each(function(index){
831                var $this = $(this);
832                if( (index+1) <=  boxesToLoad){ 
833                    $this.removeClass(itemHiddenClass).addClass(itemClass);
834                    $this.hide();
835                    newBoxes.push(this);
836                }
837            }); 
838            
839            $container.isotopeMB( 'insert', $(newBoxes), function(){
840                /* Fix Load More Button */   
841                finishLoading();
842
843                /* Force a relayout of Isotope */
844                $container.isotopeMB('layout');
845
846                // == START CUSTOMIZATION         REMEMBER: deepLinking:false , id of target1, target2 , hiddenStyle:{opacity:0,transform:"scale(0.001)"} 
847                /*if(firstTime == true && location.hash.substr(0, 2) == '#-'){
848                    var hash        = location.href.split('#-')[1];
849                    var scrollTo    = $container.find('#'+hash);
850
851                    if(scrollTo[0] != undefined){
852                        setTimeout(function(){ 
853                           $("body, html").animate({ 
854                                scrollTop: scrollTo.offset().top 
855                            }, 600);
856                        }, 500);
857                    }
858                }*/
859                // == END CUSTOMIZATION
860            });
861        }
862        loadMore( settings.boxesToLoadStart, true);
863        
864        /* Load more boxes when you click the button */
865        loadMoreButton.on('click', function(){
866            loadMore( settings.boxesToLoad );
867        });
868        
869
870        if( settings.lazyLoad ){
871
872            /* Load more boxes when you reach the bottom of the grid */
873            $container.waypoint(function(direction) {
874                if( $container.hasClass('lazy-load-ready') ){
875                    if( direction == 'down' && $container.hasClass('filtering-isotope') == false){
876                        $container.removeClass('lazy-load-ready');
877                        loadMore( settings.boxesToLoad );
878                    }
879                }
880             }, {
881                context: window,
882                continuous: true,
883                enabled: true,
884                horizontal: false,
885                offset: 'bottom-in-view',
886                triggerOnce: false,   
887             });
888
889        }
890
891    /* ====================================================================== *
892            [6] FILTER
893     * ====================================================================== */   
894
895        var filterContainer = $(settings.filterContainer);  
896
897        filterContainer.find(settings.filter).on('click', function(e){
898            var $this = $(this);
899            
900            /* Remove selected class from others */
901            var filterContainer = $this.parents(settings.filterContainer);
902            filterContainer.find(settings.filter).removeClass('selected');
903            
904            /* Add class of selected */
905            $this.addClass('selected');
906
907            /* Filter isotope */
908            var filterValue = $this.attr('data-filter');
909            var filterId = "filter";
910            if (filterContainer.data("id") != undefined) {
911                filterId = filterContainer.data("id")
912            }
913            filterTheBoxes( filterValue , filterId );
914
915            e.preventDefault();
916        });
917
918        /* DEFAULT FILTERS SELECTED */
919        filterContainer.each(function(){
920            var $this = $(this);
921            var f = $this.find(settings.filter).filter('.selected');
922            if(f[0]==undefined)return;
923
924            /* Filter isotope */
925            var filterValue = f.attr('data-filter');
926            var filterId = "filter";
927            if ($this.data("id") != undefined) {
928                filterId = $this.data("id")
929            }
930
931            //filters[ filterId ] = filterValue;
932            goAndFilterIsotope(filterValue, filterId);
933        });
934
935        seeItFiltered();
936
937        //var defFilter = filterContainer.find(settings.filter).filter('.selected').attr('data-filter');
938        //filters[ 'filter' ] = defFilter;
939
940        /* default search  selected */
941        search( $(settings.search).val() );
942
943    /* ====================================================================== *
944            [7] SEARCH
945     * ====================================================================== */     
946
947        function search(value){
948            if(value == undefined) return;
949
950            var allBoxes = $container.find('.'+itemClass+', .'+itemHiddenClass);
951            if(value == ''){
952                /* If there's nothing in the input text field then show all the boxes */
953                allBoxes.addClass('search-match');
954            }else{
955                allBoxes.removeClass('search-match');
956
957                $container.find(settings.searchTarget).each(function(){
958                    var $this = $(this);
959                    var box   = $this.parents('.'+itemClass+', .'+itemHiddenClass);
960                    if( $this.text().toLowerCase().indexOf(value.toLowerCase()) !== -1 ){
961                        box.addClass('search-match');
962                    }
963                });
964            }
965
966            setTimeout( function() {
967                filterTheBoxes('.search-match', 'search');
968            }, 100 );
969        }
970
971        $(settings.search).on('keyup', function(){
972            var value = $(this).val();
973
974            search( value );
975        });
976
977    /* ====================================================================== *
978            [8] SORTING
979     * ====================================================================== */     
980
981        function getSortDirection($this){
982            var direction = $this.data('sort-ascending');
983            if(direction == undefined){
984                direction = true;
985            }
986
987            if($this.data('sort-toggle') && $this.data('sort-toggle') == true){
988                $this.data('sort-ascending', !direction);
989            }
990
991            return direction;
992        }
993
994        $(settings.sortContainer).find(settings.sort).on('click', function(e){
995            var $this = $(this);
996
997            /* Remove selected class from others */
998            $this.parents(settings.sortContainer).find(settings.sort).removeClass('selected');
999            
1000            /* Add class of selected */
1001            $this.addClass('selected');
1002
1003            /* Sort isotope */
1004            var sortValue = $this.attr('data-sort-by');
1005            $container.isotopeMB({ sortBy: sortValue, sortAscending: getSortDirection($this) });
1006
1007            e.preventDefault();
1008        });
1009
1010    
1011    /* ====================================================================== *
1012            [9] THUMBNAIL OVERLAY EFFECT
1013     * ====================================================================== */    
1014
1015        function hideWhenDone(element){
1016            if( element.attr('data-stop') != undefined ){
1017                element.hide();
1018                element.removeAttr('data-stop');
1019            }
1020        }
1021
1022        $container.on( 'mouseenter.hoverdir, mouseleave.hoverdir', boxImageSelector, function(event){
1023            if( settings.thumbnailOverlay == false ) return;
1024
1025            var boxImage            = $(this);
1026            var effect              = settings.overlayEffect;
1027            if(boxImage.data('overlay-effect') != undefined){
1028                effect = boxImage.data('overlay-effect');
1029            }
1030            
1031            var eventType           = event.type;
1032            var thumbnailDiv        = boxImage.find('.media-box-thumbnail-container');
1033            var thumbnailOverlay    = boxImage.find('.thumbnail-overlay') ;
1034            var heightOverlay       = thumbnailOverlay.outerHeight(false);
1035            
1036            /* The effects */
1037            if( effect == 'push-up' || effect == 'push-up-100%' ){
1038                var wrapper = boxImage.find('div.wrapper-for-some-effects');
1039
1040                if( eventType === 'mouseenter' ) {
1041                    wrapper.stop().show()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 
1042                }else{
1043                    wrapper.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 
1044                }
1045            }
1046
1047            else if( effect == 'push-down' || effect == 'push-down-100%' ){
1048                var wrapper = boxImage.find('div.wrapper-for-some-effects');
1049
1050                if( eventType === 'mouseenter' ) {
1051                    wrapper.stop().show()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 
1052                }else{
1053                    wrapper.stop()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 
1054                }
1055            }
1056
1057            else if( effect == 'reveal-top' || effect == 'reveal-top-100%' ){
1058                if( eventType === 'mouseenter' ) {
1059                    thumbnailDiv.stop().show()[animation]({ 'margin-top': he
1059ightOverlay }, settings.overlaySpeed, settings.overlayEasing); 
1060                }else{
1061                    thumbnailDiv.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 
1062                }   
1063            }
1064
1065            else if( effect == 'reveal-bottom' || effect == 'reveal-bottom-100%' ){
1066                if( eventType === 'mouseenter' ) {
1067                    thumbnailDiv.stop().show()[animation]({ 'margin-top': -heightOverlay }, settings.overlaySpeed, settings.overlayEasing); 
1068                }else{
1069                    thumbnailDiv.stop()[animation]({ 'margin-top': 0 }, settings.overlaySpeed, settings.overlayEasing); 
1070                }   
1071            }
1072
1073            else if( effect.substr(0, 9) == 'direction' ){ // 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom'
1074                var direction   = _getDir( boxImage, { x : event.pageX, y : event.pageY } );
1075                
1076                if( effect == 'direction-top' ){
1077                    direction   = 0;
1078                }else if( effect == 'direction-bottom' ){
1079                    direction   = 2;
1080                }else if( effect == 'direction-right' ){
1081                    direction   = 1;
1082                }else if( effect == 'direction-left' ){
1083                    direction   = 3
1084                }
1085
1086                var cssPos      = _getPosition( direction, boxImage );
1087
1088                if( eventType == 'mouseenter' ){
1089                    thumbnailOverlay.css( { 'left' : cssPos.from, 'top' : cssPos.to } );
1090
1091                    thumbnailOverlay.stop().show().fadeTo(0, 1, function(){
1092                                                                    $(this).stop()[animation]({ 'left' : 0, 'top' : 0 }, settings.overlaySpeed, settings.overlayEasing); 
1093                                                                });
1094                }else{
1095                    if( effect == 'direction-aware-fade' ){
1096                        thumbnailOverlay.fadeOut(700);
1097                    }else{
1098                        thumbnailOverlay.stop()[animation]({ 'left' : cssPos.from, 'top' : cssPos.to }, settings.overlaySpeed, settings.overlayEasing ); 
1099                    }
1100                }
1101            }
1102
1103            else if( effect == 'fade' ){
1104
1105                if( eventType == 'mouseenter' ){
1106                    thumbnailOverlay.stop().fadeOut(0);
1107                    thumbnailOverlay.fadeIn( settings.overlaySpeed );
1108                }else{
1109                    thumbnailOverlay.stop().fadeIn(0);
1110                    thumbnailOverlay.fadeOut( settings.overlaySpeed );
1111                }
1112
1113                /* Effect of the icons */
1114                var icons = thumbnailOverlay.find('.fa');
1115                if( eventType == 'mouseenter' ){
1116                    icons.css({ scale: 1.4 }); 
1117                    icons[animation]({ scale: 1 }, 200); 
1118                }else{
1119                    icons.css({ scale: 1 }); 
1120                    icons[animation]({ scale: 1.4 }, 200); 
1121                }
1122            }
1123
1124
1125        });   
1126
1127
1128        /* ****** Methods for the direction-aware hover effect ****** */
1129
1130        var _getDir = function( $el, coordinates ) {
1131            /** the width and height of the current div **/
1132            var w = $el.width(),
1133                h = $el.height(),
1134
1135                /** calculate the x and y to get an angle to the center of the div from that x and y. **/
1136                /** gets the x value relative to the center of the DIV and "normalize" it **/
1137                x = ( coordinates.x - $el.offset().left - ( w/2 )) * ( w > h ? ( h/w ) : 1 ),
1138                y = ( coordinates.y - $el.offset().top  - ( h/2 )) * ( h > w ? ( w/h ) : 1 ),
1139            
1140                /** the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);**/
1141                /** first calculate the angle of the point, 
1142                add 180 deg to get rid of the negative values
1143                divide by 90 to get the quadrant
1144                add 3 and do a modulo by 4  to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
1145                direction = Math.round( ( ( ( Math.atan2(y, x) * (180 / Math.PI) ) + 180 ) / 90 ) + 3 )  % 4;
1146            
1147            return direction;
1148            
1149        };
1150
1151        var _getPosition = function( direction, $el ) {
1152            var fromLeft, fromTop;
1153            switch( direction ) {
1154                case 0:
1155                    // from top
1156                    if ( !settings.reverse ) { 
1157                            fromLeft = 0, fromTop = - $el.height() 
1158                    }else {  
1159                            fromLeft = 0, fromTop = - $el.height()  
1160                    }
1161                    break;
1162                case 1:
1163                    // from right
1164                    if ( !settings.reverse ) { 
1165                            fromLeft = $el.width()  , fromTop = 0
1166                    }else {  
1167                            fromLeft = - $el.width() , fromTop = 0 
1168                    }
1169                    break;
1170                case 2:
1171                    // from bottom
1172                    if ( !settings.reverse ) { 
1173                            fromLeft = 0 , fromTop = $el.height() 
1174                    }
1175                    else {  
1176                            fromLeft = 0, fromTop = - $el.height()  
1177                    }
1178                    break;
1179                case 3:
1180                    // from left
1181                    if ( !settings.reverse ) {
1182                            fromLeft = -$el.width()  , fromTop = 0
1183                    }
1184                    else {  
1185                            fromLeft =  $el.width(), fromTop = 0 
1186                    }
1187                    break;
1188            };
1189            return { from : fromLeft, to: fromTop };
1190        }; 
1191
1192
1193    /* ====================================================================== *
1194            [10] MAGNIFIC POPUP
1195     * ====================================================================== */
1196
1197        var delegate = '.mb-open-popup[data-mfp-src]';
1198        
1199        if(settings.considerFilteringInPopup){
1200            delegate = itemSelector+':not(.hidden-media-boxes-by-filter) .mb-open-popup[data-mfp-src], .'+itemHiddenClass+':not(.hidden-media-boxes-by-filter) .mb-open-popup[data-mfp-src]';
1201        }
1202        if(settings.showOnlyLoadedBoxesInPopup){
1203            delegate = itemSelector+':visible .mb-open-popup[data-mfp-src]';
1204        }
1205
1206        if(settings.magnificPopup){
1207
1208            $container.magnificPopup({
1209                delegate: delegate, // child items selector, by clicking on it popup will open
1210                type: 'image',
1211                removalDelay : 200,
1212                closeOnContentClick : false,
1213                alignTop: settings.alignTop,
1214                preload: settings.preload,
1215                mainClass : 'my-mfp-slide-bottom',
1216                gallery:{
1217                    enabled:settings.gallery
1218                },
1219                closeMarkup : '<button title="%title%" class="mfp-close"></button>',
1220                titleSrc: 'title',
1221                iframe : {
1222                    patterns : {
1223                        youtube: {
1224                          index: 'youtube.com/', // String that detects type of video (in this case YouTube). Simply via url.indexOf(index).
1225
1226                          id: 'v=', // String that splits URL in a two parts, second part should be %id%
1227                          // Or null - full URL will be returned
1228                          // Or a function that should return %id%, for example:
1229                          // id: function(url) { return 'parsed id'; } 
1230
1231                          src: 'https://www.youtube.com/embed/%id%?autoplay=1' // URL that will be set as a source for iframe. 
1232                        },
1233                        vimeo: {
1234                          index: 'vimeo.com/',
1235                          id: '/',
1236                          src: 'https://player.vimeo.com/video/%id%?autoplay=1'
1237                        },
1238                    },
1239                    markup : '<div class="mfp-iframe-scaler">'+
1240                                    '<div class="mfp-close"></div>'+
1241                                    '<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+
1242                                    '<div class="mfp-bottom-bar" style="margin-top:4px;"><div class="mfp-title"></div><div class="mfp-counter"></div></div>'+
1243                             '</div>'                      
1244                },
1245                callbacks : {
1246                    change : function() {
1247                        var item    = $(this.currItem.el);
1248                        setTimeout(function(){ 
1249                            if(item.attr('mfp-title') != undefined){
1250                                $('.mfp-title').html(item.attr('mfp-title'));    
1251                            }else{
1252                                $('.mfp-title').html('');
1253                            }
1254
1255                            // ==== SOCIAL BUTTONS ==== //
1256
1257                            var FullURL             = location.href; // the url of your page
1258                            var URLWithoutHash      = location.href.replace(location.hash,""); // the url of your page without the hashtag
1259                            var imageURL            = item.attr('data-mfp-src'); // the image URL
1260
1261                            // which URL do you want to share of the 3 options above?
1262                            var sharingURL = FullURL;
1263
1264
1265                            var social = "<div class='media-boxes-social-container'>";
1266                            if(settings.facebook != undefined){//FB
1267                              social+="<div class='media-boxes-facebook fa fa-facebook-square' data-url='"+sharingURL+"'></div>";
1268                            }
1269                            if(settings.twitter != undefined){//Twitter
1270                              social+="<div class='media-boxes-twitter fa fa-twitter-square' data-url='"+sharingURL+"'></div>";
1271                            }
1272                            if(settings.googleplus != undefined){//Google+
1273                              social+="<div class='media-boxes-googleplus fa fa-google-plus-square' data-url='"+sharingURL+"'></div>";
1274                            }
1275                            if(settings.pinterest != undefined){//Pintrest
1276                              social+="<div class='media-boxes-pinterest fa fa-pinterest-square' data-url='"+sharingURL+"'></div>";
1277                            }
1278                            social+="</div>";
1279
1280                            var oldHTML = $('.mfp-title').html();
1281                            $('.mfp-title').html(oldHTML+social);
1282
1283                            // ==== END SOCIAL BUTTONS ==== //
1284
1285
1286                        }, 5);
1287
1288                        if(settings.deepLinking){
1289                            location.hash   = '#!' + item.attr('data-mfp-src') + '||' + item.parents('.media-boxes-container').attr('id'); /* with the "src" of the image and the "id" of the container */
1290                        }
1291                    },
1292                    beforeOpen: function() {
1293                        this.container.data('scrollTop', parseInt($(window).scrollTop()));
1294                    },
1295                    open: function(){
1296                        $('html, body').scrollTop( this.container.data('scrollTop') );
1297                    },
1298                    close: function () {
1299                        if(settings.deepLinking){
1300                            window.location.hash = '#!';
1301                        }
1302                    },
1303                },
1304            });
1305
1306        }
1307
1308    /* ====================================================================== *
1309            [11] DEEP LINKING
1310     * ====================================================================== */
1311
1312        if(settings.deepLinking){
1313        
1314                function urlFromHash() {
1315                    if (location.hash.substr(0, 2) != '#!') {
1316                        return null;
1317                    }
1318                    // why not location.hash? => http://stackoverflow.com/q/4835784/298479
1319                    var hash    = location.href.split('#!')[1];
1320                    var id      = hash.split('||')[1];
1321                    var src     = hash.split('||')[0];
1322                    return {
1323                        hash: hash,
1324                        id: id,
1325                        src: src
1326                    };
1327                }
1328
1329                var hashUrl = urlFromHash();
1330                if (hashUrl) {
1331                    $container.filter('[id="' + hashUrl.id + '"]').find('.mb-open-popup[data-mfp-src="' + hashUrl.src + '"]').trigger('click');
1332                }
1333
1334                function doHash() {
1335                    var mp = $.magnificPopup.instance;
1336                    if (!mp) {
1337                        // this check is not needed in this example, but in some cases you might delay everything before
1338                        // this event e.g. until something else finished loading - in that case hashchange might trigger before
1339                        return;
1340                    }
1341                    
1342                    var url = urlFromHash();
1343                    if (!url && mp.isOpen) {
1344                        // no url => close popup
1345                        mp.close();
1346                    } else if (url) {
1347                        if ( mp.isOpen && mp.currItem && mp.currItem.el.parents('.media-boxes-container').attr('id') == url.id ) {
1348                            if( mp.currItem.el.attr('data-mfp-src') != url.src ){
1349                                // open => only update if necessary
1350                                var index = null;
1351                                $.each(mp.items, function (i, item) {
1352                                    var jqItem = item.parsed ? item.el : $(item);
1353                                    if (jqItem.attr('data-mfp-src') == url.src) {
1354                                        index = i;
1355                                        return false;
1356                                    }
1357                                });
1358                                if (index !== null) {
1359                                    mp.goTo(index);
1360                                }
1361                            }else{
1362                                // is already in the correct one
1363                            }
1364                        }else{
1365                            // not open or doesn't match the right one => simply click the matching link
1366                            $container.filter('[id="' + url.id + '"]').find('.mb-open-popup[data-mfp-src="' + url.src + '"]').trigger('click');
1367                        }
1368                    }
1369                }
1370
1371                if (window.addEventListener) {
1372                    window.addEventListener("hashchange", doHash, false);
1373                } else if (window.attachEvent) {
1374                    window.attachEvent("onhashchange", doHash);  
1375                }
1376
1377        }
1378
1379    /* ====================================================================== *
1380            [12] SOCIAL IN MAGNIFIC POPUP
1381     * ====================================================================== */
1382
1383        // OPEN WINDOWS FOR SHARING :D
1384        var openWindow = function(url){
1385            var w = window.open(url, "ftgw", "location=1,status=1,scrollbars=1,width=600,height=400");
1386            w.moveTo((screen.width / 2) - (300), (screen.height / 2) - (200));
1387        }
1388
1389        //FACEBOOK SHARE
1390        $('body').on('click', 'div.media-boxes-facebook', function(){
1391            var $this = $(this);
1392            var url = encodeURIComponent($this.data('url'));
1393            url = 'https://www.facebook.com/sharer/sharer.php?u=' + url;
1394            openWindow(url);
1395        });
1396        //TWITTER SHARE
1397        $('body').on('click', 'div.media-boxes-twitter', function(){
1398            var $this = $(this);
1399            var url = encodeURIComponent($this.data('url'));
1400            url = "https://twitter.com/intent/tweet?url=&text=" + url;
1401            openWindow(url);
1402        });
1403        //GOOGLE PLUS
1404        $('body').on('click', 'div.media-boxes-googleplus', function(){
1405            var $this = $(this);
1406            var url = encodeURIComponent($this.data('url'));
1407            url = 'https://plus.google.com/share?url=' + url
1408            openWindow(url);
1409        });
1410        //PINTREST
1411        $('body').on('click', 'div.media-boxes-pinterest', function(){
1412            var $this = $(this);
1413            var url = encodeURIComponent($this.data('url'));
1414            url = 'http://pinterest.com/pin/create/button/?url=' + url + '&media=' + url;
1415            openWindow(url);
1416        });
1417
1418
1419
1420
1421
1422
1423
1424        return this;
1425
1426    };//END OF FUSION OBJECT
1427    
1428
1429     $.fn.mediaBoxes = function(options) {
1430
1431        return this.each(function(key, value){
1432            var element = $(this);
1433            // Return early if this element already has a plugin instance
1434            if (element.data('mediaBoxes')) return element.data('mediaBoxes');
1435            // Pass options to plugin constructor
1436            var mediaBoxes = new MediaBoxes(this, options);
1437            // Store plugin object in this element's data
1438            element.data('mediaBoxes', mediaBoxes);
1439        });
1440
1441    };
1442    
1443    //Default settings
1444    $.fn.mediaBoxes.defaults = {
1445        boxesToLoadStart: 8,
1446        boxesToLoad: 4,
1447        minBoxesPerFilter: 0,
1448        lazyLoad: true,
1449        horizontalSpaceBetweenBoxes: 15,
1450        verticalSpaceBetweenBoxes: 15,
1451        columnWidth: 'auto',
1452        columns: 4,
1453        resolutions: [
1454            {
1455                maxWidth: 960,
1456                columnWidth: 'auto',
1457                columns: 3,
1458            },
1459            {
1460                maxWidth: 650,
1461                columnWidth: 'auto',
1462                columns: 2,
1463            },
1464            {
1465                maxWidth: 450,
1466                columnWidth: 'auto',
1467                columns: 1,
1468            },
1469        ],
1470        filterContainer: '#filter',
1471        filter: 'a',
1472        search: '', // i.e. #search
1473        searchTarget: '.media-box-title',
1474        sortContainer: '', // i.e. #sort
1475        sort: 'a',
1476        getSortData: {
1477          title: '.media-box-title',
1478          text: '.media-box-text',
1479        }, 
1480        waitUntilThumbLoads: true, // When they have dimensions specified
1481        waitForAllThumbsNoMatterWhat: false, // Wait for all the thumbnails to load even if they got dimensions specified
1482        thumbnailOverlay: true, //Show the overlay on mouse over
1483        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'
1484        overlaySpeed: 200,
1485        overlayEasing: 'default',
1486        showOnlyLoadedBoxesInPopup: false,
1487        considerFilteringInPopup: true,
1488        deepLinking: true,
1489        gallery: true,
1490        LoadingWord: 'Loading...',
1491        loadMoreWord: 'Load More',
1492        noMoreEntriesWord: 'No More Entries',
1493        alignTop: false,
1494        preload: [0,2],
1495        magnificPopup: true,
1496
1497        //some sharing hidden options :D
1498        /*facebook: true,
1499        twitter: true,
1500        googleplus: true,
1501        pinterest: true,*/
1502    };
1503
1504
1505
1506
1507    /* DROP DOWN PLUGIN */
1508
1509    (function(){
1510
1511
1512        /* CHECK FOR MOBILE BROWSER */ 
1513        function isMobileBrowser() {
1514            var check = false;
1515            (function(a){
1516                if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))
1517                    check = true
1518                }
1519            )(navigator.userAgent||navigator.vendor||window.opera);
1520            return check; 
1521        }
1522
1523        function start($wrapper){
1524            var $menu           = $wrapper.find('.media-boxes-drop-down-menu');
1525            var $header         = $wrapper.find('.media-boxes-drop-down-header');
1526            
1527            function mouseout(){
1528                $menu.hide(); 
1529            };
1530
1531            function mouseover(){
1532                $menu.show();
1533            };
1534
1535            function updateHeader(){
1536                var $selectedDefault    = $menu.find( '.selected' );
1537                var $selected           = $selectedDefault.length ? $selectedDefault.parents('li') : $menu.children().first();
1538
1539                
1540                $header.html( $selected.clone().find('a').append('<span class="fa fa-sort-desc"></span>').end().html() );
1541            }
1542            updateHeader();
1543
1544            function click(e){
1545                e.preventDefault();
1546                e.stopPropagation();
1547                
1548                $(this).parents('li').siblings('li').find('a').removeClass('selected').end().end().find('a').addClass('selected');
1549                updateHeader();
1550
1551                //mouseout();
1552            }
1553
1554            if(isMobileBrowser()){
1555
1556                function clickToggle(e){
1557                    e.stopPropagation();
1558
1559                    if($menu.is(":visible")){
1560                        mouseout();
1561                    }else{
1562                        mouseover();
1563                    }
1564                }
1565
1566                $('body').on('click', function(){
1567                    if($menu.is(":visible")){
1568                        mouseout();
1569                    }
1570                })
1571
1572                $header
1573                    .bind('click', clickToggle);
1574
1575                $menu.find('> li > *')
1576                    .bind('click', click);
1577            }else{
1578                $header
1579                    .bind('mouseout', mouseout)
1580                    .bind('mouseover', mouseover);
1581
1582                $menu.find('> li > *')
1583                    .bind('mouseout', mouseout)
1584                    .bind('mouseover', mouseover)
1585                    .bind('click', click);
1586            }
1587
1588            $header.on('click', 'a', function(e){
1589                e.preventDefault();
1590                //return false;
1591            });
1592
1593        }
1594
1595
1596        $('.media-boxes-drop-down').each(function(){
1597            start($(this));
1598        });
1599
1600    })();
1601
1602
1603    
1604})( 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.