/*!
 * Shuffle.js by @Vestride
 * Categorize, sort, and filter a responsive grid of items.
 * Dependencies: jQuery 1.9+, Modernizr 2.6.2+
 * @license MIT license
 * @version 3.0.0
 */

/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
 */
window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a){var e=a[d];if(!C(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.csstransforms=function(){return!!F("transform")},q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return F("transition")};for(var G in q)y(q,G)&&(v=G.toLowerCase(),e[v]=q[G](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)y(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},z(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,e.prefixed=function(a,b,c){return b?F(a,b,c):F(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document);

(function (factory) {
  if (typeof define === 'function' && define.amd) {
    define(['jquery', 'modernizr'], factory);
  } else {
    window.Shuffle = factory(window.jQuery, window.Modernizr);
  }
})(function($, Modernizr, undefined) {

'use strict';


// Validate Modernizr exists.
// Shuffle requires `csstransitions`, `csstransforms`, `csstransforms3d`,
// and `prefixed` to exist on the Modernizr object.
if (typeof Modernizr !== 'object') {
  throw new Error('Shuffle.js requires Modernizr.\n' +
      'http://vestride.github.io/Shuffle/#dependencies');
}


/**
 * Returns css prefixed properties like `-webkit-transition` or `box-sizing`
 * from `transition` or `boxSizing`, respectively.
 * @param {(string|boolean)} prop Property to be prefixed.
 * @return {string} The prefixed css property.
 */
function dashify( prop ) {
  if (!prop) {
    return '';
  }

  // Replace upper case with dash-lowercase,
  // then fix ms- prefixes because they're not capitalized.
  return prop.replace(/([A-Z])/g, function( str, m1 ) {
    return '-' + m1.toLowerCase();
  }).replace(/^ms-/,'-ms-');
}

// Constant, prefixed variables.
var TRANSITION = Modernizr.prefixed('transition');
var TRANSITION_DELAY = Modernizr.prefixed('transitionDelay');
var TRANSITION_DURATION = Modernizr.prefixed('transitionDuration');

// Note(glen): Stock Android 4.1.x browser will fail here because it wrongly
// says it supports non-prefixed transitions.
// https://github.com/Modernizr/Modernizr/issues/897
var TRANSITIONEND = {
  'WebkitTransition' : 'webkitTransitionEnd',
  'transition' : 'transitionend'
}[ TRANSITION ];

var TRANSFORM = Modernizr.prefixed('transform');
var CSS_TRANSFORM = dashify(TRANSFORM);

// Constants
var CAN_TRANSITION_TRANSFORMS = Modernizr.csstransforms && Modernizr.csstransitions;
var HAS_TRANSFORMS_3D = Modernizr.csstransforms3d;
var SHUFFLE = 'shuffle';
var COLUMN_THRESHOLD = 0.3;

// Configurable. You can change these constants to fit your application.
// The default scale and concealed scale, however, have to be different values.
var ALL_ITEMS = 'all';
var FILTER_ATTRIBUTE_KEY = 'groups';
var DEFAULT_SCALE = 1;
var CONCEALED_SCALE = 0.001;


// Underscore's throttle function.
function throttle(func, wait, options) {
  var context, args, result;
  var timeout = null;
  var previous = 0;
  options = options || {};
  var later = function() {
    previous = options.leading === false ? 0 : $.now();
    timeout = null;
    result = func.apply(context, args);
    context = args = null;
  };
  return function() {
    var now = $.now();
    if (!previous && options.leading === false) {
      previous = now;
    }
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      clearTimeout(timeout);
      timeout = null;
      previous = now;
      result = func.apply(context, args);
      context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };
}

function each(obj, iterator, context) {
  for (var i = 0, length = obj.length; i < length; i++) {
    if (iterator.call(context, obj[i], i, obj) === {}) {
      return;
    }
  }
}

function defer(fn, context, wait) {
  return setTimeout( $.proxy( fn, context ), wait );
}

function arrayMax( array ) {
  return Math.max.apply( Math, array );
}

function arrayMin( array ) {
  return Math.min.apply( Math, array );
}


/**
 * Always returns a numeric value, given a value.
 * @param {*} value Possibly numeric value.
 * @return {number} `value` or zero if `value` isn't numeric.
 * @private
 */
function getNumber(value) {
  return $.isNumeric(value) ? value : 0;
}


/**
 * Represents a coordinate pair.
 * @param {number} [x=0] X.
 * @param {number} [y=0] Y.
 */
var Point = function(x, y) {
  this.x = getNumber( x );
  this.y = getNumber( y );
};


/**
 * Whether two points are equal.
 * @param {Point} a Point A.
 * @param {Point} b Point B.
 * @return {boolean}
 */
Point.equals = function(a, b) {
  return a.x === b.x && a.y === b.y;
};


// Used for unique instance variables
var id = 0;
var $window = $( window );


/**
 * Categorize, sort, and filter a responsive grid of items.
 *
 * @param {Element} element An element which is the parent container for the grid items.
 * @param {Object} [options=Shuffle.options] Options object.
 * @constructor
 */
var Shuffle = function( element, options ) {
  options = options || {};
  $.extend( this, Shuffle.options, options, Shuffle.settings );

  this.$el = $(element);
  this.element = element;
  this.unique = 'shuffle_' + id++;

  this._fire( Shuffle.EventType.LOADING );
  this._init();

  // Dispatch the done event asynchronously so that people can bind to it after
  // Shuffle has been initialized.
  defer(function() {
    this.initialized = true;
    this._fire( Shuffle.EventType.DONE );
  }, this, 16);
};


/**
 * Events the container element emits with the .shuffle namespace.
 * For example, "done.shuffle".
 * @enum {string}
 */
Shuffle.EventType = {
  LOADING: 'loading',
  DONE: 'done',
  LAYOUT: 'layout',
  REMOVED: 'removed'
};


/** @enum {string} */
Shuffle.ClassName = {
  BASE: SHUFFLE,
  SHUFFLE_ITEM: 'shuffle-item',
  FILTERED: 'filtered',
  CONCEALED: 'concealed'
};


// Overrideable options
Shuffle.options = {
  group: ALL_ITEMS, // Initial filter group.
  speed: 250, // Transition/animation speed (milliseconds).
  easing: 'ease-out', // CSS easing function to use.
  itemSelector: '', // e.g. '.picture-item'.
  sizer: null, // Sizer element. Use an element to determine the size of columns and gutters.
  gutterWidth: 0, // A static number or function that tells the plugin how wide the gutters between columns are (in pixels).
  columnWidth: 0, // A static number or function that returns a number which tells the plugin how wide the columns are (in pixels).
  delimeter: null, // If your group is not json, and is comma delimeted, you could set delimeter to ','.
  buffer: 0, // Useful for percentage based heights when they might not always be exactly the same (in pixels).
  initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method.
  throttle: throttle, // By default, shuffle will throttle resize events. This can be changed or removed.
  throttleTime: 300, // How often shuffle can be called on resize (in milliseconds).
  sequentialFadeDelay: 150, // Delay between each item that fades in when adding items.
  supported: CAN_TRANSITION_TRANSFORMS // Whether to use transforms or absolute positioning.
};


// Not overrideable
Shuffle.settings = {
  useSizer: false,
  itemCss : { // default CSS for each item
    position: 'absolute',
    top: 0,
    left: 0,
    visibility: 'visible'
  },
  revealAppendedDelay: 300,
  lastSort: {},
  lastFilter: ALL_ITEMS,
  enabled: true,
  destroyed: false,
  initialized: false,
  _animations: [],
  styleQueue: []
};


// Expose for testing.
Shuffle.Point = Point;


/**
 * Static methods.
 */

/**
 * If the browser has 3d transforms available, build a string with those,
 * otherwise use 2d transforms.
 * @param {Point} point X and Y positions.
 * @param {number} scale Scale amount.
 * @return {string} A normalized string which can be used with the transform style.
 * @private
 */
Shuffle._getItemTransformString = function(point, scale) {
  if ( HAS_TRANSFORMS_3D ) {
    return 'translate3d(' + point.x + 'px, ' + point.y + 'px, 0) scale3d(' + scale + ', ' + scale + ', 1)';
  } else {
    return 'translate(' + point.x + 'px, ' + point.y + 'px) scale(' + scale + ')';
  }
};


/**
 * Retrieve the computed style for an element, parsed as a float. This should
 * not be used for width or height values because jQuery mangles them and they
 * are not precise enough.
 * @param {Element} element Element to get style for.
 * @param {string} style Style property.
 * @return {number} The parsed computed value or zero if that fails because IE
 *     will return 'auto' when the element doesn't have margins instead of
 *     the computed style.
 * @private
 */
Shuffle._getNumberStyle = function( element, style ) {
  return Shuffle._getFloat( $( element ).css( style )  );
};


/**
 * Parse a string as an integer.
 * @param {string} value String integer.
 * @return {number} The string as an integer or zero.
 * @private
 */
Shuffle._getInt = function(value) {
  return getNumber( parseInt( value, 10 ) );
};

/**
 * Parse a string as an float.
 * @param {string} value String float.
 * @return {number} The string as an float or zero.
 * @private
 */
Shuffle._getFloat = function(value) {
  return getNumber( parseFloat( value ) );
};


/**
 * Returns the outer width of an element, optionally including its margins.
 * The `offsetWidth` property must be used because having a scale transform
 * on the element affects the bounding box. Sadly, Firefox doesn't return an
 * integer value for offsetWidth (yet).
 * @param {Element} element The element.
 * @param {boolean} [includeMargins] Whether to include margins. Default is false.
 * @return {number} The width.
 */
Shuffle._getOuterWidth = function( element, includeMargins ) {
  var width = element.offsetWidth;

  // Use jQuery here because it uses getComputedStyle internally and is
  // cross-browser. Using the style property of the element will only work
  // if there are inline styles.
  if ( includeMargins ) {
    var marginLeft = Shuffle._getNumberStyle( element, 'marginLeft');
    var marginRight = Shuffle._getNumberStyle( element, 'marginRight');
    width += marginLeft + marginRight;
  }

  return width;
};


/**
 * Returns the outer height of an element, optionally including its margins.
 * @param {Element} element The element.
 * @param {boolean} [includeMargins] Whether to include margins. Default is false.
 * @return {number} The height.
 */
Shuffle._getOuterHeight = function( element, includeMargins ) {
  var height = element.offsetHeight;

  if ( includeMargins ) {
    var marginTop = Shuffle._getNumberStyle( element, 'marginTop');
    var marginBottom = Shuffle._getNumberStyle( element, 'marginBottom');
    height += marginTop + marginBottom;
  }

  return height;
};


/**
 * Change a property or execute a function which will not have a transition
 * @param {Element} element DOM element that won't be transitioned
 * @param {Function} callback A function which will be called while transition
 *     is set to 0ms.
 * @param {Object} [context] Optional context for the callback function.
 * @private
 */
Shuffle._skipTransition = function( element, callback, context ) {
  var duration = element.style[ TRANSITION_DURATION ];

  // Set the duration to zero so it happens immediately
  element.style[ TRANSITION_DURATION ] = '0ms'; // ms needed for firefox!

  callback.call( context );

  // Force reflow
  var reflow = element.offsetWidth;
  // Avoid jshint warnings: unused variables and expressions.
  reflow = null;

  // Put the duration back
  element.style[ TRANSITION_DURATION ] = duration;
};


/**
 * Instance methods.
 */

Shuffle.prototype._init = function() {
  this.$items = this._getItems();

  this.sizer = this._getElementOption( this.sizer );

  if ( this.sizer ) {
    this.useSizer = true;
  }

  // Add class and invalidate styles
  this.$el.addClass( Shuffle.ClassName.BASE );

  // Set initial css for each item
  this._initItems();

  // Bind resize events
  // http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer
  $window.on('resize.' + SHUFFLE + '.' + this.unique, this._getResizeFunction());

  // Get container css all in one request. Causes reflow
  var containerCSS = this.$el.css(['position', 'overflow']);
  var containerWidth = Shuffle._getOuterWidth( this.element );

  // Add styles to the container if it doesn't have them.
  this._validateStyles( containerCSS );

  // We already got the container's width above, no need to cause another reflow getting it again...
  // Calculate the number of columns there will be
  this._setColumns( containerWidth );

  // Kick off!
  this.shuffle( this.group, this.initialSort );

  // The shuffle items haven't had transitions set on them yet
  // so the user doesn't see the first layout. Set them now that the first layout is done.
  if ( this.supported ) {
    defer(function() {
      this._setTransitions();
      this.element.style[ TRANSITION ] = 'height ' + this.speed + 'ms ' + this.easing;
    }, this);
  }
};


/**
 * Returns a throttled and proxied function for the resize handler.
 * @return {Function}
 * @private
 */
Shuffle.prototype._getResizeFunction = function() {
  var resizeFunction = $.proxy( this._onResize, this );
  return this.throttle ?
      this.throttle( resizeFunction, this.throttleTime ) :
      resizeFunction;
};


/**
 * Retrieve an element from an option.
 * @param {string|jQuery|Element} option The option to check.
 * @return {?Element} The plain element or null.
 * @private
 */
Shuffle.prototype._getElementOption = function( option ) {
  // If column width is a string, treat is as a selector and search for the
  // sizer element within the outermost container
  if ( typeof option === 'string' ) {
    return this.$el.find( option )[0] || null;

  // Check for an element
  } else if ( option && option.nodeType && option.nodeType === 1 ) {
    return option;

  // Check for jQuery object
  } else if ( option && option.jquery ) {
    return option[0];
  }

  return null;
};


/**
 * Ensures the shuffle container has the css styles it needs applied to it.
 * @param {Object} styles Key value pairs for position and overflow.
 * @private
 */
Shuffle.prototype._validateStyles = function(styles) {
  // Position cannot be static.
  if ( styles.position === 'static' ) {
    this.element.style.position = 'relative';
  }

  // Overflow has to be hidden
  if ( styles.overflow !== 'hidden' ) {
    this.element.style.overflow = 'hidden';
  }
};


/**
 * Filter the elements by a category.
 * @param {string} [category] Category to filter by. If it's given, the last
 *     category will be used to filter the items.
 * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to
 *     all the items.
 * @return {jQuery} Filtered items.
 * @private
 */
Shuffle.prototype._filter = function( category, $collection ) {
  category = category || this.lastFilter;
  $collection = $collection || this.$items;

  var set = this._getFilteredSets( category, $collection );

  // Individually add/remove concealed/filtered classes
  this._toggleFilterClasses( set.filtered, set.concealed );

  // Save the last filter in case elements are appended.
  this.lastFilter = category;

  // This is saved mainly because providing a filter function (like searching)
  // will overwrite the `lastFilter` property every time its called.
  if ( typeof category === 'string' ) {
    this.group = category;
  }

  return set.filtered;
};


/**
 * Returns an object containing the filtered and concealed elements.
 * @param {string|Function} category Category or function to filter by.
 * @param {ArrayLike.<Element>} $items A collection of items to filter.
 * @return {!{filtered: jQuery, concealed: jQuery}}
 * @private
 */
Shuffle.prototype._getFilteredSets = function( category, $items ) {
  var $filtered = $();
  var $concealed = $();

  // category === 'all', add filtered class to everything
  if ( category === ALL_ITEMS ) {
    $filtered = $items;

  // Loop through each item and use provided function to determine
  // whether to hide it or not.
  } else {
    each($items, function( el ) {
      var $item = $(el);
      if ( this._doesPassFilter( category, $item ) ) {
        $filtered = $filtered.add( $item );
      } else {
        $concealed = $concealed.add( $item );
      }
    }, this);
  }

  return {
    filtered: $filtered,
    concealed: $concealed
  };
};


/**
 * Test an item to see if it passes a category.
 * @param {string|Function} category Category or function to filter by.
 * @param {jQuery} $item A single item, wrapped with jQuery.
 * @return {boolean} Whether it passes the category/filter.
 * @private
 */
Shuffle.prototype._doesPassFilter = function( category, $item ) {
  if ( $.isFunction( category ) ) {
    return category.call( $item[0], $item, this );

  // Check each element's data-groups attribute against the given category.
  } else {
    var groups = $item.data( FILTER_ATTRIBUTE_KEY );
    var keys = this.delimeter && !$.isArray( groups ) ?
        groups.split( this.delimeter ) :
        groups;
    return $.inArray(category, keys) > -1;
  }
};


/**
 * Toggles the filtered and concealed class names.
 * @param {jQuery} $filtered Filtered set.
 * @param {jQuery} $concealed Concealed set.
 * @private
 */
Shuffle.prototype._toggleFilterClasses = function( $filtered, $concealed ) {
  $filtered
    .removeClass( Shuffle.ClassName.CONCEALED )
    .addClass( Shuffle.ClassName.FILTERED );
  $concealed
    .removeClass( Shuffle.ClassName.FILTERED )
    .addClass( Shuffle.ClassName.CONCEALED );
};


/**
 * Set the initial css for each item
 * @param {jQuery} [$items] Optionally specifiy at set to initialize
 */
Shuffle.prototype._initItems = function( $items ) {
  $items = $items || this.$items;
  $items.addClass([
    Shuffle.ClassName.SHUFFLE_ITEM,
    Shuffle.ClassName.FILTERED
  ].join(' '));
  $items.css( this.itemCss ).data('point', new Point()).data('scale', DEFAULT_SCALE);
};


/**
 * Updates the filtered item count.
 * @private
 */
Shuffle.prototype._updateItemCount = function() {
  this.visibleItems = this._getFilteredItems().length;
};


/**
 * Sets css transform transition on a an element.
 * @param {Element} element Element to set transition on.
 * @private
 */
Shuffle.prototype._setTransition = function( element ) {
  element.style[ TRANSITION ] = CSS_TRANSFORM + ' ' + this.speed + 'ms ' +
    this.easing + ', opacity ' + this.speed + 'ms ' + this.easing;
};


/**
 * Sets css transform transition on a group of elements.
 * @param {ArrayLike.<Element>} $items Elements to set transitions on.
 * @private
 */
Shuffle.prototype._setTransitions = function( $items ) {
  $items = $items || this.$items;
  each($items, function( el ) {
    this._setTransition( el );
  }, this);
};


/**
 * Sets a transition delay on a collection of elements, making each delay
 * greater than the last.
 * @param {ArrayLike.<Element>} $collection Array to iterate over.
 */
Shuffle.prototype._setSequentialDelay = function( $collection ) {
  if ( !this.supported ) {
    return;
  }

  // $collection can be an array of dom elements or jquery object
  each($collection, function( el, i ) {
    // This works because the transition-property: transform, opacity;
    el.style[ TRANSITION_DELAY ] = '0ms,' + ((i + 1) * this.sequentialFadeDelay) + 'ms';
  }, this);
};


Shuffle.prototype._getItems = function() {
  return this.$el.children( this.itemSelector );
};


Shuffle.prototype._getFilteredItems = function() {
  return this.$items.filter('.' + Shuffle.ClassName.FILTERED);
};


Shuffle.prototype._getConcealedItems = function() {
  return this.$items.filter('.' + Shuffle.ClassName.CONCEALED);
};


/**
 * Returns the column size, based on column width and sizer options.
 * @param {number} containerWidth Size of the parent container.
 * @param {number} gutterSize Size of the gutters.
 * @return {number}
 * @private
 */
Shuffle.prototype._getColumnSize = function( containerWidth, gutterSize ) {
  var size;

  // If the columnWidth property is a function, then the grid is fluid
  if ( $.isFunction( this.columnWidth ) ) {
    size = this.columnWidth(containerWidth);

  // columnWidth option isn't a function, are they using a sizing element?
  } else if ( this.useSizer ) {
    size = Shuffle._getOuterWidth(this.sizer);

  // if not, how about the explicitly set option?
  } else if ( this.columnWidth ) {
    size = this.columnWidth;

  // or use the size of the first item
  } else if ( this.$items.length > 0 ) {
    size = Shuffle._getOuterWidth(this.$items[0], true);

  // if there's no items, use size of container
  } else {
    size = containerWidth;
  }

  // Don't let them set a column width of zero.
  if ( size === 0 ) {
    size = containerWidth;
  }

  return size + gutterSize;
};


/**
 * Returns the gutter size, based on gutter width and sizer options.
 * @param {number} containerWidth Size of the parent container.
 * @return {number}
 * @private
 */
Shuffle.prototype._getGutterSize = function( containerWidth ) {
  var size;
  if ( $.isFunction( this.gutterWidth ) ) {
    size = this.gutterWidth(containerWidth);
  } else if ( this.useSizer ) {
    size = Shuffle._getNumberStyle(this.sizer, 'marginLeft');
  } else {
    size = this.gutterWidth;
  }

  return size;
};


/**
 * Calculate the number of columns to be used. Gets css if using sizer element.
 * @param {number} [theContainerWidth] Optionally specify a container width if it's already available.
 */
Shuffle.prototype._setColumns = function( theContainerWidth ) {
  var containerWidth = theContainerWidth || Shuffle._getOuterWidth( this.element );
  var gutter = this._getGutterSize( containerWidth );
  var columnWidth = this._getColumnSize( containerWidth, gutter );
  var calculatedColumns = (containerWidth + gutter) / columnWidth;

  // Widths given from getComputedStyle are not precise enough...
  if ( Math.abs(Math.round(calculatedColumns) - calculatedColumns) < COLUMN_THRESHOLD ) {
    // e.g. calculatedColumns = 11.998876
    calculatedColumns = Math.round( calculatedColumns );
  }

  this.cols = Math.max( Math.floor(calculatedColumns), 1 );
  this.containerWidth = containerWidth;
  this.colWidth = columnWidth;
};

/**
 * Adjust the height of the grid
 */
Shuffle.prototype._setContainerSize = function() {
  this.$el.css( 'height', this._getContainerSize() );
};


/**
 * Based on the column heights, it returns the biggest one.
 * @return {number}
 * @private
 */
Shuffle.prototype._getContainerSize = function() {
  return arrayMax( this.positions );
};


/**
 * Fire events with .shuffle namespace
 */
Shuffle.prototype._fire = function( name, args ) {
  this.$el.trigger( name + '.' + SHUFFLE, args && args.length ? args : [ this ] );
};


/**
 * Zeros out the y columns array, which is used to determine item placement.
 * @private
 */
Shuffle.prototype._resetCols = function() {
  var i = this.cols;
  this.positions = [];
  while (i--) {
    this.positions.push( 0 );
  }
};


/**
 * Loops through each item that should be shown and calculates the x, y position.
 * @param {Array.<Element>} items Array of items that will be shown/layed out in order in their array.
 *     Because jQuery collection are always ordered in DOM order, we can't pass a jq collection.
 * @param {boolean} [isOnlyPosition=false] If true this will position the items with zero opacity.
 */
Shuffle.prototype._layout = function( items, isOnlyPosition ) {
  each(items, function( item ) {
    this._layoutItem( item, !!isOnlyPosition );
  }, this);

  // `_layout` always happens after `_shrink`, so it's safe to process the style
  // queue here with styles from the shrink method.
  this._processStyleQueue();

  // Adjust the height of the container.
  this._setContainerSize();
};


/**
 * Calculates the position of the item and pushes it onto the style queue.
 * @param {Element} item Element which is being positioned.
 * @param {boolean} isOnlyPosition Whether to position the item, but with zero
 *     opacity so that it can fade in later.
 * @private
 */
Shuffle.prototype._layoutItem = function( item, isOnlyPosition ) {
  var $item = $(item);
  var itemData = $item.data();
  var currPos = itemData.point;
  var currScale = itemData.scale;
  var itemSize = {
    width: Shuffle._getOuterWidth( item, true ),
    height: Shuffle._getOuterHeight( item, true )
  };
  var pos = this._getItemPosition( itemSize );

  // If the item will not change its position, do not add it to the render
  // queue. Transitions don't fire when setting a property to the same value.
  if ( Point.equals(currPos, pos) && currScale === DEFAULT_SCALE ) {
    return;
  }

  // Save data for shrink
  itemData.point = pos;
  itemData.scale = DEFAULT_SCALE;

  this.styleQueue.push({
    $item: $item,
    point: pos,
    scale: DEFAULT_SCALE,
    opacity: isOnlyPosition ? 0 : 1,
    skipTransition: isOnlyPosition,
    callfront: function() {
      if ( !isOnlyPosition ) {
        $item.css( 'visibility', 'visible' );
      }
    },
    callback: function() {
      if ( isOnlyPosition ) {
        $item.css( 'visibility', 'hidden' );
      }
    }
  });
};


/**
 * Determine the location of the next item, based on its size.
 * @param {{width: number, height: number}} itemSize Object with width and height.
 * @return {Point}
 * @private
 */
Shuffle.prototype._getItemPosition = function( itemSize ) {
  var columnSpan = this._getColumnSpan( itemSize.width, this.colWidth, this.cols );

  var setY = this._getColumnSet( columnSpan, this.cols );

  // Finds the index of the smallest number in the set.
  var shortColumnIndex = this._getShortColumn( setY, this.buffer );

  // Position the item
  var point = new Point(
    Math.round( this.colWidth * shortColumnIndex ),
    Math.round( setY[shortColumnIndex] ));

  // Update the columns array with the new values for each column.
  // e.g. before the update the columns could be [250, 0, 0, 0] for an item
  // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
  var setHeight = setY[shortColumnIndex] + itemSize.height;
  var setSpan = this.cols + 1 - setY.length;
  for ( var i = 0; i < setSpan; i++ ) {
    this.positions[ shortColumnIndex + i ] = setHeight;
  }

  return point;
};


/**
 * Determine the number of columns an items spans.
 * @param {number} itemWidth Width of the item.
 * @param {number} columnWidth Width of the column (includes gutter).
 * @param {number} columns Total number of columns
 * @return {number}
 * @private
 */
Shuffle.prototype._getColumnSpan = function( itemWidth, columnWidth, columns ) {
  var columnSpan = itemWidth / columnWidth;

  // If the difference between the rounded column span number and the
  // calculated column span number is really small, round the number to
  // make it fit.
  if ( Math.abs(Math.round( columnSpan ) - columnSpan ) < COLUMN_THRESHOLD ) {
    // e.g. columnSpan = 4.0089945390298745
    columnSpan = Math.round( columnSpan );
  }

  // Ensure the column span is not more than the amount of columns in the whole layout.
  return Math.min( Math.ceil( columnSpan ), columns );
};


/**
 * Retrieves the column set to use for placement.
 * @param {number} columnSpan The number of columns this current item spans.
 * @param {number} columns The total columns in the grid.
 * @return {Array.<number>} An array of numbers represeting the column set.
 * @private
 */
Shuffle.prototype._getColumnSet = function( columnSpan, columns ) {
  // The item spans only one column.
  if ( columnSpan === 1 ) {
    return this.positions;

  // The item spans more than one column, figure out how many different
  // places it could fit horizontally.
  // The group count is the number of places within the positions this block
  // could fit, ignoring the current positions of items.
  // Imagine a 2 column brick as the second item in a 4 column grid with
  // 10px height each. Find the places it would fit:
  // [10, 0, 0, 0]
  //  |   |  |
  //  *   *  *
  //
  // Then take the places which fit and get the bigger of the two:
  // max([10, 0]), max([0, 0]), max([0, 0]) = [10, 0, 0]
  //
  // Next, find the first smallest number (the short column).
  // [10, 0, 0]
  //      |
  //      *
  //
  // And that's where it should be placed!
  } else {
    var groupCount = columns + 1 - columnSpan;
    var groupY = [];

    // For how many possible positions for this item there are.
    for ( var i = 0; i < groupCount; i++ ) {
      // Find the bigger value for each place it could fit.
      groupY[i] = arrayMax( this.positions.slice( i, i + columnSpan ) );
    }

    return groupY;
  }
};


/**
 * Find index of short column, the first from the left where this item will go.
 *
 * @param {Array.<number>} positions The array to search for the smallest number.
 * @param {number} buffer Optional buffer which is very useful when the height
 *     is a percentage of the width.
 * @return {number} Index of the short column.
 * @private
 */
Shuffle.prototype._getShortColumn = function( positions, buffer ) {
  var minPosition = arrayMin( positions );
  for (var i = 0, len = positions.length; i < len; i++) {
    if ( positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer ) {
      return i;
    }
  }
  return 0;
};


/**
 * Hides the elements that don't match our filter.
 * @param {jQuery} $collection jQuery collection to shrink.
 * @private
 */
Shuffle.prototype._shrink = function( $collection ) {
  var $concealed = $collection || this._getConcealedItems();

  each($concealed, function( item ) {
    var $item = $(item);
    var itemData = $item.data();

    // Continuing would add a transitionend event listener to the element, but
    // that listener would not execute because the transform and opacity would
    // stay the same.
    if ( itemData.scale === CONCEALED_SCALE ) {
      return;
    }

    itemData.scale = CONCEALED_SCALE;

    this.styleQueue.push({
      $item: $item,
      point: itemData.point,
      scale : CONCEALED_SCALE,
      opacity: 0,
      callback: function() {
        $item.css( 'visibility', 'hidden' );
      }
    });
  }, this);
};


/**
 * Resize handler.
 * @private
 */
Shuffle.prototype._onResize = function() {
  // If shuffle is disabled, destroyed, don't do anything
  if ( !this.enabled || this.destroyed || this.isTransitioning ) {
    return;
  }

  // Will need to check height in the future if it's layed out horizontaly
  var containerWidth = Shuffle._getOuterWidth( this.element );

  // containerWidth hasn't changed, don't do anything
  if ( containerWidth === this.containerWidth ) {
    return;
  }

  this.update();
};


/**
 * Returns styles for either jQuery animate or transition.
 * @param {Object} opts Transition options.
 * @return {!Object} Transforms for transitions, left/top for animate.
 * @private
 */
Shuffle.prototype._getStylesForTransition = function( opts ) {
  var styles = {
    opacity: opts.opacity
  };

  if ( this.supported ) {
    styles[ TRANSFORM ] = Shuffle._getItemTransformString( opts.point, opts.scale );
  } else {
    styles.left = opts.point.x;
    styles.top = opts.point.y;
  }

  return styles;
};


/**
 * Transitions an item in the grid
 *
 * @param {Object} opts options.
 * @param {jQuery} opts.$item jQuery object representing the current item.
 * @param {Point} opts.point A point object with the x and y coordinates.
 * @param {number} opts.scale Amount to scale the item.
 * @param {number} opts.opacity Opacity of the item.
 * @param {Function} opts.callback Complete function for the animation.
 * @param {Function} opts.callfront Function to call before transitioning.
 * @private
 */
Shuffle.prototype._transition = function( opts ) {
  var styles = this._getStylesForTransition( opts );
  this._startItemAnimation( opts.$item, styles, opts.callfront || $.noop, opts.callback || $.noop );
};


Shuffle.prototype._startItemAnimation = function( $item, styles, callfront, callback ) {
  // Transition end handler removes its listener.
  function handleTransitionEnd( evt ) {
    // Make sure this event handler has not bubbled up from a child.
    if ( evt.target === evt.currentTarget ) {
      $( evt.target ).off( TRANSITIONEND, handleTransitionEnd );
      callback();
    }
  }

  callfront();

  // Transitions are not set until shuffle has loaded to avoid the initial transition.
  if ( !this.initialized ) {
    $item.css( styles );
    callback();
    return;
  }

  // Use CSS Transforms if we have them
  if ( this.supported ) {
    $item.css( styles );
    $item.on( TRANSITIONEND, handleTransitionEnd );

  // Use jQuery to animate left/top
  } else {
    // Save the deferred object which jQuery returns.
    var anim = $item.stop( true ).animate( styles, this.speed, 'swing', callback );
    // Push the animation to the list of pending animations.
    this._animations.push( anim.promise() );
  }
};


/**
 * Execute the styles gathered in the style queue. This applies styles to elements,
 * triggering transitions.
 * @param {boolean} noLayout Whether to trigger a layout event.
 * @private
 */
Shuffle.prototype._processStyleQueue = function( noLayout ) {
  var $transitions = $();

  // Iterate over the queue and keep track of ones that use transitions.
  each(this.styleQueue, function( transitionObj ) {
    if ( transitionObj.skipTransition ) {
      this._styleImmediately( transitionObj );
    } else {
      $transitions = $transitions.add( transitionObj.$item );
      this._transition( transitionObj );
    }
  }, this);


  if ( $transitions.length > 0 && this.initialized ) {
    // Set flag that shuffle is currently in motion.
    this.isTransitioning = true;

    if ( this.supported ) {
      this._whenCollectionDone( $transitions, TRANSITIONEND, this._movementFinished );

    // The _transition function appends a promise to the animations array.
    // When they're all complete, do things.
    } else {
      this._whenAnimationsDone( this._movementFinished );
    }

  // A call to layout happened, but none of the newly filtered items will
  // change position. Asynchronously fire the callback here.
  } else if ( !noLayout ) {
    defer( this._layoutEnd, this );
  }

  // Remove everything in the style queue
  this.styleQueue.length = 0;
};


/**
 * Apply styles without a transition.
 * @param {Object} opts Transitions options object.
 * @private
 */
Shuffle.prototype._styleImmediately = function( opts ) {
  Shuffle._skipTransition(opts.$item[0], function() {
    opts.$item.css( this._getStylesForTransition( opts ) );
  }, this);
};

Shuffle.prototype._movementFinished = function() {
  this.isTransitioning = false;
  this._layoutEnd();
};

Shuffle.prototype._layoutEnd = function() {
  this._fire( Shuffle.EventType.LAYOUT );
};

Shuffle.prototype._addItems = function( $newItems, addToEnd, isSequential ) {
  // Add classes and set initial positions.
  this._initItems( $newItems );

  // Add transition to each item.
  this._setTransitions( $newItems );

  // Update the list of
  this.$items = this._getItems();

  // Shrink all items (without transitions).
  this._shrink( $newItems );
  each(this.styleQueue, function( transitionObj ) {
    transitionObj.skipTransition = true;
  });

  // Apply shrink positions, but do not cause a layout event.
  this._processStyleQueue( true );

  if ( addToEnd ) {
    this._addItemsToEnd( $newItems, isSequential );
  } else {
    this.shuffle( this.lastFilter );
  }
};


Shuffle.prototype._addItemsToEnd = function( $newItems, isSequential ) {
  // Get ones that passed the current filter
  var $passed = this._filter( null, $newItems );
  var passed = $passed.get();

  // How many filtered elements?
  this._updateItemCount();

  this._layout( passed, true );

  if ( isSequential && this.supported ) {
    this._setSequentialDelay( passed );
  }

  this._revealAppended( passed );
};


/**
 * Triggers appended elements to fade in.
 * @param {ArrayLike.<Element>} $newFilteredItems Collection of elements.
 * @private
 */
Shuffle.prototype._revealAppended = function( newFilteredItems ) {
  defer(function() {
    each(newFilteredItems, function( el ) {
      var $item = $( el );
      this._transition({
        $item: $item,
        opacity: 1,
        point: $item.data('point'),
        scale: DEFAULT_SCALE
      });
    }, this);

    this._whenCollectionDone($(newFilteredItems), TRANSITIONEND, function() {
      $(newFilteredItems).css( TRANSITION_DELAY, '0ms' );
      this._movementFinished();
    });
  }, this, this.revealAppendedDelay);
};


/**
 * Execute a function when an event has been triggered for every item in a collection.
 * @param {jQuery} $collection Collection of elements.
 * @param {string} eventName Event to listen for.
 * @param {Function} callback Callback to execute when they're done.
 * @private
 */
Shuffle.prototype._whenCollectionDone = function( $collection, eventName, callback ) {
  var done = 0;
  var items = $collection.length;
  var self = this;

  function handleEventName( evt ) {
    if ( evt.target === evt.currentTarget ) {
      $( evt.target ).off( eventName, handleEventName );
      done++;

      // Execute callback if all items have emitted the correct event.
      if ( done === items ) {
        callback.call( self );
      }
    }
  }

  // Bind the event to all items.
  $collection.on( eventName, handleEventName );
};


/**
 * Execute a callback after jQuery `animate` for a collection has finished.
 * @param {Function} callback Callback to execute when they're done.
 * @private
 */
Shuffle.prototype._whenAnimationsDone = function( callback ) {
  $.when.apply( null, this._animations ).always( $.proxy( function() {
    this._animations.length = 0;
    callback.call( this );
  }, this ));
};


/**
 * Public Methods
 */

/**
 * The magic. This is what makes the plugin 'shuffle'
 * @param {string|Function} [category] Category to filter by. Can be a function
 * @param {Object} [sortObj] A sort object which can sort the filtered set
 */
Shuffle.prototype.shuffle = function( category, sortObj ) {
  if ( !this.enabled || this.isTransitioning ) {
    return;
  }

  if ( !category ) {
    category = ALL_ITEMS;
  }

  this._filter( category );

  // How many filtered elements?
  this._updateItemCount();

  // Shrink each concealed item
  this._shrink();

  // Update transforms on .filtered elements so they will animate to their new positions
  this.sort( sortObj );
};


/**
 * Gets the .filtered elements, sorts them, and passes them to layout.
 * @param {Object} opts the options object for the sorted plugin
 */
Shuffle.prototype.sort = function( opts ) {
  if ( this.enabled && !this.isTransitioning ) {
    this._resetCols();

    var sortOptions = opts || this.lastSort;
    var items = this._getFilteredItems().sorted( sortOptions );

    this._layout( items );

    this.lastSort = sortOptions;
  }
};


/**
 * Reposition everything.
 * @param {boolean} isOnlyLayout If true, column and gutter widths won't be
 *     recalculated.
 */
Shuffle.prototype.update = function( isOnlyLayout ) {
  if ( this.enabled && !this.isTransitioning ) {

    if ( !isOnlyLayout ) {
      // Get updated colCount
      this._setColumns();
    }

    // Layout items
    this.sort();
  }
};


/**
 * Use this instead of `update()` if you don't need the columns and gutters updated
 * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations
 * could be off.
 */
Shuffle.prototype.layout = function() {
  this.update( true );
};


/**
 * New items have been appended to shuffle. Fade them in sequentially
 * @param {jQuery} $newItems jQuery collection of new items
 * @param {boolean} [addToEnd=false] If true, new items will be added to the end / bottom
 *     of the items. If not true, items will be mixed in with the current sort order.
 * @param {boolean} [isSequential=true] If false, new items won't sequentially fade in
 */
Shuffle.prototype.appended = function( $newItems, addToEnd, isSequential ) {
  this._addItems( $newItems, addToEnd === true, isSequential !== false );
};


/**
 * Disables shuffle from updating dimensions and layout on resize
 */
Shuffle.prototype.disable = function() {
  this.enabled = false;
};


/**
 * Enables shuffle again
 * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters
 */
Shuffle.prototype.enable = function( isUpdateLayout ) {
  this.enabled = true;
  if ( isUpdateLayout !== false ) {
    this.update();
  }
};


/**
 * Remove 1 or more shuffle items
 * @param {jQuery} $collection A jQuery object containing one or more element in shuffle
 * @return {Shuffle} The shuffle object
 */
Shuffle.prototype.remove = function( $collection ) {

  // If this isn't a jquery object, exit
  if ( !$collection.length || !$collection.jquery ) {
    return;
  }

  function handleRemoved() {
    // Remove the collection in the callback
    $collection.remove();

    // Update things now that elements have been removed.
    this.$items = this._getItems();
    this._updateItemCount();

    this._fire( Shuffle.EventType.REMOVED, [ $collection, this ] );

    // Let it get garbage collected
    $collection = null;
  }

  // Hide collection first.
  this._toggleFilterClasses( $(), $collection );
  this._shrink( $collection );

  this.sort();

  this.$el.one( Shuffle.EventType.LAYOUT + '.' + SHUFFLE, $.proxy( handleRemoved, this ) );
};


/**
 * Destroys shuffle, removes events, styles, and classes
 */
Shuffle.prototype.destroy = function() {
  // If there is more than one shuffle instance on the page,
  // removing the resize handler from the window would remove them
  // all. This is why a unique value is needed.
  $window.off('.' + this.unique);

  // Reset container styles
  this.$el
      .removeClass( SHUFFLE )
      .removeAttr('style')
      .removeData( SHUFFLE );

  // Reset individual item styles
  this.$items
      .removeAttr('style')
      .removeData('point')
      .removeData('scale')
      .removeClass([
        Shuffle.ClassName.CONCEALED,
        Shuffle.ClassName.FILTERED,
        Shuffle.ClassName.SHUFFLE_ITEM
      ].join(' '));

  // Null DOM references
  this.$items = null;
  this.$el = null;
  this.sizer = null;
  this.element = null;

  // Set a flag so if a debounced resize has been triggered,
  // it can first check if it is actually destroyed and not doing anything
  this.destroyed = true;
};


// Plugin definition
$.fn.shuffle = function( opts ) {
  var args = Array.prototype.slice.call( arguments, 1 );
  return this.each(function() {
    var $this = $( this );
    var shuffle = $this.data( SHUFFLE );

    // If we don't have a stored shuffle, make a new one and save it
    if ( !shuffle ) {
      shuffle = new Shuffle( this, opts );
      $this.data( SHUFFLE, shuffle );
    } else if ( typeof opts === 'string' && shuffle[ opts ] ) {
      shuffle[ opts ].apply( shuffle, args );
    }
  });
};


// http://stackoverflow.com/a/962890/373422
function randomize( array ) {
  var tmp, current;
  var top = array.length;

  if ( !top ) {
    return array;
  }

  while ( --top ) {
    current = Math.floor( Math.random() * (top + 1) );
    tmp = array[ current ];
    array[ current ] = array[ top ];
    array[ top ] = tmp;
  }

  return array;
}


// You can return `undefined` from the `by` function to revert to DOM order
// This plugin does NOT return a jQuery object. It returns a plain array because
// jQuery sorts everything in DOM order.
$.fn.sorted = function(options) {
  var opts = $.extend({}, $.fn.sorted.defaults, options);
  var arr = this.get();
  var revert = false;

  if ( !arr.length ) {
    return [];
  }

  if ( opts.randomize ) {
    return randomize( arr );
  }

  // Sort the elements by the opts.by function.
  // If we don't have opts.by, default to DOM order
  if ( $.isFunction( opts.by ) ) {
    arr.sort(function(a, b) {

      // Exit early if we already know we want to revert
      if ( revert ) {
        return 0;
      }

      var valA = opts.by($(a));
      var valB = opts.by($(b));

      // If both values are undefined, use the DOM order
      if ( valA === undefined && valB === undefined ) {
        revert = true;
        return 0;
      }

      if ( valA < valB || valA === 'sortFirst' || valB === 'sortLast' ) {
        return -1;
      }

      if ( valA > valB || valA === 'sortLast' || valB === 'sortFirst' ) {
        return 1;
      }

      return 0;
    });
  }

  // Revert to the original array if necessary
  if ( revert ) {
    return this.get();
  }

  if ( opts.reverse ) {
    arr.reverse();
  }

  return arr;
};


$.fn.sorted.defaults = {
  reverse: false, // Use array.reverse() to reverse the results
  by: null, // Sorting function
  randomize: false // If true, this will skip the sorting and return a randomized order in the array
};

return Shuffle;

});