rails_pitfall 1.0.5 → 1.0.6

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