PageSourceSearch

https://www.playleague.it/wp-content/themes/sport/js/jquery.isotope.js?ver=7.0.6

js playleague.it collected 2026-09-24 11:06:34 UTC 44,493 bytes, 1,401 lines download raw bytes

1/**
2 * Isotope v1.5.19
3 * An exquisite jQuery plugin for magical layouts
4 * http://isotope.metafizzy.co
5 *
6 * Commercial use requires one-time license fee
7 * http://metafizzy.co/#licenses
8 *
9 * Copyright 2012 David DeSandro / Metafizzy
10 */
11
12/*jshint asi: true, browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */
13/*global jQuery: false */
14
15(function( window, $, undefined ){
16
17  'use strict';
18
19  // get global vars
20  var document = window.document;
21  var Modernizr = window.Modernizr;
22
23  // helper function
24  var capitalize = function( str ) {
25    return str.charAt(0).toUpperCase() + str.slice(1);
26  };
27
28  // ========================= getStyleProperty by kangax ===============================
29  // http://perfectionkills.com/feature-testing-css-properties/
30
31  var prefixes = 'Moz Webkit O Ms'.split(' ');
32
33  var getStyleProperty = function( propName ) {
34    var style = document.documentElement.style,
35        prefixed;
36
37    // test standard property first
38    if ( typeof style[propName] === 'string' ) {
39      return propName;
40    }
41
42    // capitalize
43    propName = capitalize( propName );
44
45    // test vendor specific properties
46    for ( var i=0, len = prefixes.length; i < len; i++ ) {
47      prefixed = prefixes[i] + propName;
48      if ( typeof style[ prefixed ] === 'string' ) {
49        return prefixed;
50      }
51    }
52  };
53
54  var transformProp = getStyleProperty('transform'),
55      transitionProp = getStyleProperty('transitionProperty');
56
57
58  // ========================= miniModernizr ===============================
59  // <3<3<3 and thanks to Faruk and Paul for doing the heavy lifting
60
61  /*!
62   * Modernizr v1.6ish: miniModernizr for Isotope
63   * http://www.modernizr.com
64   *
65   * Developed by:
66   * - Faruk Ates  http://farukat.es/
67   * - Paul Irish  http://paulirish.com/
68   *
69   * Copyright (c) 2009-2010
70   * Dual-licensed under the BSD or MIT licenses.
71   * http://www.modernizr.com/license/
72   */
73
74  /*
75   * This version whittles down the script just to check support for
76   * CSS transitions, transforms, and 3D transforms.
77  */
78
79  var tests = {
80    csstransforms: function() {
81      return !!transformProp;
82    },
83
84    csstransforms3d: function() {
85      var test = !!getStyleProperty('perspective');
86      // double check for Chrome's false positive
87      if ( test ) {
88        var vendorCSSPrefixes = ' -o- -moz- -ms- -webkit- -khtml- '.split(' '),
89            mediaQuery = '@media (' + vendorCSSPrefixes.join('transform-3d),(') + 'modernizr)',
90            $style = $('<style>' + mediaQuery + '{#modernizr{height:3px}}' + '</style>')
91                        .appendTo('head'),
92            $div = $('<div id="modernizr" />').appendTo('html');
93
94        test = $div.height() === 3;
95
96        $div.remove();
97        $style.remove();
98      }
99      return test;
100    },
101
102    csstransitions: function() {
103      return !!transitionProp;
104    }
105  };
106
107  var testName;
108
109  if ( Modernizr ) {
110    // if there's a previous Modernzir, check if there are necessary tests
111    for ( testName in tests) {
112      if ( !Modernizr.hasOwnProperty( testName ) ) {
113        // if test hasn't been run, use addTest to run it
114        Modernizr.addTest( testName, tests[ testName ] );
115      }
116    }
117  } else {
118    // or create new mini Modernizr that just has the 3 tests
119    Modernizr = window.Modernizr = {
120      _version : '1.6ish: miniModernizr for Isotope'
121    };
122
123    var classes = ' ';
124    var result;
125
126    // Run through tests
127    for ( testName in tests) {
128      result = tests[ testName ]();
129      Modernizr[ testName ] = result;
130      classes += ' ' + ( result ?  '' : 'no-' ) + testName;
131    }
132
133    // Add the new classes to the <html> element.
134    $('html').addClass( classes );
135  }
136
137
138  // ========================= isoTransform ===============================
139
140  /**
141   *  provides hooks for .css({ scale: value, translate: [x, y] })
142   *  Progressively enhanced CSS transforms
143   *  Uses hardware accelerated 3D transforms for Safari
144   *  or falls back to 2D transforms.
145   */
146
147  if ( Modernizr.csstransforms ) {
148
149        // i.e. transformFnNotations.scale(0.5) >> 'scale3d( 0.5, 0.5, 1)'
150    var transformFnNotations = Modernizr.csstransforms3d ?
151      { // 3D transform functions
152        translate : function ( position ) {
153          return 'translate3d(' + position[0] + 'px, ' + position[1] + 'px, 0) ';
154        },
155        scale : function ( scale ) {
156          return 'scale3d(' + scale + ', ' + scale + ', 1) ';
157        }
158      } :
159      { // 2D transform functions
160        translate : function ( position ) {
161          return 'translate(' + position[0] + 'px, ' + position[1] + 'px) ';
162        },
163        scale : function ( scale ) {
164          return 'scale(' + scale + ') ';
165        }
166      }
167    ;
168
169    var setIsoTransform = function ( elem, name, value ) {
170          // unpack current transform data
171      var data =  $.data( elem, 'isoTransform' ) || {},
172          newData = {},
173          fnName,
174          transformObj = {},
175          transformValue;
176
177      // i.e. newData.scale = 0.5
178      newData[ name ] = value;
179      // extend new value over current data
180      $.extend( data, newData );
181
182      for ( fnName in data ) {
183        transformValue = data[ fnName ];
184        transformObj[ fnName ] = transformFnNotations[ fnName ]( transformValue );
185      }
186
187      // get proper order
188      // ideally, we could loop through this give an array, but since we only have
189      // a couple transforms we're keeping track of, we'll do it like so
190      var translateFn = transformObj.translate || '',
191          scaleFn = transformObj.scale || '',
192          // sorting so translate always comes first
193          valueFns = translateFn + scaleFn;
194
195      // set data back in elem
196      $.data( elem, 'isoTransform', data );
197
198      // set name to vendor specific property
199      elem.style[ transformProp ] = valueFns;
200    };
201
202    // ==================== scale ===================
203
204    $.cssNumber.scale = true;
205
206    $.cssHooks.scale = {
207      set: function( elem, value ) {
208        // uncomment this bit if you want to properly parse strings
209        // if ( typeof value === 'string' ) {
210        //   value = parseFloat( value );
211        // }
212        setIsoTransform( elem, 'scale', value );
213      },
214      get: function( elem, computed ) {
215        var transform = $.data( elem, 'isoTransform' );
216        return transform && transform.scale ? transform.scale : 1;
217      }
218    };
219
220    $.fx.step.scale = function( fx ) {
221      $.cssHooks.scale.set( fx.elem, fx.now+fx.unit );
222    };
223
224
225    // ==================== translate ===================
226
227    $.cssNumber.translate = true;
228
229    $.cssHooks.translate = {
230      set: function( elem, value ) {
231
232        // uncomment this bit if you want to properly parse strings
233        // if ( typeof value === 'string' ) {
234        //   value = value.split(' ');
235        // }
236        //
237        // var i, val;
238        // for ( i = 0; i < 2; i++ ) {
239        //   val = value[i];
240        //   if ( typeof val === 'string' ) {
241        //     val = parseInt( val );
242        //   }
243        // }
244
245        setIsoTransform( elem, 'translate', value );
246      },
247
248      get: function( elem, computed ) {
249        var transform = $.data( elem, 'isoTransform' );
250        return transform && transform.translate ? transform.translate : [ 0, 0 ];
251      }
252    };
253
254  }
255
256  // ========================= get transition-end event ===============================
257  var transitionEndEvent, transitionDurProp;
258
259  if ( Modernizr.csstransitions ) {
260    transitionEndEvent = {
261      WebkitTransitionProperty: 'webkitTransitionEnd',  // webkit
262      MozTransitionProperty: 'transitionend',
263      OTransitionProperty: 'oTransitionEnd',
264      transitionProperty: 'transitionEnd'
265    }[ transitionProp ];
266
267    transitionDurProp = getStyleProperty('transitionDuration');
268  }
269
270  // ========================= smartresize ===============================
271
272  /*
273   * smartresize: debounced resize event for jQuery
274   *
275   * latest version and complete README available on Github:
276   * https://github.com/louisremi/jquery.smartresize.js
277   *
278   * Copyright 2011 @louis_remi
279   * Licensed under the MIT license.
280   */
281
282  var $event = $.event,
283      resizeTimeout;
284
285  $event.special.smartresize = {
286    setup: function() {
287      $(this).bind( "resize", $event.special.smartresize.handler );
288    },
289    teardown: function() {
290      $(this).unbind( "resize", $event.special.smartresize.handler );
291    },
292    handler: function( event, execAsap ) {
293      // Save the context
294      var context = this,
295          args = arguments;
296
297      // set correct event type
298      event.type = "smartresize";
299
300      if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
301      resizeTimeout = setTimeout(function() {
302        jQuery.event.handle.apply( context, args );
303      }, execAsap === "execAsap"? 0 : 100 );
304    }
305  };
306
307  $.fn.smartresize = function( fn ) {
308    return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
309  };
310
311
312
313// ========================= Isotope ===============================
314
315
316  // our "Widget" object constructor
317  $.Isotope = function( options, element, callback ){
318    this.element = $( element );
319
320    this._create( options );
321    this._init( callback );
322  };
323
324  // styles of container element we want to keep track of
325  var isoContainerStyles = [ 'width', 'height' ];
326
327  var $window = $(window);
328
329  $.Isotope.settings = {
330    resizable: true,
331    layoutMode : 'masonry',
332    containerClass : 'isotope',
333    itemClass : 'isotope-item',
334    hiddenClass : 'isotope-hidden',
335    hiddenStyle: { opacity: 0, scale: 0.001 },
336    visibleStyle: { opacity: 1, scale: 1 },
337    containerStyle: {
338      position: 'relative',
339      overflow: 'hidden'
340    },
341    animationEngine: 'best-available',
342    animationOptions: {
343      queue: false,
344      duration: 800
345    },
346    sortBy : 'original-order',
347    sortAscending : true,
348    resizesContainer : true,
349    transformsEnabled: !$.browser.opera, // disable transforms in Opera
350    itemPositionDataEnabled: false
351  };
352
353  $.Isotope.prototype = {
354
355    // sets up widget
356    _create : function( options ) {
357
358      this.options = $.extend( {}, $.Isotope.settings, options );
359
360      this.styleQueue = [];
361      this.elemCount = 0;
362
363      // get original styles in case we re-apply them in .destroy()
364      var elemStyle = this.element[0].style;
365      this.originalStyle = {};
366      // keep track of container styles
367      var containerStyles = isoContainerStyles.slice(0);
368      for ( var prop in this.options.containerStyle ) {
369        containerStyles.push( prop );
370      }
371      for ( var i=0, len = containerStyles.length; i < len; i++ ) {
372        prop = containerStyles[i];
373        this.originalStyle[ prop ] = elemStyle[ prop ] || '';
374      }
375      // apply container style from options
376      this.element.css( this.options.containerStyle );
377
378      this._updateAnimationEngine();
379      this._updateUsingTransforms();
380
381      // sorting
382      var originalOrderSorter = {
383        'original-order' : function( $elem, instance ) {
384          instance.elemCount ++;
385          return instance.elemCount;
386        },
387        random : function() {
388          return Math.random();
389        }
390      };
391
392      this.options.getSortData = $.extend( this.options.getSortData, originalOrderSorter );
393
394      // need to get atoms
395      this.reloadItems();
396
397      // get top left position of where the bricks should be
398      this.offset = {
399        left: parseInt( ( this.element.css('padding-left') || 0 ), 10 ),
400        top: parseInt( ( this.element.css('padding-top') || 0 ), 10 )
401      };
402
403      // add isotope class first time around
404      var instance = this;
405      setTimeout( function() {
406        instance.element.addClass( instance.options.containerClass );
407      }, 0 );
408
409      // bind resize method
410      if ( this.options.resizable ) {
411        $window.bind( 'smartresize.isotope', function() {
412          instance.resize();
413        });
414      }
415
416      // dismiss all click events from hidden events
417      this.element.delegate( '.' + this.options.hiddenClass, 'click', function(){
418        return false;
419      });
420
421    },
422
423    _getAtoms : function( $elems ) {
424      var selector = this.options.itemSelector,
425          // filter & find
426          $atoms = selector ? $elems.filter( selector ).add( $elems.find( selector ) ) : $elems,
427          // base style for atoms
428          atomStyle = { position: 'absolute' };
429
430      if ( this.usingTransforms ) {
431        atomStyle.left = 0;
432        atomStyle.top = 0;
433      }
434
435      $atoms.css( atomStyle ).addClass( this.options.itemClass );
436
437      this.updateSortData( $atoms, true );
438
439      return $atoms;
440    },
441
442    // _init fires when your instance is first created
443    // (from the constructor above), and when you
444    // attempt to initialize the widget again (by the bridge)
445    // after it has already been initialized.
446    _init : function( callback ) {
447
448      this.$filteredAtoms = this._filter( this.$allAtoms );
449      this._sort();
450      this.reLayout( callback );
451
452    },
453
454    option : function( opts ){
455      // change options AFTER initialization:
456      // signature: $('#foo').bar({ cool:false });
457      if ( $.isPlainObject( opts ) ){
458        this.options = $.extend( true, this.options, opts );
459
460        // trigger _updateOptionName if it exists
461        var updateOptionFn;
462        for ( var optionName in opts ) {
463          updateOptionFn = '_update' + capitalize( optionName );
464          if ( this[ updateOptionFn ] ) {
465            this[ updateOptionFn ]();
466          }
467        }
468      }
469    },
470
471    // ====================== updaters ====================== //
472    // kind of like setters
473
474    _updateAnimationEngine : function() {
475      var animationEngine = this.options.animationEngine.toLowerCase().replace( /[ _\-]/g, '');
476      var isUsingJQueryAnimation;
477      // set applyStyleFnName
478      switch ( animationEngine ) {
479        case 'css' :
480        case 'none' :
481          isUsingJQueryAnimation = false;
482          break;
483        case 'jquery' :
484          isUsingJQueryAnimation = true;
485          break;
486        default : // best available
487          isUsingJQueryAnimation = !Modernizr.csstransitions;
488      }
489      this.isUsingJQueryAnimation = isUsingJQueryAnimation;
490      this._updateUsingTransforms();
491    },
492
493    _updateTransformsEnabled : function() {
494      this._updateUsingTransforms();
495    },
496
497    _updateUsingTransforms : function() {
498      var usingTransforms = this.usingTransforms = this.options.transformsEnabled &&
499        Modernizr.csstransforms && Modernizr.csstransitions && !this.isUsingJQueryAnimation;
500
501      // prevent scales when transforms are disabled
502      if ( !usingTransforms ) {
503        delete this.options.hiddenStyle.scale;
504        delete this.options.visibleStyle.scale;
505      }
506
507      this.getPositionStyles = usingTransforms ? this._translate : this._positionAbs;
508    },
509
510
511    // ====================== Filtering ======================
512
513    _filter : function( $atoms ) {
514      var filter = this.options.filter === '' ? '*' : this.options.filter;
515
516      if ( !filter ) {
517        return $atoms;
518      }
519
520      var hiddenClass    = this.options.hiddenClass,
521          hiddenSelector = '.' + hiddenClass,
522          $hiddenAtoms   = $atoms.filter( hiddenSelector ),
523          $atomsToShow   = $hiddenAtoms;
524
525      if ( filter !== '*' ) {
526        $atomsToShow = $hiddenAtoms.filter( filter );
527        var $atomsToHide = $atoms.not( hiddenSelector ).not( filter ).addClass( hiddenClass );
528        this.styleQueue.push({ $el: $atomsToHide, style: this.options.hiddenStyle });
529      }
530
531      this.styleQueue.push({ $el: $atomsToShow, style: this.options.visibleStyle });
532      $atomsToShow.removeClass( hiddenClass );
533
534      return $atoms.filter( filter );
535    },
536
537    // ====================== Sorting ======================
538
539    updateSortData : function( $atoms, isIncrementingElemCount ) {
540      var instance = this,
541          getSortData = this.options.getSortData,
542          $this, sortData;
543      $atoms.each(function(){
544        $this = $(this);
545        sortData = {};
546        // get value for sort data based on fn( $elem ) passed in
547        for ( var key in getSortData ) {
548          if ( !isIncrementingElemCount && key === 'original-order' ) {
549            // keep original order original
550            sortData[ key ] = $.data( this, 'isotope-sort-data' )[ key ];
551          } else {
552            sortData[ key ] = getSortData[ key ]( $this, instance );
553          }
554        }
555        // apply sort data to element
556        $.data( this, 'isotope-sort-data', sortData );
557      });
558    },
559
560    // used on all the filtered atoms
561    _sort : function() {
562
563      var sortBy = this.options.sortBy,
564          getSorter = this._getSorter,
565          sortDir = this.options.sortAscending ? 1 : -1,
566          sortFn = function( alpha, beta ) {
567            var a = getSorter( alpha, sortBy ),
568                b = getSorter( beta, sortBy );
569            // fall back to original order if data matches
570            if ( a === b && sortBy !== 'original-order') {
571              a = getSorter( alpha, 'original-order' );
572              b = getSorter( beta, 'original-order' );
573            }
574            return ( ( a > b ) ? 1 : ( a < b ) ? -1 : 0 ) * sortDir;
575          };
576
577      this.$filteredAtoms.sort( sortFn );
578    },
579
580    _getSorter : function( elem, sortBy ) {
581      return $.data( elem, 'isotope-sort-data' )[ sortBy ];
582    },
583
584    // ====================== Layout Helpers ======================
585
586    _translate : function( x, y ) {
587      return { translate : [ x, y ] };
588    },
589
590    _positionAbs : function( x, y ) {
591      return { left: x, top: y };
592    },
593
594    _pushPosition : function( $elem, x, y ) {
595      x = Math.round( x + this.offset.left );
596      y = Math.round( y + this.offset.top );
597      var position = this.getPositionStyles( x, y );
598      this.styleQueue.push({ $el: $elem, style: position });
599      if ( this.options.itemPositionDataEnabled ) {
600        $elem.data('isotope-item-position', {x: x, y: y} );
601      }
602    },
603
604
605    // ====================== General Layout ======================
606
607    // used on collection of atoms (should be filtered, and sorted before )
608    // accepts atoms-to-be-laid-out to start with
609    layout : function( $elems, callback ) {
610
611      var layoutMode = this.options.layoutMode;
612
613      // layout logic
614      this[ '_' +  layoutMode + 'Layout' ]( $elems );
615
616      // set the size of the container
617      if ( this.options.resizesContainer ) {
618        var containerStyle = this[ '_' +  layoutMode + 'GetContainerSize' ]();
619        this.styleQueue.push({ $el: this.element, style: containerStyle });
620      }
621
622      this._processStyleQueue( $elems, callback );
623
624      this.isLaidOut = true;
625    },
626
627    _processStyleQueue : function( $elems, callback ) {
628      // are we animating the layout arrangement?
629      // use plugin-ish syntax for css or animate
630      var styleFn = !this.isLaidOut ? 'css' : (
631            this.isUsingJQueryAnimation ? 'animate' : 'css'
632          ),
633          animOpts = this.options.animationOptions,
634          onLayout = this.options.onLayout,
635          objStyleFn, processor,
636          triggerCallbackNow, callbackFn;
637
638      // default styleQueue processor, may be overwritten down below
639      processor = function( i, obj ) {
640        obj.$el[ styleFn ]( obj.style, animOpts );
641      };
642
643      if ( this._isInserting && this.isUsingJQueryAnimation ) {
644        // if using styleQueue to insert items
645        processor = function( i, obj ) {
646          // only animate if it not being inserted
647          objStyleFn = obj.$el.hasClass('no-transition') ? 'css' : styleFn;
648          obj.$el[ objStyleFn ]( obj.style, animOpts );
649        };
650
651      } else if ( callback || onLayout || animOpts.complete ) {
652        // has callback
653        var isCallbackTriggered = false,
654            // array of possible callbacks to trigger
655            callbacks = [ callback, onLayout, animOpts.complete ],
656            instance = this;
657        triggerCallbackNow = true;
658        // trigger callback only once
659        callbackFn = function() {
660          if ( isCallbackTriggered ) {
661            return;
662          }
663          var hollaback;
664          for (var i=0, len = callbacks.length; i < len; i++) {
665            hollaback = callbacks[i];
666            if ( typeof hollaback === 'function' ) {
667              hollaback.call( instance.element, $elems, instance );
668            }
669          }
670          isCallbackTriggered = true;
671        };
672
673        if ( this.isUsingJQueryAnimation && styleFn === 'animate' ) {
674          // add callback to animation options
675          animOpts.complete = callbackFn;
676          triggerCallbackNow = false;
677
678        } else if ( Modernizr.csstransitions ) {
679          // detect if first item has transition
680          var i = 0,
681              firstItem = this.styleQueue[0],
682              testElem = firstItem && firstItem.$el,
683              styleObj;
684          // get first non-empty jQ object
685          while ( !testElem || !testElem.length ) {
686            styleObj = this.styleQueue[ i++ ];
687            // HACK: sometimes styleQueue[i] is undefined
688            if ( !styleObj ) {
689              return;
690            }
691            testElem = styleObj.$el;
692          }
693          // get transition duration of the first element in that object
694          // yeah, this is inexact
695          var duration = parseFloat( getComputedStyle( testElem[0] )[ transitionDurProp ] );
696          if ( duration > 0 ) {
697            processor = function( i, obj ) {
698              obj.$el[ styleFn ]( obj.style, animOpts )
699                // trigger callback at transition end
700                .one( transitionEndEvent, callbackFn );
701            };
702            triggerCallbackNow = false;
703          }
704        }
705      }
706
707      // process styleQueue
708      $.each( this.styleQueue, processor );
709
710      if ( triggerCallbackNow ) {
711        callbackFn();
712      }
713
714      // clear out queue for next time
715      this.styleQueue = [];
716    },
717
718
719    resize : function() {
720      if ( this[ '_' + this.options.layoutMode + 'ResizeChanged' ]() ) {
721        this.reLayout();
722      }
723    },
724
725
726    reLayout : function( callback ) {
727
728      this[ '_' +  this.options.layoutMode + 'Reset' ]();
729      this.layout( this.$filteredAtoms, callback );
730
731    },
732
733    // ====================== Convenience methods ======================
734
735    // ====================== Adding items ======================
736
737    // adds a jQuery object of items to a isotope container
738    addItems : function( $content, callback ) {
739      var $newAtoms = this._getAtoms( $content );
740      // add new atoms to atoms pools
741      this.$allAtoms = this.$allAtoms.add( $newAtoms );
742
743      if ( callback ) {
744        callback( $newAtoms );
745      }
746    },
747
748    // convienence method for adding elements properly to any layout
749    // positions items, hides them, then animates them back in <--- very sezzy
750    insert : function( $content, callback ) {
751      // position items
752      this.element.append( $content );
753
754      var instance = this;
755      this.addItems( $content, function( $newAtoms ) {
756        var $newFilteredAtoms = instance._filter( $newAtoms );
757        instance._addHideAppended( $newFilteredAtoms );
758        instance._sort();
759        instance.reLayout();
760        instance._revealAppended( $newFilteredAtoms, callback );
761      });
762
763    },
764
765    // convienence method for working with Infinite Scroll
766    appended : function( $content, callback ) {
767      var instance = this;
768      this.addItems( $content, function( $newAtoms ) {
769        instance._addHideAppended( $newAtoms );
770        instance.layout( $newAtoms );
771        instance._revealAppended( $newAtoms, callback );
772      });
773    },
774
775    // adds new atoms, then hides them before positioning
776    _addHideAppended : function( $newAtoms ) {
777      this.$filteredAtoms = this.$filteredAtoms.add( $newAtoms );
778      $newAtoms.addClass('no-transition');
779
780      this._isInserting = true;
781
782      // apply hidden styles
783      this.styleQueue.push({ $el: $newAtoms, style: this.options.hiddenStyle });
784    },
785
786    // sets visible style on new atoms
787    _revealAppended : function( $newAtoms, callback ) {
788      var instance = this;
789      // apply visible style after a sec
790      setTimeout( function() {
791        // enable animation
792        $newAtoms.removeClass('no-transition');
793        // reveal newly inserted filtered elements
794        instance.styleQueue.push({ $el: $newAtoms, style: instance.options.visibleStyle });
795        instance._isInserting = false;
796        instance._processStyleQueue( $newAtoms, callback );
797      }, 10 );
798    },
799
800    // gathers all atoms
801    reloadItems : function() {
802      this.$allAtoms = this._getAtoms( this.element.children() );
803    },
804
805    // removes elements from Isotope widget
806    remove: function( $content, callback ) {
807      // remove elements from Isotope instance in callback
808      var instance = this;
809      // remove() as a callback, for after transition / animation
810      var removeContent = function() {
811        instance.$allAtoms = instance.$allAtoms.not( $content );
812        $content.remove();
813        if ( callback ) {
814          callback.call( instance.element );
815        }
816      };
817
818      if ( $content.filter( ':not(.' + this.options.hiddenClass + ')' ).length ) {
819        // if any non-hidden content needs to be removed
820        this.styleQueue.push({ $el: $content, style: this.options.hiddenStyle });
821        this.$filteredAtoms = this.$filteredAtoms.not( $content );
822        this._sort();
823        this.reLayout( removeContent );
824      } else {
825        // remove it now
826        removeContent();
827      }
828
829    },
830
831    shuffle : function( callback ) {
832      this.updateSortData( this.$allAtoms );
833      this.options.sortBy = 'random';
834      this._sort();
835      this.reLayout( callback );
836    },
837
838    // destroys widget, returns elements and container back (close) to original style
839    destroy : function() {
840
841      var usingTransforms = this.usingTransforms;
842      var options = this.options;
843
844      this.$allAtoms
845        .removeClass( options.hiddenClass + ' ' + options.itemClass )
846        .each(function(){
847          var style = this.style;
848          style.position = '';
849          style.top = '';
850          style.left = '';
851          style.opacity = '';
852          if ( usingTransforms ) {
853            style[ transformProp ] = '';
854          }
855        });
856
857      // re-apply saved container styles
858      var elemStyle = this.element[0].style;
859      for ( var prop in this.originalStyle ) {
860        elemStyle[ prop ] = this.originalStyle[ prop ];
861      }
862
863      this.element
864        .unbind('.isotope')
865        .undelegate( '.' + options.hiddenClass, 'click' )
866        .removeClass( options.containerClass )
867        .removeData('isotope');
868
869      $window.unbind('.isotope');
870
871    },
872
873
874    // ====================== LAYOUTS ======================
875
876    // calculates number of rows or columns
877    // requires columnWidth or rowHeight to be set on namespaced object
878    // i.e. this.masonry.columnWidth = 200
879    _getSegments : function( isRows ) {
880      var namespace = this.options.layoutMode,
881          measure  = isRows ? 'rowHeight' : 'columnWidth',
882          size     = isRows ? 'height' : 'width',
883          segmentsName = isRows ? 'rows' : 'cols',
884          containerSize = this.element[ size ](),
885          segments,
886                    // i.e. options.masonry && options.masonry.columnWidth
887          segmentSize = this.options[ namespace ] && this.options[ namespace ][ measure ] ||
888                    // or use the size of the first item, i.e. outerWidth
889                    this.$filteredAtoms[ 'outer' + capitalize(size) ](true) ||
890                    // if there's no items, use size of container
891                    containerSize;
892
893      segments = Math.floor( containerSize / segmentSize );
894      segments = Math.max( segments, 1 );
895
896      // i.e. this.masonry.cols = ....
897      this[ namespace ][ segmentsName ] = segments;
898      // i.e. this.masonry.columnWidth = ...
899      this[ namespace ][ measure ] = segmentSize;
900
901    },
902
903    _checkIfSegmentsChanged : function( isRows ) {
904      var namespace = this.options.layoutMode,
905          segmentsName = isRows ? 'rows' : 'cols',
906          prevSegments = this[ namespace ][ segmentsName ];
907      // update cols/rows
908      this._getSegments( isRows );
909      // return if updated cols/rows is not equal to previous
910      return ( this[ namespace ][ segmentsName ] !== prevSegments );
911    },
912
913    // ====================== Masonry ======================
914
915    _masonryReset : function() {
916      // layout-specific props
917      this.masonry = {};
918      // FIXME shouldn't have to call this again
919      this._getSegments();
920      var i = this.masonry.cols;
921      this.masonry.colYs = [];
922      while (i--) {
923        this.masonry.colYs.push( 0 );
924      }
925    },
926
927    _masonryLayout : function( $elems ) {
928      var instance = this,
929          props = instance.masonry;
930      $elems.each(function(){
931        var $this  = $(this),
932            //how many columns does this brick span
933            colSpan = Math.ceil( $this.outerWidth(true) / props.columnWidth );
934        colSpan = Math.min( colSpan, props.cols );
935
936        if ( colSpan === 1 ) {
937          // if brick spans only one column, just like singleMode
938          instance._masonryPlaceBrick( $this, props.colYs );
939        } else {
940          // brick spans more than one column
941          // how many different places could this brick fit horizontally
942          var groupCount = props.cols + 1 - colSpan,
943              groupY = [],
944              groupColY,
945              i;
946
947          // for each group potential horizontal position
948          for ( i=0; i < groupCount; i++ ) {
949            // make an array of colY values for that one group
950            groupColY = props.colYs.slice( i, i+colSpan );
951            // and get the max value of the array
952            groupY[i] = Math.max.apply( Math, groupColY );
953          }
954
955          instance._masonryPlaceBrick( $this, groupY );
956        }
957      });
958    },
959
960    // worker method that places brick in the columnSet
961    //   with the the minY
962    _masonryPlaceBrick : function( $brick, setY ) {
963      // get the minimum Y value from the columns
964      var minimumY = Math.min.apply( Math, setY ),
965          shortCol = 0;
966
967      // Find index of short column, the first from the left
968      for (var i=0, len = setY.length; i < len; i++) {
969        if ( setY[i] === minimumY ) {
970          shortCol = i;
971          break;
972        }
973      }
974
975      // position the brick
976      var x = this.masonry.columnWidth * shortCol,
977          y = minimumY;
978      this._pushPosition( $brick, x, y );
979
980      // apply setHeight to necessary columns
981      var setHeight = minimumY + $brick.outerHeight(true),
982          setSpan = this.masonry.cols + 1 - len;
983      for ( i=0; i < setSpan; i++ ) {
984        this.masonry.colYs[ shortCol + i ] = setHeight;
985      }
986
987    },
988
989    _masonryGetContainerSize : function() {
990      var containerHeight = Math.max.apply( Math, this.masonry.colYs );
991      return { height: containerHeight };
992    },
993
994    _masonryResizeChanged : function() {
995      return this._checkIfSegmentsChanged();
996    },
997
998    // ====================== fitRows ======================
999
1000    _fitRowsReset : function() {
1001      this.fitRows = {
1002        x : 0,
1003        y : 0,
1004        height : 0
1005      };
1006    },
1007
1008    _fitRowsLayout : function( $elems ) {
1009      var instance = this,
1010          containerWidth = this.element.width(),
1011          props = this.fitRows;
1012
1013      $elems.each( function() {
1014        var $this = $(this),
1015            atomW = $this.outerWidth(true),
1016            atomH = $this.outerHeight(true);
1017
1018        if ( props.x !== 0 && atomW + props.x > containerWidth ) {
1019          // if this element cannot fit in the current row
1020          props.x = 0;
1021          props.y = props.height;
1022        }
1023
1024        // position the atom
1025        instance._pushPosition( $this, props.x, props.y );
1026
1027        props.height = Math.max( props.y + atomH, props.height );
1028        props.x += atomW;
1029
1030      });
1031    },
1032
1033    _fitRowsGetContainerSize : function () {
1034      return { height : this.fitRows.height };
1035    },
1036
1037    _fitRowsResizeChanged : function() {
1038      return true;
1039    },
1040
1041
1042    // ====================== cellsByRow ======================
1043
1044    _cellsByRowReset : function() {
1045      this.cellsByRow = {
1046        index : 0
1047      };
1048      // get this.cellsByRow.columnWidth
1049      this._getSegments();
1050      // get this.cellsByRow.rowHeight
1051      this._getSegments(true);
1052    },
1053
1054    _cellsByRowLayout : function( $elems ) {
1055      var instance = this,
1056          props = this.cellsByRow;
1057      $elems.each( function(){
1058        var $this = $(this),
1059            col = props.index % props.cols,
1060            row = Math.floor( props.index / props.cols ),
1061            x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2,
1062            y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2;
1063        instance._pushPosition( $this, x, y );
1064        props.index ++;
1065      });
1066    },
1067
1068    _cellsByRowGetContainerSize : function() {
1069      return { height : Math.ceil( this.$filteredAtoms.length / this.cellsByRow.cols ) * this.cellsByRow.rowHeight + this.offset.top };
1070    },
1071
1072    _cellsByRowResizeChanged : function() {
1073      return this._checkIfSegmentsChanged();
1074    },
1075
1076
1077    // ====================== straightDown ======================
1078
1079    _straightDownReset : function() {
1080      this.straightDown = {
1081        y : 0
1082      };
1083    },
1084
1085    _straightDownLayout : function( $elems ) {
1086      var instance = this;
1087      $elems.each( function( i ){
1088        var $this = $(this);
1089        instance._pushPosition( $this, 0, instance.straightDown.y );
1090        instance.straightDown.y += $this.outerHeight(true);
1091      });
1092    },
1093
1094    _straightDownGetContainerSize : function() {
1095      return { height : this.straightDown.y };
1096    },
1097
1098    _straightDownResizeChanged : function() {
1099      return true;
1100    },
1101
1102
1103    // ====================== masonryHorizontal ======================
1104
1105    _masonryHorizontalReset : function() {
1106      // layout-specific props
1107      this.masonryHorizontal = {};
1108      // FIXME shouldn't have to call this again
1109      this._getSegments( true );
1110      var i = this.masonryHorizontal.rows;
1111      this.masonryHorizontal.rowXs = [];
1112      while (i--) {
1113        this.masonryHorizontal.rowXs.push( 0 );
1114      }
1115    },
1116
1117    _masonryHorizontalLayout : function( $elems ) {
1118      var instance = this,
1119          props = instance.masonryHorizontal;
1120      $elems.each(function(){
1121        var $this  = $(this),
1122            //how many rows does this brick span
1123            rowSpan = Math.ceil( $this.outerHeight(true) / props.rowHeight );
1124        rowSpan = Math.min( rowSpan, props.rows );
1125
1126        if ( rowSpan === 1 ) {
1127          // if brick spans only one column, just like singleMode
1128          instance._masonryHorizontalPlaceBrick( $this, props.rowXs );
1129        } else {
1130          // brick spans more than one row
1131          // how many different places could this brick fit horizontally
1132          var groupCount = props.rows + 1 - rowSpan,
1133              groupX = [],
1134              groupRowX, i;
1135
1136          // for each group potential horizontal position
1137          for ( i=0; i < groupCount; i++ ) {
1138            // make an array of colY values for that one group
1139            groupRowX = props.rowXs.slice( i, i+rowSpan );
1140            // and get the max value of the array
1141            groupX[i] = Math.max.apply( Math, groupRowX );
1142          }
1143
1144          instance._masonryHorizontalPlaceBrick( $this, groupX );
1145        }
1146      });
1147    },
1148
1149    _masonryHorizontalPlaceBrick : function( $brick, setX ) {
1150      // get the minimum Y value from the columns
1151      var minimumX  = Math.min.apply( Math, setX ),
1152          smallRow  = 0;
1153      // Find index of smallest row, the first from the top
1154      for (var i=0, len = setX.length; i < len; i++) {
1155        if ( setX[i] === minimumX ) {
1156          smallRow = i;
1157          break;
1158        }
1159      }
1160
1161      // position the brick
1162      var x = minimumX,
1163          y = this.masonryHorizontal.rowHeight * smallRow;
1164      this._pushPosition( $brick, x, y );
1165
1166      // apply setHeight to necessary columns
1167      var setWidth = minimumX + $brick.outerWidth(true),
1168          setSpan = this.masonryHorizontal.rows + 1 - len;
1169      for ( i=0; i < setSpan; i++ ) {
1170        this.masonryHorizontal.rowXs[ smallRow + i ] = setWidth;
1171      }
1172    },
1173
1174    _masonryHorizontalGetContainerSize : function() {
1175      var containerWidth = Math.max.apply( Math, this.masonryHorizontal.rowXs );
1176      return { width: containerWidth };
1177    },
1178
1179    _masonryHorizontalResizeChanged : function() {
1180      return this._checkIfSegmentsChanged(true);
1181    },
1182
1183
1184    // ====================== fitColumns ======================
1185
1186    _fitColumnsReset : function() {
1187      this.fitColumns = {
1188        x : 0,
1189        y : 0,
1190        width : 0
1191      };
1192    },
1193
1194    _fitColumnsLayout : function( $elems ) {
1195      var instance = this,
1196          containerHeight = this.element.height(),
1197          props = this.fitColumns;
1198      $elems.each( function() {
1199        var $this = $(this),
1200            atomW = $this.outerWidth(true),
1201            atomH = $this.outerHeight(true);
1202
1203        if ( props.y !== 0 && atomH + props.y > containerHeight ) {
1204          // if this element cannot fit in the current column
1205          props.x = props.width;
1206          props.y = 0;
1207        }
1208
1209        // position the atom
1210        instance._pushPosition( $this, props.x, props.y );
1211
1212        props.width = Math.max( props.x + atomW, props.width );
1213        props.y += atomH;
1214
1215      });
1216    },
1217
1218    _fitColumnsGetContainerSize : function () {
1219      return { width : this.fitColumns.width };
1220    },
1221
1222    _fitColumnsResizeChanged : function() {
1223      return true;
1224    },
1225
1226
1227
1228    // ====================== cellsByColumn ======================
1229
1230    _cellsByColumnReset : function() {
1231      this.cellsByColumn = {
1232        index : 0
1233      };
1234      // get this.cellsByColumn.columnWidth
1235      this._getSegments();
1236      // get this.cellsByColumn.rowHeight
1237      this._getSegments(true);
1238    },
1239
1240    _cellsByColumnLayout : function( $elems ) {
1241      var instance = this,
1242          props = this.cellsByColumn;
1243      $elems.each( function(){
1244        var $this = $(this),
1245            col = Math.floor( props.index / props.rows ),
1246            row = props.index % props.rows,
1247            x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2,
1248            y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2;
1249        instance._pushPosition( $this, x, y );
1250        props.index ++;
1251      });
1252    },
1253
1254    _cellsByColumnGetContainerSize : function() {
1255      return { width : Math.ceil( this.$filteredAtoms.length / this.cellsByColumn.rows ) * this.cellsByColumn.columnWidth };
1256    },
1257
1258    _cellsByColumnResizeChanged : function() {
1259      return this._checkIfSegmentsChanged(true);
1260    },
1261
1262    // ====================== straightAcross ======================
1263
1264    _straightAcrossReset : function() {
1265      this.straightAcross = {
1266        x : 0
1267      };
1268    },
1269
1270    _straightAcrossLayout : function( $elems ) {
1271      var instance = this;
1272      $elems.each( function( i ){
1273        var $this = $(this);
1274        instance._pushPosition( $this, instance.straightAcross.x, 0 );
1275        instance.straightAcross.x += $this.outerWidth(true);
1276      });
1277    },
1278
1279    _straightAcrossGetContainerSize : function() {
1280      return { width : this.straightAcross.x };
1281    },
1282
1283    _straightAcrossResizeChanged : function() {
1284      return true;
1285    }
1286
1287  };
1288
1289
1290  // ======================= imagesLoaded Plugin ===============================
1291  /*!
1292   * jQuery imagesLoaded plugin v1.1.0
1293   * http://github.com/desandro/imagesloaded
1294   *
1295   * MIT License. by Paul Irish et al.
1296   */
1297
1298
1299  // $('#my-container').imagesLoaded(myFunction)
1300  // or
1301  // $('img').imagesLoaded(myFunction)
1302
1303  // execute a callback when all images have loaded.
1304  // needed because .load() doesn't work on cached images
1305
1306  // callback function gets image collection as argument
1307  //  `this` is the container
1308
1309  $.fn.imagesLoaded = function( callback ) {
1310    var $this = this,
1311        $images = $this.find('img').add( $this.filter('img') ),
1312        len = $images.length,
1313        blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
1314        loaded = [];
1315
1316    function triggerCallback() {
1317      callback.call( $this, $images );
1318    }
1319
1320    function imgLoaded( event ) {
1321      var img = event.target;
1322      if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){
1323        loaded.push( img );
1324        if ( --len <= 0 ){
1325          setTimeout( triggerCallback );
1326          $images.unbind( '.imagesLoaded', imgLoaded );
1327        }
1328      }
1329    }
1330
1331    // if no images, trigger immediately
1332    if ( !len ) {
1333      triggerCallback();
1334    }
1335
1336    $images.bind( 'load.imagesLoaded error.imagesLoaded',  imgLoaded ).each( function() {
1337      // cached images don't fire load sometimes, so we reset src.
1338      var src = this.src;
1339      // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
1340      // data uri bypasses webkit log warning (thx doug jones)
1341      this.src = blank;
1342      this.src = src;
1343    });
1344
1345    return $this;
1346  };
1347
1348
1349  // helper function for logging errors
1350  // $.error breaks jQuery chaining
1351  var logError = function( message ) {
1352    if ( window.console ) {
1353      window.console.error( message );
1354    }
1355  };
1356
1357  // =======================  Plugin bridge  ===============================
1358  // leverages data method to either create or return $.Isotope constructor
1359  // A bit from jQuery UI
1360  //   https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
1361  // A bit from jcarousel
1362  //   https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
1363
1364  $.fn.isotope = function( options, callback ) {
1365    if ( typeof options === 'string' ) {
1366      // call method
1367      var args = Array.prototype.slice.call( arguments, 1 );
1368
1369      this.each(function(){
1370        var instance = $.data( this, 'isotope' );
1371        if ( !instance ) {
1372          logError( "cannot call methods on isotope prior to initialization; " +
1373              "attempted to call method '" + options + "'" );
1374          return;
1375        }
1376        if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
1377          logError( "no such method '" + options + "' for isotope instance" );
1378          return;
1379        }
1380        // apply method
1381        instance[ options ].apply( instance, args );
1382      });
1383    } else {
1384      this.each(function() {
1385        var instance = $.data( this, 'isotope' );
1386        if ( instance ) {
1387          // apply options & init
1388          instance.option( options );
1389          instance._init( callback );
1390        } else {
1391          // initialize new instance
1392          $.data( this, 'isotope', new $.Isotope( options, this, callback ) );
1393        }
1394      });
1395    }
1396    // return jQuery object
1397    // so plugin methods do not have to
1398    return this;
1399  };
1400
1401})( 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.