PageSourceSearch

https://www.handsfreemama.com/wp-content/plugins/uber-grid/assets/js/packery.pkgd.min.js?ver=2.1.2.1788390482

js handsfreemama.com collected 2026-09-25 23:50:01 UTC 108,257 bytes, 4,092 lines download raw bytes

1
2( function ($) {
3/*!
4 * Packery PACKAGED v1.4.3
5 * bin-packing layout library
6 *
7 * Licensed GPLv3 for open source use
8 * or Flickity Commercial License for commercial use
9 *
10 * http://packery.metafizzy.co
11 * Copyright 2015 Metafizzy
12 */
13
14/**
15 * Bridget makes jQuery widgets
16 * v1.1.0
17 * MIT license
18 */
19
20( function( window ) {
21
22
23
24// -------------------------- utils -------------------------- //
25
26var slice = Array.prototype.slice;
27
28function noop() {}
29
30// -------------------------- definition -------------------------- //
31
32function defineBridget( $ ) {
33
34// bail if no jQuery
35if ( !$ ) {
36  return;
37}
38
39// -------------------------- addOptionMethod -------------------------- //
40
41/**
42 * adds option method -> $().plugin('option', {...})
43 * @param {Function} PluginClass - constructor class
44 */
45function addOptionMethod( PluginClass ) {
46  // don't overwrite original option method
47  if ( PluginClass.prototype.option ) {
48    return;
49  }
50
51  // option setter
52  PluginClass.prototype.option = function( opts ) {
53    // bail out if not an object
54    if ( !$.isPlainObject( opts ) ){
55      return;
56    }
57    this.options = $.extend( true, this.options, opts );
58  };
59}
60
61// -------------------------- plugin bridge -------------------------- //
62
63// helper function for logging errors
64// $.error breaks jQuery chaining
65var logError = typeof console === 'undefined' ? noop :
66  function( message ) {
67    console.error( message );
68  };
69
70/**
71 * jQuery plugin bridge, access methods like $elem.plugin('method')
72 * @param {String} namespace - plugin name
73 * @param {Function} PluginClass - constructor class
74 */
75function bridge( namespace, PluginClass ) {
76  // add to jQuery fn namespace
77  $.fn[ namespace ] = function( options ) {
78    if ( typeof options === 'string' ) {
79      // call plugin method when first argument is a string
80      // get arguments for method
81      var args = slice.call( arguments, 1 );
82
83      for ( var i=0, len = this.length; i < len; i++ ) {
84        var elem = this[i];
85        var instance = $.data( elem, namespace );
86        if ( !instance ) {
87          logError( "cannot call methods on " + namespace + " prior to initialization; " +
88            "attempted to call '" + options + "'" );
89          continue;
90        }
91        if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {
92          logError( "no such method '" + options + "' for " + namespace + " instance" );
93          continue;
94        }
95
96        // trigger method with arguments
97        var returnValue = instance[ options ].apply( instance, args );
98
99        // break look and return first value if provided
100        if ( returnValue !== undefined ) {
101          return returnValue;
102        }
103      }
104      // return this if no return value
105      return this;
106    } else {
107      return this.each( function() {
108        var instance = $.data( this, namespace );
109        if ( instance ) {
110          // apply options & init
111          instance.option( options );
112          instance._init();
113        } else {
114          // initialize new instance
115          instance = new PluginClass( this, options );
116          $.data( this, namespace, instance );
117        }
118      });
119    }
120  };
121
122}
123
124// -------------------------- bridget -------------------------- //
125
126/**
127 * converts a Prototypical class into a proper jQuery plugin
128 *   the class must have a ._init method
129 * @param {String} namespace - plugin name, used in $().pluginName
130 * @param {Function} PluginClass - constructor class
131 */
132$.bridget = function( namespace, PluginClass ) {
133  addOptionMethod( PluginClass );
134  bridge( namespace, PluginClass );
135};
136
137return $.bridget;
138
139}
140
141// transport
142if ( typeof define === 'function' && define.amd ) {
143  // AMD
144  define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget );
145} else if ( typeof exports === 'object' ) {
146  defineBridget( require('jquery') );
147} else {
148  // get jquery from browser global
149  defineBridget( window.jQuery );
150}
151
152})( window );
153
154/*!
155 * classie v1.0.1
156 * class helper functions
157 * from bonzo https://github.com/ded/bonzo
158 * MIT license
159 *
160 * classie.has( elem, 'my-class' ) -> true/false
161 * classie.add( elem, 'my-new-class' )
162 * classie.remove( elem, 'my-unwanted-class' )
163 * classie.toggle( elem, 'my-class' )
164 */
165
166/*jshint browser: true, strict: true, undef: true, unused: true */
167/*global define: false, module: false */
168
169( function( window ) {
170
171
172
173// class helper functions from bonzo https://github.com/ded/bonzo
174
175function classReg( className ) {
176  return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
177}
178
179// classList support for class management
180// altho to be fair, the api sucks because it won't accept multiple classes at once
181var hasClass, addClass, removeClass;
182
183if ( 'classList' in document.documentElement ) {
184  hasClass = function( elem, c ) {
185    return elem.classList.contains( c );
186  };
187  addClass = function( elem, c ) {
188    elem.classList.add( c );
189  };
190  removeClass = function( elem, c ) {
191    elem.classList.remove( c );
192  };
193}
194else {
195  hasClass = function( elem, c ) {
196    return classReg( c ).test( elem.className );
197  };
198  addClass = function( elem, c ) {
199    if ( !hasClass( elem, c ) ) {
200      elem.className = elem.className + ' ' + c;
201    }
202  };
203  removeClass = function( elem, c ) {
204    elem.className = elem.className.replace( classReg( c ), ' ' );
205  };
206}
207
208function toggleClass( elem, c ) {
209  var fn = hasClass( elem, c ) ? removeClass : addClass;
210  fn( elem, c );
211}
212
213var classie = {
214  // full names
215  hasClass: hasClass,
216  addClass: addClass,
217  removeClass: removeClass,
218  toggleClass: toggleClass,
219  // short names
220  has: hasClass,
221  add: addClass,
222  remove: removeClass,
223  toggle: toggleClass
224};
225
226// transport
227if ( typeof define === 'function' && define.amd ) {
228  // AMD
229  define( 'classie/classie',classie );
230} else if ( typeof exports === 'object' ) {
231  // CommonJS
232  module.exports = classie;
233} else {
234  // browser global
235  window.classie = classie;
236}
237
238})( window );
239
240/*!
241 * getStyleProperty v1.0.4
242 * original by kangax
243 * http://perfectionkills.com/feature-testing-css-properties/
244 * MIT license
245 */
246
247/*jshint browser: true, strict: true, undef: true */
248/*global define: false, exports: false, module: false */
249
250( function( window ) {
251
252
253
254var prefixes = 'Webkit Moz ms Ms O'.split(' ');
255var docElemStyle = document.documentElement.style;
256
257function getStyleProperty( propName ) {
258  if ( !propName ) {
259    return;
260  }
261
262  // test standard property first
263  if ( typeof docElemStyle[ propName ] === 'string' ) {
264    return propName;
265  }
266
267  // capitalize
268  propName = propName.charAt(0).toUpperCase() + propName.slice(1);
269
270  // test vendor specific properties
271  var prefixed;
272  for ( var i=0, len = prefixes.length; i < len; i++ ) {
273    prefixed = prefixes[i] + propName;
274    if ( typeof docElemStyle[ prefixed ] === 'string' ) {
275      return prefixed;
276    }
277  }
278}
279
280// transport
281if ( typeof define === 'function' && define.amd ) {
282  // AMD
283  define( 'get-style-property/get-style-property',[],function() {
284    return getStyleProperty;
285  });
286} else if ( typeof exports === 'object' ) {
287  // CommonJS for Component
288  module.exports = getStyleProperty;
289} else {
290  // browser global
291  window.getStyleProperty = getStyleProperty;
292}
293
294})( window );
295
296/*!
297 * getSize v1.2.2
298 * measure size of elements
299 * MIT license
300 */
301
302/*jshint browser: true, strict: true, undef: true, unused: true */
303/*global define: false, exports: false, require: false, module: false, console: false */
304
305( function( window, undefined ) {
306
307
308
309// -------------------------- helpers -------------------------- //
310
311// get a number from a string, not a percentage
312function getStyleSize( value ) {
313  var num = parseFloat( value );
314  // not a percent like '100%', and a number
315  var isValid = value.indexOf('%') === -1 && !isNaN( num );
316  return isValid && num;
317}
318
319function noop() {}
320
321var logError = typeof console === 'undefined' ? noop :
322  function( message ) {
323    console.error( message );
324  };
325
326// -------------------------- measurements -------------------------- //
327
328var measurements = [
329  'paddingLeft',
330  'paddingRight',
331  'paddingTop',
332  'paddingBottom',
333  'marginLeft',
334  'marginRight',
335  'marginTop',
336  'marginBottom',
337  'borderLeftWidth',
338  'borderRightWidth',
339  'borderTopWidth',
340  'borderBottomWidth'
341];
342
343function getZeroSize() {
344  var size = {
345    width: 0,
346    height: 0,
347    innerWidth: 0,
348    innerHeight: 0,
349    outerWidth: 0,
350    outerHeight: 0
351  };
352  for ( var i=0, len = measurements.length; i < len; i++ ) {
353    var measurement = measurements[i];
354    size[ measurement ] = 0;
355  }
356  return size;
357}
358
359
360
361function defineGetSize( getStyleProperty ) {
362
363// -------------------------- setup -------------------------- //
364
365var isSetup = false;
366
367var getStyle, boxSizingProp, isBoxSizeOuter;
368
369/**
370 * setup vars and functions
371 * do it on initial getSize(), rather than on script load
372 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
373 */
374function setup() {
375  // setup once
376  if ( isSetup ) {
377    return;
378  }
379  isSetup = true;
380
381  var getComputedStyle = window.getComputedStyle;
382  getStyle = ( function() {
383    var getStyleFn = getComputedStyle ?
384      function( elem ) {
385        return getComputedStyle( elem, null );
386      } :
387      function( elem ) {
388        return elem.currentStyle;
389      };
390
391      return function getStyle( elem ) {
392        var style = getStyleFn( elem );
393        if ( !style ) {
394          logError( 'Style returned ' + style +
395            '. Are you running this code in a hidden iframe on Firefox? ' +
396            'See http://bit.ly/getsizebug1' );
397        }
398        return style;
399      };
400  })();
401
402  // -------------------------- box sizing -------------------------- //
403
404  boxSizingProp = getStyleProperty('boxSizing');
405
406  /**
407   * WebKit measures the outer-width on style.width on border-box elems
408   * IE & Firefox measures the inner-width
409   */
410  if ( boxSizingProp ) {
411    var div = document.createElement('div');
412    div.style.width = '200px';
413    div.style.padding = '1px 2px 3px 4px';
414    div.style.borderStyle = 'solid';
415    div.style.borderWidth = '1px 2px 3px 4px';
416    div.style[ boxSizingProp ] = 'border-box';
417
418    var body = document.body || document.documentElement;
419    body.appendChild( div );
420    var style = getStyle( div );
421
422    isBoxSizeOuter = getStyleSize( style.width ) === 200;
423    body.removeChild( div );
424  }
425
426}
427
428// -------------------------- getSize -------------------------- //
429
430function getSize( elem ) {
431  setup();
432
433  // use querySeletor if elem is string
434  if ( typeof elem === 'string' ) {
435    elem = document.querySelector( elem );
436  }
437
438  // do not proceed on non-objects
439  if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
440    return;
441  }
442
443  var style = getStyle( elem );
444
445  // if hidden, everything is 0
446  if ( style.display === 'none' ) {
447    return getZeroSize();
448  }
449
450  var size = {};
451  size.width = elem.offsetWidth;
452  size.height = elem.offsetHeight;
453
454  var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
455    style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
456
457  // get all measurements
458  for ( var i=0, len = measurements.length; i < len; i++ ) {
459    var measurement = measurements[i];
460    var value = style[ measurement ];
461    value = mungeNonPixel( elem, value );
462    var num = parseFloat( value );
463    // any 'auto', 'medium' value will be 0
464    size[ measurement ] = !isNaN( num ) ? num : 0;
465  }
466
467  var paddingWidth = size.paddingLeft + size.paddingRight;
468  var paddingHeight = size.paddingTop + size.paddingBottom;
469  var marginWidth = size.marginLeft + size.marginRight;
470  var marginHeight = size.marginTop + size.marginBottom;
471  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
472  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
473
474  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
475
476  // overwrite width and height if we can get it from style
477  var styleWidth = getStyleSize( style.width );
478  if ( styleWidth !== false ) {
479    size.width = styleWidth +
480      // add padding and border unless it's already including it
481      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
482  }
483
484  var styleHeight = getStyleSize( style.height );
485  if ( styleHeight !== false ) {
486    size.height = styleHeight +
487      // add padding and border unless it's already including it
488      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
489  }
490
491  size.innerWidth = size.width - ( paddingWidth + borderWidth );
492  size.innerHeight = size.height - ( paddingHeight + borderHeight );
493
494  size.outerWidth = size.width + marginWidth;
495  size.outerHeight = size.height + marginHeight;
496
497  return size;
498}
499
500// IE8 returns percent values, not pixels
501// taken from jQuery's curCSS
502function mungeNonPixel( elem, value ) {
503  // IE8 and has percent value
504  if ( window.getComputedStyle || value.indexOf('%') === -1 ) {
505    return value;
506  }
507  var style = elem.style;
508  // Remember the original values
509  var left = style.left;
510  var rs = elem.runtimeStyle;
511  var rsLeft = rs && rs.left;
512
513  // Put in the new values to get a computed value out
514  if ( rsLeft ) {
515    rs.left = elem.currentStyle.left;
516  }
517  style.left = value;
518  value = style.pixelLeft;
519
520  // Revert the changed values
521  style.left = left;
522  if ( rsLeft ) {
523    rs.left = rsLeft;
524  }
525
526  return value;
527}
528
529return getSize;
530
531}
532
533// transport
534if ( typeof define === 'function' && define.amd ) {
535  // AMD for RequireJS
536  define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );
537} else if ( typeof exports === 'object' ) {
538  // CommonJS for Component
539  module.exports = defineGetSize( require('desandro-get-style-property') );
540} else {
541  // browser global
542  window.getSize = defineGetSize( window.getStyleProperty );
543}
544
545})( window );
546
547/*!
548 * eventie v1.0.6
549 * event binding helper
550 *   eventie.bind( elem, 'click', myFn )
551 *   eventie.unbind( elem, 'click', myFn )
552 * MIT license
553 */
554
555/*jshint browser: true, undef: true, unused: true */
556/*global define: false, module: false */
557
558( function( window ) {
559
560
561
562var docElem = document.documentElement;
563
564var bind = function() {};
565
566function getIEEvent( obj ) {
567  var event = window.event;
568  // add event.target
569  event.target = event.target || event.srcElement || obj;
570  return event;
571}
572
573if ( docElem.addEventListener ) {
574  bind = function( obj, type, fn ) {
575    obj.addEventListener( type, fn, false );
576  };
577} else if ( docElem.attachEvent ) {
578  bind = function( obj, type, fn ) {
579    obj[ type + fn ] = fn.handleEvent ?
580      function() {
581        var event = getIEEvent( obj );
582        fn.handleEvent.call( fn, event );
583      } :
584      function() {
585        var event = getIEEvent( obj );
586        fn.call( obj, event );
587      };
588    obj.attachEvent( "on" + type, obj[ type + fn ] );
589  };
590}
591
592var unbind = function() {};
593
594if ( docElem.removeEventListener ) {
595  unbind = function( obj, type, fn ) {
596    obj.removeEventListener( type, fn, false );
597  };
598} else if ( docElem.detachEvent ) {
599  unbind = function( obj, type, fn ) {
600    obj.detachEvent( "on" + type, obj[ type + fn ] );
601    try {
602      delete obj[ type + fn ];
603    } catch ( err ) {
604      // can't delete window object properties
605      obj[ type + fn ] = undefined;
606    }
607  };
608}
609
610var eventie = {
611  bind: bind,
612  unbind: unbind
613};
614
615// ----- module definition ----- //
616
617if ( typeof define === 'function' && define.amd ) {
618  // AMD
619  define( 'eventie/eventie',eventie );
620} else if ( typeof exports === 'object' ) {
621  // CommonJS
622  module.exports = eventie;
623} else {
624  // browser global
625  window.eventie = eventie;
626}
627
628})( window );
629
630/*!
631 * EventEmitter v4.2.11 - git.io/ee
632 * Unlicense - http://unlicense.org/
633 * Oliver Caldwell - http://oli.me.uk/
634 * @preserve
635 */
636
637;(function () {
638
639
640    /**
641     * Class for managing events.
642     * Can be extended to provide event functionality in other classes.
643     *
644     * @class EventEmitter Manages event registering and emitting.
645     */
646    function EventEmitter() {}
647
648    // Shortcuts to improve speed and size
649    var proto = EventEmitter.prototype;
650    var exports = this;
651    var originalGlobalValue = exports.EventEmitter;
652
653    /**
654     * Finds the index of the listener for the event in its storage array.
655     *
656     * @param {Function[]} listeners Array of listeners to search through.
657     * @param {Function} listener Method to look for.
658     * @return {Number} Index of the specified listener, -1 if not found
659     * @api private
660     */
661    function indexOfListener(listeners, listener) {
662        var i = listeners.length;
663        while (i--) {
664            if (listeners[i].listener === listener) {
665                return i;
666            }
667        }
668
669        return -1;
670    }
671
672    /**
673     * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 673-1076
673writing of target method.
674     *
675     * @param {String} name The name of the target method.
676     * @return {Function} The aliased method
677     * @api private
678     */
679    function alias(name) {
680        return function aliasClosure() {
681            return this[name].apply(this, arguments);
682        };
683    }
684
685    /**
686     * Returns the listener array for the specified event.
687     * Will initialise the event object and listener arrays if required.
688     * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
689     * Each property in the object response is an array of listener functions.
690     *
691     * @param {String|RegExp} evt Name of the event to return the listeners from.
692     * @return {Function[]|Object} All listener functions for the event.
693     */
694    proto.getListeners = function getListeners(evt) {
695        var events = this._getEvents();
696        var response;
697        var key;
698
699        // Return a concatenated array of all matching events if
700        // the selector is a regular expression.
701        if (evt instanceof RegExp) {
702            response = {};
703            for (key in events) {
704                if (events.hasOwnProperty(key) && evt.test(key)) {
705                    response[key] = events[key];
706                }
707            }
708        }
709        else {
710            response = events[evt] || (events[evt] = []);
711        }
712
713        return response;
714    };
715
716    /**
717     * Takes a list of listener objects and flattens it into a list of listener functions.
718     *
719     * @param {Object[]} listeners Raw listener objects.
720     * @return {Function[]} Just the listener functions.
721     */
722    proto.flattenListeners = function flattenListeners(listeners) {
723        var flatListeners = [];
724        var i;
725
726        for (i = 0; i < listeners.length; i += 1) {
727            flatListeners.push(listeners[i].listener);
728        }
729
730        return flatListeners;
731    };
732
733    /**
734     * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
735     *
736     * @param {String|RegExp} evt Name of the event to return the listeners from.
737     * @return {Object} All listener functions for an event in an object.
738     */
739    proto.getListenersAsObject = function getListenersAsObject(evt) {
740        var listeners = this.getListeners(evt);
741        var response;
742
743        if (listeners instanceof Array) {
744            response = {};
745            response[evt] = listeners;
746        }
747
748        return response || listeners;
749    };
750
751    /**
752     * Adds a listener function to the specified event.
753     * The listener will not be added if it is a duplicate.
754     * If the listener returns true then it will be removed after it is called.
755     * If you pass a regular expression as the event name then the listener will be added to all events that match it.
756     *
757     * @param {String|RegExp} evt Name of the event to attach the listener to.
758     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
759     * @return {Object} Current instance of EventEmitter for chaining.
760     */
761    proto.addListener = function addListener(evt, listener) {
762        var listeners = this.getListenersAsObject(evt);
763        var listenerIsWrapped = typeof listener === 'object';
764        var key;
765
766        for (key in listeners) {
767            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
768                listeners[key].push(listenerIsWrapped ? listener : {
769                    listener: listener,
770                    once: false
771                });
772            }
773        }
774
775        return this;
776    };
777
778    /**
779     * Alias of addListener
780     */
781    proto.on = alias('addListener');
782
783    /**
784     * Semi-alias of addListener. It will add a listener that will be
785     * automatically removed after its first execution.
786     *
787     * @param {String|RegExp} evt Name of the event to attach the listener to.
788     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
789     * @return {Object} Current instance of EventEmitter for chaining.
790     */
791    proto.addOnceListener = function addOnceListener(evt, listener) {
792        return this.addListener(evt, {
793            listener: listener,
794            once: true
795        });
796    };
797
798    /**
799     * Alias of addOnceListener.
800     */
801    proto.once = alias('addOnceListener');
802
803    /**
804     * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
805     * You need to tell it what event names should be matched by a regex.
806     *
807     * @param {String} evt Name of the event to create.
808     * @return {Object} Current instance of EventEmitter for chaining.
809     */
810    proto.defineEvent = function defineEvent(evt) {
811        this.getListeners(evt);
812        return this;
813    };
814
815    /**
816     * Uses defineEvent to define multiple events.
817     *
818     * @param {String[]} evts An array of event names to define.
819     * @return {Object} Current instance of EventEmitter for chaining.
820     */
821    proto.defineEvents = function defineEvents(evts) {
822        for (var i = 0; i < evts.length; i += 1) {
823            this.defineEvent(evts[i]);
824        }
825        return this;
826    };
827
828    /**
829     * Removes a listener function from the specified event.
830     * When passed a regular expression as the event name, it will remove the listener from all events that match it.
831     *
832     * @param {String|RegExp} evt Name of the event to remove the listener from.
833     * @param {Function} listener Method to remove from the event.
834     * @return {Object} Current instance of EventEmitter for chaining.
835     */
836    proto.removeListener = function removeListener(evt, listener) {
837        var listeners = this.getListenersAsObject(evt);
838        var index;
839        var key;
840
841        for (key in listeners) {
842            if (listeners.hasOwnProperty(key)) {
843                index = indexOfListener(listeners[key], listener);
844
845                if (index !== -1) {
846                    listeners[key].splice(index, 1);
847                }
848            }
849        }
850
851        return this;
852    };
853
854    /**
855     * Alias of removeListener
856     */
857    proto.off = alias('removeListener');
858
859    /**
860     * Adds listeners in bulk using the manipulateListeners method.
861     * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
862     * You can also pass it a regular expression to add the array of listeners to all events that match it.
863     * Yeah, this function does quite a bit. That's probably a bad thing.
864     *
865     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
866     * @param {Function[]} [listeners] An optional array of listener functions to add.
867     * @return {Object} Current instance of EventEmitter for chaining.
868     */
869    proto.addListeners = function addListeners(evt, listeners) {
870        // Pass through to manipulateListeners
871        return this.manipulateListeners(false, evt, listeners);
872    };
873
874    /**
875     * Removes listeners in bulk using the manipulateListeners method.
876     * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
877     * You can also pass it an event name and an array of listeners to be removed.
878     * You can also pass it a regular expression to remove the listeners from all events that match it.
879     *
880     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
881     * @param {Function[]} [listeners] An optional array of listener functions to remove.
882     * @return {Object} Current instance of EventEmitter for chaining.
883     */
884    proto.removeListeners = function removeListeners(evt, listeners) {
885        // Pass through to manipulateListeners
886        return this.manipulateListeners(true, evt, listeners);
887    };
888
889    /**
890     * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
891     * The first argument will determine if the listeners are removed (true) or added (false).
892     * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
893     * You can also pass it an event name and an array of listeners to be added/removed.
894     * You can also pass it a regular expression to manipulate the listeners of all events that match it.
895     *
896     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
897     * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
898     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
899     * @return {Object} Current instance of EventEmitter for chaining.
900     */
901    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
902        var i;
903        var value;
904        var single = remove ? this.removeListener : this.addListener;
905        var multiple = remove ? this.removeListeners : this.addListeners;
906
907        // If evt is an object then pass each of its properties to this method
908        if (typeof evt === 'object' && !(evt instanceof RegExp)) {
909            for (i in evt) {
910                if (evt.hasOwnProperty(i) && (value = evt[i])) {
911                    // Pass the single listener straight through to the singular method
912                    if (typeof value === 'function') {
913                        single.call(this, i, value);
914                    }
915                    else {
916                        // Otherwise pass back to the multiple function
917                        multiple.call(this, i, value);
918                    }
919                }
920            }
921        }
922        else {
923            // So evt must be a string
924            // And listeners must be an array of listeners
925            // Loop over it and pass each one to the multiple method
926            i = listeners.length;
927            while (i--) {
928                single.call(this, evt, listeners[i]);
929            }
930        }
931
932        return this;
933    };
934
935    /**
936     * Removes all listeners from a specified event.
937     * If you do not specify an event then all listeners will be removed.
938     * That means every event will be emptied.
939     * You can also pass a regex to remove all events that match it.
940     *
941     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
942     * @return {Object} Current instance of EventEmitter for chaining.
943     */
944    proto.removeEvent = function removeEvent(evt) {
945        var type = typeof evt;
946        var events = this._getEvents();
947        var key;
948
949        // Remove different things depending on the state of evt
950        if (type === 'string') {
951            // Remove all listeners for the specified event
952            delete events[evt];
953        }
954        else if (evt instanceof RegExp) {
955            // Remove all events matching the regex.
956            for (key in events) {
957                if (events.hasOwnProperty(key) && evt.test(key)) {
958                    delete events[key];
959                }
960            }
961        }
962        else {
963            // Remove all listeners in all events
964            delete this._events;
965        }
966
967        return this;
968    };
969
970    /**
971     * Alias of removeEvent.
972     *
973     * Added to mirror the node API.
974     */
975    proto.removeAllListeners = alias('removeEvent');
976
977    /**
978     * Emits an event of your choice.
979     * When emitted, every listener attached to that event will be executed.
980     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
981     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
982     * So they will not arrive within the array on the other side, they will be separate.
983     * You can also pass a regular expression to emit to all events that match it.
984     *
985     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
986     * @param {Array} [args] Optional array of arguments to be passed to each listener.
987     * @return {Object} Current instance of EventEmitter for chaining.
988     */
989    proto.emitEvent = function emitEvent(evt, args) {
990        var listeners = this.getListenersAsObject(evt);
991        var listener;
992        var i;
993        var key;
994        var response;
995
996        for (key in listeners) {
997            if (listeners.hasOwnProperty(key)) {
998                i = listeners[key].length;
999
1000                while (i--) {
1001                    // If the listener returns true then it shall be removed from the event
1002                    // The function is executed either with a basic call or an apply if there is an args array
1003                    listener = listeners[key][i];
1004
1005                    if (listener.once === true) {
1006                        this.removeListener(evt, listener.listener);
1007                    }
1008
1009                    response = listener.listener.apply(this, args || []);
1010
1011                    if (response === this._getOnceReturnValue()) {
1012                        this.removeListener(evt, listener.listener);
1013                    }
1014                }
1015            }
1016        }
1017
1018        return this;
1019    };
1020
1021    /**
1022     * Alias of emitEvent
1023     */
1024    proto.trigger = alias('emitEvent');
1025
1026    /**
1027     * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
1028     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
1029     *
1030     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
1031     * @param {...*} Optional additional arguments to be passed to each listener.
1032     * @return {Object} Current instance of EventEmitter for chaining.
1033     */
1034    proto.emit = function emit(evt) {
1035        var args = Array.prototype.slice.call(arguments, 1);
1036        return this.emitEvent(evt, args);
1037    };
1038
1039    /**
1040     * Sets the current value to check against when executing listeners. If a
1041     * listeners return value matches the one set here then it will be removed
1042     * after execution. This value defaults to true.
1043     *
1044     * @param {*} value The new value to check for when executing listeners.
1045     * @return {Object} Current instance of EventEmitter for chaining.
1046     */
1047    proto.setOnceReturnValue = function setOnceReturnValue(value) {
1048        this._onceReturnValue = value;
1049        return this;
1050    };
1051
1052    /**
1053     * Fetches the current value to check against when executing listeners. If
1054     * the listeners return value matches this one then it should be removed
1055     * automatically. It will return true by default.
1056     *
1057     * @return {*|Boolean} The current value to check for or the default, true.
1058     * @api private
1059     */
1060    proto._getOnceReturnValue = function _getOnceReturnValue() {
1061        if (this.hasOwnProperty('_onceReturnValue')) {
1062            return this._onceReturnValue;
1063        }
1064        else {
1065            return true;
1066        }
1067    };
1068
1069    /**
1070     * Fetches the events object and creates one if required.
1071     *
1072     * @return {Object} The events storage object.
1073     * @api private
1074     */
1075    proto._getEvents = function _getEvents() {
1076        return this._events || (this
1076._events = {});
1077    };
1078
1079    /**
1080     * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
1081     *
1082     * @return {Function} Non conflicting EventEmitter class.
1083     */
1084    EventEmitter.noConflict = function noConflict() {
1085        exports.EventEmitter = originalGlobalValue;
1086        return EventEmitter;
1087    };
1088
1089    // Expose the class either via AMD, CommonJS or the global object
1090    if (typeof define === 'function' && define.amd) {
1091        define('eventEmitter/EventEmitter',[],function () {
1092            return EventEmitter;
1093        });
1094    }
1095    else if (typeof module === 'object' && module.exports){
1096        module.exports = EventEmitter;
1097    }
1098    else {
1099        exports.EventEmitter = EventEmitter;
1100    }
1101}.call(this));
1102
1103/*!
1104 * docReady v1.0.4
1105 * Cross browser DOMContentLoaded event emitter
1106 * MIT license
1107 */
1108
1109/*jshint browser: true, strict: true, undef: true, unused: true*/
1110/*global define: false, require: false, module: false */
1111
1112( function( window ) {
1113
1114
1115
1116var document = window.document;
1117// collection of functions to be triggered on ready
1118var queue = [];
1119
1120function docReady( fn ) {
1121  // throw out non-functions
1122  if ( typeof fn !== 'function' ) {
1123    return;
1124  }
1125
1126  if ( docReady.isReady ) {
1127    // ready now, hit it
1128    fn();
1129  } else {
1130    // queue function when ready
1131    queue.push( fn );
1132  }
1133}
1134
1135docReady.isReady = false;
1136
1137// triggered on various doc ready events
1138function onReady( event ) {
1139  // bail if already triggered or IE8 document is not ready just yet
1140  var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';
1141  if ( docReady.isReady || isIE8NotReady ) {
1142    return;
1143  }
1144
1145  trigger();
1146}
1147
1148function trigger() {
1149  docReady.isReady = true;
1150  // process queue
1151  for ( var i=0, len = queue.length; i < len; i++ ) {
1152    var fn = queue[i];
1153    fn();
1154  }
1155}
1156
1157function defineDocReady( eventie ) {
1158  // trigger ready if page is ready
1159  if ( document.readyState === 'complete' ) {
1160    trigger();
1161  } else {
1162    // listen for events
1163    eventie.bind( document, 'DOMContentLoaded', onReady );
1164    eventie.bind( document, 'readystatechange', onReady );
1165    eventie.bind( window, 'load', onReady );
1166  }
1167
1168  return docReady;
1169}
1170
1171// transport
1172if ( typeof define === 'function' && define.amd ) {
1173  // AMD
1174  define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady );
1175} else if ( typeof exports === 'object' ) {
1176  module.exports = defineDocReady( require('eventie') );
1177} else {
1178  // browser global
1179  window.docReady = defineDocReady( window.eventie );
1180}
1181
1182})( window );
1183
1184/**
1185 * matchesSelector v1.0.3
1186 * matchesSelector( element, '.selector' )
1187 * MIT license
1188 */
1189
1190/*jshint browser: true, strict: true, undef: true, unused: true */
1191/*global define: false, module: false */
1192
1193( function( ElemProto ) {
1194
1195
1196
1197  var matchesMethod = ( function() {
1198    // check for the standard method name first
1199    if ( ElemProto.matches ) {
1200      return 'matches';
1201    }
1202    // check un-prefixed
1203    if ( ElemProto.matchesSelector ) {
1204      return 'matchesSelector';
1205    }
1206    // check vendor prefixes
1207    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
1208
1209    for ( var i=0, len = prefixes.length; i < len; i++ ) {
1210      var prefix = prefixes[i];
1211      var method = prefix + 'MatchesSelector';
1212      if ( ElemProto[ method ] ) {
1213        return method;
1214      }
1215    }
1216  })();
1217
1218  // ----- match ----- //
1219
1220  function match( elem, selector ) {
1221    return elem[ matchesMethod ]( selector );
1222  }
1223
1224  // ----- appendToFragment ----- //
1225
1226  function checkParent( elem ) {
1227    // not needed if already has parent
1228    if ( elem.parentNode ) {
1229      return;
1230    }
1231    var fragment = document.createDocumentFragment();
1232    fragment.appendChild( elem );
1233  }
1234
1235  // ----- query ----- //
1236
1237  // fall back to using QSA
1238  // thx @jonathantneal https://gist.github.com/3062955
1239  function query( elem, selector ) {
1240    // append to fragment if no parent
1241    checkParent( elem );
1242
1243    // match elem with all selected elems of parent
1244    var elems = elem.parentNode.querySelectorAll( selector );
1245    for ( var i=0, len = elems.length; i < len; i++ ) {
1246      // return true if match
1247      if ( elems[i] === elem ) {
1248        return true;
1249      }
1250    }
1251    // otherwise return false
1252    return false;
1253  }
1254
1255  // ----- matchChild ----- //
1256
1257  function matchChild( elem, selector ) {
1258    checkParent( elem );
1259    return match( elem, selector );
1260  }
1261
1262  // ----- matchesSelector ----- //
1263
1264  var matchesSelector;
1265
1266  if ( matchesMethod ) {
1267    // IE9 supports matchesSelector, but doesn't work on orphaned elems
1268    // check for that
1269    var div = document.createElement('div');
1270    var supportsOrphans = match( div, 'div' );
1271    matchesSelector = supportsOrphans ? match : matchChild;
1272  } else {
1273    matchesSelector = query;
1274  }
1275
1276  // transport
1277  if ( typeof define === 'function' && define.amd ) {
1278    // AMD
1279    define( 'matches-selector/matches-selector',[],function() {
1280      return matchesSelector;
1281    });
1282  } else if ( typeof exports === 'object' ) {
1283    module.exports = matchesSelector;
1284  }
1285  else {
1286    // browser global
1287    window.matchesSelector = matchesSelector;
1288  }
1289
1290})( Element.prototype );
1291
1292/**
1293 * Fizzy UI utils v1.0.1
1294 * MIT license
1295 */
1296
1297/*jshint browser: true, undef: true, unused: true, strict: true */
1298
1299( function( window, factory ) {
1300  /*global define: false, module: false, require: false */
1301
1302  // universal module definition
1303
1304  if ( typeof define == 'function' && define.amd ) {
1305    // AMD
1306    define( 'fizzy-ui-utils/utils',[
1307      'doc-ready/doc-ready',
1308      'matches-selector/matches-selector'
1309    ], function( docReady, matchesSelector ) {
1310      return factory( window, docReady, matchesSelector );
1311    });
1312  } else if ( typeof exports == 'object' ) {
1313    // CommonJS
1314    module.exports = factory(
1315      window,
1316      require('doc-ready'),
1317      require('desandro-matches-selector')
1318    );
1319  } else {
1320    // browser global
1321    window.fizzyUIUtils = factory(
1322      window,
1323      window.docReady,
1324      window.matchesSelector
1325    );
1326  }
1327
1328}( window, function factory( window, docReady, matchesSelector ) {
1329
1330
1331
1332var utils = {};
1333
1334// ----- extend ----- //
1335
1336// extends objects
1337utils.extend = function( a, b ) {
1338  for ( var prop in b ) {
1339    a[ prop ] = b[ prop ];
1340  }
1341  return a;
1342};
1343
1344// ----- modulo ----- //
1345
1346utils.modulo = function( num, div ) {
1347  return ( ( num % div ) + div ) % div;
1348};
1349
1350// ----- isArray ----- //
1351
1352var objToString = Object.prototype.toString;
1353utils.isArray = function( obj ) {
1354  return objToString.call( obj ) == '[object Array]';
1355};
1356
1357// ----- makeArray ----- //
1358
1359// turn element or nodeList into an array
1360utils.makeArray = function( obj ) {
1361  var ary = [];
1362  if ( utils.isArray( obj ) ) {
1363    // use object if already an array
1364    ary = obj;
1365  } else if ( obj && typeof obj.length == 'number' ) {
1366    // convert nodeList to array
1367    for ( var i=0, len = obj.length; i < len; i++ ) {
1368      ary.push( obj[i] );
1369    }
1370  } else {
1371    // array of single index
1372    ary.push( obj );
1373  }
1374  return ary;
1375};
1376
1377// ----- indexOf ----- //
1378
1379// index of helper cause IE8
1380utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) {
1381    return ary.indexOf( obj );
1382  } : function( ary, obj ) {
1383    for ( var i=0, len = ary.length; i < len; i++ ) {
1384      if ( ary[i] === obj ) {
1385        return i;
1386      }
1387    }
1388    return -1;
1389  };
1390
1391// ----- removeFrom ----- //
1392
1393utils.removeFrom = function( ary, obj ) {
1394  var index = utils.indexOf( ary, obj );
1395  if ( index != -1 ) {
1396    ary.splice( index, 1 );
1397  }
1398};
1399
1400// ----- isElement ----- //
1401
1402// http://stackoverflow.com/a/384380/182183
1403utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ?
1404  function isElementDOM2( obj ) {
1405    return obj instanceof HTMLElement;
1406  } :
1407  function isElementQuirky( obj ) {
1408    return obj && typeof obj == 'object' &&
1409      obj.nodeType == 1 && typeof obj.nodeName == 'string';
1410  };
1411
1412// ----- setText ----- //
1413
1414utils.setText = ( function() {
1415  var setTextProperty;
1416  function setText( elem, text ) {
1417    // only check setTextProperty once
1418    setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' );
1419    elem[ setTextProperty ] = text;
1420  }
1421  return setText;
1422})();
1423
1424// ----- getParent ----- //
1425
1426utils.getParent = function( elem, selector ) {
1427  while ( elem != document.body ) {
1428    elem = elem.parentNode;
1429    if ( matchesSelector( elem, selector ) ) {
1430      return elem;
1431    }
1432  }
1433};
1434
1435// ----- getQueryElement ----- //
1436
1437// use element as selector string
1438utils.getQueryElement = function( elem ) {
1439  if ( typeof elem == 'string' ) {
1440    return document.querySelector( elem );
1441  }
1442  return elem;
1443};
1444
1445// ----- handleEvent ----- //
1446
1447// enable .ontype to trigger from .addEventListener( elem, 'type' )
1448utils.handleEvent = function( event ) {
1449  var method = 'on' + event.type;
1450  if ( this[ method ] ) {
1451    this[ method ]( event );
1452  }
1453};
1454
1455// ----- filterFindElements ----- //
1456
1457utils.filterFindElements = function( elems, selector ) {
1458  // make array of elems
1459  elems = utils.makeArray( elems );
1460  var ffElems = [];
1461
1462  for ( var i=0, len = elems.length; i < len; i++ ) {
1463    var elem = elems[i];
1464    // check that elem is an actual element
1465    if ( !utils.isElement( elem ) ) {
1466      continue;
1467    }
1468    // filter & find items if we have a selector
1469    if ( selector ) {
1470      // filter siblings
1471      if ( matchesSelector( elem, selector ) ) {
1472        ffElems.push( elem );
1473      }
1474      // find children
1475      var childElems = elem.querySelectorAll( selector );
1476      // concat childElems to filterFound array
1477      for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
1478        ffElems.push( childElems[j] );
1479      }
1480    } else {
1481      ffElems.push( elem );
1482    }
1483  }
1484
1485  return ffElems;
1486};
1487
1488// ----- debounceMethod ----- //
1489
1490utils.debounceMethod = function( _class, methodName, threshold ) {
1491  // original method
1492  var method = _class.prototype[ methodName ];
1493  var timeoutName = methodName + 'Timeout';
1494
1495  _class.prototype[ methodName ] = function() {
1496    var timeout = this[ timeoutName ];
1497    if ( timeout ) {
1498      clearTimeout( timeout );
1499    }
1500    var args = arguments;
1501
1502    var _this = this;
1503    this[ timeoutName ] = setTimeout( function() {
1504      method.apply( _this, args );
1505      delete _this[ timeoutName ];
1506    }, threshold || 100 );
1507  };
1508};
1509
1510// ----- htmlInit ----- //
1511
1512// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1513utils.toDashed = function( str ) {
1514  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
1515    return $1 + '-' + $2;
1516  }).toLowerCase();
1517};
1518
1519var console = window.console;
1520/**
1521 * allow user to initialize classes via .js-namespace class
1522 * htmlInit( Widget, 'widgetName' )
1523 * options are parsed from data-namespace-option attribute
1524 */
1525utils.htmlInit = function( WidgetClass, namespace ) {
1526  docReady( function() {
1527    var dashedNamespace = utils.toDashed( namespace );
1528    var elems = document.querySelectorAll( '.js-' + dashedNamespace );
1529    var dataAttr = 'data-' + dashedNamespace + '-options';
1530
1531    for ( var i=0, len = elems.length; i < len; i++ ) {
1532      var elem = elems[i];
1533      var attr = elem.getAttribute( dataAttr );
1534      var options;
1535      try {
1536        options = attr && JSON.parse( attr );
1537      } catch ( error ) {
1538        // log error, do not initialize
1539        if ( console ) {
1540          console.error( 'Error parsing ' + dataAttr + ' on ' +
1541            elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' +
1542            error );
1543        }
1544        continue;
1545      }
1546      // initialize
1547      var instance = new WidgetClass( elem, options );
1548      // make available via $().data('layoutname')
1549      var jQuery = window.jQuery;
1550      if ( jQuery ) {
1551        jQuery.data( elem, namespace, instance );
1552      }
1553    }
1554  });
1555};
1556
1557// -----  ----- //
1558
1559return utils;
1560
1561}));
1562
1563/**
1564 * Outlayer Item
1565 */
1566
1567( function( window, factory ) {
1568
1569  // universal module definition
1570  if ( typeof define === 'function' && define.amd ) {
1571    // AMD
1572    define( 'outlayer/item',[
1573        'eventEmitter/EventEmitter',
1574        'get-size/get-size',
1575        'get-style-property/get-style-property',
1576        'fizzy-ui-utils/utils'
1577      ],
1578      function( EventEmitter, getSize, getStyleProperty, utils ) {
1579        return factory( window, EventEmitter, getSize, getStyleProperty, utils );
1580      }
1581    );
1582  } else if (typeof exports === 'object') {
1583    // CommonJS
1584    module.exports = factory(
1585      window,
1586      require('wolfy87-eventemitter'),
1587      require('get-size'),
1588      require('desandro-get-style-property'),
1589      require('fizzy-ui-utils')
1590    );
1591  } else {
1592    // browser global
1593    window.Outlayer = {};
1594    window.Outlayer.Item = factory(
1595      window,
1596      window.EventEmitter,
1597      window.getSize,
1598      window.getStyleProperty,
1599      window.fizzyUIUtils
1600    );
1601  }
1602
1603}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) {
1604
1605
1606// ----- helpers ----- //
1607
1608var getComputedStyle = window.getComputedStyle;
1609var getStyle = getComputedStyle ?
1610  function( elem ) {
1611    return getComputedStyle( elem, null );
1612  } :
1613  function( elem ) {
1614    return elem.currentStyle;
1615  };
1616
1617
1618function isEmptyObj( obj ) {
1619  for ( var prop in obj ) {
1620    return false;
1621  }
1622  prop = null;
1623  return true;
1624}
1625
1626// -------------------------- CSS3 support -------------------------- //
1627
1628var transitionProperty = getStyleProperty('transition');
1629var transformProperty = getStyleProperty('transform');
1630var supportsCSS3 = transitionProperty && transformProperty;
1631var is3d = !!getStyleProperty('perspective');
1632
1633var transitionEndEvent = {
1634  WebkitTransition: 'webkitTransitionEnd',
1635  MozTransition: 'transitionend',
1636  OTransition: 'otransitionend',
1637  transition: 'transitionend'
1638}[ transitionProperty ];
1639
1640// properties that could have vendor prefix
1641var prefixableProperties = [
1642  'transform',
1643  'transition',
1644  'transitionDuration',
1645  'transitionProperty'
1646];
1647
1648// cache all vendor properties
1649var vendorProperties = ( function() {
1650  var cache = {};
1651  for ( var i=0, len = prefixableProperties.length; i < len; i++ ) {
1652    var prop = prefixableProperties[i];
1653    var supportedProp = getStyleProperty( prop );
1654    if ( supportedProp && supportedProp !== prop ) {
1655      cache[ prop ] = supportedProp;
1656    }
1657  }
1658  return cache;
1659})();
1660
1661// -------------------------- Item -------------------------- //
1662
1663function Item( element, layout ) {
1664  if ( !element ) {
1665    return;
1666  }
1667
1668  this.element = element;
1669  // parent layout class, i.e. Masonry, Isotope, or Packery
1670  this.layout = layout;
1671  this.position = {
1672    x: 0,
1673    y: 0
1674  };
1675
1676  this._create();
1677}
1678
1679// inherit EventEmitter
1680utils.extend( Item.prototype, EventEmitter.prototype );
1681
1682Item.prototype._create = function() {
1683  // transition objects
1684  this._transn = {
1685    ingProperties: {},
1686    clean: {},
1687    onEnd: {}
1688  };
1689
1690  this.css({
1691    position: 'absolute'
1692  });
1693};
1694
1695// trigger specified handler for event type
1696Item.prototype.handleEvent = function( event ) {
1697  var method = 'on' + event.type;
1698  if ( this[ method ] ) {
1699    this[ method ]( event );
1700  }
1701};
1702
1703Item.prototype.getSize = function() {
1704  this.size = getSize( this.element );
1705};
1706
1707/**
1708 * apply CSS styles to element
1709 * @param {Object} style
1710 */
1711Item.prototype.css = function( style ) {
1712  var elemStyle = this.element.style;
1713
1714  for ( var prop in style ) {
1715    // use vendor property if available
1716    var supportedProp = vendorProperties[ prop ] || prop;
1717    elemStyle[ supportedProp ] = style[ prop ];
1718  }
1719};
1720
1721 // measure position, and sets it
1722Item.prototype.getPosition = function() {
1723  var style = getStyle( this.element );
1724  var layoutOptions = this.layout.options;
1725  var isOriginLeft = layoutOptions.isOriginLeft;
1726  var isOriginTop = layoutOptions.isOriginTop;
1727  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
1728  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
1729  // convert percent to pixels
1730  var layoutSize = this.layout.size;
1731  var x = xValue.indexOf('%') != -1 ?
1732    ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );
1733  var y = yValue.indexOf('%') != -1 ?
1734    ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );
1735
1736  // clean up 'auto' or other non-integer values
1737  x = isNaN( x ) ? 0 : x;
1738  y = isNaN( y ) ? 0 : y;
1739  // remove padding from measurement
1740  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
1741  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
1742
1743  this.position.x = x;
1744  this.position.y = y;
1745};
1746
1747// set settled position, apply padding
1748Item.prototype.layoutPosition = function() {
1749  var layoutSize = this.layout.size;
1750  var layoutOptions = this.layout.options;
1751  var style = {};
1752
1753  // x
1754  var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight';
1755  var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right';
1756  var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left';
1757
1758  var x = this.position.x + layoutSize[ xPadding ];
1759  // set in percentage or pixels
1760  style[ xProperty ] = this.getXValue( x );
1761  // reset other property
1762  style[ xResetProperty ] = '';
1763
1764  // y
1765  var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom';
1766  var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom';
1767  var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top';
1768
1769  var y = this.position.y + layoutSize[ yPadding ];
1770  // set in percentage or pixels
1771  style[ yProperty ] = this.getYValue( y );
1772  // reset other property
1773  style[ yResetProperty ] = '';
1774
1775  this.css( style );
1776  this.emitEvent( 'layout', [ this ] );
1777};
1778
1779Item.prototype.getXValue = function( x ) {
1780  var layoutOptions = this.layout.options;
1781  return layoutOptions.percentPosition && !layoutOptions.isHorizontal ?
1782    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
1783};
1784
1785Item.prototype.getYValue = function( y ) {
1786  var layoutOptions = this.layout.options;
1787  return layoutOptions.percentPosition && layoutOptions.isHorizontal ?
1788    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
1789};
1790
1791
1792Item.prototype._transitionTo = function( x, y ) {
1793  this.getPosition();
1794  // get current x & y from top/left
1795  var curX = this.position.x;
1796  var curY = this.position.y;
1797
1798  var compareX = parseInt( x, 10 );
1799  var compareY = parseInt( y, 10 );
1800  var didNotMove = compareX === this.position.x && compareY === this.position.y;
1801
1802  // save end position
1803  this.setPosition( x, y );
1804
1805  // if did not move and not transitioning, just go to layout
1806  if ( didNotMove && !this.isTransitioning ) {
1807    this.layoutPosition();
1808    return;
1809  }
1810
1811  var transX = x - curX;
1812  var transY = y - curY;
1813  var transitionStyle = {};
1814  transitionStyle.transform = this.getTranslate( transX, transY );
1815
1816  this.transition({
1817    to: transitionStyle,
1818    onTransitionEnd: {
1819      transform: this.layoutPosition
1820    },
1821    isCleaning: true
1822  });
1823};
1824
1825Item.prototype.getTranslate = function( x, y ) {
1826  // flip cooridinates if origin on right or bottom
1827  var layoutOptions = this.layout.options;
1828  x = layoutOptions.isOriginLeft ? x : -x;
1829  y = layoutOptions.isOriginTop ? y : -y;
1830
1831  if ( is3d ) {
1832    return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
1833  }
1834
1835  return 'translate(' + x + 'px, ' + y + 'px)';
1836};
1837
1838// non transition + transform support
1839Item.prototype.goTo = function( x, y ) {
1840  this.setPosition( x, y );
1841  this.layoutPosition();
1842};
1843
1844// use transition and transforms if supported
1845Item.prototype.moveTo = supportsCSS3 ?
1846  Item.prototype._transitionTo : Item.prototype.goTo;
1847
1848Item.prototype.setPosition = function( x, y ) {
1849  this.position.x = parseInt( x, 10 );
1850  this.position.y = parseInt( y, 10 );
1851};
1852
1853// ----- transition ----- //
1854
1855/**
1856 * @param {Object} style - CSS
1857 * @param {Function} onTransitionEnd
1858 */
1859
1860// non transition, just trigger callback
1861Item.prototype._nonTransition = function( args ) {
1862  this.css( args.to );
1863  if ( args.isCleaning ) {
1864    this._removeStyles( args.to );
1865  }
1866  for ( var prop in args.onTransitionEnd ) {
1867    args.onTransitionEnd[ prop ].call( this );
1868  }
1869};
1870
1871/**
1872 * proper transition
1873 * @param {Object} args - arguments
1874 *   @param {Object} to - style to transition to
1875 *   @param {Object} from - style to start transition from
1876 *   @param {Boolean} isCleaning - removes transition styles after transition
1877 *   @param {Function} onTransitionEnd - callback
1878 */
1879Item.prototype._transition = function( args ) {
1880  // redirect to nonTransition if no transition duration
1881  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
1882    this._nonTransition( args );
1883    return;
1884  }
1885
1886  var _transition = this._transn;
1887  // keep track of onTransitionEnd callback by css property
1888  for ( var prop in args.onTransitionEnd ) {
1889    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
1890  }
1891  // keep track of properties that are transitioning
1892  for ( prop in args.to ) {
1893    _transition.ingProperties[ prop ] = true;
1894    // keep track of properties to clean up when transition is done
1895    if ( args.isCleaning ) {
1896      _transition.clean[ prop ] = true;
1897    }
1898  }
1899
1900  // set from styles
1901  if ( args.from ) {
1902    this.css( args.from );
1903    // force redraw. http://blog.alexmaccaw.com/css-transitions
1904    var h = this.element.offsetHeight;
1905    // hack for JSHint to hush about unused var
1906    h = null;
1907  }
1908  // enable transition
1909  this.enableTransition( args.to );
1910  // set styles that are transitioning
1911  this.css( args.to );
1912
1913  this.isTransitioning = true;
1914
1915};
1916
1917// dash before all cap letters, including first for
1918// WebkitTransform => -webkit-transform
1919function toDashedAll( str ) {
1920  return str.replace( /([A-Z])/g, function( $1 ) {
1921    return '-' + $1.toLowerCase();
1922  });
1923}
1924
1925var transitionProps = 'opacity,' +
vendor: 11,162 bytes, lines 1926-2372
1926  toDashedAll( vendorProperties.transform || 'transform' );
1927
1928Item.prototype.enableTransition = function(/* style */) {
1929  // HACK changing transitionProperty during a transition
1930  // will cause transition to jump
1931  if ( this.isTransitioning ) {
1932    return;
1933  }
1934
1935  // make `transition: foo, bar, baz` from style object
1936  // HACK un-comment this when enableTransition can work
1937  // while a transition is happening
1938  // var transitionValues = [];
1939  // for ( var prop in style ) {
1940  //   // dash-ify camelCased properties like WebkitTransition
1941  //   prop = vendorProperties[ prop ] || prop;
1942  //   transitionValues.push( toDashedAll( prop ) );
1943  // }
1944  // enable transition styles
1945  this.css({
1946    transitionProperty: transitionProps,
1947    transitionDuration: this.layout.options.transitionDuration
1948  });
1949  // listen for transition end event
1950  this.element.addEventListener( transitionEndEvent, this, false );
1951};
1952
1953Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ];
1954
1955// ----- events ----- //
1956
1957Item.prototype.onwebkitTransitionEnd = function( event ) {
1958  this.ontransitionend( event );
1959};
1960
1961Item.prototype.onotransitionend = function( event ) {
1962  this.ontransitionend( event );
1963};
1964
1965// properties that I munge to make my life easier
1966var dashedVendorProperties = {
1967  '-webkit-transform': 'transform',
1968  '-moz-transform': 'transform',
1969  '-o-transform': 'transform'
1970};
1971
1972Item.prototype.ontransitionend = function( event ) {
1973  // disregard bubbled events from children
1974  if ( event.target !== this.element ) {
1975    return;
1976  }
1977  var _transition = this._transn;
1978  // get property name of transitioned property, convert to prefix-free
1979  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
1980
1981  // remove property that has completed transitioning
1982  delete _transition.ingProperties[ propertyName ];
1983  // check if any properties are still transitioning
1984  if ( isEmptyObj( _transition.ingProperties ) ) {
1985    // all properties have completed transitioning
1986    this.disableTransition();
1987  }
1988  // clean style
1989  if ( propertyName in _transition.clean ) {
1990    // clean up style
1991    this.element.style[ event.propertyName ] = '';
1992    delete _transition.clean[ propertyName ];
1993  }
1994  // trigger onTransitionEnd callback
1995  if ( propertyName in _transition.onEnd ) {
1996    var onTransitionEnd = _transition.onEnd[ propertyName ];
1997    onTransitionEnd.call( this );
1998    delete _transition.onEnd[ propertyName ];
1999  }
2000
2001  this.emitEvent( 'transitionEnd', [ this ] );
2002};
2003
2004Item.prototype.disableTransition = function() {
2005  this.removeTransitionStyles();
2006  this.element.removeEventListener( transitionEndEvent, this, false );
2007  this.isTransitioning = false;
2008};
2009
2010/**
2011 * removes style property from element
2012 * @param {Object} style
2013**/
2014Item.prototype._removeStyles = function( style ) {
2015  // clean up transition styles
2016  var cleanStyle = {};
2017  for ( var prop in style ) {
2018    cleanStyle[ prop ] = '';
2019  }
2020  this.css( cleanStyle );
2021};
2022
2023var cleanTransitionStyle = {
2024  transitionProperty: '',
2025  transitionDuration: ''
2026};
2027
2028Item.prototype.removeTransitionStyles = function() {
2029  // remove transition
2030  this.css( cleanTransitionStyle );
2031};
2032
2033// ----- show/hide/remove ----- //
2034
2035// remove element from DOM
2036Item.prototype.removeElem = function() {
2037  this.element.parentNode.removeChild( this.element );
2038  // remove display: none
2039  this.css({ display: '' });
2040  this.emitEvent( 'remove', [ this ] );
2041};
2042
2043Item.prototype.remove = function() {
2044  // just remove element if no transition support or no transition
2045  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
2046    this.removeElem();
2047    return;
2048  }
2049
2050  // start transition
2051  var _this = this;
2052  this.once( 'transitionEnd', function() {
2053    _this.removeElem();
2054  });
2055  this.hide();
2056};
2057
2058Item.prototype.reveal = function() {
2059  delete this.isHidden;
2060  // remove display: none
2061  this.css({ display: '' });
2062
2063  var options = this.layout.options;
2064
2065  var onTransitionEnd = {};
2066  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
2067  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
2068
2069  this.transition({
2070    from: options.hiddenStyle,
2071    to: options.visibleStyle,
2072    isCleaning: true,
2073    onTransitionEnd: onTransitionEnd
2074  });
2075};
2076
2077Item.prototype.onRevealTransitionEnd = function() {
2078  // check if still visible
2079  // during transition, item may have been hidden
2080  if ( !this.isHidden ) {
2081    this.emitEvent('reveal');
2082  }
2083};
2084
2085/**
2086 * get style property use for hide/reveal transition end
2087 * @param {String} styleProperty - hiddenStyle/visibleStyle
2088 * @returns {String}
2089 */
2090Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) {
2091  var optionStyle = this.layout.options[ styleProperty ];
2092  // use opacity
2093  if ( optionStyle.opacity ) {
2094    return 'opacity';
2095  }
2096  // get first property
2097  for ( var prop in optionStyle ) {
2098    return prop;
2099  }
2100};
2101
2102Item.prototype.hide = function() {
2103  // set flag
2104  this.isHidden = true;
2105  // remove display: none
2106  this.css({ display: '' });
2107
2108  var options = this.layout.options;
2109
2110  var onTransitionEnd = {};
2111  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
2112  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
2113
2114  this.transition({
2115    from: options.visibleStyle,
2116    to: options.hiddenStyle,
2117    // keep hidden stuff hidden
2118    isCleaning: true,
2119    onTransitionEnd: onTransitionEnd
2120  });
2121};
2122
2123Item.prototype.onHideTransitionEnd = function() {
2124  // check if still hidden
2125  // during transition, item may have been un-hidden
2126  if ( this.isHidden ) {
2127    this.css({ display: 'none' });
2128    this.emitEvent('hide');
2129  }
2130};
2131
2132Item.prototype.destroy = function() {
2133  this.css({
2134    position: '',
2135    left: '',
2136    right: '',
2137    top: '',
2138    bottom: '',
2139    transition: '',
2140    transform: ''
2141  });
2142};
2143
2144return Item;
2145
2146}));
2147
2148/*!
2149 * Outlayer v1.4.2
2150 * the brains and guts of a layout library
2151 * MIT license
2152 */
2153
2154( function( window, factory ) {
2155
2156  // universal module definition
2157
2158  if ( typeof define == 'function' && define.amd ) {
2159    // AMD
2160    define( 'outlayer/outlayer',[
2161        'eventie/eventie',
2162        'eventEmitter/EventEmitter',
2163        'get-size/get-size',
2164        'fizzy-ui-utils/utils',
2165        './item'
2166      ],
2167      function( eventie, EventEmitter, getSize, utils, Item ) {
2168        return factory( window, eventie, EventEmitter, getSize, utils, Item);
2169      }
2170    );
2171  } else if ( typeof exports == 'object' ) {
2172    // CommonJS
2173    module.exports = factory(
2174      window,
2175      require('eventie'),
2176      require('wolfy87-eventemitter'),
2177      require('get-size'),
2178      require('fizzy-ui-utils'),
2179      require('./item')
2180    );
2181  } else {
2182    // browser global
2183    window.Outlayer = factory(
2184      window,
2185      window.eventie,
2186      window.EventEmitter,
2187      window.getSize,
2188      window.fizzyUIUtils,
2189      window.Outlayer.Item
2190    );
2191  }
2192
2193}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) {
2194
2195
2196// ----- vars ----- //
2197
2198var console = window.console;
2199var jQuery = window.jQuery;
2200var noop = function() {};
2201
2202// -------------------------- Outlayer -------------------------- //
2203
2204// globally unique identifiers
2205var GUID = 0;
2206// internal store of all Outlayer intances
2207var instances = {};
2208
2209
2210/**
2211 * @param {Element, String} element
2212 * @param {Object} options
2213 * @constructor
2214 */
2215function Outlayer( element, options ) {
2216  var queryElement = utils.getQueryElement( element );
2217  if ( !queryElement ) {
2218    if ( console ) {
2219      console.error( 'Bad element for ' + this.constructor.namespace +
2220        ': ' + ( queryElement || element ) );
2221    }
2222    return;
2223  }
2224  this.element = queryElement;
2225  // add jQuery
2226  if ( jQuery ) {
2227    this.$element = jQuery( this.element );
2228  }
2229
2230  // options
2231  this.options = utils.extend( {}, this.constructor.defaults );
2232  this.option( options );
2233
2234  // add id for Outlayer.getFromElement
2235  var id = ++GUID;
2236  this.element.outlayerGUID = id; // expando
2237  instances[ id ] = this; // associate via id
2238
2239  // kick it off
2240  this._create();
2241
2242  if ( this.options.isInitLayout ) {
2243    this.layout();
2244  }
2245}
2246
2247// settings are for internal use only
2248Outlayer.namespace = 'outlayer';
2249Outlayer.Item = Item;
2250
2251// default options
2252Outlayer.defaults = {
2253  containerStyle: {
2254    position: 'relative'
2255  },
2256  isInitLayout: true,
2257  isOriginLeft: true,
2258  isOriginTop: true,
2259  isResizeBound: true,
2260  isResizingContainer: true,
2261  // item options
2262  transitionDuration: '0.4s',
2263  hiddenStyle: {
2264    opacity: 0,
2265    transform: 'scale(0.001)'
2266  },
2267  visibleStyle: {
2268    opacity: 1,
2269    transform: 'scale(1)'
2270  }
2271};
2272
2273// inherit EventEmitter
2274utils.extend( Outlayer.prototype, EventEmitter.prototype );
2275
2276/**
2277 * set options
2278 * @param {Object} opts
2279 */
2280Outlayer.prototype.option = function( opts ) {
2281  utils.extend( this.options, opts );
2282};
2283
2284Outlayer.prototype._create = function() {
2285  // get items from children
2286  this.reloadItems();
2287  // elements that affect layout, but are not laid out
2288  this.stamps = [];
2289  this.stamp( this.options.stamp );
2290  // set container style
2291  utils.extend( this.element.style, this.options.containerStyle );
2292
2293  // bind resize method
2294  if ( this.options.isResizeBound ) {
2295    this.bindResize();
2296  }
2297};
2298
2299// goes through all children again and gets bricks in proper order
2300Outlayer.prototype.reloadItems = function() {
2301  // collection of item elements
2302  this.items = this._itemize( this.element.children );
2303};
2304
2305
2306/**
2307 * turn elements into Outlayer.Items to be used in layout
2308 * @param {Array or NodeList or HTMLElement} elems
2309 * @returns {Array} items - collection of new Outlayer Items
2310 */
2311Outlayer.prototype._itemize = function( elems ) {
2312
2313  var itemElems = this._filterFindItemElements( elems );
2314  var Item = this.constructor.Item;
2315
2316  // create new Outlayer Items for collection
2317  var items = [];
2318  for ( var i=0, len = itemElems.length; i < len; i++ ) {
2319    var elem = itemElems[i];
2320    var item = new Item( elem, this );
2321    items.push( item );
2322  }
2323
2324  return items;
2325};
2326
2327/**
2328 * get item elements to be used in layout
2329 * @param {Array or NodeList or HTMLElement} elems
2330 * @returns {Array} items - item elements
2331 */
2332Outlayer.prototype._filterFindItemElements = function( elems ) {
2333  return utils.filterFindElements( elems, this.options.itemSelector );
2334};
2335
2336/**
2337 * getter method for getting item elements
2338 * @returns {Array} elems - collection of item elements
2339 */
2340Outlayer.prototype.getItemElements = function() {
2341  var elems = [];
2342  for ( var i=0, len = this.items.length; i < len; i++ ) {
2343    elems.push( this.items[i].element );
2344  }
2345  return elems;
2346};
2347
2348// ----- init & layout ----- //
2349
2350/**
2351 * lays out all items
2352 */
2353Outlayer.prototype.layout = function() {
2354  this._resetLayout();
2355  this._manageStamps();
2356
2357  // don't animate first layout
2358  var isInstant = this.options.isLayoutInstant !== undefined ?
2359    this.options.isLayoutInstant : !this._isLayoutInited;
2360  this.layoutItems( this.items, isInstant );
2361
2362  // flag for initalized
2363  this._isLayoutInited = true;
2364};
2365
2366// _init is alias for layout
2367Outlayer.prototype._init = Outlayer.prototype.layout;
2368
2369/**
2370 * logic before any new layout
2371 */
2372Outlayer.prototype._resetLayout = function() {
vendor: 6,719 bytes, lines 2373-2649
2373  this.getSize();
2374};
2375
2376
2377Outlayer.prototype.getSize = function() {
2378  this.size = getSize( this.element );
2379};
2380
2381/**
2382 * get measurement from option, for columnWidth, rowHeight, gutter
2383 * if option is String -> get element from selector string, & get size of element
2384 * if option is Element -> get size of element
2385 * else use option as a number
2386 *
2387 * @param {String} measurement
2388 * @param {String} size - width or height
2389 * @private
2390 */
2391Outlayer.prototype._getMeasurement = function( measurement, size ) {
2392  var option = this.options[ measurement ];
2393  var elem;
2394  if ( !option ) {
2395    // default to 0
2396    this[ measurement ] = 0;
2397  } else {
2398    // use option as an element
2399    if ( typeof option === 'string' ) {
2400      elem = this.element.querySelector( option );
2401    } else if ( utils.isElement( option ) ) {
2402      elem = option;
2403    }
2404    // use size of element, if element
2405    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
2406  }
2407};
2408
2409/**
2410 * layout a collection of item elements
2411 * @api public
2412 */
2413Outlayer.prototype.layoutItems = function( items, isInstant ) {
2414  items = this._getItemsForLayout( items );
2415
2416  this._layoutItems( items, isInstant );
2417
2418  this._postLayout();
2419};
2420
2421/**
2422 * get the items to be laid out
2423 * you may want to skip over some items
2424 * @param {Array} items
2425 * @returns {Array} items
2426 */
2427Outlayer.prototype._getItemsForLayout = function( items ) {
2428  var layoutItems = [];
2429  for ( var i=0, len = items.length; i < len; i++ ) {
2430    var item = items[i];
2431    if ( !item.isIgnored ) {
2432      layoutItems.push( item );
2433    }
2434  }
2435  return layoutItems;
2436};
2437
2438/**
2439 * layout items
2440 * @param {Array} items
2441 * @param {Boolean} isInstant
2442 */
2443Outlayer.prototype._layoutItems = function( items, isInstant ) {
2444  this._emitCompleteOnItems( 'layout', items );
2445
2446  if ( !items || !items.length ) {
2447    // no items, emit event with empty array
2448    return;
2449  }
2450
2451  var queue = [];
2452
2453  for ( var i=0, len = items.length; i < len; i++ ) {
2454    var item = items[i];
2455    // get x/y object from method
2456    var position = this._getItemLayoutPosition( item );
2457    // enqueue
2458    position.item = item;
2459    position.isInstant = isInstant || item.isLayoutInstant;
2460    queue.push( position );
2461  }
2462
2463  this._processLayoutQueue( queue );
2464};
2465
2466/**
2467 * get item layout position
2468 * @param {Outlayer.Item} item
2469 * @returns {Object} x and y position
2470 */
2471Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) {
2472  return {
2473    x: 0,
2474    y: 0
2475  };
2476};
2477
2478/**
2479 * iterate over array and position each item
2480 * Reason being - separating this logic prevents 'layout invalidation'
2481 * thx @paul_irish
2482 * @param {Array} queue
2483 */
2484Outlayer.prototype._processLayoutQueue = function( queue ) {
2485  for ( var i=0, len = queue.length; i < len; i++ ) {
2486    var obj = queue[i];
2487    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );
2488  }
2489};
2490
2491/**
2492 * Sets position of item in DOM
2493 * @param {Outlayer.Item} item
2494 * @param {Number} x - horizontal position
2495 * @param {Number} y - vertical position
2496 * @param {Boolean} isInstant - disables transitions
2497 */
2498Outlayer.prototype._positionItem = function( item, x, y, isInstant ) {
2499  if ( isInstant ) {
2500    // if not transition, just set CSS
2501    item.goTo( x, y );
2502  } else {
2503    item.moveTo( x, y );
2504  }
2505};
2506
2507/**
2508 * Any logic you want to do after each layout,
2509 * i.e. size the container
2510 */
2511Outlayer.prototype._postLayout = function() {
2512  this.resizeContainer();
2513};
2514
2515Outlayer.prototype.resizeContainer = function() {
2516  if ( !this.options.isResizingContainer ) {
2517    return;
2518  }
2519  var size = this._getContainerSize();
2520  if ( size ) {
2521    this._setContainerMeasure( size.width, true );
2522    this._setContainerMeasure( size.height, false );
2523  }
2524};
2525
2526/**
2527 * Sets width or height of container if returned
2528 * @returns {Object} size
2529 *   @param {Number} width
2530 *   @param {Number} height
2531 */
2532Outlayer.prototype._getContainerSize = noop;
2533
2534/**
2535 * @param {Number} measure - size of width or height
2536 * @param {Boolean} isWidth
2537 */
2538Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) {
2539  if ( measure === undefined ) {
2540    return;
2541  }
2542
2543  var elemSize = this.size;
2544  // add padding and border width if border box
2545  if ( elemSize.isBorderBox ) {
2546    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
2547      elemSize.borderLeftWidth + elemSize.borderRightWidth :
2548      elemSize.paddingBottom + elemSize.paddingTop +
2549      elemSize.borderTopWidth + elemSize.borderBottomWidth;
2550  }
2551
2552  measure = Math.max( measure, 0 );
2553  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
2554};
2555
2556/**
2557 * emit eventComplete on a collection of items events
2558 * @param {String} eventName
2559 * @param {Array} items - Outlayer.Items
2560 */
2561Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) {
2562  var _this = this;
2563  function onComplete() {
2564    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
2565  }
2566
2567  var count = items.length;
2568  if ( !items || !count ) {
2569    onComplete();
2570    return;
2571  }
2572
2573  var doneCount = 0;
2574  function tick() {
2575    doneCount++;
2576    if ( doneCount === count ) {
2577      onComplete();
2578    }
2579  }
2580
2581  // bind callback
2582  for ( var i=0, len = items.length; i < len; i++ ) {
2583    var item = items[i];
2584    item.once( eventName, tick );
2585  }
2586};
2587
2588/**
2589 * emits events via eventEmitter and jQuery events
2590 * @param {String} type - name of event
2591 * @param {Event} event - original event
2592 * @param {Array} args - extra arguments
2593 */
2594Outlayer.prototype.dispatchEvent = function( type, event, args ) {
2595  // add original event to arguments
2596  var emitArgs = event ? [ event ].concat( args ) : args;
2597  this.emitEvent( type, emitArgs );
2598
2599  if ( jQuery ) {
2600    // set this.$element
2601    this.$element = this.$element || jQuery( this.element );
2602    if ( event ) {
2603      // create jQuery event
2604      var $event = jQuery.Event( event );
2605      $event.type = type;
2606      this.$element.trigger( $event, args );
2607    } else {
2608      // just trigger with type if no event available
2609      this.$element.trigger( type, args );
2610    }
2611  }
2612};
2613
2614// -------------------------- ignore & stamps -------------------------- //
2615
2616
2617/**
2618 * keep item in collection, but do not lay it out
2619 * ignored items do not get skipped in layout
2620 * @param {Element} elem
2621 */
2622Outlayer.prototype.ignore = function( elem ) {
2623  var item = this.getItem( elem );
2624  if ( item ) {
2625    item.isIgnored = true;
2626  }
2627};
2628
2629/**
2630 * return item to layout collection
2631 * @param {Element} elem
2632 */
2633Outlayer.prototype.unignore = function( elem ) {
2634  var item = this.getItem( elem );
2635  if ( item ) {
2636    delete item.isIgnored;
2637  }
2638};
2639
2640/**
2641 * adds elements to stamps
2642 * @param {NodeList, Array, Element, or String} elems
2643 */
2644Outlayer.prototype.stamp = function( elems ) {
2645  elems = this._find( elems );
2646  if ( !elems ) {
2647    return;
2648  }
2649
2650  this.stamps = this.stamps.concat( elems );
2651  // ignore
2652  for ( var i=0, len = elems.length; i < len; i++ ) {
2653    var elem = elems[i];
2654    this.ignore( elem );
2655  }
2656};
2657
2658/**
2659 * removes elements to stamps
2660 * @param {NodeList, Array, or Element} elems
2661 */
2662Outlayer.prototype.unstamp = function( elems ) {
2663  elems = this._find( elems );
2664  if ( !elems ){
2665    return;
2666  }
2667
2668  for ( var i=0, len = elems.length; i < len; i++ ) {
2669    var elem = elems[i];
2670    // filter out removed stamp elements
2671    utils.removeFrom( this.stamps, elem );
2672    this.unignore( elem );
2673  }
2674
2675};
2676
2677/**
2678 * finds child elements
2679 * @param {NodeList, Array, Element, or String} elems
2680 * @returns {Array} elems
2681 */
2682Outlayer.prototype._find = function( elems ) {
2683  if ( !elems ) {
2684    return;
2685  }
2686  // if string, use argument as selector string
2687  if ( typeof elems === 'string' ) {
2688    elems = this.element.querySelectorAll( elems );
2689  }
2690  elems = utils.makeArray( elems );
2691  return elems;
2692};
2693
2694Outlayer.prototype._manageStamps = function() {
2695  if ( !this.stamps || !this.stamps.length ) {
2696    return;
2697  }
2698
2699  this._getBoundingRect();
2700
2701  for ( var i=0, len = this.stamps.length; i < len; i++ ) {
2702    var stamp = this.stamps[i];
2703    this._manageStamp( stamp );
2704  }
2705};
2706
2707// update boundingLeft / Top
2708Outlayer.prototype._getBoundingRect = function() {
2709  // get bounding rect for container element
2710  var boundingRect = this.element.getBoundingClientRect();
2711  var size = this.size;
2712  this._boundingRect = {
2713    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
2714    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
2715    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
2716    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
2717  };
2718};
2719
2720/**
2721 * @param {Element} stamp
2722**/
2723Outlayer.prototype._manageStamp = noop;
2724
2725/**
2726 * get x/y position of element relative to container element
2727 * @param {Element} elem
2728 * @returns {Object} offset - has left, top, right, bottom
2729 */
2730Outlayer.prototype._getElementOffset = function( elem ) {
2731  var boundingRect = elem.getBoundingClientRect();
2732  var thisRect = this._boundingRect;
2733  var size = getSize( elem );
2734  var offset = {
2735    left: boundingRect.left - thisRect.left - size.marginLeft,
2736    top: boundingRect.top - thisRect.top - size.marginTop,
2737    right: thisRect.right - boundingRect.right - size.marginRight,
2738    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
2739  };
2740  return offset;
2741};
2742
2743// -------------------------- resize -------------------------- //
2744
2745// enable event handlers for listeners
2746// i.e. resize -> onresize
2747Outlayer.prototype.handleEvent = function( event ) {
2748  var method = 'on' + event.type;
2749  if ( this[ method ] ) {
2750    this[ method ]( event );
2751  }
2752};
2753
2754/**
2755 * Bind layout to window resizing
2756 */
2757Outlayer.prototype.bindResize = function() {
2758  // bind just one listener
2759  if ( this.isResizeBound ) {
2760    return;
2761  }
2762  eventie.bind( window, 'resize', this );
2763  this.isResizeBound = true;
2764};
2765
2766/**
2767 * Unbind layout to window resizing
2768 */
2769Outlayer.prototype.unbindResize = function() {
2770  if ( this.isResizeBound ) {
2771    eventie.unbind( window, 'resize', this );
2772  }
2773  this.isResizeBound = false;
2774};
2775
2776// original debounce by John Hann
2777// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
2778
2779// this fires every resize
2780Outlayer.prototype.onresize = function() {
2781  if ( this.resizeTimeout ) {
2782    clearTimeout( this.resizeTimeout );
2783  }
2784
2785  var _this = this;
2786  function delayed() {
2787    _this.resize();
2788    delete _this.resizeTimeout;
2789  }
2790
2791  this.resizeTimeout = setTimeout( delayed, 100 );
2792};
2793
2794// debounced, layout on resize
2795Outlayer.prototype.resize = function() {
2796  // don't trigger if size did not change
2797  // or if resize was unbound. See #9
2798  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
2799    return;
2800  }
2801
2802  this.layout();
2803};
2804
2805/**
2806 * check if layout is needed post layout
2807 * @returns Boolean
2808 */
2809Outlayer.prototype.needsResizeLayout = function() {
2810  var size = getSize( this.element );
2811  // check that this.size and size are there
2812  // IE8 triggers resize on body size change, so they might not be
2813  var hasSizes = this.size && size;
2814  return hasSizes && size.innerWidth !== this.size.innerWidth;
2815};
2816
2817// -------------------------- methods -------------------------- //
2818
2819/**
2820 * add items to Outlayer instance
2821 * @param {Array or NodeList or Element} elems
2822 * @returns {Array} items - Outlayer.Items
2823**/
2824Outlayer.prototype.addItems = function( elems ) {
2825  var items = this._itemize( elems );
2826  // add items to collection
2827  if ( items.length ) {
2828    this.items = this.items.concat( items );
2829  }
2830  return items;
2831};
2832
2833/**
2834 * Layout newly-appended item elements
2835 * @param {Array or NodeList or Element} elems
2836 */
2837Outlayer.prototype.appended = function( elems ) {
2838  var items = this.addItems( elems );
2839  if ( !items.length ) {
2840    return;
2841  }
2842  // layout and reveal just the new items
2843  this.layoutItems( items, true );
2844  this.reveal( items );
2845};
2846
2847/**
2848 * Layout prepended elements
2849 * @param {Array or NodeList or Element} elems
2850 */
2851Outlayer.prototype.prepended = function( elems ) {
2852  var items = this._itemize( elems );
2853  if ( !items.length ) {
2854    return;
2855  }
2856  // add items to beginning of collection
2857  var previousItems = this.items.slice(0);
2858  this.items = items.concat( previousItems );
2859  // start new layout
2860  this._resetLayout();
2861  this._manageStamps();
2862  // layout new stuff without transition
2863  this.layoutItems( items, true );
2864  this.reveal( items );
2865  // layout previous items
2866  this.layoutItems( previousItems );
2867};
2868
2869/**
2870 * reveal a collection of items
2871 * @param {Array of Outlayer.Items} items
2872 */
2873Outlayer.prototype.reveal = function( items ) {
2874  this._emitCompleteOnItems( 'reveal', items );
2875
2876  var len = items && items.length;
2877  for ( var i=0; len && i < len; i++ ) {
2878    var item = items[i];
2879    item.reveal();
2880  }
2881};
2882
2883/**
2884 * hide a collection of items
2885 * @param {Array of Outlayer.Items} items
2886 */
2887Outlayer.prototype.hide = function( items ) {
2888  this._emitCompleteOnItems( 'hide', items );
2889
2890  var len = items && items.length;
2891  for ( var i=0; len && i < len; i++ ) {
2892    var item = items[i];
2893    item.hide();
2894  }
2895};
2896
2897/**
2898 * reveal item elements
2899 * @param {Array}, {Element}, {NodeList} items
2900 */
2901Outlayer.prototype.revealItemElements = function( elems ) {
2902  var items = this.getItems( elems );
2903  this.reveal( items );
2904};
2905
2906/**
2907 * hide item elements
2908 * @param {Array}, {Element}, {NodeList} items
2909 */
2910Outlayer.prototype.hideItemElements = function( elems ) {
2911  var items = this.getItems( elems );
2912  this.hide( items );
2913};
2914
2915/**
2916 * get Outlayer.Item, given an Element
2917 * @param {Element} elem
2918 * @param {Function} callback
2919 * @returns {Outlayer.Item} item
2920 */
2921Outlayer.prototype.getItem = function( elem ) {
2922  // loop through items to get the one that matches
2923  for ( var i=0, len = this.items.length; i < len; i++ ) {
2924    var item = this.items[i];
2925    if ( item.element === elem ) {
2926      // return item
2927      return item;
2928    }
2929  }
2930};
2931
2932/**
2933 * get collection of Outlayer.Items, given Elements
2934 * @param {Array} elems
2935 * @returns {Array} items - Outlayer.Items
2936 */
2937Outlayer.prototype.getItems = function( elems ) {
2938  elems = utils.makeArray( elems );
2939  var items = [];
2940  for ( var i=0, len = elems.length; i < len; i++ ) {
2941    var elem = elems[i];
2942    var item = this.getItem( elem );
2943    if ( item ) {
2944      items.push( item );
2945    }
2946  }
2947
2948  return items;
2949};
2950
2951/**
2952 * remove element(s) from instance and DOM
2953 * @param {Array or NodeList or Element} elems
2954 */
2955Outlayer.prototype.remove = function( elems ) {
2956  var removeItems = this.getItems( elems );
2957
2958  this._emitCompleteOnItems( 'remove', removeItems );
2959
2960  // bail if no items to remove
2961  if ( !removeItems || !removeItems.length ) {
2962    return;
2963  }
2964
2965  for ( var i=0, len = removeItems.length; i < len; i++ ) {
2966    var item = removeItems[i];
2967    item.remove();
2968    // remove item from collection
2969    utils.removeFrom( this.items, item );
2970  }
2971};
2972
2973// ----- destroy ----- //
2974
2975// remove and disable Outlayer instance
2976Outlayer.prototype.destroy = function() {
2977  // clean up dynamic styles
2978  var style = this.element.style;
2979  style.height = '';
2980  style.position = '';
2981  style.width = '';
2982  // destroy items
2983  for ( var i=0, len = this.items.length; i < len; i++ ) {
2984    var item = this.items[i];
2985    item.destroy();
2986  }
2987
2988  this.unbindResize();
2989
2990  var id = this.element.outlayerGUID;
2991  delete instances[ id ]; // remove reference to instance by id
2992  delete this.element.outlayerGUID;
2993  // remove data for jQuery
2994  if ( jQuery ) {
2995    jQuery.removeData( this.element, this.constructor.namespace );
2996  }
2997
2998};
2999
3000// -------------------------- data -------------------------- //
3001
3002/**
3003 * get Outlayer instance from element
3004 * @param {Element} elem
3005 * @returns {Outlayer}
3006 */
3007Outlayer.data = function( elem ) {
3008  elem = utils.getQueryElement( elem );
3009  var id = elem && elem.outlayerGUID;
3010  return id && instances[ id ];
3011};
3012
3013
3014// -------------------------- create Outlayer class -------------------------- //
3015
3016/**
3017 * create a layout class
3018 * @param {String} namespace
3019 */
3020Outlayer.create = function( namespace, options ) {
3021  // sub-class Outlayer
3022  function Layout() {
3023    Outlayer.apply( this, arguments );
3024  }
3025  // inherit Outlayer prototype, use Object.create if there
3026  if ( Object.create ) {
3027    Layout.prototype = Object.create( Outlayer.prototype );
3028  } else {
3029    utils.extend( Layout.prototype, Outlayer.prototype );
3030  }
3031  // set contructor, used for namespace and Item
3032  Layout.prototype.constructor = Layout;
3033
3034  Layout.defaults = utils.extend( {}, Outlayer.defaults );
3035  // apply new options
3036  utils.extend( Layout.defaults, options );
3037  // keep prototype.settings for backwards compatibility (Packery v1.2.0)
3038  Layout.prototype.settings = {};
3039
3040  Layout.namespace = namespace;
3041
3042  Layout.data = Outlayer.data;
3043
3044  // sub-class Item
3045  Layout.Item = function LayoutItem() {
3046    Item.apply( this, arguments );
3047  };
3048
3049  Layout.Item.prototype = new Item();
3050
3051  // -------------------------- declarative -------------------------- //
3052
3053  utils.htmlInit( Layout, namespace );
3054
3055  // -------------------------- jQuery bridge -------------------------- //
3056
3057  // make into jQuery plugin
3058  if ( jQuery && jQuery.bridget ) {
3059    jQuery.bridget( namespace, Layout );
3060  }
3061
3062  return Layout;
3063};
3064
3065// ----- fin ----- //
3066
3067// back in global
3068Outlayer.Item = Item;
3069
3070return Outlayer;
3071
3072}));
3073
3074
3075/**
3076 * Rect
3077 * low-level utility class for basic geometry
3078 */
3079
3080( function( window, factory ) {
3081
3082  // universal module definition
3083  if ( typeof define == 'function' && define.amd ) {
3084    // AMD
3085    define( 'packery/js/rect',factory );
3086  } else if ( typeof exports == 'object' ) {
3087    // CommonJS
3088    module.exports = factory();
3089  } else {
3090    // browser global
3091    window.Packery = window.Packery || {};
3092    window.Packery.Rect = factory();
3093  }
3094
3095}( window, function factory() {
3096
3097
3098// -------------------------- Packery -------------------------- //
3099
3100// global namespace
3101var Packery = window.Packery = function() {};
3102
3103// -------------------------- Rect -------------------------- //
3104
3105function Rect( props ) {
3106  // extend properties from defaults
3107  for ( var prop in Rect.defaults ) {
3108    this[ prop ] = Rect.defaults[ prop ];
3109  }
3110
3111  for ( prop in props ) {
3112    this[ prop ] = props[ prop ];
3113  }
3114
3115}
3116
3117// make available
3118Packery.Rect = Rect;
3119
3120Rect.defaults = {
3121  x: 0,
3122  y: 0,
3123  width: 0,
3124  height: 0
3125};
3126
3127/**
3128 * Determines whether or not this rectangle wholly encloses another rectangle or point.
3129 * @param {Rect} rect
3130 * @returns {Boolean}
3131**/
3132Rect.prototype.contains = function( rect ) {
3133  // points don't have width or height
3134  var otherWidth = rect.width || 0;
3135  var otherHeight = rect.height || 0;
3136  return this.x <= rect.x &&
3137    this.y <= rect.y &&
3138    this.x + this.width >= rect.x + otherWidth &&
3139    this.y + this.height >= rect.y + otherHeight;
3140};
3141
3142/**
3143 * Determines whether or not the rectangle intersects with another.
3144 * @param {Rect} rect
3145 * @returns {Boolean}
3146**/
3147Rect.prototype.overlaps = function( rect ) {
3148  var thisRight = this.x + this.width;
3149  var thisBottom = this.y + this.height;
3150  var rectRight = rect.x + rect.width;
3151  var rectBottom = rect.y + rect.height;
3152
3153  // http://stackoverflow.com/a/306332
3154  return this.x < rectRight &&
3155    thisRight > rect.x &&
3156    this.y < rectBottom &&
3157    thisBottom > rect.y;
3158};
3159
3160/**
3161 * @param {Rect} rect - the overlapping rect
3162 * @returns {Array} freeRects - rects representing the area around the rect
3163**/
3164Rect.prototype.getMaximalFreeRects = function( rect ) {
3165
3166  // if no intersection, return false
3167  if ( !this.overlaps( rect ) ) {
3168    return false;
vendor: 6,336 bytes, lines 3169-3443
3169  }
3170
3171  var freeRects = [];
3172  var freeRect;
3173
3174  var thisRight = this.x + this.width;
3175  var thisBottom = this.y + this.height;
3176  var rectRight = rect.x + rect.width;
3177  var rectBottom = rect.y + rect.height;
3178
3179  // top
3180  if ( this.y < rect.y ) {
3181    freeRect = new Rect({
3182      x: this.x,
3183      y: this.y,
3184      width: this.width,
3185      height: rect.y - this.y
3186    });
3187    freeRects.push( freeRect );
3188  }
3189
3190  // right
3191  if ( thisRight > rectRight ) {
3192    freeRect = new Rect({
3193      x: rectRight,
3194      y: this.y,
3195      width: thisRight - rectRight,
3196      height: this.height
3197    });
3198    freeRects.push( freeRect );
3199  }
3200
3201  // bottom
3202  if ( thisBottom > rectBottom ) {
3203    freeRect = new Rect({
3204      x: this.x,
3205      y: rectBottom,
3206      width: this.width,
3207      height: thisBottom - rectBottom
3208    });
3209    freeRects.push( freeRect );
3210  }
3211
3212  // left
3213  if ( this.x < rect.x ) {
3214    freeRect = new Rect({
3215      x: this.x,
3216      y: this.y,
3217      width: rect.x - this.x,
3218      height: this.height
3219    });
3220    freeRects.push( freeRect );
3221  }
3222
3223  return freeRects;
3224};
3225
3226Rect.prototype.canFit = function( rect ) {
3227  return this.width >= rect.width && this.height >= rect.height;
3228};
3229
3230return Rect;
3231
3232}));
3233
3234/**
3235 * Packer
3236 * bin-packing algorithm
3237 */
3238
3239( function( window, factory ) {
3240
3241  // universal module definition
3242  if ( typeof define == 'function' && define.amd ) {
3243    // AMD
3244    define( 'packery/js/packer',[ './rect' ], factory );
3245  } else if ( typeof exports == 'object' ) {
3246    // CommonJS
3247    module.exports = factory(
3248      require('./rect')
3249    );
3250  } else {
3251    // browser global
3252    var Packery = window.Packery = window.Packery || {};
3253    Packery.Packer = factory( Packery.Rect );
3254  }
3255
3256}( window, function factory( Rect ) {
3257
3258
3259// -------------------------- Packer -------------------------- //
3260
3261/**
3262 * @param {Number} width
3263 * @param {Number} height
3264 * @param {String} sortDirection
3265 *   topLeft for vertical, leftTop for horizontal
3266 */
3267function Packer( width, height, sortDirection ) {
3268  this.width = width || 0;
3269  this.height = height || 0;
3270  this.sortDirection = sortDirection || 'downwardLeftToRight';
3271
3272  this.reset();
3273}
3274
3275Packer.prototype.reset = function() {
3276  this.spaces = [];
3277  this.newSpaces = [];
3278
3279  var initialSpace = new Rect({
3280    x: 0,
3281    y: 0,
3282    width: this.width,
3283    height: this.height
3284  });
3285
3286  this.spaces.push( initialSpace );
3287  // set sorter
3288  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
3289};
3290
3291// change x and y of rect to fit with in Packer's available spaces
3292Packer.prototype.pack = function( rect ) {
3293  for ( var i=0, len = this.spaces.length; i < len; i++ ) {
3294    var space = this.spaces[i];
3295    if ( space.canFit( rect ) ) {
3296      this.placeInSpace( rect, space );
3297      break;
3298    }
3299  }
3300};
3301
3302Packer.prototype.placeInSpace = function( rect, space ) {
3303  // place rect in space
3304  rect.x = space.x;
3305  rect.y = space.y;
3306
3307  this.placed( rect );
3308};
3309
3310// update spaces with placed rect
3311Packer.prototype.placed = function( rect ) {
3312  // update spaces
3313  var revisedSpaces = [];
3314  for ( var i=0, len = this.spaces.length; i < len; i++ ) {
3315    var space = this.spaces[i];
3316    var newSpaces = space.getMaximalFreeRects( rect );
3317    // add either the original space or the new spaces to the revised spaces
3318    if ( newSpaces ) {
3319      revisedSpaces.push.apply( revisedSpaces, newSpaces );
3320    } else {
3321      revisedSpaces.push( space );
3322    }
3323  }
3324
3325  this.spaces = revisedSpaces;
3326
3327  this.mergeSortSpaces();
3328};
3329
3330Packer.prototype.mergeSortSpaces = function() {
3331  // remove redundant spaces
3332  Packer.mergeRects( this.spaces );
3333  this.spaces.sort( this.sorter );
3334};
3335
3336// add a space back
3337Packer.prototype.addSpace = function( rect ) {
3338  this.spaces.push( rect );
3339  this.mergeSortSpaces();
3340};
3341
3342// -------------------------- utility functions -------------------------- //
3343
3344/**
3345 * Remove redundant rectangle from array of rectangles
3346 * @param {Array} rects: an array of Rects
3347 * @returns {Array} rects: an array of Rects
3348**/
3349Packer.mergeRects = function( rects ) {
3350  for ( var i=0, len = rects.length; i < len; i++ ) {
3351    var rect = rects[i];
3352    // skip over this rect if it was already removed
3353    if ( !rect ) {
3354      continue;
3355    }
3356    // clone rects we're testing, remove this rect
3357    var compareRects = rects.slice(0);
3358    // do not compare with self
3359    compareRects.splice( i, 1 );
3360    // compare this rect with others
3361    var removedCount = 0;
3362    for ( var j=0, jLen = compareRects.length; j < jLen; j++ ) {
3363      var compareRect = compareRects[j];
3364      // if this rect contains another,
3365      // remove that rect from test collection
3366      var indexAdjust = i > j ? 0 : 1;
3367      if ( rect.contains( compareRect ) ) {
3368        // console.log( 'current test rects:' + testRects.length, testRects );
3369        // console.log( i, j, indexAdjust, rect, compareRect );
3370        rects.splice( j + indexAdjust - removedCount, 1 );
3371        removedCount++;
3372      }
3373    }
3374  }
3375
3376  return rects;
3377};
3378
3379
3380// -------------------------- sorters -------------------------- //
3381
3382// functions for sorting rects in order
3383var sorters = {
3384  // top down, then left to right
3385  downwardLeftToRight: function( a, b ) {
3386    return a.y - b.y || a.x - b.x;
3387  },
3388  // left to right, then top down
3389  rightwardTopToBottom: function( a, b ) {
3390    return a.x - b.x || a.y - b.y;
3391  }
3392};
3393
3394
3395// --------------------------  -------------------------- //
3396
3397return Packer;
3398
3399}));
3400/**
3401 * Packery Item Element
3402**/
3403
3404( function( window, factory ) {
3405
3406  // universal module definition
3407
3408  if ( typeof define == 'function' && define.amd ) {
3409    // AMD
3410    define( 'packery/js/item',[
3411        'get-style-property/get-style-property',
3412        'outlayer/outlayer',
3413        './rect'
3414      ],
3415      factory );
3416  } else if ( typeof exports == 'object' ) {
3417    // CommonJS
3418    module.exports = factory(
3419      require('desandro-get-style-property'),
3420      require('outlayer'),
3421      require('./rect')
3422    );
3423  } else {
3424    // browser global
3425    window.Packery.Item = factory(
3426      window.getStyleProperty,
3427      window.Outlayer,
3428      window.Packery.Rect
3429    );
3430  }
3431
3432}( window, function factory( getStyleProperty, Outlayer, Rect ) {
3433
3434
3435// -------------------------- Item -------------------------- //
3436
3437var transformProperty = getStyleProperty('transform');
3438
3439// sub-class Item
3440var Item = function PackeryItem() {
3441  Outlayer.Item.apply( this, arguments );
3442};
3443
3444Item.prototype = new Outlayer.Item();
3445
3446var protoCreate = Item.prototype._create;
3447Item.prototype._create = function() {
3448  // call default _create logic
3449  protoCreate.call( this );
3450  this.rect = new Rect();
3451  // rect used for placing, in drag or Packery.fit()
3452  this.placeRect = new Rect();
3453};
3454
3455// -------------------------- drag -------------------------- //
3456
3457Item.prototype.dragStart = function() {
3458  this.getPosition();
3459  this.removeTransitionStyles();
3460  // remove transform property from transition
3461  if ( this.isTransitioning && transformProperty ) {
3462    this.element.style[ transformProperty ] = 'none';
3463  }
3464  this.getSize();
3465  // create place rect, used for position when dragged then dropped
3466  // or when positioning
3467  this.isPlacing = true;
3468  this.needsPositioning = false;
3469  this.positionPlaceRect( this.position.x, this.position.y );
3470  this.isTransitioning = false;
3471  this.didDrag = false;
3472};
3473
3474/**
3475 * handle item when it is dragged
3476 * @param {Number} x - horizontal position of dragged item
3477 * @param {Number} y - vertical position of dragged item
3478 */
3479Item.prototype.dragMove = function( x, y ) {
3480  this.didDrag = true;
3481  var packerySize = this.layout.size;
3482  x -= packerySize.paddingLeft;
3483  y -= packerySize.paddingTop;
3484  this.positionPlaceRect( x, y );
3485};
3486
3487Item.prototype.dragStop = function() {
3488  this.getPosition();
3489  var isDiffX = this.position.x != this.placeRect.x;
3490  var isDiffY = this.position.y != this.placeRect.y;
3491  // set post-drag positioning flag
3492  this.needsPositioning = isDiffX || isDiffY;
3493  // reset flag
3494  this.didDrag = false;
3495};
3496
3497// -------------------------- placing -------------------------- //
3498
3499/**
3500 * position a rect that will occupy space in the packer
3501 * @param {Number} x
3502 * @param {Number} y
3503 * @param {Boolean} isMaxYContained
3504 */
3505Item.prototype.positionPlaceRect = function( x, y, isMaxYOpen ) {
3506  this.placeRect.x = this.getPlaceRectCoord( x, true );
3507  this.placeRect.y = this.getPlaceRectCoord( y, false, isMaxYOpen );
3508};
3509
3510/**
3511 * get x/y coordinate for place rect
3512 * @param {Number} coord - x or y
3513 * @param {Boolean} isX
3514 * @param {Boolean} isMaxOpen - does not limit value to outer bound
3515 * @returns {Number} coord - processed x or y
3516 */
3517Item.prototype.getPlaceRectCoord = function( coord, isX, isMaxOpen ) {
3518  var measure = isX ? 'Width' : 'Height';
3519  var size = this.size[ 'outer' + measure ];
3520  var segment = this.layout[ isX ? 'columnWidth' : 'rowHeight' ];
3521  var parentSize = this.layout.size[ 'inner' + measure ];
3522
3523  // additional parentSize calculations for Y
3524  if ( !isX ) {
3525    parentSize = Math.max( parentSize, this.layout.maxY );
3526    // prevent gutter from bumping up height when non-vertical grid
3527    if ( !this.layout.rowHeight ) {
3528      parentSize -= this.layout.gutter;
3529    }
3530  }
3531
3532  var max;
3533
3534  if ( segment ) {
3535    segment += this.layout.gutter;
3536    // allow for last column to reach the edge
3537    parentSize += isX ? this.layout.gutter : 0;
3538    // snap to closest segment
3539    coord = Math.round( coord / segment );
3540    // contain to outer bound
3541    // contain non-growing bound, allow growing bound to grow
3542    var mathMethod;
3543    if ( this.layout.options.isHorizontal ) {
3544      mathMethod = !isX ? 'floor' : 'ceil';
3545    } else {
3546      mathMethod = isX ? 'floor' : 'ceil';
3547    }
3548    var maxSegments = Math[ mathMethod ]( parentSize / segment );
3549    maxSegments -= Math.ceil( size / segment );
3550    max = maxSegments;
3551  } else {
3552    max = parentSize - size;
3553  }
3554
vendor: 3,406 bytes, lines 3555-3705
3555  coord = isMaxOpen ? coord : Math.min( coord, max );
3556  coord *= segment || 1;
3557
3558  return Math.max( 0, coord );
3559};
3560
3561Item.prototype.copyPlaceRectPosition = function() {
3562  this.rect.x = this.placeRect.x;
3563  this.rect.y = this.placeRect.y;
3564};
3565
3566// -----  ----- //
3567
3568// remove element from DOM
3569Item.prototype.removeElem = function() {
3570  this.element.parentNode.removeChild( this.element );
3571  // add space back to packer
3572  this.layout.packer.addSpace( this.rect );
3573  this.emitEvent( 'remove', [ this ] );
3574};
3575
3576// -----  ----- //
3577
3578return Item;
3579
3580}));
3581
3582/*!
3583 * Packery v1.4.3
3584 * bin-packing layout library
3585 *
3586 * Licensed GPLv3 for open source use
3587 * or Flickity Commercial License for commercial use
3588 *
3589 * http://packery.metafizzy.co
3590 * Copyright 2015 Metafizzy
3591 */
3592
3593( function( window, factory ) {
3594
3595  // universal module definition
3596  if ( typeof define == 'function' && define.amd ) {
3597    // AMD
3598    define( [
3599        'classie/classie',
3600        'get-size/get-size',
3601        'outlayer/outlayer',
3602        'packery/js/rect',
3603        'packery/js/packer',
3604        'packery/js/item'
3605      ],
3606      factory );
3607  } else if ( typeof exports == 'object' ) {
3608    // CommonJS
3609    module.exports = factory(
3610      require('desandro-classie'),
3611      require('get-size'),
3612      require('outlayer'),
3613      require('./rect'),
3614      require('./packer'),
3615      require('./item')
3616    );
3617  } else {
3618    // browser global
3619    window.Packery = factory(
3620      window.classie,
3621      window.getSize,
3622      window.Outlayer,
3623      window.Packery.Rect,
3624      window.Packery.Packer,
3625      window.Packery.Item
3626    );
3627  }
3628
3629}( window, function factory( classie, getSize, Outlayer, Rect, Packer, Item ) {
3630
3631
3632// ----- Rect ----- //
3633
3634// allow for pixel rounding errors IE8-IE11 & Firefox; #227
3635Rect.prototype.canFit = function( rect ) {
3636  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
3637};
3638
3639// -------------------------- Packery -------------------------- //
3640
3641// create an Outlayer layout class
3642var Packery = Outlayer.create('packery');
3643Packery.Item = Item;
3644
3645Packery.prototype._create = function() {
3646  // call super
3647  Outlayer.prototype._create.call( this );
3648
3649  // initial properties
3650  this.packer = new Packer();
3651
3652  // Left over from v1.0
3653  this.stamp( this.options.stamped );
3654
3655  // create drag handlers
3656  var _this = this;
3657  this.handleDraggabilly = {
3658    dragStart: function() {
3659      _this.itemDragStart( this.element );
3660    },
3661    dragMove: function() {
3662      _this.itemDragMove( this.element, this.position.x, this.position.y );
3663    },
3664    dragEnd: function() {
3665      _this.itemDragEnd( this.element );
3666    }
3667  };
3668
3669  this.handleUIDraggable = {
3670    start: function handleUIDraggableStart( event, ui ) {
3671      // HTML5 may trigger dragstart, dismiss HTML5 dragging
3672      if ( !ui ) {
3673        return;
3674      }
3675      _this.itemDragStart( event.currentTarget );
3676    },
3677    drag: function handleUIDraggableDrag( event, ui ) {
3678      if ( !ui ) {
3679        return;
3680      }
3681      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
3682    },
3683    stop: function handleUIDraggableStop( event, ui ) {
3684      if ( !ui ) {
3685        return;
3686      }
3687      _this.itemDragEnd( event.currentTarget );
3688    }
3689  };
3690
3691};
3692
3693
3694// ----- init & layout ----- //
3695
3696/**
3697 * logic before any new layout
3698 */
3699Packery.prototype._resetLayout = function() {
3700  this.getSize();
3701
3702  this._getMeasurements();
3703
3704  // reset packer
3705  var packer = this.packer;
3706  // packer settings, if horizontal or vertical
3707  if ( this.options.isHorizontal ) {
3708    packer.width = Number.POSITIVE_INFINITY;
3709    packer.height = this.size.innerHeight + this.gutter;
3710    packer.sortDirection = 'rightwardTopToBottom';
3711  } else {
3712    packer.width = this.size.innerWidth + this.gutter;
3713    packer.height = Number.POSITIVE_INFINITY;
3714    packer.sortDirection = 'downwardLeftToRight';
3715  }
3716
3717  packer.reset();
3718
3719  // layout
3720  this.maxY = 0;
3721  this.maxX = 0;
3722};
3723
3724/**
3725 * update columnWidth, rowHeight, & gutter
3726 * @private
3727 */
3728Packery.prototype._getMeasurements = function() {
3729  this._getMeasurement( 'columnWidth', 'width' );
3730  this._getMeasurement( 'rowHeight', 'height' );
3731  this._getMeasurement( 'gutter', 'width' );
3732};
3733
3734Packery.prototype._getItemLayoutPosition = function( item ) {
3735  this._packItem( item );
3736  return item.rect;
3737};
3738
3739
3740/**
3741 * layout item in packer
3742 * @param {Packery.Item} item
3743 */
3744Packery.prototype._packItem = function( item ) {
3745  this._setRectSize( item.element, item.rect );
3746  // pack the rect in the packer
3747  this.packer.pack( item.rect );
3748  this._setMaxXY( item.rect );
3749};
3750
3751/**
3752 * set max X and Y value, for size of container
3753 * @param {Packery.Rect} rect
3754 * @private
3755 */
3756Packery.prototype._setMaxXY = function( rect ) {
3757  this.maxX = Math.max( rect.x + rect.width, this.maxX );
3758  this.maxY = Math.max( rect.y + rect.height, this.maxY );
3759};
3760
3761/**
3762 * set the width and height of a rect, applying columnWidth and rowHeight
3763 * @param {Element} elem
3764 * @param {Packery.Rect} rect
3765 */
3766Packery.prototype._setRectSize = function( elem, rect ) {
3767  var size = getSize( elem );
3768  var w = size.outerWidth;
3769  var h = size.outerHeight;
3770  // size for columnWidth and rowHeight, if available
3771  // only check if size is non-zero, #177
3772  if ( w || h ) {
3773    w = this._applyGridGutter( w, this.columnWidth );
3774    h = this._applyGridGutter( h, this.rowHeight );
3775  }
3776  // rect must fit in packer
3777  rect.width = Math.min( w, this.packer.width );
3778  rect.height = Math.min( h, this.packer.height );
3779};
3780
3781/**
3782 * fits item to columnWidth/rowHeight and adds gutter
3783 * @param {Number} measurement - item width or height
3784 * @param {Number} gridSize - columnWidth or rowHeight
3785 * @returns measurement
3786 */
3787Packery.prototype._applyGridGutter = function( measurement, gridSize ) {
3788  // just add gutter if no gridSize
3789  if ( !gridSize ) {
3790    return measurement + this.gutter;
3791  }
3792  gridSize += this.gutter;
3793  // fit item to columnWidth/rowHeight
3794  var remainder = measurement % gridSize;
3795  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
3796  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
3797  return measurement;
3798};
3799
3800Packery.prototype._getContainerSize = function() {
3801  if ( this.options.isHorizontal ) {
3802    return {
3803      width: this.maxX - this.gutter
3804    };
3805  } else {
3806    return {
3807      height: this.maxY - this.gutter
3808    };
3809  }
3810};
3811
3812
3813// -------------------------- stamp -------------------------- //
3814
3815/**
3816 * makes space for element
3817 * @param {Element} elem
3818 */
3819Packery.prototype._manageStamp = function( elem ) {
3820
3821  var item = this.getItem( elem );
3822  var rect;
3823  if ( item && item.isPlacing ) {
3824    rect = item.placeRect;
3825  } else {
3826    var offset = this._getElementOffset( elem );
3827    rect = new Rect({
3828      x: this.options.isOriginLeft ? offset.left : offset.right,
3829      y: this.options.isOriginTop ? offset.top : offset.bottom
3830    });
3831  }
3832
3833  this._setRectSize( elem, rect );
3834  // save its space in the packer
3835  this.packer.placed( rect );
3836  this._setMaxXY( rect );
3837};
3838
3839// -------------------------- methods -------------------------- //
3840
3841function verticalSorter( a, b ) {
3842  return a.position.y - b.position.y || a.position.x - b.position.x;
3843}
3844
3845function horizontalSorter( a, b ) {
3846  return a.position.x - b.position.x || a.position.y - b.position.y;
3847}
3848
3849Packery.prototype.sortItemsByPosition = function() {
3850  var sorter = this.options.isHorizontal ? horizontalSorter : verticalSorter;
3851  this.items.sort( sorter );
3852};
3853
3854/**
3855 * Fit item element in its current position
3856 * Packery will position elements around it
3857 * useful for expanding elements
3858 *
3859 * @param {Element} elem
3860 * @param {Number} x - horizontal destination position, optional
3861 * @param {Number} y - vertical destination position, optional
3862 */
3863Packery.prototype.fit = function( elem, x, y ) {
3864  var item = this.getItem( elem );
3865  if ( !item ) {
3866    return;
3867  }
3868
3869  // prepare internal properties
3870  this._getMeasurements();
3871
3872  // stamp item to get it out of layout
3873  this.stamp( item.element );
3874  // required for positionPlaceRect
3875  item.getSize();
3876  // set placing flag
3877  item.isPlacing = true;
3878  // fall back to current position for fitting
3879  x = x === undefined ? item.rect.x: x;
3880  y = y === undefined ? item.rect.y: y;
3881
3882  // position it best at its destination
3883  item.positionPlaceRect( x, y, true );
3884
3885  this._bindFitEvents( item );
3886  item.moveTo( item.placeRect.x, item.placeRect.y );
3887  // layout everything else
3888  this.layout();
3889
3890  // return back to regularly scheduled programming
3891  this.unstamp( item.element );
3892  this.sortItemsByPosition();
3893  // un set placing flag, back to normal
3894  item.isPlacing = false;
3895  // copy place rect position
3896  item.copyPlaceRectPosition();
3897};
3898
3899/**
3900 * emit event when item is fit and other items are laid out
3901 * @param {Packery.Item} item
3902 * @private
3903 */
3904Packery.prototype._bindFitEvents = function( item ) {
3905  var _this = this;
3906  var ticks = 0;
3907  function tick() {
3908    ticks++;
3909    if ( ticks != 2 ) {
3910      return;
3911    }
3912    _this.dispatchEvent( 'fitComplete', null, [ item ] );
3913  }
3914  // when item is laid out
3915  item.on( 'layout', function() {
3916    tick();
3917    return true;
3918  });
3919  // when all items are laid out
3920  this.on( 'layoutComplete', function() {
3921    tick();
3922    return true;
3923  });
3924};
3925
3926// -------------------------- resize -------------------------- //
3927
3928// debounced, layout on resize
3929Packery.prototype.resize = function() {
3930  // don't trigger if size did not change
3931  var size = getSize( this.element );
3932  // check that this.size and size are there
3933  // IE8 triggers resize on body size change, so they might not be
3934  var hasSizes = this.size && size;
3935  var innerSize = this.options.isHorizontal ? 'innerHeight' : 'innerWidth';
3936  if ( hasSizes && size[ innerSize ] == this.size[ innerSize ] ) {
3937    return;
3938  }
3939
3940  this.layout();
3941};
3942
3943// -------------------------- drag -------------------------- //
3944
3945/**
3946 * handle an item drag start event
3947 * @param {Element} elem
3948 */
3949Packery.prototype.itemDragStart = function( elem ) {
3950  this.stamp( elem );
3951  var item = this.getItem( elem );
3952  if ( item ) {
3953    item.dragStart();
3954  }
3955};
3956
3957/**
3958 * handle an item drag move event
3959 * @param {Element} elem
3960 * @param {Number} x - horizontal change in position
3961 * @param {Number} y - vertical change in position
3962 */
3963Packery.prototype.itemDragMove = function( elem, x, y ) {
3964  var item = this.getItem( elem );
3965  if ( item ) {
3966    item.dragMove( x, y );
3967  }
3968
3969  // debounce
3970  var _this = this;
3971  // debounce triggering layout
3972  function delayed() {
3973    _this.layout();
3974    delete _this.dragTimeout;
3975  }
3976
3977  this.clearDragTimeout();
3978
3979  this.dragTimeout = setTimeout( delayed, 40 );
3980};
3981
3982Packery.prototype.clearDragTimeout = function() {
3983  if ( this.dragTimeout ) {
3984    clearTimeout( this.dragTimeout );
3985  }
3986};
3987
3988/**
3989 * handle an item drag end event
3990 * @param {Element} elem
3991 */
3992Packery.prototype.itemDragEnd = function( elem ) {
3993  var item = this.getItem( elem );
3994  var itemDidDrag;
3995  if ( item ) {
3996    itemDidDrag = item.didDrag;
3997    item.dragStop();
3998  }
3999  // if elem didn't move, or if it doesn't need positioning
4000  // unignore and unstamp and call it a day
4001  if ( !item || ( !itemDidDrag && !item.needsPositioning ) ) {
4002    this.unstamp( elem );
4003    return;
4004  }
4005  // procced with dragged item
4006
4007  classie.add( item.element, 'is-positioning-post-drag' );
4008
4009  // save this var, as it could get reset in dragStart
4010  var onLayoutComplete = this._getDragEndLayoutComplete( elem, item );
4011
4012  if ( item.needsPositioning ) {
4013    item.on( 'layout', onLayoutComplete );
4014    item.moveTo( item.placeRect.x, item.placeRect.y );
4015  } else if ( item ) {
4016    // item didn't need placement
4017    item.copyPlaceRectPosition();
4018  }
4019
4020  this.clearDragTimeout();
4021  this.on( 'layoutComplete', onLayoutComplete );
4022  this.layout();
4023
4024};
4025
4026/**
4027 * get drag end callback
4028 * @param {Element} elem
4029 * @param {Packery.Item} item
4030 * @returns {Function} onLayoutComplete
4031 */
4032Packery.prototype._getDragEndLayoutComplete = function( elem, item ) {
4033  var itemNeedsPositioning = item && item.needsPositioning;
4034  var completeCount = 0;
4035  var asyncCount = itemNeedsPositioning ? 2 : 1;
4036  var _this = this;
4037
4038  return function onLayoutComplete() {
4039    completeCount++;
4040    // don't proceed if not complete
4041    if ( completeCount != asyncCount ) {
4042      return true;
4043    }
4044    // reset item
4045    if ( item ) {
4046      classie.remove( item.element, 'is-positioning-post-drag' );
4047      item.isPlacing = false;
4048      item.copyPlaceRectPosition();
4049    }
4050
4051    _this.unstamp( elem );
4052    // only sort when item moved
4053    _this.sortItemsByPosition();
4054
4055    // emit item drag event now that everything is done
4056    if ( itemNeedsPositioning ) {
4057      _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
4058    }
4059    // listen once
4060    return true;
4061  };
4062};
4063
4064/**
4065 * binds Draggabilly events
4066 * @param {Draggabilly} draggie
4067 */
4068Packery.prototype.bindDraggabillyEvents = function( draggie ) {
4069  draggie.on( 'dragStart', this.handleDraggabilly.dragStart );
4070  draggie.on( 'dragMove', this.handleDraggabilly.dragMove );
4071  draggie.on( 'dragEnd', this.handleDraggabilly.dragEnd );
4072};
4073
4074/**
4075 * binds jQuery UI Draggable events
4076 * @param {jQuery} $elems
4077 */
4078Packery.prototype.bindUIDraggableEvents = function( $elems ) {
4079  $elems
4080    .on( 'dragstart', this.handleUIDraggable.start )
4081    .on( 'drag', this.handleUIDraggable.drag )
4082    .on( 'dragstop', this.handleUIDraggable.stop );
4083};
4084
4085Packery.Rect = Rect;
4086Packery.Packer = Packer;
4087
4088return Packery;
4089
4090}));
4091
4092})(window.uberGridjQuery || window.jQuery || 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.