diff --git a/dist/shuffle.js b/dist/shuffle.js index a84ba71..f60006d 100644 --- a/dist/shuffle.js +++ b/dist/shuffle.js @@ -855,7 +855,6 @@ var Shuffle = function (_TinyEmitter) { _this.options = Object.assign({}, Shuffle.options, options); - _this.useSizer = false; _this.lastSort = {}; _this.group = Shuffle.ALL_ITEMS; _this.lastFilter = Shuffle.ALL_ITEMS; @@ -888,10 +887,6 @@ var Shuffle = function (_TinyEmitter) { this.options.sizer = this._getElementOption(this.options.sizer); - if (this.options.sizer) { - this.useSizer = true; - } - // Add class and invalidate styles this.element.classList.add(Shuffle.Classes.BASE); @@ -1032,7 +1027,7 @@ var Shuffle = function (_TinyEmitter) { /** * Returns an object containing the visible and hidden elements. * @param {string|Function} category Category or function to filter by. - * @param {Array.} items A collection of items to filter. + * @param {Element[]} items A collection of items to filter. * @return {!{visible: Array, hidden: Array}} * @private */ @@ -1123,7 +1118,7 @@ var Shuffle = function (_TinyEmitter) { /** * Set the initial css for each item - * @param {Array.} items Set to initialize. + * @param {ShuffleItem[]} items Set to initialize. * @private */ @@ -1137,7 +1132,7 @@ var Shuffle = function (_TinyEmitter) { /** * Remove element reference and styles. - * @param {Array.} items Set to dispose. + * @param {ShuffleItem[]} items Set to dispose. * @private */ @@ -1164,7 +1159,7 @@ var Shuffle = function (_TinyEmitter) { * Sets css transform transition on a group of elements. This is not executed * at the same time as `item.init` so that transitions don't occur upon * initialization of Shuffle. - * @param {Array.} items Shuffle items to set transitions on. + * @param {ShuffleItem[]} items Shuffle items to set transitions on. * @protected */ @@ -1195,7 +1190,7 @@ var Shuffle = function (_TinyEmitter) { /** * When new elements are added to the shuffle container, update the array of * items because that is the order `_layout` calls them. - * @param {Array.} items Items to track. + * @param {ShuffleItem[]} items Items to track. */ }, { @@ -1241,7 +1236,7 @@ var Shuffle = function (_TinyEmitter) { size = this.options.columnWidth(containerWidth); // columnWidth option isn't a function, are they using a sizing element? - } else if (this.useSizer) { + } else if (this.options.sizer) { size = Shuffle.getSize(this.options.sizer).width; // if not, how about the explicitly set option? @@ -1278,7 +1273,7 @@ var Shuffle = function (_TinyEmitter) { var size = void 0; if (typeof this.options.gutterWidth === 'function') { size = this.options.gutterWidth(containerWidth); - } else if (this.useSizer) { + } else if (this.options.sizer) { size = getNumberStyle(this.options.sizer, 'marginLeft'); } else { size = this.options.gutterWidth; @@ -1384,7 +1379,7 @@ var Shuffle = function (_TinyEmitter) { /** * Loops through each item that should be shown and calculates the x, y position. - * @param {Array.} items Array of items that will be shown/layed + * @param {ShuffleItem[]} items Array of items that will be shown/layed * out in order in their array. */ @@ -1435,8 +1430,8 @@ var Shuffle = function (_TinyEmitter) { /** * Return an array of Point instances representing the future positions of * each item. - * @param {Array.} items Array of sorted shuffle items. - * @return {Array.} + * @param {ShuffleItem[]} items Array of sorted shuffle items. + * @return {Point[]} * @private */ @@ -1486,9 +1481,9 @@ var Shuffle = function (_TinyEmitter) { /** * Mutate positions before they're applied. - * @param {Array.} itemRects Item data objects. + * @param {Rect[]} itemRects Item data objects. * @param {number} containerWidth Width of the containing element. - * @return {Array.} + * @return {Point[]} * @protected */ @@ -1500,7 +1495,7 @@ var Shuffle = function (_TinyEmitter) { /** * Hides the elements that don't match our filter. - * @param {Array.} collection Collection to shrink. + * @param {ShuffleItem[]} collection Collection to shrink. * @private */ @@ -1662,7 +1657,7 @@ var Shuffle = function (_TinyEmitter) { /** * Wait for each transition to finish, the emit the layout event. - * @param {Array.} transitions Array of transition objects. + * @param {Object[]} transitions Array of transition objects. */ }, { @@ -1695,7 +1690,7 @@ var Shuffle = function (_TinyEmitter) { /** * Apply styles without a transition. - * @param {Array.} objects Array of transition objects. + * @param {Object[]} objects Array of transition objects. * @private */ @@ -1727,7 +1722,7 @@ var Shuffle = function (_TinyEmitter) { /** * The magic. This is what makes the plugin 'shuffle' - * @param {string|Function|Array.} [category] Category to filter by. + * @param {string|Function|string[]} [category] Category to filter by. * Can be a function, string, or array of strings. * @param {Object} [sortObj] A sort object which can sort the visible set */ @@ -1787,13 +1782,14 @@ var Shuffle = function (_TinyEmitter) { /** * Reposition everything. - * @param {boolean} isOnlyLayout If true, column and gutter widths won't be - * recalculated. + * @param {boolean} [isOnlyLayout=false] If true, column and gutter widths won't be recalculated. */ }, { key: 'update', - value: function update(isOnlyLayout) { + value: function update() { + var isOnlyLayout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + if (this.isEnabled) { if (!isOnlyLayout) { // Get updated colCount @@ -1820,7 +1816,7 @@ var Shuffle = function (_TinyEmitter) { /** * New items have been appended to shuffle. Mix them in with the current * filter or sort status. - * @param {Array.} newItems Collection of new items. + * @param {Element[]} newItems Collection of new items. */ }, { @@ -1870,10 +1866,10 @@ var Shuffle = function (_TinyEmitter) { } /** - * Remove 1 or more shuffle items - * @param {Array.} elements An array containing one or more + * Remove 1 or more shuffle items. + * @param {Element[]} elements An array containing one or more * elements in shuffle - * @return {Shuffle} The shuffle object + * @return {Shuffle} The shuffle instance. */ }, { @@ -1927,7 +1923,7 @@ var Shuffle = function (_TinyEmitter) { /** * Retrieve a shuffle item by its element. * @param {Element} element Element to look for. - * @return {?ShuffleItem} A shuffle item or null if it's not found. + * @return {?ShuffleItem} A shuffle item or undefined if it's not found. */ }, { @@ -2017,13 +2013,15 @@ var Shuffle = function (_TinyEmitter) { * follow the W3C spec here. * * @param {Element} element The element. - * @param {boolean} [includeMargins] Whether to include margins. Default is false. + * @param {boolean} [includeMargins=false] Whether to include margins. * @return {{width: number, height: number}} The width and height. */ }], [{ key: 'getSize', - value: function getSize(element, includeMargins) { + value: function getSize(element) { + var includeMargins = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + // Store the styles so that they can be used by others without asking for it again. var styles = window.getComputedStyle(element, null); var width = getNumberStyle(element, 'width', styles); @@ -2046,7 +2044,7 @@ var Shuffle = function (_TinyEmitter) { /** * Change a property or execute a function which will not have a transition - * @param {Array.} elements DOM elements that won't be transitioned. + * @param {Element[]} elements DOM elements that won't be transitioned. * @param {Function} callback A function which will be called while transition * is set to 0ms. * @private @@ -2093,9 +2091,7 @@ Shuffle.ShuffleItem = ShuffleItem; Shuffle.ALL_ITEMS = 'all'; Shuffle.FILTER_ATTRIBUTE_KEY = 'groups'; -/** - * @enum {string} - */ +/** @enum {string} */ Shuffle.EventType = { LAYOUT: 'shuffle:layout', REMOVED: 'shuffle:removed' @@ -2104,9 +2100,7 @@ Shuffle.EventType = { /** @enum {string} */ Shuffle.Classes = Classes; -/** - * @enum {string} - */ +/** @enum {string} */ Shuffle.FilterMode = { ANY: 'any', ALL: 'all' @@ -2179,9 +2173,10 @@ Shuffle.options = { isCentered: false }; +Shuffle.Point = Point; +Shuffle.Rect = Rect; + // Expose for testing. Hack at your own risk. -Shuffle.__Point = Point; -Shuffle.__Rect = Rect; Shuffle.__sorter = sorter; Shuffle.__getColumnSpan = getColumnSpan; Shuffle.__getAvailablePositions = getAvailablePositions; diff --git a/dist/shuffle.js.map b/dist/shuffle.js.map index 3eb37b3..5856cfb 100644 --- a/dist/shuffle.js.map +++ b/dist/shuffle.js.map @@ -1 +1 @@ -{"version":3,"file":"shuffle.js","sources":["../node_modules/tiny-emitter/index.js","../node_modules/matches-selector/index.js","../node_modules/throttleit/index.js","../node_modules/array-parallel/index.js","../src/get-number.js","../src/point.js","../src/rect.js","../src/classes.js","../src/shuffle-item.js","../src/computed-size.js","../src/get-number-style.js","../src/sorter.js","../src/on-transition-end.js","../src/array-max.js","../src/array-min.js","../src/layout.js","../src/shuffle.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\n","'use strict';\n\nvar proto = typeof Element !== 'undefined' ? Element.prototype : {};\nvar vendor = proto.matches\n || proto.matchesSelector\n || proto.webkitMatchesSelector\n || proto.mozMatchesSelector\n || proto.msMatchesSelector\n || proto.oMatchesSelector;\n\nmodule.exports = match;\n\n/**\n * Match `el` to `selector`.\n *\n * @param {Element} el\n * @param {String} selector\n * @return {Boolean}\n * @api public\n */\n\nfunction match(el, selector) {\n if (!el || el.nodeType !== 1) return false;\n if (vendor) return vendor.call(el, selector);\n var nodes = el.parentNode.querySelectorAll(selector);\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i] == el) return true;\n }\n return false;\n}\n","module.exports = throttle;\n\n/**\n * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds.\n *\n * @param {Function} func Function to wrap.\n * @param {Number} wait Number of milliseconds that must elapse between `func` invocations.\n * @return {Function} A new function that wraps the `func` function passed in.\n */\n\nfunction throttle (func, wait) {\n var ctx, args, rtn, timeoutID; // caching\n var last = 0;\n\n return function throttled () {\n ctx = this;\n args = arguments;\n var delta = new Date() - last;\n if (!timeoutID)\n if (delta >= wait) call();\n else timeoutID = setTimeout(call, wait - delta);\n return rtn;\n };\n\n function call () {\n timeoutID = 0;\n last = +new Date();\n rtn = func.apply(ctx, args);\n ctx = null;\n args = null;\n }\n}\n","module.exports = function parallel(fns, context, callback) {\n if (!callback) {\n if (typeof context === 'function') {\n callback = context\n context = null\n } else {\n callback = noop\n }\n }\n\n var pending = fns && fns.length\n if (!pending) return callback(null, []);\n\n var finished = false\n var results = new Array(pending)\n\n fns.forEach(context ? function (fn, i) {\n fn.call(context, maybeDone(i))\n } : function (fn, i) {\n fn(maybeDone(i))\n })\n\n function maybeDone(i) {\n return function (err, result) {\n if (finished) return;\n\n if (err) {\n callback(err, results)\n finished = true\n return\n }\n\n results[i] = result\n\n if (!--pending) callback(null, results);\n }\n }\n}\n\nfunction noop() {}\n","/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param {*} value Possibly numeric value.\n * @return {number} `value` or zero if `value` isn't numeric.\n */\nexport default function getNumber(value) {\n return parseFloat(value) || 0;\n}\n","import getNumber from './get-number';\n\nclass Point {\n\n /**\n * Represents a coordinate pair.\n * @param {number} [x=0] X.\n * @param {number} [y=0] Y.\n */\n constructor(x, y) {\n this.x = getNumber(x);\n this.y = getNumber(y);\n }\n\n /**\n * Whether two points are equal.\n * @param {Point} a Point A.\n * @param {Point} b Point B.\n * @return {boolean}\n */\n static equals(a, b) {\n return a.x === b.x && a.y === b.y;\n }\n}\n\nexport default Point;\n","export default class Rect {\n /**\n * Class for representing rectangular regions.\n * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n * @param {number} x Left.\n * @param {number} y Top.\n * @param {number} w Width.\n * @param {number} h Height.\n * @param {number} id Identifier\n * @constructor\n */\n constructor(x, y, w, h, id) {\n this.id = id;\n\n /** @type {number} */\n this.left = x;\n\n /** @type {number} */\n this.top = y;\n\n /** @type {number} */\n this.width = w;\n\n /** @type {number} */\n this.height = h;\n }\n\n /**\n * Returns whether two rectangles intersect.\n * @param {Rect} a A Rectangle.\n * @param {Rect} b A Rectangle.\n * @return {boolean} Whether a and b intersect.\n */\n static intersects(a, b) {\n return (\n a.left < b.left + b.width && b.left < a.left + a.width &&\n a.top < b.top + b.height && b.top < a.top + a.height);\n }\n}\n","export default {\n BASE: 'shuffle',\n SHUFFLE_ITEM: 'shuffle-item',\n VISIBLE: 'shuffle-item--visible',\n HIDDEN: 'shuffle-item--hidden',\n};\n","import Point from './point';\nimport Classes from './classes';\n\nlet id = 0;\n\nclass ShuffleItem {\n constructor(element) {\n id += 1;\n this.id = id;\n this.element = element;\n this.isVisible = true;\n }\n\n show() {\n this.isVisible = true;\n this.element.classList.remove(Classes.HIDDEN);\n this.element.classList.add(Classes.VISIBLE);\n this.element.removeAttribute('aria-hidden');\n }\n\n hide() {\n this.isVisible = false;\n this.element.classList.remove(Classes.VISIBLE);\n this.element.classList.add(Classes.HIDDEN);\n this.element.setAttribute('aria-hidden', true);\n }\n\n init() {\n this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]);\n this.applyCss(ShuffleItem.Css.INITIAL);\n this.scale = ShuffleItem.Scale.VISIBLE;\n this.point = new Point();\n }\n\n addClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.add(className);\n });\n }\n\n removeClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.remove(className);\n });\n }\n\n applyCss(obj) {\n Object.keys(obj).forEach((key) => {\n this.element.style[key] = obj[key];\n });\n }\n\n dispose() {\n this.removeClasses([\n Classes.HIDDEN,\n Classes.VISIBLE,\n Classes.SHUFFLE_ITEM,\n ]);\n\n this.element.removeAttribute('style');\n this.element = null;\n }\n}\n\nShuffleItem.Css = {\n INITIAL: {\n position: 'absolute',\n top: 0,\n left: 0,\n visibility: 'visible',\n 'will-change': 'transform',\n },\n VISIBLE: {\n before: {\n opacity: 1,\n visibility: 'visible',\n },\n after: {},\n },\n HIDDEN: {\n before: {\n opacity: 0,\n },\n after: {\n visibility: 'hidden',\n },\n },\n};\n\nShuffleItem.Scale = {\n VISIBLE: 1,\n HIDDEN: 0.001,\n};\n\nexport default ShuffleItem;\n","const element = document.body || document.documentElement;\nconst e = document.createElement('div');\ne.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\nelement.appendChild(e);\n\nconst width = window.getComputedStyle(e, null).width;\nconst ret = width === '10px';\n\nelement.removeChild(e);\n\nexport default ret;\n","import getNumber from './get-number';\nimport COMPUTED_SIZE_INCLUDES_PADDING from './computed-size';\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param {Element} element Element to get style for.\n * @param {string} style Style property.\n * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to\n * use instead of asking for them again.\n * @return {number} The parsed computed value or zero if that fails because IE\n * will return 'auto' when the element doesn't have margins instead of\n * the computed style.\n */\nexport default function getNumberStyle(element, style,\n styles = window.getComputedStyle(element, null)) {\n let value = getNumber(styles[style]);\n\n // Support IE<=11 and W3C spec.\n if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'width') {\n value += getNumber(styles.paddingLeft) +\n getNumber(styles.paddingRight) +\n getNumber(styles.borderLeftWidth) +\n getNumber(styles.borderRightWidth);\n } else if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'height') {\n value += getNumber(styles.paddingTop) +\n getNumber(styles.paddingBottom) +\n getNumber(styles.borderTopWidth) +\n getNumber(styles.borderBottomWidth);\n }\n\n return value;\n}\n","/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param {Array} array Array to shuffle.\n * @return {Array} Randomly sorted array.\n */\nfunction randomize(array) {\n let n = array.length;\n\n while (n) {\n n -= 1;\n const i = Math.floor(Math.random() * (n + 1));\n const temp = array[i];\n array[i] = array[n];\n array[n] = temp;\n }\n\n return array;\n}\n\nconst defaults = {\n // Use array.reverse() to reverse the results\n reverse: false,\n\n // Sorting function\n by: null,\n\n // If true, this will skip the sorting and return a randomized order in the array\n randomize: false,\n\n // Determines which property of each item in the array is passed to the\n // sorting method.\n key: 'element',\n};\n\n// You can return `undefined` from the `by` function to revert to DOM order.\nexport default function sorter(arr, options) {\n const opts = Object.assign({}, defaults, options);\n const original = Array.from(arr);\n let revert = false;\n\n if (!arr.length) {\n return [];\n }\n\n if (opts.randomize) {\n return randomize(arr);\n }\n\n // Sort the elements by the opts.by function.\n // If we don't have opts.by, default to DOM order\n if (typeof opts.by === 'function') {\n arr.sort((a, b) => {\n // Exit early if we already know we want to revert\n if (revert) {\n return 0;\n }\n\n const valA = opts.by(a[opts.key]);\n const valB = opts.by(b[opts.key]);\n\n // If both values are undefined, use the DOM order\n if (valA === undefined && valB === undefined) {\n revert = true;\n return 0;\n }\n\n if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {\n return -1;\n }\n\n if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {\n return 1;\n }\n\n return 0;\n });\n }\n\n // Revert to the original array if necessary\n if (revert) {\n return original;\n }\n\n if (opts.reverse) {\n arr.reverse();\n }\n\n return arr;\n}\n","const transitions = {};\nconst eventName = 'transitionend';\nlet count = 0;\n\nfunction uniqueId() {\n count += 1;\n return eventName + count;\n}\n\nexport function cancelTransitionEnd(id) {\n if (transitions[id]) {\n transitions[id].element.removeEventListener(eventName, transitions[id].listener);\n transitions[id] = null;\n return true;\n }\n\n return false;\n}\n\nexport function onTransitionEnd(element, callback) {\n const id = uniqueId();\n const listener = (evt) => {\n if (evt.currentTarget === evt.target) {\n cancelTransitionEnd(id);\n callback(evt);\n }\n };\n\n element.addEventListener(eventName, listener);\n\n transitions[id] = { element, listener };\n\n return id;\n}\n","export default function arrayMax(array) {\n return Math.max.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","export default function arrayMin(array) {\n return Math.min.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","import Point from './point';\nimport Rect from './rect';\nimport arrayMax from './array-max';\nimport arrayMin from './array-min';\n\n/**\n * Determine the number of columns an items spans.\n * @param {number} itemWidth Width of the item.\n * @param {number} columnWidth Width of the column (includes gutter).\n * @param {number} columns Total number of columns\n * @param {number} threshold A buffer value for the size of the column to fit.\n * @return {number}\n */\nexport function getColumnSpan(itemWidth, columnWidth, columns, threshold) {\n let columnSpan = itemWidth / columnWidth;\n\n // If the difference between the rounded column span number and the\n // calculated column span number is really small, round the number to\n // make it fit.\n if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {\n // e.g. columnSpan = 4.0089945390298745\n columnSpan = Math.round(columnSpan);\n }\n\n // Ensure the column span is not more than the amount of columns in the whole layout.\n return Math.min(Math.ceil(columnSpan), columns);\n}\n\n/**\n * Retrieves the column set to use for placement.\n * @param {number} columnSpan The number of columns this current item spans.\n * @param {number} columns The total columns in the grid.\n * @return {Array.} An array of numbers represeting the column set.\n */\nexport function getAvailablePositions(positions, columnSpan, columns) {\n // The item spans only one column.\n if (columnSpan === 1) {\n return positions;\n }\n\n // The item spans more than one column, figure out how many different\n // places it could fit horizontally.\n // The group count is the number of places within the positions this block\n // could fit, ignoring the current positions of items.\n // Imagine a 2 column brick as the second item in a 4 column grid with\n // 10px height each. Find the places it would fit:\n // [20, 10, 10, 0]\n // | | |\n // * * *\n //\n // Then take the places which fit and get the bigger of the two:\n // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]\n //\n // Next, find the first smallest number (the short column).\n // [20, 10, 0]\n // |\n // *\n //\n // And that's where it should be placed!\n //\n // Another example where the second column's item extends past the first:\n // [10, 20, 10, 0] => [20, 20, 10] => 10\n const available = [];\n\n // For how many possible positions for this item there are.\n for (let i = 0; i <= columns - columnSpan; i++) {\n // Find the bigger value for each place it could fit.\n available.push(arrayMax(positions.slice(i, i + columnSpan)));\n }\n\n return available;\n}\n\n/**\n * Find index of short column, the first from the left where this item will go.\n *\n * @param {Array.} positions The array to search for the smallest number.\n * @param {number} buffer Optional buffer which is very useful when the height\n * is a percentage of the width.\n * @return {number} Index of the short column.\n */\nexport function getShortColumn(positions, buffer) {\n const minPosition = arrayMin(positions);\n for (let i = 0, len = positions.length; i < len; i++) {\n if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n return i;\n }\n }\n\n return 0;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param {Object} itemSize Object with width and height.\n * @param {Array.} positions Positions of the other current items.\n * @param {number} gridSize The column width or row height.\n * @param {number} total The total number of columns or rows.\n * @param {number} threshold Buffer value for the column to fit.\n * @param {number} buffer Vertical buffer for the height of items.\n * @return {Point}\n */\nexport function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {\n const span = getColumnSpan(itemSize.width, gridSize, total, threshold);\n const setY = getAvailablePositions(positions, span, total);\n const shortColumnIndex = getShortColumn(setY, buffer);\n\n // Position the item\n const point = new Point(\n Math.round(gridSize * shortColumnIndex),\n Math.round(setY[shortColumnIndex]));\n\n // Update the columns array with the new values for each column.\n // e.g. before the update the columns could be [250, 0, 0, 0] for an item\n // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].\n const setHeight = setY[shortColumnIndex] + itemSize.height;\n for (let i = 0; i < span; i++) {\n positions[shortColumnIndex + i] = setHeight;\n }\n\n return point;\n}\n\n/**\n * This method attempts to center items. This method could potentially be slow\n * with a large number of items because it must place items, then check every\n * previous item to ensure there is no overlap.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n */\nexport function getCenteredPositions(itemRects, containerWidth) {\n const rowMap = {};\n\n // Populate rows by their offset because items could jump between rows like:\n // a c\n // bbb\n itemRects.forEach((itemRect) => {\n if (rowMap[itemRect.top]) {\n // Push the point to the last row array.\n rowMap[itemRect.top].push(itemRect);\n } else {\n // Start of a new row.\n rowMap[itemRect.top] = [itemRect];\n }\n });\n\n // For each row, find the end of the last item, then calculate\n // the remaining space by dividing it by 2. Then add that\n // offset to the x position of each point.\n let rects = [];\n const rows = [];\n const centeredRows = [];\n Object.keys(rowMap).forEach((key) => {\n const itemRects = rowMap[key];\n rows.push(itemRects);\n const lastItem = itemRects[itemRects.length - 1];\n const end = lastItem.left + lastItem.width;\n const offset = Math.round((containerWidth - end) / 2);\n\n let finalRects = itemRects;\n let canMove = false;\n if (offset > 0) {\n const newRects = [];\n canMove = itemRects.every((r) => {\n const newRect = new Rect(r.left + offset, r.top, r.width, r.height, r.id);\n\n // Check all current rects to make sure none overlap.\n const noOverlap = !rects.some(r => Rect.intersects(newRect, r));\n\n newRects.push(newRect);\n return noOverlap;\n });\n\n // If none of the rectangles overlapped, the whole group can be centered.\n if (canMove) {\n finalRects = newRects;\n }\n }\n\n // If the items are not going to be offset, ensure that the original\n // placement for this row will not overlap previous rows (row-spanning\n // elements could be in the way).\n if (!canMove) {\n let intersectingRect;\n const hasOverlap = itemRects.some(itemRect => rects.some((r) => {\n const intersects = Rect.intersects(itemRect, r);\n if (intersects) {\n intersectingRect = r;\n }\n return intersects;\n }));\n\n // If there is any overlap, replace the overlapping row with the original.\n if (hasOverlap) {\n const rowIndex = centeredRows.findIndex(items => items.includes(intersectingRect));\n centeredRows.splice(rowIndex, 1, rows[rowIndex]);\n }\n }\n\n rects = rects.concat(finalRects);\n centeredRows.push(finalRects);\n });\n\n // Reduce array of arrays to a single array of points.\n // https://stackoverflow.com/a/10865042/373422\n // Then reset sort back to how the items were passed to this method.\n // Remove the wrapper object with index, map to a Point.\n return [].concat.apply([], centeredRows) // eslint-disable-line prefer-spread\n .sort((a, b) => (a.id - b.id))\n .map(itemRect => new Point(itemRect.left, itemRect.top));\n}\n","import TinyEmitter from 'tiny-emitter';\nimport matches from 'matches-selector';\nimport throttle from 'throttleit';\nimport parallel from 'array-parallel';\n\nimport Point from './point';\nimport Rect from './rect';\nimport ShuffleItem from './shuffle-item';\nimport Classes from './classes';\nimport getNumberStyle from './get-number-style';\nimport sorter from './sorter';\nimport { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';\nimport {\n getItemPosition,\n getColumnSpan,\n getAvailablePositions,\n getShortColumn,\n getCenteredPositions,\n} from './layout';\nimport arrayMax from './array-max';\n\nfunction arrayUnique(x) {\n return Array.from(new Set(x));\n}\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n\n /**\n * Categorize, sort, and filter a responsive grid of items.\n *\n * @param {Element} element An element which is the parent container for the grid items.\n * @param {Object} [options=Shuffle.options] Options object.\n * @constructor\n */\n constructor(element, options = {}) {\n super();\n this.options = Object.assign({}, Shuffle.options, options);\n\n this.useSizer = false;\n this.lastSort = {};\n this.group = Shuffle.ALL_ITEMS;\n this.lastFilter = Shuffle.ALL_ITEMS;\n this.isEnabled = true;\n this.isDestroyed = false;\n this.isInitialized = false;\n this._transitions = [];\n this.isTransitioning = false;\n this._queue = [];\n\n const el = this._getElementOption(element);\n\n if (!el) {\n throw new TypeError('Shuffle needs to be initialized with an element.');\n }\n\n this.element = el;\n this.id = 'shuffle_' + id;\n id += 1;\n\n this._init();\n this.isInitialized = true;\n }\n\n _init() {\n this.items = this._getItems();\n\n this.options.sizer = this._getElementOption(this.options.sizer);\n\n if (this.options.sizer) {\n this.useSizer = true;\n }\n\n // Add class and invalidate styles\n this.element.classList.add(Shuffle.Classes.BASE);\n\n // Set initial css for each item\n this._initItems(this.items);\n\n // Bind resize events\n this._onResize = this._getResizeFunction();\n window.addEventListener('resize', this._onResize);\n\n // If the page has not already emitted the `load` event, call layout on load.\n // This avoids layout issues caused by images and fonts loading after the\n // instance has been initialized.\n if (document.readyState !== 'complete') {\n const layout = this.layout.bind(this);\n window.addEventListener('load', function onLoad() {\n window.removeEventListener('load', onLoad);\n layout();\n });\n }\n\n // Get container css all in one request. Causes reflow\n const containerCss = window.getComputedStyle(this.element, null);\n const containerWidth = Shuffle.getSize(this.element).width;\n\n // Add styles to the container if it doesn't have them.\n this._validateStyles(containerCss);\n\n // We already got the container's width above, no need to cause another\n // reflow getting it again... Calculate the number of columns there will be\n this._setColumns(containerWidth);\n\n // Kick off!\n this.filter(this.options.group, this.options.initialSort);\n\n // The shuffle items haven't had transitions set on them yet so the user\n // doesn't see the first layout. Set them now that the first layout is done.\n // First, however, a synchronous layout must be caused for the previous\n // styles to be applied without transitions.\n this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n this.setItemTransitions(this.items);\n this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;\n }\n\n /**\n * Returns a throttled and proxied function for the resize handler.\n * @return {Function}\n * @private\n */\n _getResizeFunction() {\n const resizeFunction = this._handleResize.bind(this);\n return this.options.throttle ?\n this.options.throttle(resizeFunction, this.options.throttleTime) :\n resizeFunction;\n }\n\n /**\n * Retrieve an element from an option.\n * @param {string|jQuery|Element} option The option to check.\n * @return {?Element} The plain element or null.\n * @private\n */\n _getElementOption(option) {\n // If column width is a string, treat is as a selector and search for the\n // sizer element within the outermost container\n if (typeof option === 'string') {\n return this.element.querySelector(option);\n\n // Check for an element\n } else if (option && option.nodeType && option.nodeType === 1) {\n return option;\n\n // Check for jQuery object\n } else if (option && option.jquery) {\n return option[0];\n }\n\n return null;\n }\n\n /**\n * Ensures the shuffle container has the css styles it needs applied to it.\n * @param {Object} styles Key value pairs for position and overflow.\n * @private\n */\n _validateStyles(styles) {\n // Position cannot be static.\n if (styles.position === 'static') {\n this.element.style.position = 'relative';\n }\n\n // Overflow has to be hidden.\n if (styles.overflow !== 'hidden') {\n this.element.style.overflow = 'hidden';\n }\n }\n\n /**\n * Filter the elements by a category.\n * @param {string} [category] Category to filter by. If it's given, the last\n * category will be used to filter the items.\n * @param {Array} [collection] Optionally filter a collection. Defaults to\n * all the items.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _filter(category = this.lastFilter, collection = this.items) {\n const set = this._getFilteredSets(category, collection);\n\n // Individually add/remove hidden/visible classes\n this._toggleFilterClasses(set);\n\n // Save the last filter in case elements are appended.\n this.lastFilter = category;\n\n // This is saved mainly because providing a filter function (like searching)\n // will overwrite the `lastFilter` property every time its called.\n if (typeof category === 'string') {\n this.group = category;\n }\n\n return set;\n }\n\n /**\n * Returns an object containing the visible and hidden elements.\n * @param {string|Function} category Category or function to filter by.\n * @param {Array.} items A collection of items to filter.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _getFilteredSets(category, items) {\n let visible = [];\n const hidden = [];\n\n // category === 'all', add visible class to everything\n if (category === Shuffle.ALL_ITEMS) {\n visible = items;\n\n // Loop through each item and use provided function to determine\n // whether to hide it or not.\n } else {\n items.forEach((item) => {\n if (this._doesPassFilter(category, item.element)) {\n visible.push(item);\n } else {\n hidden.push(item);\n }\n });\n }\n\n return {\n visible,\n hidden,\n };\n }\n\n /**\n * Test an item to see if it passes a category.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element} element An element to test.\n * @return {boolean} Whether it passes the category/filter.\n * @private\n */\n _doesPassFilter(category, element) {\n if (typeof category === 'function') {\n return category.call(element, element, this);\n }\n\n // Check each element's data-groups attribute against the given category.\n const attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY);\n const keys = this.options.delimeter ?\n attr.split(this.options.delimeter) :\n JSON.parse(attr);\n\n function testCategory(category) {\n return keys.includes(category);\n }\n\n if (Array.isArray(category)) {\n if (this.options.filterMode === Shuffle.FilterMode.ANY) {\n return category.some(testCategory);\n }\n return category.every(testCategory);\n }\n\n return keys.includes(category);\n }\n\n /**\n * Toggles the visible and hidden class names.\n * @param {{visible, hidden}} Object with visible and hidden arrays.\n * @private\n */\n _toggleFilterClasses({ visible, hidden }) {\n visible.forEach((item) => {\n item.show();\n });\n\n hidden.forEach((item) => {\n item.hide();\n });\n }\n\n /**\n * Set the initial css for each item\n * @param {Array.} items Set to initialize.\n * @private\n */\n _initItems(items) {\n items.forEach((item) => {\n item.init();\n });\n }\n\n /**\n * Remove element reference and styles.\n * @param {Array.} items Set to dispose.\n * @private\n */\n _disposeItems(items) {\n items.forEach((item) => {\n item.dispose();\n });\n }\n\n /**\n * Updates the visible item count.\n * @private\n */\n _updateItemCount() {\n this.visibleItems = this._getFilteredItems().length;\n }\n\n /**\n * Sets css transform transition on a group of elements. This is not executed\n * at the same time as `item.init` so that transitions don't occur upon\n * initialization of Shuffle.\n * @param {Array.} items Shuffle items to set transitions on.\n * @protected\n */\n setItemTransitions(items) {\n const speed = this.options.speed;\n const easing = this.options.easing;\n\n const str = this.options.useTransforms ?\n `transform ${speed}ms ${easing}, opacity ${speed}ms ${easing}` :\n `top ${speed}ms ${easing}, left ${speed}ms ${easing}, opacity ${speed}ms ${easing}`;\n\n items.forEach((item) => {\n item.element.style.transition = str;\n });\n }\n\n _getItems() {\n return Array.from(this.element.children)\n .filter(el => matches(el, this.options.itemSelector))\n .map(el => new ShuffleItem(el));\n }\n\n /**\n * When new elements are added to the shuffle container, update the array of\n * items because that is the order `_layout` calls them.\n * @param {Array.} items Items to track.\n */\n _saveNewItems(items) {\n const children = Array.from(this.element.children);\n this.items = sorter(this.items.concat(items), {\n by(element) {\n return children.indexOf(element);\n },\n });\n }\n\n _getFilteredItems() {\n return this.items.filter(item => item.isVisible);\n }\n\n _getConcealedItems() {\n return this.items.filter(item => !item.isVisible);\n }\n\n /**\n * Returns the column size, based on column width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @param {number} gutterSize Size of the gutters.\n * @return {number}\n * @private\n */\n _getColumnSize(containerWidth, gutterSize) {\n let size;\n\n // If the columnWidth property is a function, then the grid is fluid\n if (typeof this.options.columnWidth === 'function') {\n size = this.options.columnWidth(containerWidth);\n\n // columnWidth option isn't a function, are they using a sizing element?\n } else if (this.useSizer) {\n size = Shuffle.getSize(this.options.sizer).width;\n\n // if not, how about the explicitly set option?\n } else if (this.options.columnWidth) {\n size = this.options.columnWidth;\n\n // or use the size of the first item\n } else if (this.items.length > 0) {\n size = Shuffle.getSize(this.items[0].element, true).width;\n\n // if there's no items, use size of container\n } else {\n size = containerWidth;\n }\n\n // Don't let them set a column width of zero.\n if (size === 0) {\n size = containerWidth;\n }\n\n return size + gutterSize;\n }\n\n /**\n * Returns the gutter size, based on gutter width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @return {number}\n * @private\n */\n _getGutterSize(containerWidth) {\n let size;\n if (typeof this.options.gutterWidth === 'function') {\n size = this.options.gutterWidth(containerWidth);\n } else if (this.useSizer) {\n size = getNumberStyle(this.options.sizer, 'marginLeft');\n } else {\n size = this.options.gutterWidth;\n }\n\n return size;\n }\n\n /**\n * Calculate the number of columns to be used. Gets css if using sizer element.\n * @param {number} [containerWidth] Optionally specify a container width if\n * it's already available.\n */\n _setColumns(containerWidth = Shuffle.getSize(this.element).width) {\n const gutter = this._getGutterSize(containerWidth);\n const columnWidth = this._getColumnSize(containerWidth, gutter);\n let calculatedColumns = (containerWidth + gutter) / columnWidth;\n\n // Widths given from getStyles are not precise enough...\n if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) <\n this.options.columnThreshold) {\n // e.g. calculatedColumns = 11.998876\n calculatedColumns = Math.round(calculatedColumns);\n }\n\n this.cols = Math.max(Math.floor(calculatedColumns), 1);\n this.containerWidth = containerWidth;\n this.colWidth = columnWidth;\n }\n\n /**\n * Adjust the height of the grid\n */\n _setContainerSize() {\n this.element.style.height = this._getContainerSize() + 'px';\n }\n\n /**\n * Based on the column heights, it returns the biggest one.\n * @return {number}\n * @private\n */\n _getContainerSize() {\n return arrayMax(this.positions);\n }\n\n /**\n * Get the clamped stagger amount.\n * @param {number} index Index of the item to be staggered.\n * @return {number}\n */\n _getStaggerAmount(index) {\n return Math.min(index * this.options.staggerAmount, this.options.staggerAmountMax);\n }\n\n /**\n * Emit an event from this instance.\n * @param {string} name Event name.\n * @param {Object} [data={}] Optional object data.\n */\n _dispatch(name, data = {}) {\n if (this.isDestroyed) {\n return;\n }\n\n data.shuffle = this;\n this.emit(name, data);\n }\n\n /**\n * Zeros out the y columns array, which is used to determine item placement.\n * @private\n */\n _resetCols() {\n let i = this.cols;\n this.positions = [];\n while (i) {\n i -= 1;\n this.positions.push(0);\n }\n }\n\n /**\n * Loops through each item that should be shown and calculates the x, y position.\n * @param {Array.} items Array of items that will be shown/layed\n * out in order in their array.\n */\n _layout(items) {\n const itemPositions = this._getNextPositions(items);\n\n let count = 0;\n items.forEach((item, i) => {\n const currPos = item.point;\n const currScale = item.scale;\n const nextPosition = itemPositions[i];\n\n function callback() {\n item.element.style.transitionDelay = '';\n item.applyCss(ShuffleItem.Css.VISIBLE.after);\n }\n\n // If the item will not change its position, do not add it to the render\n // queue. Transitions don't fire when setting a property to the same value.\n if (Point.equals(currPos, nextPosition) && currScale === ShuffleItem.Scale.VISIBLE) {\n item.applyCss(ShuffleItem.Css.VISIBLE.before);\n callback();\n return;\n }\n\n item.point = nextPosition;\n item.scale = ShuffleItem.Scale.VISIBLE;\n\n // Clone the object so that the `before` object isn't modified when the\n // transition delay is added.\n const styles = Object.assign({}, ShuffleItem.Css.VISIBLE.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Return an array of Point instances representing the future positions of\n * each item.\n * @param {Array.} items Array of sorted shuffle items.\n * @return {Array.}\n * @private\n */\n _getNextPositions(items) {\n // If position data is going to be changed, add the item's size to the\n // transformer to allow for calculations.\n if (this.options.isCentered) {\n const itemsData = items.map((item, i) => {\n const itemSize = Shuffle.getSize(item.element, true);\n const point = this._getItemPosition(itemSize);\n return new Rect(point.x, point.y, itemSize.width, itemSize.height, i);\n });\n\n return this.getTransformedPositions(itemsData, this.containerWidth);\n }\n\n // If no transforms are going to happen, simply return an array of the\n // future points of each item.\n return items.map(item => this._getItemPosition(Shuffle.getSize(item.element, true)));\n }\n\n /**\n * Determine the location of the next item, based on its size.\n * @param {{width: number, height: number}} itemSize Object with width and height.\n * @return {Point}\n * @private\n */\n _getItemPosition(itemSize) {\n return getItemPosition({\n itemSize,\n positions: this.positions,\n gridSize: this.colWidth,\n total: this.cols,\n threshold: this.options.columnThreshold,\n buffer: this.options.buffer,\n });\n }\n\n /**\n * Mutate positions before they're applied.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n * @protected\n */\n getTransformedPositions(itemRects, containerWidth) {\n return getCenteredPositions(itemRects, containerWidth);\n }\n\n /**\n * Hides the elements that don't match our filter.\n * @param {Array.} collection Collection to shrink.\n * @private\n */\n _shrink(collection = this._getConcealedItems()) {\n let count = 0;\n collection.forEach((item) => {\n function callback() {\n item.applyCss(ShuffleItem.Css.HIDDEN.after);\n }\n\n // Continuing would add a transitionend event listener to the element, but\n // that listener would not execute because the transform and opacity would\n // stay the same.\n // The callback is executed here because it is not guaranteed to be called\n // after the transitionend event because the transitionend could be\n // canceled if another animation starts.\n if (item.scale === ShuffleItem.Scale.HIDDEN) {\n item.applyCss(ShuffleItem.Css.HIDDEN.before);\n callback();\n return;\n }\n\n item.scale = ShuffleItem.Scale.HIDDEN;\n\n const styles = Object.assign({}, ShuffleItem.Css.HIDDEN.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Resize handler.\n * @private\n */\n _handleResize() {\n // If shuffle is disabled, destroyed, don't do anything\n if (!this.isEnabled || this.isDestroyed) {\n return;\n }\n\n this.update();\n }\n\n /**\n * Returns styles which will be applied to the an item for a transition.\n * @param {Object} obj Transition options.\n * @return {!Object} Transforms for transitions, left/top for animate.\n * @protected\n */\n getStylesForTransition({ item, styles }) {\n if (!styles.transitionDelay) {\n styles.transitionDelay = '0ms';\n }\n\n const x = item.point.x;\n const y = item.point.y;\n\n if (this.options.useTransforms) {\n styles.transform = `translate(${x}px, ${y}px) scale(${item.scale})`;\n } else {\n styles.left = x + 'px';\n styles.top = y + 'px';\n }\n\n return styles;\n }\n\n /**\n * Listen for the transition end on an element and execute the itemCallback\n * when it finishes.\n * @param {Element} element Element to listen on.\n * @param {Function} itemCallback Callback for the item.\n * @param {Function} done Callback to notify `parallel` that this one is done.\n */\n _whenTransitionDone(element, itemCallback, done) {\n const id = onTransitionEnd(element, (evt) => {\n itemCallback();\n done(null, evt);\n });\n\n this._transitions.push(id);\n }\n\n /**\n * Return a function which will set CSS styles and call the `done` function\n * when (if) the transition finishes.\n * @param {Object} opts Transition object.\n * @return {Function} A function to be called with a `done` function.\n */\n _getTransitionFunction(opts) {\n return (done) => {\n opts.item.applyCss(this.getStylesForTransition(opts));\n this._whenTransitionDone(opts.item.element, opts.callback, done);\n };\n }\n\n /**\n * Execute the styles gathered in the style queue. This applies styles to elements,\n * triggering transitions.\n * @private\n */\n _processQueue() {\n if (this.isTransitioning) {\n this._cancelMovement();\n }\n\n const hasSpeed = this.options.speed > 0;\n const hasQueue = this._queue.length > 0;\n\n if (hasQueue && hasSpeed && this.isInitialized) {\n this._startTransitions(this._queue);\n } else if (hasQueue) {\n this._styleImmediately(this._queue);\n this._dispatch(Shuffle.EventType.LAYOUT);\n\n // A call to layout happened, but none of the newly visible items will\n // change position or the transition duration is zero, which will not trigger\n // the transitionend event.\n } else {\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n // Remove everything in the style queue\n this._queue.length = 0;\n }\n\n /**\n * Wait for each transition to finish, the emit the layout event.\n * @param {Array.} transitions Array of transition objects.\n */\n _startTransitions(transitions) {\n // Set flag that shuffle is currently in motion.\n this.isTransitioning = true;\n\n // Create an array of functions to be called.\n const callbacks = transitions.map(obj => this._getTransitionFunction(obj));\n\n parallel(callbacks, this._movementFinished.bind(this));\n }\n\n _cancelMovement() {\n // Remove the transition end event for each listener.\n this._transitions.forEach(cancelTransitionEnd);\n\n // Reset the array.\n this._transitions.length = 0;\n\n // Show it's no longer active.\n this.isTransitioning = false;\n }\n\n /**\n * Apply styles without a transition.\n * @param {Array.} objects Array of transition objects.\n * @private\n */\n _styleImmediately(objects) {\n if (objects.length) {\n const elements = objects.map(obj => obj.item.element);\n\n Shuffle._skipTransitions(elements, () => {\n objects.forEach((obj) => {\n obj.item.applyCss(this.getStylesForTransition(obj));\n obj.callback();\n });\n });\n }\n }\n\n _movementFinished() {\n this._transitions.length = 0;\n this.isTransitioning = false;\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n /**\n * The magic. This is what makes the plugin 'shuffle'\n * @param {string|Function|Array.} [category] Category to filter by.\n * Can be a function, string, or array of strings.\n * @param {Object} [sortObj] A sort object which can sort the visible set\n */\n filter(category, sortObj) {\n if (!this.isEnabled) {\n return;\n }\n\n if (!category || (category && category.length === 0)) {\n category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign\n }\n\n this._filter(category);\n\n // Shrink each hidden item\n this._shrink();\n\n // How many visible elements?\n this._updateItemCount();\n\n // Update transforms on visible elements so they will animate to their new positions.\n this.sort(sortObj);\n }\n\n /**\n * Gets the visible elements, sorts them, and passes them to layout.\n * @param {Object} sortOptions The options object to pass to `sorter`.\n */\n sort(sortOptions = this.lastSort) {\n if (!this.isEnabled) {\n return;\n }\n\n this._resetCols();\n\n const items = sorter(this._getFilteredItems(), sortOptions);\n\n this._layout(items);\n\n // `_layout` always happens after `_shrink`, so it's safe to process the style\n // queue here with styles from the shrink method.\n this._processQueue();\n\n // Adjust the height of the container.\n this._setContainerSize();\n\n this.lastSort = sortOptions;\n }\n\n /**\n * Reposition everything.\n * @param {boolean} isOnlyLayout If true, column and gutter widths won't be\n * recalculated.\n */\n update(isOnlyLayout) {\n if (this.isEnabled) {\n if (!isOnlyLayout) {\n // Get updated colCount\n this._setColumns();\n }\n\n // Layout items\n this.sort();\n }\n }\n\n /**\n * Use this instead of `update()` if you don't need the columns and gutters updated\n * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations\n * could be off.\n */\n layout() {\n this.update(true);\n }\n\n /**\n * New items have been appended to shuffle. Mix them in with the current\n * filter or sort status.\n * @param {Array.} newItems Collection of new items.\n */\n add(newItems) {\n const items = arrayUnique(newItems).map(el => new ShuffleItem(el));\n\n // Add classes and set initial positions.\n this._initItems(items);\n\n // Add transition to each item.\n this.setItemTransitions(items);\n\n // Update the list of items.\n this._saveNewItems(items);\n\n // Update layout/visibility of new and old items.\n this.filter(this.lastFilter);\n }\n\n /**\n * Disables shuffle from updating dimensions and layout on resize\n */\n disable() {\n this.isEnabled = false;\n }\n\n /**\n * Enables shuffle again\n * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters\n */\n enable(isUpdateLayout = true) {\n this.isEnabled = true;\n if (isUpdateLayout) {\n this.update();\n }\n }\n\n /**\n * Remove 1 or more shuffle items\n * @param {Array.} elements An array containing one or more\n * elements in shuffle\n * @return {Shuffle} The shuffle object\n */\n remove(elements) {\n if (!elements.length) {\n return;\n }\n\n const collection = arrayUnique(elements);\n\n const oldItems = collection\n .map(element => this.getItemByElement(element))\n .filter(item => !!item);\n\n const handleLayout = () => {\n this._disposeItems(oldItems);\n\n // Remove the collection in the callback\n collection.forEach((element) => {\n element.parentNode.removeChild(element);\n });\n\n this._dispatch(Shuffle.EventType.REMOVED, { collection });\n };\n\n // Hide collection first.\n this._toggleFilterClasses({\n visible: [],\n hidden: oldItems,\n });\n\n this._shrink(oldItems);\n\n this.sort();\n\n // Update the list of items here because `remove` could be called again\n // with an item that is in the process of being removed.\n this.items = this.items.filter(item => !oldItems.includes(item));\n this._updateItemCount();\n\n this.once(Shuffle.EventType.LAYOUT, handleLayout);\n }\n\n /**\n * Retrieve a shuffle item by its element.\n * @param {Element} element Element to look for.\n * @return {?ShuffleItem} A shuffle item or null if it's not found.\n */\n getItemByElement(element) {\n return this.items.find(item => item.element === element);\n }\n\n /**\n * Dump the elements currently stored and reinitialize all child elements which\n * match the `itemSelector`.\n */\n resetItems() {\n // Remove refs to current items.\n this._disposeItems(this.items);\n this.isInitialized = false;\n\n // Find new items in the DOM.\n this.items = this._getItems();\n\n // Set initial styles on the new items.\n this._initItems(this.items);\n\n this.once(Shuffle.EventType.LAYOUT, () => {\n // Add transition to each item.\n this.setItemTransitions(this.items);\n this.isInitialized = true;\n });\n\n // Lay out all items.\n this.sort();\n }\n\n /**\n * Destroys shuffle, removes events, styles, and classes\n */\n destroy() {\n this._cancelMovement();\n window.removeEventListener('resize', this._onResize);\n\n // Reset container styles\n this.element.classList.remove('shuffle');\n this.element.removeAttribute('style');\n\n // Reset individual item styles\n this._disposeItems(this.items);\n\n this.items.length = 0;\n this._transitions.length = 0;\n\n // Null DOM references\n this.options.sizer = null;\n this.element = null;\n\n // Set a flag so if a debounced resize has been triggered,\n // it can first check if it is actually isDestroyed and not doing anything\n this.isDestroyed = true;\n this.isEnabled = false;\n }\n\n /**\n * Returns the outer width of an element, optionally including its margins.\n *\n * There are a few different methods for getting the width of an element, none of\n * which work perfectly for all Shuffle's use cases.\n *\n * 1. getBoundingClientRect() `left` and `right` properties.\n * - Accounts for transform scaled elements, making it useless for Shuffle\n * elements which have shrunk.\n * 2. The `offsetWidth` property.\n * - This value stays the same regardless of the elements transform property,\n * however, it does not return subpixel values.\n * 3. getComputedStyle()\n * - This works great Chrome, Firefox, Safari, but IE<=11 does not include\n * padding and border when box-sizing: border-box is set, requiring a feature\n * test and extra work to add the padding back for IE and other browsers which\n * follow the W3C spec here.\n *\n * @param {Element} element The element.\n * @param {boolean} [includeMargins] Whether to include margins. Default is false.\n * @return {{width: number, height: number}} The width and height.\n */\n static getSize(element, includeMargins) {\n // Store the styles so that they can be used by others without asking for it again.\n const styles = window.getComputedStyle(element, null);\n let width = getNumberStyle(element, 'width', styles);\n let height = getNumberStyle(element, 'height', styles);\n\n if (includeMargins) {\n const marginLeft = getNumberStyle(element, 'marginLeft', styles);\n const marginRight = getNumberStyle(element, 'marginRight', styles);\n const marginTop = getNumberStyle(element, 'marginTop', styles);\n const marginBottom = getNumberStyle(element, 'marginBottom', styles);\n width += marginLeft + marginRight;\n height += marginTop + marginBottom;\n }\n\n return {\n width,\n height,\n };\n }\n\n /**\n * Change a property or execute a function which will not have a transition\n * @param {Array.} elements DOM elements that won't be transitioned.\n * @param {Function} callback A function which will be called while transition\n * is set to 0ms.\n * @private\n */\n static _skipTransitions(elements, callback) {\n const zero = '0ms';\n\n // Save current duration and delay.\n const data = elements.map((element) => {\n const style = element.style;\n const duration = style.transitionDuration;\n const delay = style.transitionDelay;\n\n // Set the duration to zero so it happens immediately\n style.transitionDuration = zero;\n style.transitionDelay = zero;\n\n return {\n duration,\n delay,\n };\n });\n\n callback();\n\n // Cause forced synchronous layout.\n elements[0].offsetWidth; // eslint-disable-line no-unused-expressions\n\n // Put the duration back\n elements.forEach((element, i) => {\n element.style.transitionDuration = data[i].duration;\n element.style.transitionDelay = data[i].delay;\n });\n }\n}\n\nShuffle.ShuffleItem = ShuffleItem;\n\nShuffle.ALL_ITEMS = 'all';\nShuffle.FILTER_ATTRIBUTE_KEY = 'groups';\n\n/**\n * @enum {string}\n */\nShuffle.EventType = {\n LAYOUT: 'shuffle:layout',\n REMOVED: 'shuffle:removed',\n};\n\n/** @enum {string} */\nShuffle.Classes = Classes;\n\n/**\n * @enum {string}\n */\nShuffle.FilterMode = {\n ANY: 'any',\n ALL: 'all',\n};\n\n// Overrideable options\nShuffle.options = {\n // Initial filter group.\n group: Shuffle.ALL_ITEMS,\n\n // Transition/animation speed (milliseconds).\n speed: 250,\n\n // CSS easing function to use.\n easing: 'ease',\n\n // e.g. '.picture-item'.\n itemSelector: '*',\n\n // Element or selector string. Use an element to determine the size of columns\n // and gutters.\n sizer: null,\n\n // A static number or function that tells the plugin how wide the gutters\n // between columns are (in pixels).\n gutterWidth: 0,\n\n // A static number or function that returns a number which tells the plugin\n // how wide the columns are (in pixels).\n columnWidth: 0,\n\n // If your group is not json, and is comma delimeted, you could set delimeter\n // to ','.\n delimeter: null,\n\n // Useful for percentage based heights when they might not always be exactly\n // the same (in pixels).\n buffer: 0,\n\n // Reading the width of elements isn't precise enough and can cause columns to\n // jump between values.\n columnThreshold: 0.01,\n\n // Shuffle can be isInitialized with a sort object. It is the same object\n // given to the sort method.\n initialSort: null,\n\n // By default, shuffle will throttle resize events. This can be changed or\n // removed.\n throttle,\n\n // How often shuffle can be called on resize (in milliseconds).\n throttleTime: 300,\n\n // Transition delay offset for each item in milliseconds.\n staggerAmount: 15,\n\n // Maximum stagger delay in milliseconds.\n staggerAmountMax: 250,\n\n // Whether to use transforms or absolute positioning.\n useTransforms: true,\n\n // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With \"any\",\n // the element passes the test if any of its groups are in the array. With \"all\",\n // the element only passes if all groups are in the array.\n filterMode: Shuffle.FilterMode.ANY,\n\n // Whether to center grid items in the row with the leftover space.\n isCentered: false,\n};\n\n// Expose for testing. Hack at your own risk.\nShuffle.__Point = Point;\nShuffle.__Rect = Rect;\nShuffle.__sorter = sorter;\nShuffle.__getColumnSpan = getColumnSpan;\nShuffle.__getAvailablePositions = getAvailablePositions;\nShuffle.__getShortColumn = getShortColumn;\nShuffle.__getCenteredPositions = getCenteredPositions;\n\nexport default Shuffle;\n"],"names":["getNumber","value","parseFloat","Point","x","y","a","b","Rect","w","h","id","left","top","width","height","ShuffleItem","element","isVisible","classList","remove","Classes","HIDDEN","add","VISIBLE","removeAttribute","setAttribute","addClasses","SHUFFLE_ITEM","applyCss","Css","INITIAL","scale","Scale","point","classes","forEach","className","obj","keys","key","style","removeClasses","document","body","documentElement","e","createElement","cssText","appendChild","window","getComputedStyle","ret","removeChild","getNumberStyle","styles","COMPUTED_SIZE_INCLUDES_PADDING","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","randomize","array","n","length","i","Math","floor","random","temp","defaults","sorter","arr","options","opts","Object","assign","original","Array","from","revert","by","sort","valA","valB","undefined","reverse","transitions","eventName","count","uniqueId","cancelTransitionEnd","removeEventListener","listener","onTransitionEnd","callback","evt","currentTarget","target","addEventListener","arrayMax","max","apply","arrayMin","min","getColumnSpan","itemWidth","columnWidth","columns","threshold","columnSpan","abs","round","ceil","getAvailablePositions","positions","available","push","slice","getShortColumn","buffer","minPosition","len","getItemPosition","itemSize","gridSize","total","span","setY","shortColumnIndex","setHeight","getCenteredPositions","itemRects","containerWidth","rowMap","itemRect","rects","rows","centeredRows","lastItem","end","offset","finalRects","canMove","newRects","every","r","newRect","noOverlap","some","intersects","intersectingRect","hasOverlap","rowIndex","findIndex","items","includes","splice","concat","map","arrayUnique","Set","Shuffle","useSizer","lastSort","group","ALL_ITEMS","lastFilter","isEnabled","isDestroyed","isInitialized","_transitions","isTransitioning","_queue","el","_getElementOption","TypeError","_init","_getItems","sizer","BASE","_initItems","_onResize","_getResizeFunction","readyState","layout","bind","onLoad","containerCss","getSize","_validateStyles","_setColumns","filter","initialSort","offsetWidth","setItemTransitions","transition","speed","easing","resizeFunction","_handleResize","throttle","throttleTime","option","querySelector","nodeType","jquery","position","overflow","category","collection","set","_getFilteredSets","_toggleFilterClasses","visible","hidden","item","_doesPassFilter","call","attr","getAttribute","FILTER_ATTRIBUTE_KEY","delimeter","split","JSON","parse","testCategory","isArray","filterMode","FilterMode","ANY","show","hide","init","dispose","visibleItems","_getFilteredItems","str","useTransforms","children","matches","itemSelector","indexOf","gutterSize","size","gutterWidth","gutter","_getGutterSize","_getColumnSize","calculatedColumns","columnThreshold","cols","colWidth","_getContainerSize","index","staggerAmount","staggerAmountMax","name","data","shuffle","emit","itemPositions","_getNextPositions","currPos","currScale","nextPosition","transitionDelay","after","equals","before","_getStaggerAmount","isCentered","itemsData","_getItemPosition","getTransformedPositions","_getConcealedItems","update","transform","itemCallback","done","getStylesForTransition","_whenTransitionDone","_cancelMovement","hasSpeed","hasQueue","_startTransitions","_styleImmediately","_dispatch","EventType","LAYOUT","callbacks","_getTransitionFunction","_movementFinished","objects","elements","_skipTransitions","sortObj","_filter","_shrink","_updateItemCount","sortOptions","_resetCols","_layout","_processQueue","_setContainerSize","isOnlyLayout","newItems","_saveNewItems","isUpdateLayout","oldItems","getItemByElement","handleLayout","_disposeItems","parentNode","REMOVED","once","find","includeMargins","marginLeft","marginRight","marginTop","marginBottom","zero","duration","transitionDuration","delay","TinyEmitter","__Point","__Rect","__sorter","__getColumnSpan","__getAvailablePositions","__getShortColumn","__getCenteredPositions"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"shuffle.js","sources":["../node_modules/tiny-emitter/index.js","../node_modules/matches-selector/index.js","../node_modules/throttleit/index.js","../node_modules/array-parallel/index.js","../src/get-number.js","../src/point.js","../src/rect.js","../src/classes.js","../src/shuffle-item.js","../src/computed-size.js","../src/get-number-style.js","../src/sorter.js","../src/on-transition-end.js","../src/array-max.js","../src/array-min.js","../src/layout.js","../src/shuffle.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\n","'use strict';\n\nvar proto = typeof Element !== 'undefined' ? Element.prototype : {};\nvar vendor = proto.matches\n || proto.matchesSelector\n || proto.webkitMatchesSelector\n || proto.mozMatchesSelector\n || proto.msMatchesSelector\n || proto.oMatchesSelector;\n\nmodule.exports = match;\n\n/**\n * Match `el` to `selector`.\n *\n * @param {Element} el\n * @param {String} selector\n * @return {Boolean}\n * @api public\n */\n\nfunction match(el, selector) {\n if (!el || el.nodeType !== 1) return false;\n if (vendor) return vendor.call(el, selector);\n var nodes = el.parentNode.querySelectorAll(selector);\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i] == el) return true;\n }\n return false;\n}\n","module.exports = throttle;\n\n/**\n * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds.\n *\n * @param {Function} func Function to wrap.\n * @param {Number} wait Number of milliseconds that must elapse between `func` invocations.\n * @return {Function} A new function that wraps the `func` function passed in.\n */\n\nfunction throttle (func, wait) {\n var ctx, args, rtn, timeoutID; // caching\n var last = 0;\n\n return function throttled () {\n ctx = this;\n args = arguments;\n var delta = new Date() - last;\n if (!timeoutID)\n if (delta >= wait) call();\n else timeoutID = setTimeout(call, wait - delta);\n return rtn;\n };\n\n function call () {\n timeoutID = 0;\n last = +new Date();\n rtn = func.apply(ctx, args);\n ctx = null;\n args = null;\n }\n}\n","module.exports = function parallel(fns, context, callback) {\n if (!callback) {\n if (typeof context === 'function') {\n callback = context\n context = null\n } else {\n callback = noop\n }\n }\n\n var pending = fns && fns.length\n if (!pending) return callback(null, []);\n\n var finished = false\n var results = new Array(pending)\n\n fns.forEach(context ? function (fn, i) {\n fn.call(context, maybeDone(i))\n } : function (fn, i) {\n fn(maybeDone(i))\n })\n\n function maybeDone(i) {\n return function (err, result) {\n if (finished) return;\n\n if (err) {\n callback(err, results)\n finished = true\n return\n }\n\n results[i] = result\n\n if (!--pending) callback(null, results);\n }\n }\n}\n\nfunction noop() {}\n","/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param {*} value Possibly numeric value.\n * @return {number} `value` or zero if `value` isn't numeric.\n */\nexport default function getNumber(value) {\n return parseFloat(value) || 0;\n}\n","import getNumber from './get-number';\n\nclass Point {\n\n /**\n * Represents a coordinate pair.\n * @param {number} [x=0] X.\n * @param {number} [y=0] Y.\n */\n constructor(x, y) {\n this.x = getNumber(x);\n this.y = getNumber(y);\n }\n\n /**\n * Whether two points are equal.\n * @param {Point} a Point A.\n * @param {Point} b Point B.\n * @return {boolean}\n */\n static equals(a, b) {\n return a.x === b.x && a.y === b.y;\n }\n}\n\nexport default Point;\n","export default class Rect {\n /**\n * Class for representing rectangular regions.\n * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n * @param {number} x Left.\n * @param {number} y Top.\n * @param {number} w Width.\n * @param {number} h Height.\n * @param {number} id Identifier\n * @constructor\n */\n constructor(x, y, w, h, id) {\n this.id = id;\n\n /** @type {number} */\n this.left = x;\n\n /** @type {number} */\n this.top = y;\n\n /** @type {number} */\n this.width = w;\n\n /** @type {number} */\n this.height = h;\n }\n\n /**\n * Returns whether two rectangles intersect.\n * @param {Rect} a A Rectangle.\n * @param {Rect} b A Rectangle.\n * @return {boolean} Whether a and b intersect.\n */\n static intersects(a, b) {\n return (\n a.left < b.left + b.width && b.left < a.left + a.width &&\n a.top < b.top + b.height && b.top < a.top + a.height);\n }\n}\n","export default {\n BASE: 'shuffle',\n SHUFFLE_ITEM: 'shuffle-item',\n VISIBLE: 'shuffle-item--visible',\n HIDDEN: 'shuffle-item--hidden',\n};\n","import Point from './point';\nimport Classes from './classes';\n\nlet id = 0;\n\nclass ShuffleItem {\n constructor(element) {\n id += 1;\n this.id = id;\n this.element = element;\n this.isVisible = true;\n }\n\n show() {\n this.isVisible = true;\n this.element.classList.remove(Classes.HIDDEN);\n this.element.classList.add(Classes.VISIBLE);\n this.element.removeAttribute('aria-hidden');\n }\n\n hide() {\n this.isVisible = false;\n this.element.classList.remove(Classes.VISIBLE);\n this.element.classList.add(Classes.HIDDEN);\n this.element.setAttribute('aria-hidden', true);\n }\n\n init() {\n this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]);\n this.applyCss(ShuffleItem.Css.INITIAL);\n this.scale = ShuffleItem.Scale.VISIBLE;\n this.point = new Point();\n }\n\n addClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.add(className);\n });\n }\n\n removeClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.remove(className);\n });\n }\n\n applyCss(obj) {\n Object.keys(obj).forEach((key) => {\n this.element.style[key] = obj[key];\n });\n }\n\n dispose() {\n this.removeClasses([\n Classes.HIDDEN,\n Classes.VISIBLE,\n Classes.SHUFFLE_ITEM,\n ]);\n\n this.element.removeAttribute('style');\n this.element = null;\n }\n}\n\nShuffleItem.Css = {\n INITIAL: {\n position: 'absolute',\n top: 0,\n left: 0,\n visibility: 'visible',\n 'will-change': 'transform',\n },\n VISIBLE: {\n before: {\n opacity: 1,\n visibility: 'visible',\n },\n after: {},\n },\n HIDDEN: {\n before: {\n opacity: 0,\n },\n after: {\n visibility: 'hidden',\n },\n },\n};\n\nShuffleItem.Scale = {\n VISIBLE: 1,\n HIDDEN: 0.001,\n};\n\nexport default ShuffleItem;\n","const element = document.body || document.documentElement;\nconst e = document.createElement('div');\ne.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\nelement.appendChild(e);\n\nconst width = window.getComputedStyle(e, null).width;\nconst ret = width === '10px';\n\nelement.removeChild(e);\n\nexport default ret;\n","import getNumber from './get-number';\nimport COMPUTED_SIZE_INCLUDES_PADDING from './computed-size';\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param {Element} element Element to get style for.\n * @param {string} style Style property.\n * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to\n * use instead of asking for them again.\n * @return {number} The parsed computed value or zero if that fails because IE\n * will return 'auto' when the element doesn't have margins instead of\n * the computed style.\n */\nexport default function getNumberStyle(element, style,\n styles = window.getComputedStyle(element, null)) {\n let value = getNumber(styles[style]);\n\n // Support IE<=11 and W3C spec.\n if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'width') {\n value += getNumber(styles.paddingLeft) +\n getNumber(styles.paddingRight) +\n getNumber(styles.borderLeftWidth) +\n getNumber(styles.borderRightWidth);\n } else if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'height') {\n value += getNumber(styles.paddingTop) +\n getNumber(styles.paddingBottom) +\n getNumber(styles.borderTopWidth) +\n getNumber(styles.borderBottomWidth);\n }\n\n return value;\n}\n","/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param {Array} array Array to shuffle.\n * @return {Array} Randomly sorted array.\n */\nfunction randomize(array) {\n let n = array.length;\n\n while (n) {\n n -= 1;\n const i = Math.floor(Math.random() * (n + 1));\n const temp = array[i];\n array[i] = array[n];\n array[n] = temp;\n }\n\n return array;\n}\n\nconst defaults = {\n // Use array.reverse() to reverse the results\n reverse: false,\n\n // Sorting function\n by: null,\n\n // If true, this will skip the sorting and return a randomized order in the array\n randomize: false,\n\n // Determines which property of each item in the array is passed to the\n // sorting method.\n key: 'element',\n};\n\n// You can return `undefined` from the `by` function to revert to DOM order.\nexport default function sorter(arr, options) {\n const opts = Object.assign({}, defaults, options);\n const original = Array.from(arr);\n let revert = false;\n\n if (!arr.length) {\n return [];\n }\n\n if (opts.randomize) {\n return randomize(arr);\n }\n\n // Sort the elements by the opts.by function.\n // If we don't have opts.by, default to DOM order\n if (typeof opts.by === 'function') {\n arr.sort((a, b) => {\n // Exit early if we already know we want to revert\n if (revert) {\n return 0;\n }\n\n const valA = opts.by(a[opts.key]);\n const valB = opts.by(b[opts.key]);\n\n // If both values are undefined, use the DOM order\n if (valA === undefined && valB === undefined) {\n revert = true;\n return 0;\n }\n\n if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {\n return -1;\n }\n\n if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {\n return 1;\n }\n\n return 0;\n });\n }\n\n // Revert to the original array if necessary\n if (revert) {\n return original;\n }\n\n if (opts.reverse) {\n arr.reverse();\n }\n\n return arr;\n}\n","const transitions = {};\nconst eventName = 'transitionend';\nlet count = 0;\n\nfunction uniqueId() {\n count += 1;\n return eventName + count;\n}\n\nexport function cancelTransitionEnd(id) {\n if (transitions[id]) {\n transitions[id].element.removeEventListener(eventName, transitions[id].listener);\n transitions[id] = null;\n return true;\n }\n\n return false;\n}\n\nexport function onTransitionEnd(element, callback) {\n const id = uniqueId();\n const listener = (evt) => {\n if (evt.currentTarget === evt.target) {\n cancelTransitionEnd(id);\n callback(evt);\n }\n };\n\n element.addEventListener(eventName, listener);\n\n transitions[id] = { element, listener };\n\n return id;\n}\n","export default function arrayMax(array) {\n return Math.max.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","export default function arrayMin(array) {\n return Math.min.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","import Point from './point';\nimport Rect from './rect';\nimport arrayMax from './array-max';\nimport arrayMin from './array-min';\n\n/**\n * Determine the number of columns an items spans.\n * @param {number} itemWidth Width of the item.\n * @param {number} columnWidth Width of the column (includes gutter).\n * @param {number} columns Total number of columns\n * @param {number} threshold A buffer value for the size of the column to fit.\n * @return {number}\n */\nexport function getColumnSpan(itemWidth, columnWidth, columns, threshold) {\n let columnSpan = itemWidth / columnWidth;\n\n // If the difference between the rounded column span number and the\n // calculated column span number is really small, round the number to\n // make it fit.\n if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {\n // e.g. columnSpan = 4.0089945390298745\n columnSpan = Math.round(columnSpan);\n }\n\n // Ensure the column span is not more than the amount of columns in the whole layout.\n return Math.min(Math.ceil(columnSpan), columns);\n}\n\n/**\n * Retrieves the column set to use for placement.\n * @param {number} columnSpan The number of columns this current item spans.\n * @param {number} columns The total columns in the grid.\n * @return {Array.} An array of numbers represeting the column set.\n */\nexport function getAvailablePositions(positions, columnSpan, columns) {\n // The item spans only one column.\n if (columnSpan === 1) {\n return positions;\n }\n\n // The item spans more than one column, figure out how many different\n // places it could fit horizontally.\n // The group count is the number of places within the positions this block\n // could fit, ignoring the current positions of items.\n // Imagine a 2 column brick as the second item in a 4 column grid with\n // 10px height each. Find the places it would fit:\n // [20, 10, 10, 0]\n // | | |\n // * * *\n //\n // Then take the places which fit and get the bigger of the two:\n // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]\n //\n // Next, find the first smallest number (the short column).\n // [20, 10, 0]\n // |\n // *\n //\n // And that's where it should be placed!\n //\n // Another example where the second column's item extends past the first:\n // [10, 20, 10, 0] => [20, 20, 10] => 10\n const available = [];\n\n // For how many possible positions for this item there are.\n for (let i = 0; i <= columns - columnSpan; i++) {\n // Find the bigger value for each place it could fit.\n available.push(arrayMax(positions.slice(i, i + columnSpan)));\n }\n\n return available;\n}\n\n/**\n * Find index of short column, the first from the left where this item will go.\n *\n * @param {Array.} positions The array to search for the smallest number.\n * @param {number} buffer Optional buffer which is very useful when the height\n * is a percentage of the width.\n * @return {number} Index of the short column.\n */\nexport function getShortColumn(positions, buffer) {\n const minPosition = arrayMin(positions);\n for (let i = 0, len = positions.length; i < len; i++) {\n if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n return i;\n }\n }\n\n return 0;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param {Object} itemSize Object with width and height.\n * @param {Array.} positions Positions of the other current items.\n * @param {number} gridSize The column width or row height.\n * @param {number} total The total number of columns or rows.\n * @param {number} threshold Buffer value for the column to fit.\n * @param {number} buffer Vertical buffer for the height of items.\n * @return {Point}\n */\nexport function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {\n const span = getColumnSpan(itemSize.width, gridSize, total, threshold);\n const setY = getAvailablePositions(positions, span, total);\n const shortColumnIndex = getShortColumn(setY, buffer);\n\n // Position the item\n const point = new Point(\n Math.round(gridSize * shortColumnIndex),\n Math.round(setY[shortColumnIndex]));\n\n // Update the columns array with the new values for each column.\n // e.g. before the update the columns could be [250, 0, 0, 0] for an item\n // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].\n const setHeight = setY[shortColumnIndex] + itemSize.height;\n for (let i = 0; i < span; i++) {\n positions[shortColumnIndex + i] = setHeight;\n }\n\n return point;\n}\n\n/**\n * This method attempts to center items. This method could potentially be slow\n * with a large number of items because it must place items, then check every\n * previous item to ensure there is no overlap.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n */\nexport function getCenteredPositions(itemRects, containerWidth) {\n const rowMap = {};\n\n // Populate rows by their offset because items could jump between rows like:\n // a c\n // bbb\n itemRects.forEach((itemRect) => {\n if (rowMap[itemRect.top]) {\n // Push the point to the last row array.\n rowMap[itemRect.top].push(itemRect);\n } else {\n // Start of a new row.\n rowMap[itemRect.top] = [itemRect];\n }\n });\n\n // For each row, find the end of the last item, then calculate\n // the remaining space by dividing it by 2. Then add that\n // offset to the x position of each point.\n let rects = [];\n const rows = [];\n const centeredRows = [];\n Object.keys(rowMap).forEach((key) => {\n const itemRects = rowMap[key];\n rows.push(itemRects);\n const lastItem = itemRects[itemRects.length - 1];\n const end = lastItem.left + lastItem.width;\n const offset = Math.round((containerWidth - end) / 2);\n\n let finalRects = itemRects;\n let canMove = false;\n if (offset > 0) {\n const newRects = [];\n canMove = itemRects.every((r) => {\n const newRect = new Rect(r.left + offset, r.top, r.width, r.height, r.id);\n\n // Check all current rects to make sure none overlap.\n const noOverlap = !rects.some(r => Rect.intersects(newRect, r));\n\n newRects.push(newRect);\n return noOverlap;\n });\n\n // If none of the rectangles overlapped, the whole group can be centered.\n if (canMove) {\n finalRects = newRects;\n }\n }\n\n // If the items are not going to be offset, ensure that the original\n // placement for this row will not overlap previous rows (row-spanning\n // elements could be in the way).\n if (!canMove) {\n let intersectingRect;\n const hasOverlap = itemRects.some(itemRect => rects.some((r) => {\n const intersects = Rect.intersects(itemRect, r);\n if (intersects) {\n intersectingRect = r;\n }\n return intersects;\n }));\n\n // If there is any overlap, replace the overlapping row with the original.\n if (hasOverlap) {\n const rowIndex = centeredRows.findIndex(items => items.includes(intersectingRect));\n centeredRows.splice(rowIndex, 1, rows[rowIndex]);\n }\n }\n\n rects = rects.concat(finalRects);\n centeredRows.push(finalRects);\n });\n\n // Reduce array of arrays to a single array of points.\n // https://stackoverflow.com/a/10865042/373422\n // Then reset sort back to how the items were passed to this method.\n // Remove the wrapper object with index, map to a Point.\n return [].concat.apply([], centeredRows) // eslint-disable-line prefer-spread\n .sort((a, b) => (a.id - b.id))\n .map(itemRect => new Point(itemRect.left, itemRect.top));\n}\n","import TinyEmitter from 'tiny-emitter';\nimport matches from 'matches-selector';\nimport throttle from 'throttleit';\nimport parallel from 'array-parallel';\n\nimport Point from './point';\nimport Rect from './rect';\nimport ShuffleItem from './shuffle-item';\nimport Classes from './classes';\nimport getNumberStyle from './get-number-style';\nimport sorter from './sorter';\nimport { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';\nimport {\n getItemPosition,\n getColumnSpan,\n getAvailablePositions,\n getShortColumn,\n getCenteredPositions,\n} from './layout';\nimport arrayMax from './array-max';\n\nfunction arrayUnique(x) {\n return Array.from(new Set(x));\n}\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n\n /**\n * Categorize, sort, and filter a responsive grid of items.\n *\n * @param {Element} element An element which is the parent container for the grid items.\n * @param {Object} [options=Shuffle.options] Options object.\n * @constructor\n */\n constructor(element, options = {}) {\n super();\n this.options = Object.assign({}, Shuffle.options, options);\n\n this.lastSort = {};\n this.group = Shuffle.ALL_ITEMS;\n this.lastFilter = Shuffle.ALL_ITEMS;\n this.isEnabled = true;\n this.isDestroyed = false;\n this.isInitialized = false;\n this._transitions = [];\n this.isTransitioning = false;\n this._queue = [];\n\n const el = this._getElementOption(element);\n\n if (!el) {\n throw new TypeError('Shuffle needs to be initialized with an element.');\n }\n\n this.element = el;\n this.id = 'shuffle_' + id;\n id += 1;\n\n this._init();\n this.isInitialized = true;\n }\n\n _init() {\n this.items = this._getItems();\n\n this.options.sizer = this._getElementOption(this.options.sizer);\n\n // Add class and invalidate styles\n this.element.classList.add(Shuffle.Classes.BASE);\n\n // Set initial css for each item\n this._initItems(this.items);\n\n // Bind resize events\n this._onResize = this._getResizeFunction();\n window.addEventListener('resize', this._onResize);\n\n // If the page has not already emitted the `load` event, call layout on load.\n // This avoids layout issues caused by images and fonts loading after the\n // instance has been initialized.\n if (document.readyState !== 'complete') {\n const layout = this.layout.bind(this);\n window.addEventListener('load', function onLoad() {\n window.removeEventListener('load', onLoad);\n layout();\n });\n }\n\n // Get container css all in one request. Causes reflow\n const containerCss = window.getComputedStyle(this.element, null);\n const containerWidth = Shuffle.getSize(this.element).width;\n\n // Add styles to the container if it doesn't have them.\n this._validateStyles(containerCss);\n\n // We already got the container's width above, no need to cause another\n // reflow getting it again... Calculate the number of columns there will be\n this._setColumns(containerWidth);\n\n // Kick off!\n this.filter(this.options.group, this.options.initialSort);\n\n // The shuffle items haven't had transitions set on them yet so the user\n // doesn't see the first layout. Set them now that the first layout is done.\n // First, however, a synchronous layout must be caused for the previous\n // styles to be applied without transitions.\n this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n this.setItemTransitions(this.items);\n this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;\n }\n\n /**\n * Returns a throttled and proxied function for the resize handler.\n * @return {Function}\n * @private\n */\n _getResizeFunction() {\n const resizeFunction = this._handleResize.bind(this);\n return this.options.throttle ?\n this.options.throttle(resizeFunction, this.options.throttleTime) :\n resizeFunction;\n }\n\n /**\n * Retrieve an element from an option.\n * @param {string|jQuery|Element} option The option to check.\n * @return {?Element} The plain element or null.\n * @private\n */\n _getElementOption(option) {\n // If column width is a string, treat is as a selector and search for the\n // sizer element within the outermost container\n if (typeof option === 'string') {\n return this.element.querySelector(option);\n\n // Check for an element\n } else if (option && option.nodeType && option.nodeType === 1) {\n return option;\n\n // Check for jQuery object\n } else if (option && option.jquery) {\n return option[0];\n }\n\n return null;\n }\n\n /**\n * Ensures the shuffle container has the css styles it needs applied to it.\n * @param {Object} styles Key value pairs for position and overflow.\n * @private\n */\n _validateStyles(styles) {\n // Position cannot be static.\n if (styles.position === 'static') {\n this.element.style.position = 'relative';\n }\n\n // Overflow has to be hidden.\n if (styles.overflow !== 'hidden') {\n this.element.style.overflow = 'hidden';\n }\n }\n\n /**\n * Filter the elements by a category.\n * @param {string} [category] Category to filter by. If it's given, the last\n * category will be used to filter the items.\n * @param {Array} [collection] Optionally filter a collection. Defaults to\n * all the items.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _filter(category = this.lastFilter, collection = this.items) {\n const set = this._getFilteredSets(category, collection);\n\n // Individually add/remove hidden/visible classes\n this._toggleFilterClasses(set);\n\n // Save the last filter in case elements are appended.\n this.lastFilter = category;\n\n // This is saved mainly because providing a filter function (like searching)\n // will overwrite the `lastFilter` property every time its called.\n if (typeof category === 'string') {\n this.group = category;\n }\n\n return set;\n }\n\n /**\n * Returns an object containing the visible and hidden elements.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element[]} items A collection of items to filter.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _getFilteredSets(category, items) {\n let visible = [];\n const hidden = [];\n\n // category === 'all', add visible class to everything\n if (category === Shuffle.ALL_ITEMS) {\n visible = items;\n\n // Loop through each item and use provided function to determine\n // whether to hide it or not.\n } else {\n items.forEach((item) => {\n if (this._doesPassFilter(category, item.element)) {\n visible.push(item);\n } else {\n hidden.push(item);\n }\n });\n }\n\n return {\n visible,\n hidden,\n };\n }\n\n /**\n * Test an item to see if it passes a category.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element} element An element to test.\n * @return {boolean} Whether it passes the category/filter.\n * @private\n */\n _doesPassFilter(category, element) {\n if (typeof category === 'function') {\n return category.call(element, element, this);\n }\n\n // Check each element's data-groups attribute against the given category.\n const attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY);\n const keys = this.options.delimeter ?\n attr.split(this.options.delimeter) :\n JSON.parse(attr);\n\n function testCategory(category) {\n return keys.includes(category);\n }\n\n if (Array.isArray(category)) {\n if (this.options.filterMode === Shuffle.FilterMode.ANY) {\n return category.some(testCategory);\n }\n return category.every(testCategory);\n }\n\n return keys.includes(category);\n }\n\n /**\n * Toggles the visible and hidden class names.\n * @param {{visible, hidden}} Object with visible and hidden arrays.\n * @private\n */\n _toggleFilterClasses({ visible, hidden }) {\n visible.forEach((item) => {\n item.show();\n });\n\n hidden.forEach((item) => {\n item.hide();\n });\n }\n\n /**\n * Set the initial css for each item\n * @param {ShuffleItem[]} items Set to initialize.\n * @private\n */\n _initItems(items) {\n items.forEach((item) => {\n item.init();\n });\n }\n\n /**\n * Remove element reference and styles.\n * @param {ShuffleItem[]} items Set to dispose.\n * @private\n */\n _disposeItems(items) {\n items.forEach((item) => {\n item.dispose();\n });\n }\n\n /**\n * Updates the visible item count.\n * @private\n */\n _updateItemCount() {\n this.visibleItems = this._getFilteredItems().length;\n }\n\n /**\n * Sets css transform transition on a group of elements. This is not executed\n * at the same time as `item.init` so that transitions don't occur upon\n * initialization of Shuffle.\n * @param {ShuffleItem[]} items Shuffle items to set transitions on.\n * @protected\n */\n setItemTransitions(items) {\n const speed = this.options.speed;\n const easing = this.options.easing;\n\n const str = this.options.useTransforms ?\n `transform ${speed}ms ${easing}, opacity ${speed}ms ${easing}` :\n `top ${speed}ms ${easing}, left ${speed}ms ${easing}, opacity ${speed}ms ${easing}`;\n\n items.forEach((item) => {\n item.element.style.transition = str;\n });\n }\n\n _getItems() {\n return Array.from(this.element.children)\n .filter(el => matches(el, this.options.itemSelector))\n .map(el => new ShuffleItem(el));\n }\n\n /**\n * When new elements are added to the shuffle container, update the array of\n * items because that is the order `_layout` calls them.\n * @param {ShuffleItem[]} items Items to track.\n */\n _saveNewItems(items) {\n const children = Array.from(this.element.children);\n this.items = sorter(this.items.concat(items), {\n by(element) {\n return children.indexOf(element);\n },\n });\n }\n\n _getFilteredItems() {\n return this.items.filter(item => item.isVisible);\n }\n\n _getConcealedItems() {\n return this.items.filter(item => !item.isVisible);\n }\n\n /**\n * Returns the column size, based on column width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @param {number} gutterSize Size of the gutters.\n * @return {number}\n * @private\n */\n _getColumnSize(containerWidth, gutterSize) {\n let size;\n\n // If the columnWidth property is a function, then the grid is fluid\n if (typeof this.options.columnWidth === 'function') {\n size = this.options.columnWidth(containerWidth);\n\n // columnWidth option isn't a function, are they using a sizing element?\n } else if (this.options.sizer) {\n size = Shuffle.getSize(this.options.sizer).width;\n\n // if not, how about the explicitly set option?\n } else if (this.options.columnWidth) {\n size = this.options.columnWidth;\n\n // or use the size of the first item\n } else if (this.items.length > 0) {\n size = Shuffle.getSize(this.items[0].element, true).width;\n\n // if there's no items, use size of container\n } else {\n size = containerWidth;\n }\n\n // Don't let them set a column width of zero.\n if (size === 0) {\n size = containerWidth;\n }\n\n return size + gutterSize;\n }\n\n /**\n * Returns the gutter size, based on gutter width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @return {number}\n * @private\n */\n _getGutterSize(containerWidth) {\n let size;\n if (typeof this.options.gutterWidth === 'function') {\n size = this.options.gutterWidth(containerWidth);\n } else if (this.options.sizer) {\n size = getNumberStyle(this.options.sizer, 'marginLeft');\n } else {\n size = this.options.gutterWidth;\n }\n\n return size;\n }\n\n /**\n * Calculate the number of columns to be used. Gets css if using sizer element.\n * @param {number} [containerWidth] Optionally specify a container width if\n * it's already available.\n */\n _setColumns(containerWidth = Shuffle.getSize(this.element).width) {\n const gutter = this._getGutterSize(containerWidth);\n const columnWidth = this._getColumnSize(containerWidth, gutter);\n let calculatedColumns = (containerWidth + gutter) / columnWidth;\n\n // Widths given from getStyles are not precise enough...\n if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) <\n this.options.columnThreshold) {\n // e.g. calculatedColumns = 11.998876\n calculatedColumns = Math.round(calculatedColumns);\n }\n\n this.cols = Math.max(Math.floor(calculatedColumns), 1);\n this.containerWidth = containerWidth;\n this.colWidth = columnWidth;\n }\n\n /**\n * Adjust the height of the grid\n */\n _setContainerSize() {\n this.element.style.height = this._getContainerSize() + 'px';\n }\n\n /**\n * Based on the column heights, it returns the biggest one.\n * @return {number}\n * @private\n */\n _getContainerSize() {\n return arrayMax(this.positions);\n }\n\n /**\n * Get the clamped stagger amount.\n * @param {number} index Index of the item to be staggered.\n * @return {number}\n */\n _getStaggerAmount(index) {\n return Math.min(index * this.options.staggerAmount, this.options.staggerAmountMax);\n }\n\n /**\n * Emit an event from this instance.\n * @param {string} name Event name.\n * @param {Object} [data={}] Optional object data.\n */\n _dispatch(name, data = {}) {\n if (this.isDestroyed) {\n return;\n }\n\n data.shuffle = this;\n this.emit(name, data);\n }\n\n /**\n * Zeros out the y columns array, which is used to determine item placement.\n * @private\n */\n _resetCols() {\n let i = this.cols;\n this.positions = [];\n while (i) {\n i -= 1;\n this.positions.push(0);\n }\n }\n\n /**\n * Loops through each item that should be shown and calculates the x, y position.\n * @param {ShuffleItem[]} items Array of items that will be shown/layed\n * out in order in their array.\n */\n _layout(items) {\n const itemPositions = this._getNextPositions(items);\n\n let count = 0;\n items.forEach((item, i) => {\n const currPos = item.point;\n const currScale = item.scale;\n const nextPosition = itemPositions[i];\n\n function callback() {\n item.element.style.transitionDelay = '';\n item.applyCss(ShuffleItem.Css.VISIBLE.after);\n }\n\n // If the item will not change its position, do not add it to the render\n // queue. Transitions don't fire when setting a property to the same value.\n if (Point.equals(currPos, nextPosition) && currScale === ShuffleItem.Scale.VISIBLE) {\n item.applyCss(ShuffleItem.Css.VISIBLE.before);\n callback();\n return;\n }\n\n item.point = nextPosition;\n item.scale = ShuffleItem.Scale.VISIBLE;\n\n // Clone the object so that the `before` object isn't modified when the\n // transition delay is added.\n const styles = Object.assign({}, ShuffleItem.Css.VISIBLE.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Return an array of Point instances representing the future positions of\n * each item.\n * @param {ShuffleItem[]} items Array of sorted shuffle items.\n * @return {Point[]}\n * @private\n */\n _getNextPositions(items) {\n // If position data is going to be changed, add the item's size to the\n // transformer to allow for calculations.\n if (this.options.isCentered) {\n const itemsData = items.map((item, i) => {\n const itemSize = Shuffle.getSize(item.element, true);\n const point = this._getItemPosition(itemSize);\n return new Rect(point.x, point.y, itemSize.width, itemSize.height, i);\n });\n\n return this.getTransformedPositions(itemsData, this.containerWidth);\n }\n\n // If no transforms are going to happen, simply return an array of the\n // future points of each item.\n return items.map(item => this._getItemPosition(Shuffle.getSize(item.element, true)));\n }\n\n /**\n * Determine the location of the next item, based on its size.\n * @param {{width: number, height: number}} itemSize Object with width and height.\n * @return {Point}\n * @private\n */\n _getItemPosition(itemSize) {\n return getItemPosition({\n itemSize,\n positions: this.positions,\n gridSize: this.colWidth,\n total: this.cols,\n threshold: this.options.columnThreshold,\n buffer: this.options.buffer,\n });\n }\n\n /**\n * Mutate positions before they're applied.\n * @param {Rect[]} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Point[]}\n * @protected\n */\n getTransformedPositions(itemRects, containerWidth) {\n return getCenteredPositions(itemRects, containerWidth);\n }\n\n /**\n * Hides the elements that don't match our filter.\n * @param {ShuffleItem[]} collection Collection to shrink.\n * @private\n */\n _shrink(collection = this._getConcealedItems()) {\n let count = 0;\n collection.forEach((item) => {\n function callback() {\n item.applyCss(ShuffleItem.Css.HIDDEN.after);\n }\n\n // Continuing would add a transitionend event listener to the element, but\n // that listener would not execute because the transform and opacity would\n // stay the same.\n // The callback is executed here because it is not guaranteed to be called\n // after the transitionend event because the transitionend could be\n // canceled if another animation starts.\n if (item.scale === ShuffleItem.Scale.HIDDEN) {\n item.applyCss(ShuffleItem.Css.HIDDEN.before);\n callback();\n return;\n }\n\n item.scale = ShuffleItem.Scale.HIDDEN;\n\n const styles = Object.assign({}, ShuffleItem.Css.HIDDEN.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Resize handler.\n * @private\n */\n _handleResize() {\n // If shuffle is disabled, destroyed, don't do anything\n if (!this.isEnabled || this.isDestroyed) {\n return;\n }\n\n this.update();\n }\n\n /**\n * Returns styles which will be applied to the an item for a transition.\n * @param {Object} obj Transition options.\n * @return {!Object} Transforms for transitions, left/top for animate.\n * @protected\n */\n getStylesForTransition({ item, styles }) {\n if (!styles.transitionDelay) {\n styles.transitionDelay = '0ms';\n }\n\n const x = item.point.x;\n const y = item.point.y;\n\n if (this.options.useTransforms) {\n styles.transform = `translate(${x}px, ${y}px) scale(${item.scale})`;\n } else {\n styles.left = x + 'px';\n styles.top = y + 'px';\n }\n\n return styles;\n }\n\n /**\n * Listen for the transition end on an element and execute the itemCallback\n * when it finishes.\n * @param {Element} element Element to listen on.\n * @param {Function} itemCallback Callback for the item.\n * @param {Function} done Callback to notify `parallel` that this one is done.\n */\n _whenTransitionDone(element, itemCallback, done) {\n const id = onTransitionEnd(element, (evt) => {\n itemCallback();\n done(null, evt);\n });\n\n this._transitions.push(id);\n }\n\n /**\n * Return a function which will set CSS styles and call the `done` function\n * when (if) the transition finishes.\n * @param {Object} opts Transition object.\n * @return {Function} A function to be called with a `done` function.\n */\n _getTransitionFunction(opts) {\n return (done) => {\n opts.item.applyCss(this.getStylesForTransition(opts));\n this._whenTransitionDone(opts.item.element, opts.callback, done);\n };\n }\n\n /**\n * Execute the styles gathered in the style queue. This applies styles to elements,\n * triggering transitions.\n * @private\n */\n _processQueue() {\n if (this.isTransitioning) {\n this._cancelMovement();\n }\n\n const hasSpeed = this.options.speed > 0;\n const hasQueue = this._queue.length > 0;\n\n if (hasQueue && hasSpeed && this.isInitialized) {\n this._startTransitions(this._queue);\n } else if (hasQueue) {\n this._styleImmediately(this._queue);\n this._dispatch(Shuffle.EventType.LAYOUT);\n\n // A call to layout happened, but none of the newly visible items will\n // change position or the transition duration is zero, which will not trigger\n // the transitionend event.\n } else {\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n // Remove everything in the style queue\n this._queue.length = 0;\n }\n\n /**\n * Wait for each transition to finish, the emit the layout event.\n * @param {Object[]} transitions Array of transition objects.\n */\n _startTransitions(transitions) {\n // Set flag that shuffle is currently in motion.\n this.isTransitioning = true;\n\n // Create an array of functions to be called.\n const callbacks = transitions.map(obj => this._getTransitionFunction(obj));\n\n parallel(callbacks, this._movementFinished.bind(this));\n }\n\n _cancelMovement() {\n // Remove the transition end event for each listener.\n this._transitions.forEach(cancelTransitionEnd);\n\n // Reset the array.\n this._transitions.length = 0;\n\n // Show it's no longer active.\n this.isTransitioning = false;\n }\n\n /**\n * Apply styles without a transition.\n * @param {Object[]} objects Array of transition objects.\n * @private\n */\n _styleImmediately(objects) {\n if (objects.length) {\n const elements = objects.map(obj => obj.item.element);\n\n Shuffle._skipTransitions(elements, () => {\n objects.forEach((obj) => {\n obj.item.applyCss(this.getStylesForTransition(obj));\n obj.callback();\n });\n });\n }\n }\n\n _movementFinished() {\n this._transitions.length = 0;\n this.isTransitioning = false;\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n /**\n * The magic. This is what makes the plugin 'shuffle'\n * @param {string|Function|string[]} [category] Category to filter by.\n * Can be a function, string, or array of strings.\n * @param {Object} [sortObj] A sort object which can sort the visible set\n */\n filter(category, sortObj) {\n if (!this.isEnabled) {\n return;\n }\n\n if (!category || (category && category.length === 0)) {\n category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign\n }\n\n this._filter(category);\n\n // Shrink each hidden item\n this._shrink();\n\n // How many visible elements?\n this._updateItemCount();\n\n // Update transforms on visible elements so they will animate to their new positions.\n this.sort(sortObj);\n }\n\n /**\n * Gets the visible elements, sorts them, and passes them to layout.\n * @param {Object} sortOptions The options object to pass to `sorter`.\n */\n sort(sortOptions = this.lastSort) {\n if (!this.isEnabled) {\n return;\n }\n\n this._resetCols();\n\n const items = sorter(this._getFilteredItems(), sortOptions);\n\n this._layout(items);\n\n // `_layout` always happens after `_shrink`, so it's safe to process the style\n // queue here with styles from the shrink method.\n this._processQueue();\n\n // Adjust the height of the container.\n this._setContainerSize();\n\n this.lastSort = sortOptions;\n }\n\n /**\n * Reposition everything.\n * @param {boolean} [isOnlyLayout=false] If true, column and gutter widths won't be recalculated.\n */\n update(isOnlyLayout = false) {\n if (this.isEnabled) {\n if (!isOnlyLayout) {\n // Get updated colCount\n this._setColumns();\n }\n\n // Layout items\n this.sort();\n }\n }\n\n /**\n * Use this instead of `update()` if you don't need the columns and gutters updated\n * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations\n * could be off.\n */\n layout() {\n this.update(true);\n }\n\n /**\n * New items have been appended to shuffle. Mix them in with the current\n * filter or sort status.\n * @param {Element[]} newItems Collection of new items.\n */\n add(newItems) {\n const items = arrayUnique(newItems).map(el => new ShuffleItem(el));\n\n // Add classes and set initial positions.\n this._initItems(items);\n\n // Add transition to each item.\n this.setItemTransitions(items);\n\n // Update the list of items.\n this._saveNewItems(items);\n\n // Update layout/visibility of new and old items.\n this.filter(this.lastFilter);\n }\n\n /**\n * Disables shuffle from updating dimensions and layout on resize\n */\n disable() {\n this.isEnabled = false;\n }\n\n /**\n * Enables shuffle again\n * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters\n */\n enable(isUpdateLayout = true) {\n this.isEnabled = true;\n if (isUpdateLayout) {\n this.update();\n }\n }\n\n /**\n * Remove 1 or more shuffle items.\n * @param {Element[]} elements An array containing one or more\n * elements in shuffle\n * @return {Shuffle} The shuffle instance.\n */\n remove(elements) {\n if (!elements.length) {\n return;\n }\n\n const collection = arrayUnique(elements);\n\n const oldItems = collection\n .map(element => this.getItemByElement(element))\n .filter(item => !!item);\n\n const handleLayout = () => {\n this._disposeItems(oldItems);\n\n // Remove the collection in the callback\n collection.forEach((element) => {\n element.parentNode.removeChild(element);\n });\n\n this._dispatch(Shuffle.EventType.REMOVED, { collection });\n };\n\n // Hide collection first.\n this._toggleFilterClasses({\n visible: [],\n hidden: oldItems,\n });\n\n this._shrink(oldItems);\n\n this.sort();\n\n // Update the list of items here because `remove` could be called again\n // with an item that is in the process of being removed.\n this.items = this.items.filter(item => !oldItems.includes(item));\n this._updateItemCount();\n\n this.once(Shuffle.EventType.LAYOUT, handleLayout);\n }\n\n /**\n * Retrieve a shuffle item by its element.\n * @param {Element} element Element to look for.\n * @return {?ShuffleItem} A shuffle item or undefined if it's not found.\n */\n getItemByElement(element) {\n return this.items.find(item => item.element === element);\n }\n\n /**\n * Dump the elements currently stored and reinitialize all child elements which\n * match the `itemSelector`.\n */\n resetItems() {\n // Remove refs to current items.\n this._disposeItems(this.items);\n this.isInitialized = false;\n\n // Find new items in the DOM.\n this.items = this._getItems();\n\n // Set initial styles on the new items.\n this._initItems(this.items);\n\n this.once(Shuffle.EventType.LAYOUT, () => {\n // Add transition to each item.\n this.setItemTransitions(this.items);\n this.isInitialized = true;\n });\n\n // Lay out all items.\n this.sort();\n }\n\n /**\n * Destroys shuffle, removes events, styles, and classes\n */\n destroy() {\n this._cancelMovement();\n window.removeEventListener('resize', this._onResize);\n\n // Reset container styles\n this.element.classList.remove('shuffle');\n this.element.removeAttribute('style');\n\n // Reset individual item styles\n this._disposeItems(this.items);\n\n this.items.length = 0;\n this._transitions.length = 0;\n\n // Null DOM references\n this.options.sizer = null;\n this.element = null;\n\n // Set a flag so if a debounced resize has been triggered,\n // it can first check if it is actually isDestroyed and not doing anything\n this.isDestroyed = true;\n this.isEnabled = false;\n }\n\n /**\n * Returns the outer width of an element, optionally including its margins.\n *\n * There are a few different methods for getting the width of an element, none of\n * which work perfectly for all Shuffle's use cases.\n *\n * 1. getBoundingClientRect() `left` and `right` properties.\n * - Accounts for transform scaled elements, making it useless for Shuffle\n * elements which have shrunk.\n * 2. The `offsetWidth` property.\n * - This value stays the same regardless of the elements transform property,\n * however, it does not return subpixel values.\n * 3. getComputedStyle()\n * - This works great Chrome, Firefox, Safari, but IE<=11 does not include\n * padding and border when box-sizing: border-box is set, requiring a feature\n * test and extra work to add the padding back for IE and other browsers which\n * follow the W3C spec here.\n *\n * @param {Element} element The element.\n * @param {boolean} [includeMargins=false] Whether to include margins.\n * @return {{width: number, height: number}} The width and height.\n */\n static getSize(element, includeMargins = false) {\n // Store the styles so that they can be used by others without asking for it again.\n const styles = window.getComputedStyle(element, null);\n let width = getNumberStyle(element, 'width', styles);\n let height = getNumberStyle(element, 'height', styles);\n\n if (includeMargins) {\n const marginLeft = getNumberStyle(element, 'marginLeft', styles);\n const marginRight = getNumberStyle(element, 'marginRight', styles);\n const marginTop = getNumberStyle(element, 'marginTop', styles);\n const marginBottom = getNumberStyle(element, 'marginBottom', styles);\n width += marginLeft + marginRight;\n height += marginTop + marginBottom;\n }\n\n return {\n width,\n height,\n };\n }\n\n /**\n * Change a property or execute a function which will not have a transition\n * @param {Element[]} elements DOM elements that won't be transitioned.\n * @param {Function} callback A function which will be called while transition\n * is set to 0ms.\n * @private\n */\n static _skipTransitions(elements, callback) {\n const zero = '0ms';\n\n // Save current duration and delay.\n const data = elements.map((element) => {\n const style = element.style;\n const duration = style.transitionDuration;\n const delay = style.transitionDelay;\n\n // Set the duration to zero so it happens immediately\n style.transitionDuration = zero;\n style.transitionDelay = zero;\n\n return {\n duration,\n delay,\n };\n });\n\n callback();\n\n // Cause forced synchronous layout.\n elements[0].offsetWidth; // eslint-disable-line no-unused-expressions\n\n // Put the duration back\n elements.forEach((element, i) => {\n element.style.transitionDuration = data[i].duration;\n element.style.transitionDelay = data[i].delay;\n });\n }\n}\n\nShuffle.ShuffleItem = ShuffleItem;\n\nShuffle.ALL_ITEMS = 'all';\nShuffle.FILTER_ATTRIBUTE_KEY = 'groups';\n\n/** @enum {string} */\nShuffle.EventType = {\n LAYOUT: 'shuffle:layout',\n REMOVED: 'shuffle:removed',\n};\n\n/** @enum {string} */\nShuffle.Classes = Classes;\n\n/** @enum {string} */\nShuffle.FilterMode = {\n ANY: 'any',\n ALL: 'all',\n};\n\n// Overrideable options\nShuffle.options = {\n // Initial filter group.\n group: Shuffle.ALL_ITEMS,\n\n // Transition/animation speed (milliseconds).\n speed: 250,\n\n // CSS easing function to use.\n easing: 'ease',\n\n // e.g. '.picture-item'.\n itemSelector: '*',\n\n // Element or selector string. Use an element to determine the size of columns\n // and gutters.\n sizer: null,\n\n // A static number or function that tells the plugin how wide the gutters\n // between columns are (in pixels).\n gutterWidth: 0,\n\n // A static number or function that returns a number which tells the plugin\n // how wide the columns are (in pixels).\n columnWidth: 0,\n\n // If your group is not json, and is comma delimeted, you could set delimeter\n // to ','.\n delimeter: null,\n\n // Useful for percentage based heights when they might not always be exactly\n // the same (in pixels).\n buffer: 0,\n\n // Reading the width of elements isn't precise enough and can cause columns to\n // jump between values.\n columnThreshold: 0.01,\n\n // Shuffle can be isInitialized with a sort object. It is the same object\n // given to the sort method.\n initialSort: null,\n\n // By default, shuffle will throttle resize events. This can be changed or\n // removed.\n throttle,\n\n // How often shuffle can be called on resize (in milliseconds).\n throttleTime: 300,\n\n // Transition delay offset for each item in milliseconds.\n staggerAmount: 15,\n\n // Maximum stagger delay in milliseconds.\n staggerAmountMax: 250,\n\n // Whether to use transforms or absolute positioning.\n useTransforms: true,\n\n // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With \"any\",\n // the element passes the test if any of its groups are in the array. With \"all\",\n // the element only passes if all groups are in the array.\n filterMode: Shuffle.FilterMode.ANY,\n\n // Whether to center grid items in the row with the leftover space.\n isCentered: false,\n};\n\nShuffle.Point = Point;\nShuffle.Rect = Rect;\n\n// Expose for testing. Hack at your own risk.\nShuffle.__sorter = sorter;\nShuffle.__getColumnSpan = getColumnSpan;\nShuffle.__getAvailablePositions = getAvailablePositions;\nShuffle.__getShortColumn = getShortColumn;\nShuffle.__getCenteredPositions = getCenteredPositions;\n\nexport default Shuffle;\n"],"names":["getNumber","value","parseFloat","Point","x","y","a","b","Rect","w","h","id","left","top","width","height","ShuffleItem","element","isVisible","classList","remove","Classes","HIDDEN","add","VISIBLE","removeAttribute","setAttribute","addClasses","SHUFFLE_ITEM","applyCss","Css","INITIAL","scale","Scale","point","classes","forEach","className","obj","keys","key","style","removeClasses","document","body","documentElement","e","createElement","cssText","appendChild","window","getComputedStyle","ret","removeChild","getNumberStyle","styles","COMPUTED_SIZE_INCLUDES_PADDING","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","randomize","array","n","length","i","Math","floor","random","temp","defaults","sorter","arr","options","opts","Object","assign","original","Array","from","revert","by","sort","valA","valB","undefined","reverse","transitions","eventName","count","uniqueId","cancelTransitionEnd","removeEventListener","listener","onTransitionEnd","callback","evt","currentTarget","target","addEventListener","arrayMax","max","apply","arrayMin","min","getColumnSpan","itemWidth","columnWidth","columns","threshold","columnSpan","abs","round","ceil","getAvailablePositions","positions","available","push","slice","getShortColumn","buffer","minPosition","len","getItemPosition","itemSize","gridSize","total","span","setY","shortColumnIndex","setHeight","getCenteredPositions","itemRects","containerWidth","rowMap","itemRect","rects","rows","centeredRows","lastItem","end","offset","finalRects","canMove","newRects","every","r","newRect","noOverlap","some","intersects","intersectingRect","hasOverlap","rowIndex","findIndex","items","includes","splice","concat","map","arrayUnique","Set","Shuffle","lastSort","group","ALL_ITEMS","lastFilter","isEnabled","isDestroyed","isInitialized","_transitions","isTransitioning","_queue","el","_getElementOption","TypeError","_init","_getItems","sizer","BASE","_initItems","_onResize","_getResizeFunction","readyState","layout","bind","onLoad","containerCss","getSize","_validateStyles","_setColumns","filter","initialSort","offsetWidth","setItemTransitions","transition","speed","easing","resizeFunction","_handleResize","throttle","throttleTime","option","querySelector","nodeType","jquery","position","overflow","category","collection","set","_getFilteredSets","_toggleFilterClasses","visible","hidden","item","_doesPassFilter","call","attr","getAttribute","FILTER_ATTRIBUTE_KEY","delimeter","split","JSON","parse","testCategory","isArray","filterMode","FilterMode","ANY","show","hide","init","dispose","visibleItems","_getFilteredItems","str","useTransforms","children","matches","itemSelector","indexOf","gutterSize","size","gutterWidth","gutter","_getGutterSize","_getColumnSize","calculatedColumns","columnThreshold","cols","colWidth","_getContainerSize","index","staggerAmount","staggerAmountMax","name","data","shuffle","emit","itemPositions","_getNextPositions","currPos","currScale","nextPosition","transitionDelay","after","equals","before","_getStaggerAmount","isCentered","itemsData","_getItemPosition","getTransformedPositions","_getConcealedItems","update","transform","itemCallback","done","getStylesForTransition","_whenTransitionDone","_cancelMovement","hasSpeed","hasQueue","_startTransitions","_styleImmediately","_dispatch","EventType","LAYOUT","callbacks","_getTransitionFunction","_movementFinished","objects","elements","_skipTransitions","sortObj","_filter","_shrink","_updateItemCount","sortOptions","_resetCols","_layout","_processQueue","_setContainerSize","isOnlyLayout","newItems","_saveNewItems","isUpdateLayout","oldItems","getItemByElement","handleLayout","_disposeItems","parentNode","REMOVED","once","find","includeMargins","marginLeft","marginRight","marginTop","marginBottom","zero","duration","transitionDuration","delay","TinyEmitter","__sorter","__getColumnSpan","__getAvailablePositions","__getShortColumn","__getCenteredPositions"],"mappings":"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"} \ No newline at end of file diff --git a/dist/shuffle.min.js b/dist/shuffle.min.js index c097480..c2bdd10 100644 --- a/dist/shuffle.min.js +++ b/dist/shuffle.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Shuffle=e()}(this,function(){"use strict";function t(){}function e(){}function i(t){return parseFloat(t)||0}function n(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:window.getComputedStyle(t,null),s=i(n[e]);return F||"width"!==e?F||"height"!==e||(s+=i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth)):s+=i(n.paddingLeft)+i(n.paddingRight)+i(n.borderLeftWidth)+i(n.borderRightWidth),s}function s(t){for(var e=t.length;e;){e-=1;var i=Math.floor(Math.random()*(e+1)),n=t[i];t[i]=t[e],t[e]=n}return t}function o(t,e){var i=Object.assign({},x,e),n=Array.from(t),o=!1;return t.length?i.randomize?s(t):("function"==typeof i.by&&t.sort(function(t,e){if(o)return 0;var n=i.by(t[i.key]),s=i.by(e[i.key]);return void 0===n&&void 0===s?(o=!0,0):ns||"sortLast"===n||"sortFirst"===s?1:0}),o?n:(i.reverse&&t.reverse(),t)):[]}function r(){return B+=1,N+B}function a(t){return!!O[t]&&(O[t].element.removeEventListener(N,O[t].listener),O[t]=null,!0)}function l(t,e){var i=r(),n=function(t){t.currentTarget===t.target&&(a(i),e(t))};return t.addEventListener(N,n),O[i]={element:t,listener:n},i}function u(t){return Math.max.apply(Math,t)}function h(t){return Math.min.apply(Math,t)}function f(t,e,i,n){var s=t/e;return Math.abs(Math.round(s)-s)=i-e&&t[n]<=i+e)return n;return 0}function m(t){for(var e=t.itemSize,i=t.positions,n=t.gridSize,s=t.total,o=t.threshold,r=t.buffer,a=f(e.width,n,s,o),l=c(i,a,s),u=d(l,r),h=new w(Math.round(n*u),Math.round(l[u])),m=l[u]+e.height,p=0;p0){var c=[];(f=r.every(function(t){var e=new L(t.left+u,t.top,t.width,t.height,t.id),i=!n.some(function(t){return L.intersects(e,t)});return c.push(e),i}))&&(h=c)}if(!f){var d=void 0;if(r.some(function(t){return n.some(function(e){var i=L.intersects(t,e);return i&&(d=e),i})})){var m=o.findIndex(function(t){return t.includes(d)});o.splice(m,1,s[m])}}n=n.concat(h),o.push(h)}),[].concat.apply([],o).sort(function(t,e){return t.id-e.id}).map(function(t){return new w(t.left,t.top)})}function v(t){return Array.from(new Set(t))}t.prototype={on:function(t,e,i){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this},once:function(t,e,i){function n(){s.off(t,n),e.apply(i,arguments)}var s=this;return n._=e,this.on(t,n,i)},emit:function(t){var e=[].slice.call(arguments,1),i=((this.e||(this.e={}))[t]||[]).slice(),n=0,s=i.length;for(n;n1&&void 0!==arguments[1]?arguments[1]:{};S(this,e);var n=T(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));n.options=Object.assign({},e.options,i),n.useSizer=!1,n.lastSort={},n.group=e.ALL_ITEMS,n.lastFilter=e.ALL_ITEMS,n.isEnabled=!0,n.isDestroyed=!1,n.isInitialized=!1,n._transitions=[],n.isTransitioning=!1,n._queue=[];var s=n._getElementOption(t);if(!s)throw new TypeError("Shuffle needs to be initialized with an element.");return n.element=s,n.id="shuffle_"+V,V+=1,n._init(),n.isInitialized=!0,n}return k(e,t),b(e,[{key:"_init",value:function(){if(this.items=this._getItems(),this.options.sizer=this._getElementOption(this.options.sizer),this.options.sizer&&(this.useSizer=!0),this.element.classList.add(e.Classes.BASE),this._initItems(this.items),this._onResize=this._getResizeFunction(),window.addEventListener("resize",this._onResize),"complete"!==document.readyState){var t=this.layout.bind(this);window.addEventListener("load",function e(){window.removeEventListener("load",e),t()})}var i=window.getComputedStyle(this.element,null),n=e.getSize(this.element).width;this._validateStyles(i),this._setColumns(n),this.filter(this.options.group,this.options.initialSort),this.element.offsetWidth,this.setItemTransitions(this.items),this.element.style.transition="height "+this.options.speed+"ms "+this.options.easing}},{key:"_getResizeFunction",value:function(){var t=this._handleResize.bind(this);return this.options.throttle?this.options.throttle(t,this.options.throttleTime):t}},{key:"_getElementOption",value:function(t){return"string"==typeof t?this.element.querySelector(t):t&&t.nodeType&&1===t.nodeType?t:t&&t.jquery?t[0]:null}},{key:"_validateStyles",value:function(t){"static"===t.position&&(this.element.style.position="relative"),"hidden"!==t.overflow&&(this.element.style.overflow="hidden")}},{key:"_filter",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastFilter,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.items,i=this._getFilteredSets(t,e);return this._toggleFilterClasses(i),this.lastFilter=t,"string"==typeof t&&(this.group=t),i}},{key:"_getFilteredSets",value:function(t,i){var n=this,s=[],o=[];return t===e.ALL_ITEMS?s=i:i.forEach(function(e){n._doesPassFilter(t,e.element)?s.push(e):o.push(e)}),{visible:s,hidden:o}}},{key:"_doesPassFilter",value:function(t,i){function n(t){return o.includes(t)}if("function"==typeof t)return t.call(i,i,this);var s=i.getAttribute("data-"+e.FILTER_ATTRIBUTE_KEY),o=this.options.delimeter?s.split(this.options.delimeter):JSON.parse(s);return Array.isArray(t)?this.options.filterMode===e.FilterMode.ANY?t.some(n):t.every(n):o.includes(t)}},{key:"_toggleFilterClasses",value:function(t){var e=t.visible,i=t.hidden;e.forEach(function(t){t.show()}),i.forEach(function(t){t.hide()})}},{key:"_initItems",value:function(t){t.forEach(function(t){t.init()})}},{key:"_disposeItems",value:function(t){t.forEach(function(t){t.dispose()})}},{key:"_updateItemCount",value:function(){this.visibleItems=this._getFilteredItems().length}},{key:"setItemTransitions",value:function(t){var e=this.options.speed,i=this.options.easing,n=this.options.useTransforms?"transform "+e+"ms "+i+", opacity "+e+"ms "+i:"top "+e+"ms "+i+", left "+e+"ms "+i+", opacity "+e+"ms "+i;t.forEach(function(t){t.element.style.transition=n})}},{key:"_getItems",value:function(){var t=this;return Array.from(this.element.children).filter(function(e){return E(e,t.options.itemSelector)}).map(function(t){return new M(t)})}},{key:"_saveNewItems",value:function(t){var e=Array.from(this.element.children);this.items=o(this.items.concat(t),{by:function(t){return e.indexOf(t)}})}},{key:"_getFilteredItems",value:function(){return this.items.filter(function(t){return t.isVisible})}},{key:"_getConcealedItems",value:function(){return this.items.filter(function(t){return!t.isVisible})}},{key:"_getColumnSize",value:function(t,i){var n=void 0;return 0===(n="function"==typeof this.options.columnWidth?this.options.columnWidth(t):this.useSizer?e.getSize(this.options.sizer).width:this.options.columnWidth?this.options.columnWidth:this.items.length>0?e.getSize(this.items[0].element,!0).width:t)&&(n=t),n+i}},{key:"_getGutterSize",value:function(t){return"function"==typeof this.options.gutterWidth?this.options.gutterWidth(t):this.useSizer?n(this.options.sizer,"marginLeft"):this.options.gutterWidth}},{key:"_setColumns",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:e.getSize(this.element).width,i=this._getGutterSize(t),n=this._getColumnSize(t,i),s=(t+i)/n;Math.abs(Math.round(s)-s)1&&void 0!==arguments[1]?arguments[1]:{};this.isDestroyed||(e.shuffle=this,this.emit(t,e))}},{key:"_resetCols",value:function(){var t=this.cols;for(this.positions=[];t;)t-=1,this.positions.push(0)}},{key:"_layout",value:function(t){var e=this,i=this._getNextPositions(t),n=0;t.forEach(function(t,s){function o(){t.element.style.transitionDelay="",t.applyCss(M.Css.VISIBLE.after)}var r=t.point,a=t.scale,l=i[s];if(w.equals(r,l)&&a===M.Scale.VISIBLE)return t.applyCss(M.Css.VISIBLE.before),void o();t.point=l,t.scale=M.Scale.VISIBLE;var u=Object.assign({},M.Css.VISIBLE.before);u.transitionDelay=e._getStaggerAmount(n)+"ms",e._queue.push({item:t,styles:u,callback:o}),n+=1})}},{key:"_getNextPositions",value:function(t){var i=this;if(this.options.isCentered){var n=t.map(function(t,n){var s=e.getSize(t.element,!0),o=i._getItemPosition(s);return new L(o.x,o.y,s.width,s.height,n)});return this.getTransformedPositions(n,this.containerWidth)}return t.map(function(t){return i._getItemPosition(e.getSize(t.element,!0))})}},{key:"_getItemPosition",value:function(t){return m({itemSize:t,positions:this.positions,gridSize:this.colWidth,total:this.cols,threshold:this.options.columnThreshold,buffer:this.options.buffer})}},{key:"getTransformedPositions",value:function(t,e){return p(t,e)}},{key:"_shrink",value:function(){var t=this,e=0;(arguments.length>0&&void 0!==arguments[0]?arguments[0]:this._getConcealedItems()).forEach(function(i){function n(){i.applyCss(M.Css.HIDDEN.after)}if(i.scale===M.Scale.HIDDEN)return i.applyCss(M.Css.HIDDEN.before),void n();i.scale=M.Scale.HIDDEN;var s=Object.assign({},M.Css.HIDDEN.before);s.transitionDelay=t._getStaggerAmount(e)+"ms",t._queue.push({item:i,styles:s,callback:n}),e+=1})}},{key:"_handleResize",value:function(){this.isEnabled&&!this.isDestroyed&&this.update()}},{key:"getStylesForTransition",value:function(t){var e=t.item,i=t.styles;i.transitionDelay||(i.transitionDelay="0ms");var n=e.point.x,s=e.point.y;return this.options.useTransforms?i.transform="translate("+n+"px, "+s+"px) scale("+e.scale+")":(i.left=n+"px",i.top=s+"px"),i}},{key:"_whenTransitionDone",value:function(t,e,i){var n=l(t,function(t){e(),i(null,t)});this._transitions.push(n)}},{key:"_getTransitionFunction",value:function(t){var e=this;return function(i){t.item.applyCss(e.getStylesForTransition(t)),e._whenTransitionDone(t.item.element,t.callback,i)}}},{key:"_processQueue",value:function(){this.isTransitioning&&this._cancelMovement();var t=this.options.speed>0,i=this._queue.length>0;i&&t&&this.isInitialized?this._startTransitions(this._queue):i?(this._styleImmediately(this._queue),this._dispatch(e.EventType.LAYOUT)):this._dispatch(e.EventType.LAYOUT),this._queue.length=0}},{key:"_startTransitions",value:function(t){var e=this;this.isTransitioning=!0;var i=t.map(function(t){return e._getTransitionFunction(t)});I(i,this._movementFinished.bind(this))}},{key:"_cancelMovement",value:function(){this._transitions.forEach(a),this._transitions.length=0,this.isTransitioning=!1}},{key:"_styleImmediately",value:function(t){var i=this;if(t.length){var n=t.map(function(t){return t.item.element});e._skipTransitions(n,function(){t.forEach(function(t){t.item.applyCss(i.getStylesForTransition(t)),t.callback()})})}}},{key:"_movementFinished",value:function(){this._transitions.length=0,this.isTransitioning=!1,this._dispatch(e.EventType.LAYOUT)}},{key:"filter",value:function(t,i){this.isEnabled&&((!t||t&&0===t.length)&&(t=e.ALL_ITEMS),this._filter(t),this._shrink(),this._updateItemCount(),this.sort(i))}},{key:"sort",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastSort;if(this.isEnabled){this._resetCols();var e=o(this._getFilteredItems(),t);this._layout(e),this._processQueue(),this._setContainerSize(),this.lastSort=t}}},{key:"update",value:function(t){this.isEnabled&&(t||this._setColumns(),this.sort())}},{key:"layout",value:function(){this.update(!0)}},{key:"add",value:function(t){var e=v(t).map(function(t){return new M(t)});this._initItems(e),this.setItemTransitions(e),this._saveNewItems(e),this.filter(this.lastFilter)}},{key:"disable",value:function(){this.isEnabled=!1}},{key:"enable",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.isEnabled=!0,t&&this.update()}},{key:"remove",value:function(t){var i=this;if(t.length){var n=v(t),s=n.map(function(t){return i.getItemByElement(t)}).filter(function(t){return!!t});this._toggleFilterClasses({visible:[],hidden:s}),this._shrink(s),this.sort(),this.items=this.items.filter(function(t){return!s.includes(t)}),this._updateItemCount(),this.once(e.EventType.LAYOUT,function(){i._disposeItems(s),n.forEach(function(t){t.parentNode.removeChild(t)}),i._dispatch(e.EventType.REMOVED,{collection:n})})}}},{key:"getItemByElement",value:function(t){return this.items.find(function(e){return e.element===t})}},{key:"resetItems",value:function(){var t=this;this._disposeItems(this.items),this.isInitialized=!1,this.items=this._getItems(),this._initItems(this.items),this.once(e.EventType.LAYOUT,function(){t.setItemTransitions(t.items),t.isInitialized=!0}),this.sort()}},{key:"destroy",value:function(){this._cancelMovement(),window.removeEventListener("resize",this._onResize),this.element.classList.remove("shuffle"),this.element.removeAttribute("style"),this._disposeItems(this.items),this.items.length=0,this._transitions.length=0,this.options.sizer=null,this.element=null,this.isDestroyed=!0,this.isEnabled=!1}}],[{key:"getSize",value:function(t,e){var i=window.getComputedStyle(t,null),s=n(t,"width",i),o=n(t,"height",i);return e&&(s+=n(t,"marginLeft",i)+n(t,"marginRight",i),o+=n(t,"marginTop",i)+n(t,"marginBottom",i)),{width:s,height:o}}},{key:"_skipTransitions",value:function(t,e){var i=t.map(function(t){var e=t.style,i=e.transitionDuration,n=e.transitionDelay;return e.transitionDuration="0ms",e.transitionDelay="0ms",{duration:i,delay:n}});e(),t[0].offsetWidth,t.forEach(function(t,e){t.style.transitionDuration=i[e].duration,t.style.transitionDelay=i[e].delay})}}]),e}(y);return W.ShuffleItem=M,W.ALL_ITEMS="all",W.FILTER_ATTRIBUTE_KEY="groups",W.EventType={LAYOUT:"shuffle:layout",REMOVED:"shuffle:removed"},W.Classes=C,W.FilterMode={ANY:"any",ALL:"all"},W.options={group:W.ALL_ITEMS,speed:250,easing:"ease",itemSelector:"*",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,columnThreshold:.01,initialSort:null,throttle:function(t,e){function i(){r=0,a=+new Date,o=t.apply(n,s),n=null,s=null}var n,s,o,r,a=0;return function(){n=this,s=arguments;var t=new Date-a;return r||(t>=e?i():r=setTimeout(i,e-t)),o}},throttleTime:300,staggerAmount:15,staggerAmountMax:250,useTransforms:!0,filterMode:W.FilterMode.ANY,isCentered:!1},W.__Point=w,W.__Rect=L,W.__sorter=o,W.__getColumnSpan=f,W.__getAvailablePositions=c,W.__getShortColumn=d,W.__getCenteredPositions=p,W}); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Shuffle=e()}(this,function(){"use strict";function t(){}function e(){}function i(t){return parseFloat(t)||0}function n(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:window.getComputedStyle(t,null),s=i(n[e]);return F||"width"!==e?F||"height"!==e||(s+=i(n.paddingTop)+i(n.paddingBottom)+i(n.borderTopWidth)+i(n.borderBottomWidth)):s+=i(n.paddingLeft)+i(n.paddingRight)+i(n.borderLeftWidth)+i(n.borderRightWidth),s}function s(t){for(var e=t.length;e;){e-=1;var i=Math.floor(Math.random()*(e+1)),n=t[i];t[i]=t[e],t[e]=n}return t}function o(t,e){var i=Object.assign({},x,e),n=Array.from(t),o=!1;return t.length?i.randomize?s(t):("function"==typeof i.by&&t.sort(function(t,e){if(o)return 0;var n=i.by(t[i.key]),s=i.by(e[i.key]);return void 0===n&&void 0===s?(o=!0,0):ns||"sortLast"===n||"sortFirst"===s?1:0}),o?n:(i.reverse&&t.reverse(),t)):[]}function r(){return B+=1,N+B}function a(t){return!!O[t]&&(O[t].element.removeEventListener(N,O[t].listener),O[t]=null,!0)}function l(t,e){var i=r(),n=function(t){t.currentTarget===t.target&&(a(i),e(t))};return t.addEventListener(N,n),O[i]={element:t,listener:n},i}function u(t){return Math.max.apply(Math,t)}function h(t){return Math.min.apply(Math,t)}function f(t,e,i,n){var s=t/e;return Math.abs(Math.round(s)-s)=i-e&&t[n]<=i+e)return n;return 0}function m(t){for(var e=t.itemSize,i=t.positions,n=t.gridSize,s=t.total,o=t.threshold,r=t.buffer,a=f(e.width,n,s,o),l=c(i,a,s),u=d(l,r),h=new w(Math.round(n*u),Math.round(l[u])),m=l[u]+e.height,p=0;p0){var c=[];(f=r.every(function(t){var e=new L(t.left+u,t.top,t.width,t.height,t.id),i=!n.some(function(t){return L.intersects(e,t)});return c.push(e),i}))&&(h=c)}if(!f){var d=void 0;if(r.some(function(t){return n.some(function(e){var i=L.intersects(t,e);return i&&(d=e),i})})){var m=o.findIndex(function(t){return t.includes(d)});o.splice(m,1,s[m])}}n=n.concat(h),o.push(h)}),[].concat.apply([],o).sort(function(t,e){return t.id-e.id}).map(function(t){return new w(t.left,t.top)})}function v(t){return Array.from(new Set(t))}t.prototype={on:function(t,e,i){var n=this.e||(this.e={});return(n[t]||(n[t]=[])).push({fn:e,ctx:i}),this},once:function(t,e,i){function n(){s.off(t,n),e.apply(i,arguments)}var s=this;return n._=e,this.on(t,n,i)},emit:function(t){var e=[].slice.call(arguments,1),i=((this.e||(this.e={}))[t]||[]).slice(),n=0,s=i.length;for(n;n1&&void 0!==arguments[1]?arguments[1]:{};b(this,e);var n=T(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));n.options=Object.assign({},e.options,i),n.lastSort={},n.group=e.ALL_ITEMS,n.lastFilter=e.ALL_ITEMS,n.isEnabled=!0,n.isDestroyed=!1,n.isInitialized=!1,n._transitions=[],n.isTransitioning=!1,n._queue=[];var s=n._getElementOption(t);if(!s)throw new TypeError("Shuffle needs to be initialized with an element.");return n.element=s,n.id="shuffle_"+V,V+=1,n._init(),n.isInitialized=!0,n}return k(e,t),S(e,[{key:"_init",value:function(){if(this.items=this._getItems(),this.options.sizer=this._getElementOption(this.options.sizer),this.element.classList.add(e.Classes.BASE),this._initItems(this.items),this._onResize=this._getResizeFunction(),window.addEventListener("resize",this._onResize),"complete"!==document.readyState){var t=this.layout.bind(this);window.addEventListener("load",function e(){window.removeEventListener("load",e),t()})}var i=window.getComputedStyle(this.element,null),n=e.getSize(this.element).width;this._validateStyles(i),this._setColumns(n),this.filter(this.options.group,this.options.initialSort),this.element.offsetWidth,this.setItemTransitions(this.items),this.element.style.transition="height "+this.options.speed+"ms "+this.options.easing}},{key:"_getResizeFunction",value:function(){var t=this._handleResize.bind(this);return this.options.throttle?this.options.throttle(t,this.options.throttleTime):t}},{key:"_getElementOption",value:function(t){return"string"==typeof t?this.element.querySelector(t):t&&t.nodeType&&1===t.nodeType?t:t&&t.jquery?t[0]:null}},{key:"_validateStyles",value:function(t){"static"===t.position&&(this.element.style.position="relative"),"hidden"!==t.overflow&&(this.element.style.overflow="hidden")}},{key:"_filter",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastFilter,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.items,i=this._getFilteredSets(t,e);return this._toggleFilterClasses(i),this.lastFilter=t,"string"==typeof t&&(this.group=t),i}},{key:"_getFilteredSets",value:function(t,i){var n=this,s=[],o=[];return t===e.ALL_ITEMS?s=i:i.forEach(function(e){n._doesPassFilter(t,e.element)?s.push(e):o.push(e)}),{visible:s,hidden:o}}},{key:"_doesPassFilter",value:function(t,i){function n(t){return o.includes(t)}if("function"==typeof t)return t.call(i,i,this);var s=i.getAttribute("data-"+e.FILTER_ATTRIBUTE_KEY),o=this.options.delimeter?s.split(this.options.delimeter):JSON.parse(s);return Array.isArray(t)?this.options.filterMode===e.FilterMode.ANY?t.some(n):t.every(n):o.includes(t)}},{key:"_toggleFilterClasses",value:function(t){var e=t.visible,i=t.hidden;e.forEach(function(t){t.show()}),i.forEach(function(t){t.hide()})}},{key:"_initItems",value:function(t){t.forEach(function(t){t.init()})}},{key:"_disposeItems",value:function(t){t.forEach(function(t){t.dispose()})}},{key:"_updateItemCount",value:function(){this.visibleItems=this._getFilteredItems().length}},{key:"setItemTransitions",value:function(t){var e=this.options.speed,i=this.options.easing,n=this.options.useTransforms?"transform "+e+"ms "+i+", opacity "+e+"ms "+i:"top "+e+"ms "+i+", left "+e+"ms "+i+", opacity "+e+"ms "+i;t.forEach(function(t){t.element.style.transition=n})}},{key:"_getItems",value:function(){var t=this;return Array.from(this.element.children).filter(function(e){return E(e,t.options.itemSelector)}).map(function(t){return new M(t)})}},{key:"_saveNewItems",value:function(t){var e=Array.from(this.element.children);this.items=o(this.items.concat(t),{by:function(t){return e.indexOf(t)}})}},{key:"_getFilteredItems",value:function(){return this.items.filter(function(t){return t.isVisible})}},{key:"_getConcealedItems",value:function(){return this.items.filter(function(t){return!t.isVisible})}},{key:"_getColumnSize",value:function(t,i){var n=void 0;return 0===(n="function"==typeof this.options.columnWidth?this.options.columnWidth(t):this.options.sizer?e.getSize(this.options.sizer).width:this.options.columnWidth?this.options.columnWidth:this.items.length>0?e.getSize(this.items[0].element,!0).width:t)&&(n=t),n+i}},{key:"_getGutterSize",value:function(t){return"function"==typeof this.options.gutterWidth?this.options.gutterWidth(t):this.options.sizer?n(this.options.sizer,"marginLeft"):this.options.gutterWidth}},{key:"_setColumns",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:e.getSize(this.element).width,i=this._getGutterSize(t),n=this._getColumnSize(t,i),s=(t+i)/n;Math.abs(Math.round(s)-s)1&&void 0!==arguments[1]?arguments[1]:{};this.isDestroyed||(e.shuffle=this,this.emit(t,e))}},{key:"_resetCols",value:function(){var t=this.cols;for(this.positions=[];t;)t-=1,this.positions.push(0)}},{key:"_layout",value:function(t){var e=this,i=this._getNextPositions(t),n=0;t.forEach(function(t,s){function o(){t.element.style.transitionDelay="",t.applyCss(M.Css.VISIBLE.after)}var r=t.point,a=t.scale,l=i[s];if(w.equals(r,l)&&a===M.Scale.VISIBLE)return t.applyCss(M.Css.VISIBLE.before),void o();t.point=l,t.scale=M.Scale.VISIBLE;var u=Object.assign({},M.Css.VISIBLE.before);u.transitionDelay=e._getStaggerAmount(n)+"ms",e._queue.push({item:t,styles:u,callback:o}),n+=1})}},{key:"_getNextPositions",value:function(t){var i=this;if(this.options.isCentered){var n=t.map(function(t,n){var s=e.getSize(t.element,!0),o=i._getItemPosition(s);return new L(o.x,o.y,s.width,s.height,n)});return this.getTransformedPositions(n,this.containerWidth)}return t.map(function(t){return i._getItemPosition(e.getSize(t.element,!0))})}},{key:"_getItemPosition",value:function(t){return m({itemSize:t,positions:this.positions,gridSize:this.colWidth,total:this.cols,threshold:this.options.columnThreshold,buffer:this.options.buffer})}},{key:"getTransformedPositions",value:function(t,e){return p(t,e)}},{key:"_shrink",value:function(){var t=this,e=0;(arguments.length>0&&void 0!==arguments[0]?arguments[0]:this._getConcealedItems()).forEach(function(i){function n(){i.applyCss(M.Css.HIDDEN.after)}if(i.scale===M.Scale.HIDDEN)return i.applyCss(M.Css.HIDDEN.before),void n();i.scale=M.Scale.HIDDEN;var s=Object.assign({},M.Css.HIDDEN.before);s.transitionDelay=t._getStaggerAmount(e)+"ms",t._queue.push({item:i,styles:s,callback:n}),e+=1})}},{key:"_handleResize",value:function(){this.isEnabled&&!this.isDestroyed&&this.update()}},{key:"getStylesForTransition",value:function(t){var e=t.item,i=t.styles;i.transitionDelay||(i.transitionDelay="0ms");var n=e.point.x,s=e.point.y;return this.options.useTransforms?i.transform="translate("+n+"px, "+s+"px) scale("+e.scale+")":(i.left=n+"px",i.top=s+"px"),i}},{key:"_whenTransitionDone",value:function(t,e,i){var n=l(t,function(t){e(),i(null,t)});this._transitions.push(n)}},{key:"_getTransitionFunction",value:function(t){var e=this;return function(i){t.item.applyCss(e.getStylesForTransition(t)),e._whenTransitionDone(t.item.element,t.callback,i)}}},{key:"_processQueue",value:function(){this.isTransitioning&&this._cancelMovement();var t=this.options.speed>0,i=this._queue.length>0;i&&t&&this.isInitialized?this._startTransitions(this._queue):i?(this._styleImmediately(this._queue),this._dispatch(e.EventType.LAYOUT)):this._dispatch(e.EventType.LAYOUT),this._queue.length=0}},{key:"_startTransitions",value:function(t){var e=this;this.isTransitioning=!0;var i=t.map(function(t){return e._getTransitionFunction(t)});I(i,this._movementFinished.bind(this))}},{key:"_cancelMovement",value:function(){this._transitions.forEach(a),this._transitions.length=0,this.isTransitioning=!1}},{key:"_styleImmediately",value:function(t){var i=this;if(t.length){var n=t.map(function(t){return t.item.element});e._skipTransitions(n,function(){t.forEach(function(t){t.item.applyCss(i.getStylesForTransition(t)),t.callback()})})}}},{key:"_movementFinished",value:function(){this._transitions.length=0,this.isTransitioning=!1,this._dispatch(e.EventType.LAYOUT)}},{key:"filter",value:function(t,i){this.isEnabled&&((!t||t&&0===t.length)&&(t=e.ALL_ITEMS),this._filter(t),this._shrink(),this._updateItemCount(),this.sort(i))}},{key:"sort",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastSort;if(this.isEnabled){this._resetCols();var e=o(this._getFilteredItems(),t);this._layout(e),this._processQueue(),this._setContainerSize(),this.lastSort=t}}},{key:"update",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.isEnabled&&(t||this._setColumns(),this.sort())}},{key:"layout",value:function(){this.update(!0)}},{key:"add",value:function(t){var e=v(t).map(function(t){return new M(t)});this._initItems(e),this.setItemTransitions(e),this._saveNewItems(e),this.filter(this.lastFilter)}},{key:"disable",value:function(){this.isEnabled=!1}},{key:"enable",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.isEnabled=!0,t&&this.update()}},{key:"remove",value:function(t){var i=this;if(t.length){var n=v(t),s=n.map(function(t){return i.getItemByElement(t)}).filter(function(t){return!!t});this._toggleFilterClasses({visible:[],hidden:s}),this._shrink(s),this.sort(),this.items=this.items.filter(function(t){return!s.includes(t)}),this._updateItemCount(),this.once(e.EventType.LAYOUT,function(){i._disposeItems(s),n.forEach(function(t){t.parentNode.removeChild(t)}),i._dispatch(e.EventType.REMOVED,{collection:n})})}}},{key:"getItemByElement",value:function(t){return this.items.find(function(e){return e.element===t})}},{key:"resetItems",value:function(){var t=this;this._disposeItems(this.items),this.isInitialized=!1,this.items=this._getItems(),this._initItems(this.items),this.once(e.EventType.LAYOUT,function(){t.setItemTransitions(t.items),t.isInitialized=!0}),this.sort()}},{key:"destroy",value:function(){this._cancelMovement(),window.removeEventListener("resize",this._onResize),this.element.classList.remove("shuffle"),this.element.removeAttribute("style"),this._disposeItems(this.items),this.items.length=0,this._transitions.length=0,this.options.sizer=null,this.element=null,this.isDestroyed=!0,this.isEnabled=!1}}],[{key:"getSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=window.getComputedStyle(t,null),s=n(t,"width",i),o=n(t,"height",i);return e&&(s+=n(t,"marginLeft",i)+n(t,"marginRight",i),o+=n(t,"marginTop",i)+n(t,"marginBottom",i)),{width:s,height:o}}},{key:"_skipTransitions",value:function(t,e){var i=t.map(function(t){var e=t.style,i=e.transitionDuration,n=e.transitionDelay;return e.transitionDuration="0ms",e.transitionDelay="0ms",{duration:i,delay:n}});e(),t[0].offsetWidth,t.forEach(function(t,e){t.style.transitionDuration=i[e].duration,t.style.transitionDelay=i[e].delay})}}]),e}(y);return W.ShuffleItem=M,W.ALL_ITEMS="all",W.FILTER_ATTRIBUTE_KEY="groups",W.EventType={LAYOUT:"shuffle:layout",REMOVED:"shuffle:removed"},W.Classes=C,W.FilterMode={ANY:"any",ALL:"all"},W.options={group:W.ALL_ITEMS,speed:250,easing:"ease",itemSelector:"*",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,columnThreshold:.01,initialSort:null,throttle:function(t,e){function i(){r=0,a=+new Date,o=t.apply(n,s),n=null,s=null}var n,s,o,r,a=0;return function(){n=this,s=arguments;var t=new Date-a;return r||(t>=e?i():r=setTimeout(i,e-t)),o}},throttleTime:300,staggerAmount:15,staggerAmountMax:250,useTransforms:!0,filterMode:W.FilterMode.ANY,isCentered:!1},W.Point=w,W.Rect=L,W.__sorter=o,W.__getColumnSpan=f,W.__getAvailablePositions=c,W.__getShortColumn=d,W.__getCenteredPositions=p,W}); //# sourceMappingURL=shuffle.min.js.map diff --git a/dist/shuffle.min.js.map b/dist/shuffle.min.js.map index d70fda7..b202c44 100644 --- a/dist/shuffle.min.js.map +++ b/dist/shuffle.min.js.map @@ -1 +1 @@ -{"version":3,"file":"shuffle.min.js","sources":["../node_modules/tiny-emitter/index.js","../node_modules/array-parallel/index.js","../src/get-number.js","../src/get-number-style.js","../src/sorter.js","../src/on-transition-end.js","../src/array-max.js","../src/array-min.js","../src/layout.js","../src/shuffle.js","../node_modules/matches-selector/index.js","../src/point.js","../src/rect.js","../src/classes.js","../src/shuffle-item.js","../src/computed-size.js","../node_modules/throttleit/index.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\n","module.exports = function parallel(fns, context, callback) {\n if (!callback) {\n if (typeof context === 'function') {\n callback = context\n context = null\n } else {\n callback = noop\n }\n }\n\n var pending = fns && fns.length\n if (!pending) return callback(null, []);\n\n var finished = false\n var results = new Array(pending)\n\n fns.forEach(context ? function (fn, i) {\n fn.call(context, maybeDone(i))\n } : function (fn, i) {\n fn(maybeDone(i))\n })\n\n function maybeDone(i) {\n return function (err, result) {\n if (finished) return;\n\n if (err) {\n callback(err, results)\n finished = true\n return\n }\n\n results[i] = result\n\n if (!--pending) callback(null, results);\n }\n }\n}\n\nfunction noop() {}\n","/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param {*} value Possibly numeric value.\n * @return {number} `value` or zero if `value` isn't numeric.\n */\nexport default function getNumber(value) {\n return parseFloat(value) || 0;\n}\n","import getNumber from './get-number';\nimport COMPUTED_SIZE_INCLUDES_PADDING from './computed-size';\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param {Element} element Element to get style for.\n * @param {string} style Style property.\n * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to\n * use instead of asking for them again.\n * @return {number} The parsed computed value or zero if that fails because IE\n * will return 'auto' when the element doesn't have margins instead of\n * the computed style.\n */\nexport default function getNumberStyle(element, style,\n styles = window.getComputedStyle(element, null)) {\n let value = getNumber(styles[style]);\n\n // Support IE<=11 and W3C spec.\n if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'width') {\n value += getNumber(styles.paddingLeft) +\n getNumber(styles.paddingRight) +\n getNumber(styles.borderLeftWidth) +\n getNumber(styles.borderRightWidth);\n } else if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'height') {\n value += getNumber(styles.paddingTop) +\n getNumber(styles.paddingBottom) +\n getNumber(styles.borderTopWidth) +\n getNumber(styles.borderBottomWidth);\n }\n\n return value;\n}\n","/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param {Array} array Array to shuffle.\n * @return {Array} Randomly sorted array.\n */\nfunction randomize(array) {\n let n = array.length;\n\n while (n) {\n n -= 1;\n const i = Math.floor(Math.random() * (n + 1));\n const temp = array[i];\n array[i] = array[n];\n array[n] = temp;\n }\n\n return array;\n}\n\nconst defaults = {\n // Use array.reverse() to reverse the results\n reverse: false,\n\n // Sorting function\n by: null,\n\n // If true, this will skip the sorting and return a randomized order in the array\n randomize: false,\n\n // Determines which property of each item in the array is passed to the\n // sorting method.\n key: 'element',\n};\n\n// You can return `undefined` from the `by` function to revert to DOM order.\nexport default function sorter(arr, options) {\n const opts = Object.assign({}, defaults, options);\n const original = Array.from(arr);\n let revert = false;\n\n if (!arr.length) {\n return [];\n }\n\n if (opts.randomize) {\n return randomize(arr);\n }\n\n // Sort the elements by the opts.by function.\n // If we don't have opts.by, default to DOM order\n if (typeof opts.by === 'function') {\n arr.sort((a, b) => {\n // Exit early if we already know we want to revert\n if (revert) {\n return 0;\n }\n\n const valA = opts.by(a[opts.key]);\n const valB = opts.by(b[opts.key]);\n\n // If both values are undefined, use the DOM order\n if (valA === undefined && valB === undefined) {\n revert = true;\n return 0;\n }\n\n if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {\n return -1;\n }\n\n if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {\n return 1;\n }\n\n return 0;\n });\n }\n\n // Revert to the original array if necessary\n if (revert) {\n return original;\n }\n\n if (opts.reverse) {\n arr.reverse();\n }\n\n return arr;\n}\n","const transitions = {};\nconst eventName = 'transitionend';\nlet count = 0;\n\nfunction uniqueId() {\n count += 1;\n return eventName + count;\n}\n\nexport function cancelTransitionEnd(id) {\n if (transitions[id]) {\n transitions[id].element.removeEventListener(eventName, transitions[id].listener);\n transitions[id] = null;\n return true;\n }\n\n return false;\n}\n\nexport function onTransitionEnd(element, callback) {\n const id = uniqueId();\n const listener = (evt) => {\n if (evt.currentTarget === evt.target) {\n cancelTransitionEnd(id);\n callback(evt);\n }\n };\n\n element.addEventListener(eventName, listener);\n\n transitions[id] = { element, listener };\n\n return id;\n}\n","export default function arrayMax(array) {\n return Math.max.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","export default function arrayMin(array) {\n return Math.min.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","import Point from './point';\nimport Rect from './rect';\nimport arrayMax from './array-max';\nimport arrayMin from './array-min';\n\n/**\n * Determine the number of columns an items spans.\n * @param {number} itemWidth Width of the item.\n * @param {number} columnWidth Width of the column (includes gutter).\n * @param {number} columns Total number of columns\n * @param {number} threshold A buffer value for the size of the column to fit.\n * @return {number}\n */\nexport function getColumnSpan(itemWidth, columnWidth, columns, threshold) {\n let columnSpan = itemWidth / columnWidth;\n\n // If the difference between the rounded column span number and the\n // calculated column span number is really small, round the number to\n // make it fit.\n if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {\n // e.g. columnSpan = 4.0089945390298745\n columnSpan = Math.round(columnSpan);\n }\n\n // Ensure the column span is not more than the amount of columns in the whole layout.\n return Math.min(Math.ceil(columnSpan), columns);\n}\n\n/**\n * Retrieves the column set to use for placement.\n * @param {number} columnSpan The number of columns this current item spans.\n * @param {number} columns The total columns in the grid.\n * @return {Array.} An array of numbers represeting the column set.\n */\nexport function getAvailablePositions(positions, columnSpan, columns) {\n // The item spans only one column.\n if (columnSpan === 1) {\n return positions;\n }\n\n // The item spans more than one column, figure out how many different\n // places it could fit horizontally.\n // The group count is the number of places within the positions this block\n // could fit, ignoring the current positions of items.\n // Imagine a 2 column brick as the second item in a 4 column grid with\n // 10px height each. Find the places it would fit:\n // [20, 10, 10, 0]\n // | | |\n // * * *\n //\n // Then take the places which fit and get the bigger of the two:\n // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]\n //\n // Next, find the first smallest number (the short column).\n // [20, 10, 0]\n // |\n // *\n //\n // And that's where it should be placed!\n //\n // Another example where the second column's item extends past the first:\n // [10, 20, 10, 0] => [20, 20, 10] => 10\n const available = [];\n\n // For how many possible positions for this item there are.\n for (let i = 0; i <= columns - columnSpan; i++) {\n // Find the bigger value for each place it could fit.\n available.push(arrayMax(positions.slice(i, i + columnSpan)));\n }\n\n return available;\n}\n\n/**\n * Find index of short column, the first from the left where this item will go.\n *\n * @param {Array.} positions The array to search for the smallest number.\n * @param {number} buffer Optional buffer which is very useful when the height\n * is a percentage of the width.\n * @return {number} Index of the short column.\n */\nexport function getShortColumn(positions, buffer) {\n const minPosition = arrayMin(positions);\n for (let i = 0, len = positions.length; i < len; i++) {\n if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n return i;\n }\n }\n\n return 0;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param {Object} itemSize Object with width and height.\n * @param {Array.} positions Positions of the other current items.\n * @param {number} gridSize The column width or row height.\n * @param {number} total The total number of columns or rows.\n * @param {number} threshold Buffer value for the column to fit.\n * @param {number} buffer Vertical buffer for the height of items.\n * @return {Point}\n */\nexport function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {\n const span = getColumnSpan(itemSize.width, gridSize, total, threshold);\n const setY = getAvailablePositions(positions, span, total);\n const shortColumnIndex = getShortColumn(setY, buffer);\n\n // Position the item\n const point = new Point(\n Math.round(gridSize * shortColumnIndex),\n Math.round(setY[shortColumnIndex]));\n\n // Update the columns array with the new values for each column.\n // e.g. before the update the columns could be [250, 0, 0, 0] for an item\n // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].\n const setHeight = setY[shortColumnIndex] + itemSize.height;\n for (let i = 0; i < span; i++) {\n positions[shortColumnIndex + i] = setHeight;\n }\n\n return point;\n}\n\n/**\n * This method attempts to center items. This method could potentially be slow\n * with a large number of items because it must place items, then check every\n * previous item to ensure there is no overlap.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n */\nexport function getCenteredPositions(itemRects, containerWidth) {\n const rowMap = {};\n\n // Populate rows by their offset because items could jump between rows like:\n // a c\n // bbb\n itemRects.forEach((itemRect) => {\n if (rowMap[itemRect.top]) {\n // Push the point to the last row array.\n rowMap[itemRect.top].push(itemRect);\n } else {\n // Start of a new row.\n rowMap[itemRect.top] = [itemRect];\n }\n });\n\n // For each row, find the end of the last item, then calculate\n // the remaining space by dividing it by 2. Then add that\n // offset to the x position of each point.\n let rects = [];\n const rows = [];\n const centeredRows = [];\n Object.keys(rowMap).forEach((key) => {\n const itemRects = rowMap[key];\n rows.push(itemRects);\n const lastItem = itemRects[itemRects.length - 1];\n const end = lastItem.left + lastItem.width;\n const offset = Math.round((containerWidth - end) / 2);\n\n let finalRects = itemRects;\n let canMove = false;\n if (offset > 0) {\n const newRects = [];\n canMove = itemRects.every((r) => {\n const newRect = new Rect(r.left + offset, r.top, r.width, r.height, r.id);\n\n // Check all current rects to make sure none overlap.\n const noOverlap = !rects.some(r => Rect.intersects(newRect, r));\n\n newRects.push(newRect);\n return noOverlap;\n });\n\n // If none of the rectangles overlapped, the whole group can be centered.\n if (canMove) {\n finalRects = newRects;\n }\n }\n\n // If the items are not going to be offset, ensure that the original\n // placement for this row will not overlap previous rows (row-spanning\n // elements could be in the way).\n if (!canMove) {\n let intersectingRect;\n const hasOverlap = itemRects.some(itemRect => rects.some((r) => {\n const intersects = Rect.intersects(itemRect, r);\n if (intersects) {\n intersectingRect = r;\n }\n return intersects;\n }));\n\n // If there is any overlap, replace the overlapping row with the original.\n if (hasOverlap) {\n const rowIndex = centeredRows.findIndex(items => items.includes(intersectingRect));\n centeredRows.splice(rowIndex, 1, rows[rowIndex]);\n }\n }\n\n rects = rects.concat(finalRects);\n centeredRows.push(finalRects);\n });\n\n // Reduce array of arrays to a single array of points.\n // https://stackoverflow.com/a/10865042/373422\n // Then reset sort back to how the items were passed to this method.\n // Remove the wrapper object with index, map to a Point.\n return [].concat.apply([], centeredRows) // eslint-disable-line prefer-spread\n .sort((a, b) => (a.id - b.id))\n .map(itemRect => new Point(itemRect.left, itemRect.top));\n}\n","import TinyEmitter from 'tiny-emitter';\nimport matches from 'matches-selector';\nimport throttle from 'throttleit';\nimport parallel from 'array-parallel';\n\nimport Point from './point';\nimport Rect from './rect';\nimport ShuffleItem from './shuffle-item';\nimport Classes from './classes';\nimport getNumberStyle from './get-number-style';\nimport sorter from './sorter';\nimport { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';\nimport {\n getItemPosition,\n getColumnSpan,\n getAvailablePositions,\n getShortColumn,\n getCenteredPositions,\n} from './layout';\nimport arrayMax from './array-max';\n\nfunction arrayUnique(x) {\n return Array.from(new Set(x));\n}\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n\n /**\n * Categorize, sort, and filter a responsive grid of items.\n *\n * @param {Element} element An element which is the parent container for the grid items.\n * @param {Object} [options=Shuffle.options] Options object.\n * @constructor\n */\n constructor(element, options = {}) {\n super();\n this.options = Object.assign({}, Shuffle.options, options);\n\n this.useSizer = false;\n this.lastSort = {};\n this.group = Shuffle.ALL_ITEMS;\n this.lastFilter = Shuffle.ALL_ITEMS;\n this.isEnabled = true;\n this.isDestroyed = false;\n this.isInitialized = false;\n this._transitions = [];\n this.isTransitioning = false;\n this._queue = [];\n\n const el = this._getElementOption(element);\n\n if (!el) {\n throw new TypeError('Shuffle needs to be initialized with an element.');\n }\n\n this.element = el;\n this.id = 'shuffle_' + id;\n id += 1;\n\n this._init();\n this.isInitialized = true;\n }\n\n _init() {\n this.items = this._getItems();\n\n this.options.sizer = this._getElementOption(this.options.sizer);\n\n if (this.options.sizer) {\n this.useSizer = true;\n }\n\n // Add class and invalidate styles\n this.element.classList.add(Shuffle.Classes.BASE);\n\n // Set initial css for each item\n this._initItems(this.items);\n\n // Bind resize events\n this._onResize = this._getResizeFunction();\n window.addEventListener('resize', this._onResize);\n\n // If the page has not already emitted the `load` event, call layout on load.\n // This avoids layout issues caused by images and fonts loading after the\n // instance has been initialized.\n if (document.readyState !== 'complete') {\n const layout = this.layout.bind(this);\n window.addEventListener('load', function onLoad() {\n window.removeEventListener('load', onLoad);\n layout();\n });\n }\n\n // Get container css all in one request. Causes reflow\n const containerCss = window.getComputedStyle(this.element, null);\n const containerWidth = Shuffle.getSize(this.element).width;\n\n // Add styles to the container if it doesn't have them.\n this._validateStyles(containerCss);\n\n // We already got the container's width above, no need to cause another\n // reflow getting it again... Calculate the number of columns there will be\n this._setColumns(containerWidth);\n\n // Kick off!\n this.filter(this.options.group, this.options.initialSort);\n\n // The shuffle items haven't had transitions set on them yet so the user\n // doesn't see the first layout. Set them now that the first layout is done.\n // First, however, a synchronous layout must be caused for the previous\n // styles to be applied without transitions.\n this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n this.setItemTransitions(this.items);\n this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;\n }\n\n /**\n * Returns a throttled and proxied function for the resize handler.\n * @return {Function}\n * @private\n */\n _getResizeFunction() {\n const resizeFunction = this._handleResize.bind(this);\n return this.options.throttle ?\n this.options.throttle(resizeFunction, this.options.throttleTime) :\n resizeFunction;\n }\n\n /**\n * Retrieve an element from an option.\n * @param {string|jQuery|Element} option The option to check.\n * @return {?Element} The plain element or null.\n * @private\n */\n _getElementOption(option) {\n // If column width is a string, treat is as a selector and search for the\n // sizer element within the outermost container\n if (typeof option === 'string') {\n return this.element.querySelector(option);\n\n // Check for an element\n } else if (option && option.nodeType && option.nodeType === 1) {\n return option;\n\n // Check for jQuery object\n } else if (option && option.jquery) {\n return option[0];\n }\n\n return null;\n }\n\n /**\n * Ensures the shuffle container has the css styles it needs applied to it.\n * @param {Object} styles Key value pairs for position and overflow.\n * @private\n */\n _validateStyles(styles) {\n // Position cannot be static.\n if (styles.position === 'static') {\n this.element.style.position = 'relative';\n }\n\n // Overflow has to be hidden.\n if (styles.overflow !== 'hidden') {\n this.element.style.overflow = 'hidden';\n }\n }\n\n /**\n * Filter the elements by a category.\n * @param {string} [category] Category to filter by. If it's given, the last\n * category will be used to filter the items.\n * @param {Array} [collection] Optionally filter a collection. Defaults to\n * all the items.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _filter(category = this.lastFilter, collection = this.items) {\n const set = this._getFilteredSets(category, collection);\n\n // Individually add/remove hidden/visible classes\n this._toggleFilterClasses(set);\n\n // Save the last filter in case elements are appended.\n this.lastFilter = category;\n\n // This is saved mainly because providing a filter function (like searching)\n // will overwrite the `lastFilter` property every time its called.\n if (typeof category === 'string') {\n this.group = category;\n }\n\n return set;\n }\n\n /**\n * Returns an object containing the visible and hidden elements.\n * @param {string|Function} category Category or function to filter by.\n * @param {Array.} items A collection of items to filter.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _getFilteredSets(category, items) {\n let visible = [];\n const hidden = [];\n\n // category === 'all', add visible class to everything\n if (category === Shuffle.ALL_ITEMS) {\n visible = items;\n\n // Loop through each item and use provided function to determine\n // whether to hide it or not.\n } else {\n items.forEach((item) => {\n if (this._doesPassFilter(category, item.element)) {\n visible.push(item);\n } else {\n hidden.push(item);\n }\n });\n }\n\n return {\n visible,\n hidden,\n };\n }\n\n /**\n * Test an item to see if it passes a category.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element} element An element to test.\n * @return {boolean} Whether it passes the category/filter.\n * @private\n */\n _doesPassFilter(category, element) {\n if (typeof category === 'function') {\n return category.call(element, element, this);\n }\n\n // Check each element's data-groups attribute against the given category.\n const attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY);\n const keys = this.options.delimeter ?\n attr.split(this.options.delimeter) :\n JSON.parse(attr);\n\n function testCategory(category) {\n return keys.includes(category);\n }\n\n if (Array.isArray(category)) {\n if (this.options.filterMode === Shuffle.FilterMode.ANY) {\n return category.some(testCategory);\n }\n return category.every(testCategory);\n }\n\n return keys.includes(category);\n }\n\n /**\n * Toggles the visible and hidden class names.\n * @param {{visible, hidden}} Object with visible and hidden arrays.\n * @private\n */\n _toggleFilterClasses({ visible, hidden }) {\n visible.forEach((item) => {\n item.show();\n });\n\n hidden.forEach((item) => {\n item.hide();\n });\n }\n\n /**\n * Set the initial css for each item\n * @param {Array.} items Set to initialize.\n * @private\n */\n _initItems(items) {\n items.forEach((item) => {\n item.init();\n });\n }\n\n /**\n * Remove element reference and styles.\n * @param {Array.} items Set to dispose.\n * @private\n */\n _disposeItems(items) {\n items.forEach((item) => {\n item.dispose();\n });\n }\n\n /**\n * Updates the visible item count.\n * @private\n */\n _updateItemCount() {\n this.visibleItems = this._getFilteredItems().length;\n }\n\n /**\n * Sets css transform transition on a group of elements. This is not executed\n * at the same time as `item.init` so that transitions don't occur upon\n * initialization of Shuffle.\n * @param {Array.} items Shuffle items to set transitions on.\n * @protected\n */\n setItemTransitions(items) {\n const speed = this.options.speed;\n const easing = this.options.easing;\n\n const str = this.options.useTransforms ?\n `transform ${speed}ms ${easing}, opacity ${speed}ms ${easing}` :\n `top ${speed}ms ${easing}, left ${speed}ms ${easing}, opacity ${speed}ms ${easing}`;\n\n items.forEach((item) => {\n item.element.style.transition = str;\n });\n }\n\n _getItems() {\n return Array.from(this.element.children)\n .filter(el => matches(el, this.options.itemSelector))\n .map(el => new ShuffleItem(el));\n }\n\n /**\n * When new elements are added to the shuffle container, update the array of\n * items because that is the order `_layout` calls them.\n * @param {Array.} items Items to track.\n */\n _saveNewItems(items) {\n const children = Array.from(this.element.children);\n this.items = sorter(this.items.concat(items), {\n by(element) {\n return children.indexOf(element);\n },\n });\n }\n\n _getFilteredItems() {\n return this.items.filter(item => item.isVisible);\n }\n\n _getConcealedItems() {\n return this.items.filter(item => !item.isVisible);\n }\n\n /**\n * Returns the column size, based on column width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @param {number} gutterSize Size of the gutters.\n * @return {number}\n * @private\n */\n _getColumnSize(containerWidth, gutterSize) {\n let size;\n\n // If the columnWidth property is a function, then the grid is fluid\n if (typeof this.options.columnWidth === 'function') {\n size = this.options.columnWidth(containerWidth);\n\n // columnWidth option isn't a function, are they using a sizing element?\n } else if (this.useSizer) {\n size = Shuffle.getSize(this.options.sizer).width;\n\n // if not, how about the explicitly set option?\n } else if (this.options.columnWidth) {\n size = this.options.columnWidth;\n\n // or use the size of the first item\n } else if (this.items.length > 0) {\n size = Shuffle.getSize(this.items[0].element, true).width;\n\n // if there's no items, use size of container\n } else {\n size = containerWidth;\n }\n\n // Don't let them set a column width of zero.\n if (size === 0) {\n size = containerWidth;\n }\n\n return size + gutterSize;\n }\n\n /**\n * Returns the gutter size, based on gutter width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @return {number}\n * @private\n */\n _getGutterSize(containerWidth) {\n let size;\n if (typeof this.options.gutterWidth === 'function') {\n size = this.options.gutterWidth(containerWidth);\n } else if (this.useSizer) {\n size = getNumberStyle(this.options.sizer, 'marginLeft');\n } else {\n size = this.options.gutterWidth;\n }\n\n return size;\n }\n\n /**\n * Calculate the number of columns to be used. Gets css if using sizer element.\n * @param {number} [containerWidth] Optionally specify a container width if\n * it's already available.\n */\n _setColumns(containerWidth = Shuffle.getSize(this.element).width) {\n const gutter = this._getGutterSize(containerWidth);\n const columnWidth = this._getColumnSize(containerWidth, gutter);\n let calculatedColumns = (containerWidth + gutter) / columnWidth;\n\n // Widths given from getStyles are not precise enough...\n if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) <\n this.options.columnThreshold) {\n // e.g. calculatedColumns = 11.998876\n calculatedColumns = Math.round(calculatedColumns);\n }\n\n this.cols = Math.max(Math.floor(calculatedColumns), 1);\n this.containerWidth = containerWidth;\n this.colWidth = columnWidth;\n }\n\n /**\n * Adjust the height of the grid\n */\n _setContainerSize() {\n this.element.style.height = this._getContainerSize() + 'px';\n }\n\n /**\n * Based on the column heights, it returns the biggest one.\n * @return {number}\n * @private\n */\n _getContainerSize() {\n return arrayMax(this.positions);\n }\n\n /**\n * Get the clamped stagger amount.\n * @param {number} index Index of the item to be staggered.\n * @return {number}\n */\n _getStaggerAmount(index) {\n return Math.min(index * this.options.staggerAmount, this.options.staggerAmountMax);\n }\n\n /**\n * Emit an event from this instance.\n * @param {string} name Event name.\n * @param {Object} [data={}] Optional object data.\n */\n _dispatch(name, data = {}) {\n if (this.isDestroyed) {\n return;\n }\n\n data.shuffle = this;\n this.emit(name, data);\n }\n\n /**\n * Zeros out the y columns array, which is used to determine item placement.\n * @private\n */\n _resetCols() {\n let i = this.cols;\n this.positions = [];\n while (i) {\n i -= 1;\n this.positions.push(0);\n }\n }\n\n /**\n * Loops through each item that should be shown and calculates the x, y position.\n * @param {Array.} items Array of items that will be shown/layed\n * out in order in their array.\n */\n _layout(items) {\n const itemPositions = this._getNextPositions(items);\n\n let count = 0;\n items.forEach((item, i) => {\n const currPos = item.point;\n const currScale = item.scale;\n const nextPosition = itemPositions[i];\n\n function callback() {\n item.element.style.transitionDelay = '';\n item.applyCss(ShuffleItem.Css.VISIBLE.after);\n }\n\n // If the item will not change its position, do not add it to the render\n // queue. Transitions don't fire when setting a property to the same value.\n if (Point.equals(currPos, nextPosition) && currScale === ShuffleItem.Scale.VISIBLE) {\n item.applyCss(ShuffleItem.Css.VISIBLE.before);\n callback();\n return;\n }\n\n item.point = nextPosition;\n item.scale = ShuffleItem.Scale.VISIBLE;\n\n // Clone the object so that the `before` object isn't modified when the\n // transition delay is added.\n const styles = Object.assign({}, ShuffleItem.Css.VISIBLE.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Return an array of Point instances representing the future positions of\n * each item.\n * @param {Array.} items Array of sorted shuffle items.\n * @return {Array.}\n * @private\n */\n _getNextPositions(items) {\n // If position data is going to be changed, add the item's size to the\n // transformer to allow for calculations.\n if (this.options.isCentered) {\n const itemsData = items.map((item, i) => {\n const itemSize = Shuffle.getSize(item.element, true);\n const point = this._getItemPosition(itemSize);\n return new Rect(point.x, point.y, itemSize.width, itemSize.height, i);\n });\n\n return this.getTransformedPositions(itemsData, this.containerWidth);\n }\n\n // If no transforms are going to happen, simply return an array of the\n // future points of each item.\n return items.map(item => this._getItemPosition(Shuffle.getSize(item.element, true)));\n }\n\n /**\n * Determine the location of the next item, based on its size.\n * @param {{width: number, height: number}} itemSize Object with width and height.\n * @return {Point}\n * @private\n */\n _getItemPosition(itemSize) {\n return getItemPosition({\n itemSize,\n positions: this.positions,\n gridSize: this.colWidth,\n total: this.cols,\n threshold: this.options.columnThreshold,\n buffer: this.options.buffer,\n });\n }\n\n /**\n * Mutate positions before they're applied.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n * @protected\n */\n getTransformedPositions(itemRects, containerWidth) {\n return getCenteredPositions(itemRects, containerWidth);\n }\n\n /**\n * Hides the elements that don't match our filter.\n * @param {Array.} collection Collection to shrink.\n * @private\n */\n _shrink(collection = this._getConcealedItems()) {\n let count = 0;\n collection.forEach((item) => {\n function callback() {\n item.applyCss(ShuffleItem.Css.HIDDEN.after);\n }\n\n // Continuing would add a transitionend event listener to the element, but\n // that listener would not execute because the transform and opacity would\n // stay the same.\n // The callback is executed here because it is not guaranteed to be called\n // after the transitionend event because the transitionend could be\n // canceled if another animation starts.\n if (item.scale === ShuffleItem.Scale.HIDDEN) {\n item.applyCss(ShuffleItem.Css.HIDDEN.before);\n callback();\n return;\n }\n\n item.scale = ShuffleItem.Scale.HIDDEN;\n\n const styles = Object.assign({}, ShuffleItem.Css.HIDDEN.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Resize handler.\n * @private\n */\n _handleResize() {\n // If shuffle is disabled, destroyed, don't do anything\n if (!this.isEnabled || this.isDestroyed) {\n return;\n }\n\n this.update();\n }\n\n /**\n * Returns styles which will be applied to the an item for a transition.\n * @param {Object} obj Transition options.\n * @return {!Object} Transforms for transitions, left/top for animate.\n * @protected\n */\n getStylesForTransition({ item, styles }) {\n if (!styles.transitionDelay) {\n styles.transitionDelay = '0ms';\n }\n\n const x = item.point.x;\n const y = item.point.y;\n\n if (this.options.useTransforms) {\n styles.transform = `translate(${x}px, ${y}px) scale(${item.scale})`;\n } else {\n styles.left = x + 'px';\n styles.top = y + 'px';\n }\n\n return styles;\n }\n\n /**\n * Listen for the transition end on an element and execute the itemCallback\n * when it finishes.\n * @param {Element} element Element to listen on.\n * @param {Function} itemCallback Callback for the item.\n * @param {Function} done Callback to notify `parallel` that this one is done.\n */\n _whenTransitionDone(element, itemCallback, done) {\n const id = onTransitionEnd(element, (evt) => {\n itemCallback();\n done(null, evt);\n });\n\n this._transitions.push(id);\n }\n\n /**\n * Return a function which will set CSS styles and call the `done` function\n * when (if) the transition finishes.\n * @param {Object} opts Transition object.\n * @return {Function} A function to be called with a `done` function.\n */\n _getTransitionFunction(opts) {\n return (done) => {\n opts.item.applyCss(this.getStylesForTransition(opts));\n this._whenTransitionDone(opts.item.element, opts.callback, done);\n };\n }\n\n /**\n * Execute the styles gathered in the style queue. This applies styles to elements,\n * triggering transitions.\n * @private\n */\n _processQueue() {\n if (this.isTransitioning) {\n this._cancelMovement();\n }\n\n const hasSpeed = this.options.speed > 0;\n const hasQueue = this._queue.length > 0;\n\n if (hasQueue && hasSpeed && this.isInitialized) {\n this._startTransitions(this._queue);\n } else if (hasQueue) {\n this._styleImmediately(this._queue);\n this._dispatch(Shuffle.EventType.LAYOUT);\n\n // A call to layout happened, but none of the newly visible items will\n // change position or the transition duration is zero, which will not trigger\n // the transitionend event.\n } else {\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n // Remove everything in the style queue\n this._queue.length = 0;\n }\n\n /**\n * Wait for each transition to finish, the emit the layout event.\n * @param {Array.} transitions Array of transition objects.\n */\n _startTransitions(transitions) {\n // Set flag that shuffle is currently in motion.\n this.isTransitioning = true;\n\n // Create an array of functions to be called.\n const callbacks = transitions.map(obj => this._getTransitionFunction(obj));\n\n parallel(callbacks, this._movementFinished.bind(this));\n }\n\n _cancelMovement() {\n // Remove the transition end event for each listener.\n this._transitions.forEach(cancelTransitionEnd);\n\n // Reset the array.\n this._transitions.length = 0;\n\n // Show it's no longer active.\n this.isTransitioning = false;\n }\n\n /**\n * Apply styles without a transition.\n * @param {Array.} objects Array of transition objects.\n * @private\n */\n _styleImmediately(objects) {\n if (objects.length) {\n const elements = objects.map(obj => obj.item.element);\n\n Shuffle._skipTransitions(elements, () => {\n objects.forEach((obj) => {\n obj.item.applyCss(this.getStylesForTransition(obj));\n obj.callback();\n });\n });\n }\n }\n\n _movementFinished() {\n this._transitions.length = 0;\n this.isTransitioning = false;\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n /**\n * The magic. This is what makes the plugin 'shuffle'\n * @param {string|Function|Array.} [category] Category to filter by.\n * Can be a function, string, or array of strings.\n * @param {Object} [sortObj] A sort object which can sort the visible set\n */\n filter(category, sortObj) {\n if (!this.isEnabled) {\n return;\n }\n\n if (!category || (category && category.length === 0)) {\n category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign\n }\n\n this._filter(category);\n\n // Shrink each hidden item\n this._shrink();\n\n // How many visible elements?\n this._updateItemCount();\n\n // Update transforms on visible elements so they will animate to their new positions.\n this.sort(sortObj);\n }\n\n /**\n * Gets the visible elements, sorts them, and passes them to layout.\n * @param {Object} sortOptions The options object to pass to `sorter`.\n */\n sort(sortOptions = this.lastSort) {\n if (!this.isEnabled) {\n return;\n }\n\n this._resetCols();\n\n const items = sorter(this._getFilteredItems(), sortOptions);\n\n this._layout(items);\n\n // `_layout` always happens after `_shrink`, so it's safe to process the style\n // queue here with styles from the shrink method.\n this._processQueue();\n\n // Adjust the height of the container.\n this._setContainerSize();\n\n this.lastSort = sortOptions;\n }\n\n /**\n * Reposition everything.\n * @param {boolean} isOnlyLayout If true, column and gutter widths won't be\n * recalculated.\n */\n update(isOnlyLayout) {\n if (this.isEnabled) {\n if (!isOnlyLayout) {\n // Get updated colCount\n this._setColumns();\n }\n\n // Layout items\n this.sort();\n }\n }\n\n /**\n * Use this instead of `update()` if you don't need the columns and gutters updated\n * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations\n * could be off.\n */\n layout() {\n this.update(true);\n }\n\n /**\n * New items have been appended to shuffle. Mix them in with the current\n * filter or sort status.\n * @param {Array.} newItems Collection of new items.\n */\n add(newItems) {\n const items = arrayUnique(newItems).map(el => new ShuffleItem(el));\n\n // Add classes and set initial positions.\n this._initItems(items);\n\n // Add transition to each item.\n this.setItemTransitions(items);\n\n // Update the list of items.\n this._saveNewItems(items);\n\n // Update layout/visibility of new and old items.\n this.filter(this.lastFilter);\n }\n\n /**\n * Disables shuffle from updating dimensions and layout on resize\n */\n disable() {\n this.isEnabled = false;\n }\n\n /**\n * Enables shuffle again\n * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters\n */\n enable(isUpdateLayout = true) {\n this.isEnabled = true;\n if (isUpdateLayout) {\n this.update();\n }\n }\n\n /**\n * Remove 1 or more shuffle items\n * @param {Array.} elements An array containing one or more\n * elements in shuffle\n * @return {Shuffle} The shuffle object\n */\n remove(elements) {\n if (!elements.length) {\n return;\n }\n\n const collection = arrayUnique(elements);\n\n const oldItems = collection\n .map(element => this.getItemByElement(element))\n .filter(item => !!item);\n\n const handleLayout = () => {\n this._disposeItems(oldItems);\n\n // Remove the collection in the callback\n collection.forEach((element) => {\n element.parentNode.removeChild(element);\n });\n\n this._dispatch(Shuffle.EventType.REMOVED, { collection });\n };\n\n // Hide collection first.\n this._toggleFilterClasses({\n visible: [],\n hidden: oldItems,\n });\n\n this._shrink(oldItems);\n\n this.sort();\n\n // Update the list of items here because `remove` could be called again\n // with an item that is in the process of being removed.\n this.items = this.items.filter(item => !oldItems.includes(item));\n this._updateItemCount();\n\n this.once(Shuffle.EventType.LAYOUT, handleLayout);\n }\n\n /**\n * Retrieve a shuffle item by its element.\n * @param {Element} element Element to look for.\n * @return {?ShuffleItem} A shuffle item or null if it's not found.\n */\n getItemByElement(element) {\n return this.items.find(item => item.element === element);\n }\n\n /**\n * Dump the elements currently stored and reinitialize all child elements which\n * match the `itemSelector`.\n */\n resetItems() {\n // Remove refs to current items.\n this._disposeItems(this.items);\n this.isInitialized = false;\n\n // Find new items in the DOM.\n this.items = this._getItems();\n\n // Set initial styles on the new items.\n this._initItems(this.items);\n\n this.once(Shuffle.EventType.LAYOUT, () => {\n // Add transition to each item.\n this.setItemTransitions(this.items);\n this.isInitialized = true;\n });\n\n // Lay out all items.\n this.sort();\n }\n\n /**\n * Destroys shuffle, removes events, styles, and classes\n */\n destroy() {\n this._cancelMovement();\n window.removeEventListener('resize', this._onResize);\n\n // Reset container styles\n this.element.classList.remove('shuffle');\n this.element.removeAttribute('style');\n\n // Reset individual item styles\n this._disposeItems(this.items);\n\n this.items.length = 0;\n this._transitions.length = 0;\n\n // Null DOM references\n this.options.sizer = null;\n this.element = null;\n\n // Set a flag so if a debounced resize has been triggered,\n // it can first check if it is actually isDestroyed and not doing anything\n this.isDestroyed = true;\n this.isEnabled = false;\n }\n\n /**\n * Returns the outer width of an element, optionally including its margins.\n *\n * There are a few different methods for getting the width of an element, none of\n * which work perfectly for all Shuffle's use cases.\n *\n * 1. getBoundingClientRect() `left` and `right` properties.\n * - Accounts for transform scaled elements, making it useless for Shuffle\n * elements which have shrunk.\n * 2. The `offsetWidth` property.\n * - This value stays the same regardless of the elements transform property,\n * however, it does not return subpixel values.\n * 3. getComputedStyle()\n * - This works great Chrome, Firefox, Safari, but IE<=11 does not include\n * padding and border when box-sizing: border-box is set, requiring a feature\n * test and extra work to add the padding back for IE and other browsers which\n * follow the W3C spec here.\n *\n * @param {Element} element The element.\n * @param {boolean} [includeMargins] Whether to include margins. Default is false.\n * @return {{width: number, height: number}} The width and height.\n */\n static getSize(element, includeMargins) {\n // Store the styles so that they can be used by others without asking for it again.\n const styles = window.getComputedStyle(element, null);\n let width = getNumberStyle(element, 'width', styles);\n let height = getNumberStyle(element, 'height', styles);\n\n if (includeMargins) {\n const marginLeft = getNumberStyle(element, 'marginLeft', styles);\n const marginRight = getNumberStyle(element, 'marginRight', styles);\n const marginTop = getNumberStyle(element, 'marginTop', styles);\n const marginBottom = getNumberStyle(element, 'marginBottom', styles);\n width += marginLeft + marginRight;\n height += marginTop + marginBottom;\n }\n\n return {\n width,\n height,\n };\n }\n\n /**\n * Change a property or execute a function which will not have a transition\n * @param {Array.} elements DOM elements that won't be transitioned.\n * @param {Function} callback A function which will be called while transition\n * is set to 0ms.\n * @private\n */\n static _skipTransitions(elements, callback) {\n const zero = '0ms';\n\n // Save current duration and delay.\n const data = elements.map((element) => {\n const style = element.style;\n const duration = style.transitionDuration;\n const delay = style.transitionDelay;\n\n // Set the duration to zero so it happens immediately\n style.transitionDuration = zero;\n style.transitionDelay = zero;\n\n return {\n duration,\n delay,\n };\n });\n\n callback();\n\n // Cause forced synchronous layout.\n elements[0].offsetWidth; // eslint-disable-line no-unused-expressions\n\n // Put the duration back\n elements.forEach((element, i) => {\n element.style.transitionDuration = data[i].duration;\n element.style.transitionDelay = data[i].delay;\n });\n }\n}\n\nShuffle.ShuffleItem = ShuffleItem;\n\nShuffle.ALL_ITEMS = 'all';\nShuffle.FILTER_ATTRIBUTE_KEY = 'groups';\n\n/**\n * @enum {string}\n */\nShuffle.EventType = {\n LAYOUT: 'shuffle:layout',\n REMOVED: 'shuffle:removed',\n};\n\n/** @enum {string} */\nShuffle.Classes = Classes;\n\n/**\n * @enum {string}\n */\nShuffle.FilterMode = {\n ANY: 'any',\n ALL: 'all',\n};\n\n// Overrideable options\nShuffle.options = {\n // Initial filter group.\n group: Shuffle.ALL_ITEMS,\n\n // Transition/animation speed (milliseconds).\n speed: 250,\n\n // CSS easing function to use.\n easing: 'ease',\n\n // e.g. '.picture-item'.\n itemSelector: '*',\n\n // Element or selector string. Use an element to determine the size of columns\n // and gutters.\n sizer: null,\n\n // A static number or function that tells the plugin how wide the gutters\n // between columns are (in pixels).\n gutterWidth: 0,\n\n // A static number or function that returns a number which tells the plugin\n // how wide the columns are (in pixels).\n columnWidth: 0,\n\n // If your group is not json, and is comma delimeted, you could set delimeter\n // to ','.\n delimeter: null,\n\n // Useful for percentage based heights when they might not always be exactly\n // the same (in pixels).\n buffer: 0,\n\n // Reading the width of elements isn't precise enough and can cause columns to\n // jump between values.\n columnThreshold: 0.01,\n\n // Shuffle can be isInitialized with a sort object. It is the same object\n // given to the sort method.\n initialSort: null,\n\n // By default, shuffle will throttle resize events. This can be changed or\n // removed.\n throttle,\n\n // How often shuffle can be called on resize (in milliseconds).\n throttleTime: 300,\n\n // Transition delay offset for each item in milliseconds.\n staggerAmount: 15,\n\n // Maximum stagger delay in milliseconds.\n staggerAmountMax: 250,\n\n // Whether to use transforms or absolute positioning.\n useTransforms: true,\n\n // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With \"any\",\n // the element passes the test if any of its groups are in the array. With \"all\",\n // the element only passes if all groups are in the array.\n filterMode: Shuffle.FilterMode.ANY,\n\n // Whether to center grid items in the row with the leftover space.\n isCentered: false,\n};\n\n// Expose for testing. Hack at your own risk.\nShuffle.__Point = Point;\nShuffle.__Rect = Rect;\nShuffle.__sorter = sorter;\nShuffle.__getColumnSpan = getColumnSpan;\nShuffle.__getAvailablePositions = getAvailablePositions;\nShuffle.__getShortColumn = getShortColumn;\nShuffle.__getCenteredPositions = getCenteredPositions;\n\nexport default Shuffle;\n","'use strict';\n\nvar proto = typeof Element !== 'undefined' ? Element.prototype : {};\nvar vendor = proto.matches\n || proto.matchesSelector\n || proto.webkitMatchesSelector\n || proto.mozMatchesSelector\n || proto.msMatchesSelector\n || proto.oMatchesSelector;\n\nmodule.exports = match;\n\n/**\n * Match `el` to `selector`.\n *\n * @param {Element} el\n * @param {String} selector\n * @return {Boolean}\n * @api public\n */\n\nfunction match(el, selector) {\n if (!el || el.nodeType !== 1) return false;\n if (vendor) return vendor.call(el, selector);\n var nodes = el.parentNode.querySelectorAll(selector);\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i] == el) return true;\n }\n return false;\n}\n","import getNumber from './get-number';\n\nclass Point {\n\n /**\n * Represents a coordinate pair.\n * @param {number} [x=0] X.\n * @param {number} [y=0] Y.\n */\n constructor(x, y) {\n this.x = getNumber(x);\n this.y = getNumber(y);\n }\n\n /**\n * Whether two points are equal.\n * @param {Point} a Point A.\n * @param {Point} b Point B.\n * @return {boolean}\n */\n static equals(a, b) {\n return a.x === b.x && a.y === b.y;\n }\n}\n\nexport default Point;\n","export default class Rect {\n /**\n * Class for representing rectangular regions.\n * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n * @param {number} x Left.\n * @param {number} y Top.\n * @param {number} w Width.\n * @param {number} h Height.\n * @param {number} id Identifier\n * @constructor\n */\n constructor(x, y, w, h, id) {\n this.id = id;\n\n /** @type {number} */\n this.left = x;\n\n /** @type {number} */\n this.top = y;\n\n /** @type {number} */\n this.width = w;\n\n /** @type {number} */\n this.height = h;\n }\n\n /**\n * Returns whether two rectangles intersect.\n * @param {Rect} a A Rectangle.\n * @param {Rect} b A Rectangle.\n * @return {boolean} Whether a and b intersect.\n */\n static intersects(a, b) {\n return (\n a.left < b.left + b.width && b.left < a.left + a.width &&\n a.top < b.top + b.height && b.top < a.top + a.height);\n }\n}\n","export default {\n BASE: 'shuffle',\n SHUFFLE_ITEM: 'shuffle-item',\n VISIBLE: 'shuffle-item--visible',\n HIDDEN: 'shuffle-item--hidden',\n};\n","import Point from './point';\nimport Classes from './classes';\n\nlet id = 0;\n\nclass ShuffleItem {\n constructor(element) {\n id += 1;\n this.id = id;\n this.element = element;\n this.isVisible = true;\n }\n\n show() {\n this.isVisible = true;\n this.element.classList.remove(Classes.HIDDEN);\n this.element.classList.add(Classes.VISIBLE);\n this.element.removeAttribute('aria-hidden');\n }\n\n hide() {\n this.isVisible = false;\n this.element.classList.remove(Classes.VISIBLE);\n this.element.classList.add(Classes.HIDDEN);\n this.element.setAttribute('aria-hidden', true);\n }\n\n init() {\n this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]);\n this.applyCss(ShuffleItem.Css.INITIAL);\n this.scale = ShuffleItem.Scale.VISIBLE;\n this.point = new Point();\n }\n\n addClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.add(className);\n });\n }\n\n removeClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.remove(className);\n });\n }\n\n applyCss(obj) {\n Object.keys(obj).forEach((key) => {\n this.element.style[key] = obj[key];\n });\n }\n\n dispose() {\n this.removeClasses([\n Classes.HIDDEN,\n Classes.VISIBLE,\n Classes.SHUFFLE_ITEM,\n ]);\n\n this.element.removeAttribute('style');\n this.element = null;\n }\n}\n\nShuffleItem.Css = {\n INITIAL: {\n position: 'absolute',\n top: 0,\n left: 0,\n visibility: 'visible',\n 'will-change': 'transform',\n },\n VISIBLE: {\n before: {\n opacity: 1,\n visibility: 'visible',\n },\n after: {},\n },\n HIDDEN: {\n before: {\n opacity: 0,\n },\n after: {\n visibility: 'hidden',\n },\n },\n};\n\nShuffleItem.Scale = {\n VISIBLE: 1,\n HIDDEN: 0.001,\n};\n\nexport default ShuffleItem;\n","const element = document.body || document.documentElement;\nconst e = document.createElement('div');\ne.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\nelement.appendChild(e);\n\nconst width = window.getComputedStyle(e, null).width;\nconst ret = width === '10px';\n\nelement.removeChild(e);\n\nexport default ret;\n","module.exports = throttle;\n\n/**\n * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds.\n *\n * @param {Function} func Function to wrap.\n * @param {Number} wait Number of milliseconds that must elapse between `func` invocations.\n * @return {Function} A new function that wraps the `func` function passed in.\n */\n\nfunction throttle (func, wait) {\n var ctx, args, rtn, timeoutID; // caching\n var last = 0;\n\n return function throttled () {\n ctx = this;\n args = arguments;\n var delta = new Date() - last;\n if (!timeoutID)\n if (delta >= wait) call();\n else timeoutID = setTimeout(call, wait - delta);\n return rtn;\n };\n\n function call () {\n timeoutID = 0;\n last = +new Date();\n rtn = func.apply(ctx, args);\n ctx = null;\n args = null;\n }\n}\n"],"names":["E","noop","getNumber","value","parseFloat","getNumberStyle","element","style","styles","window","getComputedStyle","COMPUTED_SIZE_INCLUDES_PADDING","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth","randomize","array","n","length","i","Math","floor","random","temp","sorter","arr","options","opts","Object","assign","defaults","original","Array","from","revert","by","sort","a","b","valA","key","valB","undefined","reverse","uniqueId","eventName","count","cancelTransitionEnd","id","transitions","removeEventListener","listener","onTransitionEnd","callback","evt","currentTarget","target","addEventListener","arrayMax","max","apply","arrayMin","min","getColumnSpan","itemWidth","columnWidth","columns","threshold","columnSpan","abs","round","ceil","getAvailablePositions","positions","available","push","slice","getShortColumn","buffer","minPosition","len","getItemPosition","itemSize","gridSize","total","span","width","setY","shortColumnIndex","point","Point","setHeight","height","getCenteredPositions","itemRects","containerWidth","rowMap","forEach","itemRect","top","rects","rows","centeredRows","keys","lastItem","end","left","offset","finalRects","canMove","newRects","every","r","newRect","Rect","noOverlap","some","intersects","intersectingRect","rowIndex","findIndex","items","includes","splice","concat","map","arrayUnique","x","Set","prototype","on","name","ctx","e","this","fn","once","self","off","arguments","_","emit","data","call","evtArr","evts","liveEvents","proto","Element","vendor","matches","matchesSelector","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","el","selector","nodeType","nodes","parentNode","querySelectorAll","fns","context","maybeDone","err","result","finished","results","pending","y","w","h","ShuffleItem","isVisible","classList","remove","Classes","HIDDEN","add","VISIBLE","removeAttribute","setAttribute","addClasses","SHUFFLE_ITEM","applyCss","Css","INITIAL","scale","Scale","classes","className","obj","removeClasses","document","body","documentElement","createElement","cssText","appendChild","ret","removeChild","Shuffle","useSizer","lastSort","group","ALL_ITEMS","lastFilter","isEnabled","isDestroyed","isInitialized","_transitions","isTransitioning","_queue","_this","_getElementOption","TypeError","_init","_getItems","sizer","BASE","_initItems","_onResize","_getResizeFunction","readyState","layout","bind","onLoad","containerCss","getSize","_validateStyles","_setColumns","filter","initialSort","offsetWidth","setItemTransitions","transition","speed","easing","resizeFunction","_handleResize","throttle","throttleTime","option","querySelector","jquery","position","overflow","category","collection","set","_getFilteredSets","_toggleFilterClasses","visible","hidden","item","_this2","_doesPassFilter","testCategory","attr","getAttribute","FILTER_ATTRIBUTE_KEY","delimeter","split","JSON","parse","isArray","filterMode","FilterMode","ANY","show","hide","init","dispose","visibleItems","_getFilteredItems","str","useTransforms","children","_this3","itemSelector","indexOf","gutterSize","size","gutterWidth","gutter","_getGutterSize","_getColumnSize","calculatedColumns","columnThreshold","cols","colWidth","_getContainerSize","index","staggerAmount","staggerAmountMax","shuffle","itemPositions","_getNextPositions","transitionDelay","after","currPos","currScale","nextPosition","equals","before","_this4","_getStaggerAmount","isCentered","itemsData","_this5","_getItemPosition","getTransformedPositions","_getConcealedItems","_this6","update","transform","itemCallback","done","_this7","getStylesForTransition","_whenTransitionDone","_cancelMovement","hasSpeed","hasQueue","_startTransitions","_styleImmediately","_dispatch","EventType","LAYOUT","callbacks","_this8","_getTransitionFunction","_movementFinished","objects","elements","_skipTransitions","_this9","sortObj","_filter","_shrink","_updateItemCount","sortOptions","_resetCols","_layout","_processQueue","_setContainerSize","isOnlyLayout","newItems","_saveNewItems","isUpdateLayout","oldItems","_this10","getItemByElement","_disposeItems","REMOVED","find","_this11","includeMargins","duration","transitionDuration","delay","TinyEmitter","func","wait","timeoutID","last","Date","rtn","args","delta","setTimeout","__Point","__Rect","__sorter","__getColumnSpan","__getAvailablePositions","__getShortColumn","__getCenteredPositions"],"mappings":"mLAAA,SAASA,KCuCT,SAASC,KClCT,SAAwBC,EAAUC,UACzBC,WAAWD,IAAU,ECO9B,SAAwBE,EAAeC,EAASC,OAC9CC,yDAASC,OAAOC,iBAAiBJ,EAAS,MACtCH,EAAQD,EAAUM,EAAOD,WAGxBI,GAA4C,UAAVJ,EAK3BI,GAA4C,WAAVJ,OACnCL,EAAUM,EAAOI,YACxBV,EAAUM,EAAOK,eACjBX,EAAUM,EAAOM,gBACjBZ,EAAUM,EAAOO,uBARVb,EAAUM,EAAOQ,aACxBd,EAAUM,EAAOS,cACjBf,EAAUM,EAAOU,iBACjBhB,EAAUM,EAAOW,kBAQdhB,ECvBT,SAASiB,EAAUC,WACbC,EAAID,EAAME,OAEPD,GAAG,IACH,MACCE,EAAIC,KAAKC,MAAMD,KAAKE,UAAYL,EAAI,IACpCM,EAAOP,EAAMG,KACbA,GAAKH,EAAMC,KACXA,GAAKM,SAGNP,EAmBT,SAAwBQ,EAAOC,EAAKC,OAC5BC,EAAOC,OAAOC,UAAWC,EAAUJ,GACnCK,EAAWC,MAAMC,KAAKR,GACxBS,GAAS,SAERT,EAAIP,OAILS,EAAKZ,UACAA,EAAUU,IAKI,mBAAZE,EAAKQ,MACVC,KAAK,SAACC,EAAGC,MAEPJ,SACK,MAGHK,EAAOZ,EAAKQ,GAAGE,EAAEV,EAAKa,MACtBC,EAAOd,EAAKQ,GAAGG,EAAEX,EAAKa,kBAGfE,IAATH,QAA+BG,IAATD,MACf,EACF,GAGLF,EAAOE,GAAiB,cAATF,GAAiC,aAATE,GACjC,EAGNF,EAAOE,GAAiB,aAATF,GAAgC,cAATE,EACjC,EAGF,IAKPP,EACKH,GAGLJ,EAAKgB,WACHA,UAGClB,OCrFT,SAASmB,cACE,EACFC,EAAYC,EAGrB,SAAgBC,EAAoBC,WAC9BC,EAAYD,OACFA,GAAI/C,QAAQiD,oBAAoBL,EAAWI,EAAYD,GAAIG,YAC3DH,GAAM,MACX,GAMX,SAAgBI,EAAgBnD,EAASoD,OACjCL,EAAKJ,IACLO,EAAW,SAACG,GACZA,EAAIC,gBAAkBD,EAAIE,WACRR,KACXM,cAILG,iBAAiBZ,EAAWM,KAExBH,IAAQ/C,UAASkD,YAEtBH,EChCM,SAASU,EAAS1C,UACxBI,KAAKuC,IAAIC,MAAMxC,KAAMJ,GCDf,SAAS6C,EAAS7C,UACxBI,KAAK0C,IAAIF,MAAMxC,KAAMJ,GCY9B,SAAgB+C,EAAcC,EAAWC,EAAaC,EAASC,OACzDC,EAAaJ,EAAYC,SAKzB7C,KAAKiD,IAAIjD,KAAKkD,MAAMF,GAAcA,GAAcD,MAErC/C,KAAKkD,MAAMF,IAInBhD,KAAK0C,IAAI1C,KAAKmD,KAAKH,GAAaF,GASzC,SAAgBM,EAAsBC,EAAWL,EAAYF,MAExC,IAAfE,SACKK,MA4BJ,IAHCC,KAGGvD,EAAI,EAAGA,GAAK+C,EAAUE,EAAYjD,MAE/BwD,KAAKjB,EAASe,EAAUG,MAAMzD,EAAGA,EAAIiD,YAG1CM,EAWT,SAAgBG,EAAeJ,EAAWK,OAEnC,IADCC,EAAclB,EAASY,GACpBtD,EAAI,EAAG6D,EAAMP,EAAUvD,OAAQC,EAAI6D,EAAK7D,OAC3CsD,EAAUtD,IAAM4D,EAAcD,GAAUL,EAAUtD,IAAM4D,EAAcD,SACjE3D,SAIJ,EAaT,SAAgB8D,SAcT,IAd2BC,IAAAA,SAAUT,IAAAA,UAAWU,IAAAA,SAAUC,IAAAA,MAAOjB,IAAAA,UAAWW,IAAAA,OAC3EO,EAAOtB,EAAcmB,EAASI,MAAOH,EAAUC,EAAOjB,GACtDoB,EAAOf,EAAsBC,EAAWY,EAAMD,GAC9CI,EAAmBX,EAAeU,EAAMT,GAGxCW,EAAQ,IAAIC,EAChBtE,KAAKkD,MAAMa,EAAWK,GACtBpE,KAAKkD,MAAMiB,EAAKC,KAKZG,EAAYJ,EAAKC,GAAoBN,EAASU,OAC3CzE,EAAI,EAAGA,EAAIkE,EAAMlE,MACdqE,EAAmBrE,GAAKwE,SAG7BF,EAWT,SAAgBI,EAAqBC,EAAWC,OACxCC,OAKIC,QAAQ,SAACC,GACbF,EAAOE,EAASC,OAEXD,EAASC,KAAKxB,KAAKuB,KAGnBA,EAASC,MAAQD,SAOxBE,KACEC,KACAC,mBACCC,KAAKP,GAAQC,QAAQ,SAACzD,OACrBsD,EAAYE,EAAOxD,KACpBmC,KAAKmB,OACJU,EAAWV,EAAUA,EAAU5E,OAAS,GACxCuF,EAAMD,EAASE,KAAOF,EAASlB,MAC/BqB,EAASvF,KAAKkD,OAAOyB,EAAiBU,GAAO,GAE/CG,EAAad,EACbe,GAAU,KACVF,EAAS,EAAG,KACRG,QACIhB,EAAUiB,MAAM,SAACC,OACnBC,EAAU,IAAIC,EAAKF,EAAEN,KAAOC,EAAQK,EAAEb,IAAKa,EAAE1B,MAAO0B,EAAEpB,OAAQoB,EAAEhE,IAGhEmE,GAAaf,EAAMgB,KAAK,mBAAKF,EAAKG,WAAWJ,EAASD,cAEnDrC,KAAKsC,GACPE,SAKML,OAOZD,EAAS,KACRS,YACexB,EAAUsB,KAAK,mBAAYhB,EAAMgB,KAAK,SAACJ,OAClDK,EAAaH,EAAKG,WAAWnB,EAAUc,UACzCK,MACiBL,GAEdK,MAIO,KACRE,EAAWjB,EAAakB,UAAU,mBAASC,EAAMC,SAASJ,OACnDK,OAAOJ,EAAU,EAAGlB,EAAKkB,OAIlCnB,EAAMwB,OAAOhB,KACRjC,KAAKiC,QAOVgB,OAAOhE,SAAU0C,GACxBlE,KAAK,SAACC,EAAGC,UAAOD,EAAEW,GAAKV,EAAEU,KACzB6E,IAAI,mBAAY,IAAInC,EAAMQ,EAASQ,KAAMR,EAASC,OC7LvD,SAAS2B,EAAYC,UACZ/F,MAAMC,KAAK,IAAI+F,IAAID,ITjB5BpI,EAAEsI,WACAC,GAAI,SAAUC,EAAM9E,EAAU+E,GAC5B,IAAIC,EAAIC,KAAKD,IAAMC,KAAKD,MAOxB,OALCA,EAAEF,KAAUE,EAAEF,QAAaxD,MAC1B4D,GAAIlF,EACJ+E,IAAKA,IAGAE,MAGTE,KAAM,SAAUL,EAAM9E,EAAU+E,GAE9B,SAASjF,IACPsF,EAAKC,IAAIP,EAAMhF,GACfE,EAASO,MAAMwE,EAAKO,WAHtB,IAAIF,EAAOH,KAOX,OADAnF,EAASyF,EAAIvF,EACNiF,KAAKJ,GAAGC,EAAMhF,EAAUiF,IAGjCS,KAAM,SAAUV,GACd,IAAIW,KAAUlE,MAAMmE,KAAKJ,UAAW,GAChCK,IAAWV,KAAKD,IAAMC,KAAKD,OAASF,QAAavD,QACjDzD,EAAI,EACJ6D,EAAMgE,EAAO9H,OAEjB,IAAKC,EAAGA,EAAI6D,EAAK7D,IACf6H,EAAO7H,GAAGoH,GAAG3E,MAAMoF,EAAO7H,GAAGiH,IAAKU,GAGpC,OAAOR,MAGTI,IAAK,SAAUP,EAAM9E,GACnB,IAAIgF,EAAIC,KAAKD,IAAMC,KAAKD,MACpBY,EAAOZ,EAAEF,GACTe,KAEJ,GAAID,GAAQ5F,EACV,IAAK,IAAIlC,EAAI,EAAG6D,EAAMiE,EAAK/H,OAAQC,EAAI6D,EAAK7D,IACtC8H,EAAK9H,GAAGoH,KAAOlF,GAAY4F,EAAK9H,GAAGoH,GAAGK,IAAMvF,GAC9C6F,EAAWvE,KAAKsE,EAAK9H,IAY3B,OAJC+H,EAAiB,OACdb,EAAEF,GAAQe,SACHb,EAAEF,GAENG,OAIX,MAAiB3I,EU/DbwJ,EAA2B,oBAAZC,QAA0BA,QAAQnB,aACjDoB,EAASF,EAAMG,SACdH,EAAMI,iBACNJ,EAAMK,uBACNL,EAAMM,oBACNN,EAAMO,mBACNP,EAAMQ,mBAaX,SAAeC,EAAIC,GACjB,IAAKD,GAAsB,IAAhBA,EAAGE,SAAgB,OAAO,EACrC,GAAIT,EAAQ,OAAOA,EAAON,KAAKa,EAAIC,GAEnC,IAAK,IADDE,EAAQH,EAAGI,WAAWC,iBAAiBJ,GAClC1I,EAAI,EAAGA,EAAI4I,EAAM7I,OAAQC,IAChC,GAAI4I,EAAM5I,IAAMyI,EAAI,OAAO,EAE7B,OAAO,KT5BQ,SAAkBM,EAAKC,EAAS9G,GAsB/C,SAAS+G,EAAUjJ,GACjB,OAAO,SAAUkJ,EAAKC,GACpB,IAAIC,EAAJ,CAEA,GAAIF,EAGF,OAFAhH,EAASgH,EAAKG,QACdD,GAAW,GAIbC,EAAQrJ,GAAKmJ,IAENG,GAASpH,EAAS,KAAMmH,KAjC9BnH,IACoB,mBAAZ8G,GACT9G,EAAW8G,EACXA,EAAU,MAEV9G,EAAWzD,GAIf,IAAI6K,EAAUP,GAAOA,EAAIhJ,OACzB,IAAKuJ,EAAS,OAAOpH,EAAS,SAE9B,IAAIkH,GAAW,EACXC,EAAU,IAAIxI,MAAMyI,GAExBP,EAAIjE,QAAQkE,EAAU,SAAU5B,EAAIpH,GAClCoH,EAAGQ,KAAKoB,EAASC,EAAUjJ,KACzB,SAAUoH,EAAIpH,GAChBoH,EAAG6B,EAAUjJ,2zBUjBXuE,wBAOQqC,EAAG2C,kBACR3C,EAAIlI,EAAUkI,QACd2C,EAAI7K,EAAU6K,iDASPrI,EAAGC,UACRD,EAAE0F,IAAMzF,EAAEyF,GAAK1F,EAAEqI,IAAMpI,EAAEoI,WCrBfxD,wBAWPa,EAAG2C,EAAGC,EAAGC,EAAG5H,kBACjBA,GAAKA,OAGL0D,KAAOqB,OAGP5B,IAAMuE,OAGNpF,MAAQqF,OAGR/E,OAASgF,oDASEvI,EAAGC,UAEjBD,EAAEqE,KAAOpE,EAAEoE,KAAOpE,EAAEgD,OAAShD,EAAEoE,KAAOrE,EAAEqE,KAAOrE,EAAEiD,OACjDjD,EAAE8D,IAAM7D,EAAE6D,IAAM7D,EAAEsD,QAAUtD,EAAE6D,IAAM9D,EAAE8D,IAAM9D,EAAEuD,wBCnC5C,uBACQ,uBACL,+BACD,wBCDN5C,EAAK,EAEH6H,wBACQ5K,gBACJ,OACD+C,GAAKA,OACL/C,QAAUA,OACV6K,WAAY,gDAIZA,WAAY,OACZ7K,QAAQ8K,UAAUC,OAAOC,EAAQC,aACjCjL,QAAQ8K,UAAUI,IAAIF,EAAQG,cAC9BnL,QAAQoL,gBAAgB,mDAIxBP,WAAY,OACZ7K,QAAQ8K,UAAUC,OAAOC,EAAQG,cACjCnL,QAAQ8K,UAAUI,IAAIF,EAAQC,aAC9BjL,QAAQqL,aAAa,eAAe,uCAIpCC,YAAYN,EAAQO,aAAcP,EAAQG,eAC1CK,SAASZ,EAAYa,IAAIC,cACzBC,MAAQf,EAAYgB,MAAMT,aAC1B3F,MAAQ,IAAIC,qCAGRoG,gBACD7F,QAAQ,SAAC8F,KACV9L,QAAQ8K,UAAUI,IAAIY,2CAIjBD,gBACJ7F,QAAQ,SAAC8F,KACV9L,QAAQ8K,UAAUC,OAAOe,sCAIzBC,qBACAzF,KAAKyF,GAAK/F,QAAQ,SAACzD,KACnBvC,QAAQC,MAAMsC,GAAOwJ,EAAIxJ,4CAK3ByJ,eACHhB,EAAQC,OACRD,EAAQG,QACRH,EAAQO,oBAGLvL,QAAQoL,gBAAgB,cACxBpL,QAAU,cAInB4K,EAAYa,uBAEE,eACL,OACC,aACM,wBACG,sCAIJ,aACG,6CAMH,qBAGG,YAKlBb,EAAYgB,eACD,SACD,MC3FV,IAAM5L,EAAUiM,SAASC,MAAQD,SAASE,gBACpC/D,EAAI6D,SAASG,cAAc,OACjChE,EAAEnI,MAAMoM,QAAU,gDAClBrM,EAAQsM,YAAYlE,GAEpB,IACMmE,EAAgB,SADRpM,OAAOC,iBAAiBgI,EAAG,MAAM/C,MAG/CrF,EAAQwM,YAAYpE,GXapB,IAAMvG,YAEK,KAGL,gBAGO,MAIN,WCjCDmB,KACAJ,EAAY,gBACdC,EAAQ,EIwBRE,EAAK,EAEH0J,yBASQzM,OAASyB,yIAEdA,QAAUE,OAAOC,UAAW6K,EAAQhL,QAASA,KAE7CiL,UAAW,IACXC,cACAC,MAAQH,EAAQI,YAChBC,WAAaL,EAAQI,YACrBE,WAAY,IACZC,aAAc,IACdC,eAAgB,IAChBC,kBACAC,iBAAkB,IAClBC,cAECzD,EAAK0D,EAAKC,kBAAkBtN,OAE7B2J,QACG,IAAI4D,UAAU,6DAGjBvN,QAAU2J,IACV5G,GAAK,WAAaA,KACjB,IAEDyK,UACAP,eAAgB,6DAIhBzF,MAAQa,KAAKoF,iBAEbhM,QAAQiM,MAAQrF,KAAKiF,kBAAkBjF,KAAK5G,QAAQiM,OAErDrF,KAAK5G,QAAQiM,aACVhB,UAAW,QAIb1M,QAAQ8K,UAAUI,IAAIuB,EAAQzB,QAAQ2C,WAGtCC,WAAWvF,KAAKb,YAGhBqG,UAAYxF,KAAKyF,4BACftK,iBAAiB,SAAU6E,KAAKwF,WAKX,aAAxB5B,SAAS8B,WAA2B,KAChCC,EAAS3F,KAAK2F,OAAOC,KAAK5F,aACzB7E,iBAAiB,OAAQ,SAAS0K,WAChCjL,oBAAoB,OAAQiL,aAMjCC,EAAehO,OAAOC,iBAAiBiI,KAAKrI,QAAS,MACrD8F,EAAiB2G,EAAQ2B,QAAQ/F,KAAKrI,SAASqF,WAGhDgJ,gBAAgBF,QAIhBG,YAAYxI,QAGZyI,OAAOlG,KAAK5G,QAAQmL,MAAOvE,KAAK5G,QAAQ+M,kBAMxCxO,QAAQyO,iBACRC,mBAAmBrG,KAAKb,YACxBxH,QAAQC,MAAM0O,WAAa,UAAYtG,KAAK5G,QAAQmN,MAAQ,MAAQvG,KAAK5G,QAAQoN,wDAShFC,EAAiBzG,KAAK0G,cAAcd,KAAK5F,aACxCA,KAAK5G,QAAQuN,SAChB3G,KAAK5G,QAAQuN,SAASF,EAAgBzG,KAAK5G,QAAQwN,cACnDH,4CASYI,SAGM,iBAAXA,EACF7G,KAAKrI,QAAQmP,cAAcD,GAGzBA,GAAUA,EAAOrF,UAAgC,IAApBqF,EAAOrF,SACtCqF,EAGEA,GAAUA,EAAOE,OACnBF,EAAO,GAGT,6CAQOhP,GAEU,WAApBA,EAAOmP,gBACJrP,QAAQC,MAAMoP,SAAW,YAIR,WAApBnP,EAAOoP,gBACJtP,QAAQC,MAAMqP,SAAW,gDAa1BC,yDAAWlH,KAAKyE,WAAY0C,yDAAanH,KAAKb,MAC9CiI,EAAMpH,KAAKqH,iBAAiBH,EAAUC,eAGvCG,qBAAqBF,QAGrB3C,WAAayC,EAIM,iBAAbA,SACJ3C,MAAQ2C,GAGRE,2CAUQF,EAAU/H,cACrBoI,KACEC,YAGFN,IAAa9C,EAAQI,YACbrF,IAKJxB,QAAQ,SAAC8J,GACTC,EAAKC,gBAAgBT,EAAUO,EAAK9P,WAC9B0E,KAAKoL,KAENpL,KAAKoL,kEAkBJP,EAAUvP,YAWfiQ,EAAaV,UACbjJ,EAAKmB,SAAS8H,MAXC,mBAAbA,SACFA,EAASzG,KAAK9I,EAASA,EAASqI,UAInC6H,EAAOlQ,EAAQmQ,aAAa,QAAU1D,EAAQ2D,sBAC9C9J,EAAO+B,KAAK5G,QAAQ4O,UACpBH,EAAKI,MAAMjI,KAAK5G,QAAQ4O,WACxBE,KAAKC,MAAMN,UAMbnO,MAAM0O,QAAQlB,GACZlH,KAAK5G,QAAQiP,aAAejE,EAAQkE,WAAWC,IAC1CrB,EAASpI,KAAK8I,GAEhBV,EAASzI,MAAMmJ,GAGjB3J,EAAKmB,SAAS8H,uDAQAK,IAAAA,QAASC,IAAAA,SACtB7J,QAAQ,SAAC8J,KACVe,WAGA7K,QAAQ,SAAC8J,KACTgB,4CASEtJ,KACHxB,QAAQ,SAAC8J,KACRiB,+CASKvJ,KACNxB,QAAQ,SAAC8J,KACRkB,4DASFC,aAAe5I,KAAK6I,oBAAoBjQ,kDAU5BuG,OACXoH,EAAQvG,KAAK5G,QAAQmN,MACrBC,EAASxG,KAAK5G,QAAQoN,OAEtBsC,EAAM9I,KAAK5G,QAAQ2P,2BACVxC,QAAWC,eAAmBD,QAAWC,SAC/CD,QAAWC,YAAgBD,QAAWC,eAAmBD,QAAWC,IAEvE7I,QAAQ,SAAC8J,KACR9P,QAAQC,MAAM0O,WAAawC,0DAK3BpP,MAAMC,KAAKqG,KAAKrI,QAAQqR,UAC5B9C,OAAO,mBAAMlF,EAAQM,EAAI2H,EAAK7P,QAAQ8P,gBACtC3J,IAAI,mBAAM,IAAIgD,EAAYjB,2CAQjBnC,OACN6J,EAAWtP,MAAMC,KAAKqG,KAAKrI,QAAQqR,eACpC7J,MAAQjG,EAAO8G,KAAKb,MAAMG,OAAOH,gBACjCxH,UACMqR,EAASG,QAAQxR,yDAMrBqI,KAAKb,MAAM+G,OAAO,mBAAQuB,EAAKjF,gEAI/BxC,KAAKb,MAAM+G,OAAO,mBAASuB,EAAKjF,mDAU1B/E,EAAgB2L,OACzBC,gBAwBS,OArB2B,mBAA7BrJ,KAAK5G,QAAQuC,YACfqE,KAAK5G,QAAQuC,YAAY8B,GAGvBuC,KAAKqE,SACPD,EAAQ2B,QAAQ/F,KAAK5G,QAAQiM,OAAOrI,MAGlCgD,KAAK5G,QAAQuC,YACfqE,KAAK5G,QAAQuC,YAGXqE,KAAKb,MAAMvG,OAAS,EACtBwL,EAAQ2B,QAAQ/F,KAAKb,MAAM,GAAGxH,SAAS,GAAMqF,MAI7CS,OAKAA,GAGF4L,EAAOD,yCASD3L,SAE2B,mBAA7BuC,KAAK5G,QAAQkQ,YACftJ,KAAK5G,QAAQkQ,YAAY7L,GACvBuC,KAAKqE,SACP3M,EAAesI,KAAK5G,QAAQiM,MAAO,cAEnCrF,KAAK5G,QAAQkQ,sDAWZ7L,yDAAiB2G,EAAQ2B,QAAQ/F,KAAKrI,SAASqF,MACnDuM,EAASvJ,KAAKwJ,eAAe/L,GAC7B9B,EAAcqE,KAAKyJ,eAAehM,EAAgB8L,GACpDG,GAAqBjM,EAAiB8L,GAAU5N,EAGhD7C,KAAKiD,IAAIjD,KAAKkD,MAAM0N,GAAqBA,GACzC1J,KAAK5G,QAAQuQ,oBAEK7Q,KAAKkD,MAAM0N,SAG5BE,KAAO9Q,KAAKuC,IAAIvC,KAAKC,MAAM2Q,GAAoB,QAC/CjM,eAAiBA,OACjBoM,SAAWlO,mDAOXhE,QAAQC,MAAM0F,OAAS0C,KAAK8J,oBAAsB,wDAShD1O,EAAS4E,KAAK7D,qDAQL4N,UACTjR,KAAK0C,IAAIuO,EAAQ/J,KAAK5G,QAAQ4Q,cAAehK,KAAK5G,QAAQ6Q,oDAQzDpK,OAAMW,4DACVR,KAAK2E,gBAIJuF,QAAUlK,UACVO,KAAKV,EAAMW,6CAQZ3H,EAAImH,KAAK4J,cACRzN,aACEtD,MACA,OACAsD,UAAUE,KAAK,mCAShB8C,cACAgL,EAAgBnK,KAAKoK,kBAAkBjL,GAEzC3E,EAAQ,IACNmD,QAAQ,SAAC8J,EAAM5O,YAKVkC,MACFpD,QAAQC,MAAMyS,gBAAkB,KAChClH,SAASZ,EAAYa,IAAIN,QAAQwH,WANlCC,EAAU9C,EAAKtK,MACfqN,EAAY/C,EAAKnE,MACjBmH,EAAeN,EAActR,MAS/BuE,EAAMsN,OAAOH,EAASE,IAAiBD,IAAcjI,EAAYgB,MAAMT,iBACpEK,SAASZ,EAAYa,IAAIN,QAAQ6H,mBAKnCxN,MAAQsN,IACRnH,MAAQf,EAAYgB,MAAMT,YAIzBjL,EAASyB,OAAOC,UAAWgJ,EAAYa,IAAIN,QAAQ6H,UAClDN,gBAAkBO,EAAKC,kBAAkBrQ,GAAS,OAEpDuK,OAAO1I,sCAMH,8CAWK8C,iBAGZa,KAAK5G,QAAQ0R,WAAY,KACrBC,EAAY5L,EAAMI,IAAI,SAACkI,EAAM5O,OAC3B+D,EAAWwH,EAAQ2B,QAAQ0B,EAAK9P,SAAS,GACzCwF,EAAQ6N,EAAKC,iBAAiBrO,UAC7B,IAAIgC,EAAKzB,EAAMsC,EAAGtC,EAAMiF,EAAGxF,EAASI,MAAOJ,EAASU,OAAQzE,YAG9DmH,KAAKkL,wBAAwBH,EAAW/K,KAAKvC,uBAK/C0B,EAAMI,IAAI,mBAAQyL,EAAKC,iBAAiB7G,EAAQ2B,QAAQ0B,EAAK9P,SAAS,+CAS9DiF,UACRD,wBAEMqD,KAAK7D,mBACN6D,KAAK6J,eACR7J,KAAK4J,eACD5J,KAAK5G,QAAQuQ,uBAChB3J,KAAK5G,QAAQoD,yDAWDgB,EAAWC,UAC1BF,EAAqBC,EAAWC,gDASnCjD,EAAQ,0DADOwF,KAAKmL,sBAEbxN,QAAQ,SAAC8J,YACT1M,MACFoI,SAASZ,EAAYa,IAAIR,OAAO0H,UASnC7C,EAAKnE,QAAUf,EAAYgB,MAAMX,gBAC9BO,SAASZ,EAAYa,IAAIR,OAAO+H,mBAKlCrH,MAAQf,EAAYgB,MAAMX,WAEzB/K,EAASyB,OAAOC,UAAWgJ,EAAYa,IAAIR,OAAO+H,UACjDN,gBAAkBe,EAAKP,kBAAkBrQ,GAAS,OAEpDuK,OAAO1I,sCAMH,4CAUN2D,KAAK0E,YAAa1E,KAAK2E,kBAIvB0G,+DASkB5D,IAAAA,KAAM5P,IAAAA,OACxBA,EAAOwS,oBACHA,gBAAkB,WAGrB5K,EAAIgI,EAAKtK,MAAMsC,EACf2C,EAAIqF,EAAKtK,MAAMiF,SAEjBpC,KAAK5G,QAAQ2P,gBACRuC,uBAAyB7L,SAAQ2C,eAAcqF,EAAKnE,aAEpDlF,KAAOqB,EAAI,OACX5B,IAAMuE,EAAI,MAGZvK,8CAUWF,EAAS4T,EAAcC,OACnC9Q,EAAKI,EAAgBnD,EAAS,SAACqD,SAE9B,KAAMA,UAGR6J,aAAaxI,KAAK3B,kDASFrB,qBACd,SAACmS,KACD/D,KAAKtE,SAASsI,EAAKC,uBAAuBrS,MAC1CsS,oBAAoBtS,EAAKoO,KAAK9P,QAAS0B,EAAK0B,SAAUyQ,4CAUzDxL,KAAK8E,sBACF8G,sBAGDC,EAAW7L,KAAK5G,QAAQmN,MAAQ,EAChCuF,EAAW9L,KAAK+E,OAAOnM,OAAS,EAElCkT,GAAYD,GAAY7L,KAAK4E,mBAC1BmH,kBAAkB/L,KAAK+E,QACnB+G,QACJE,kBAAkBhM,KAAK+E,aACvBkH,UAAU7H,EAAQ8H,UAAUC,cAM5BF,UAAU7H,EAAQ8H,UAAUC,aAI9BpH,OAAOnM,OAAS,4CAOL+B,mBAEXmK,iBAAkB,MAGjBsH,EAAYzR,EAAY4E,IAAI,mBAAO8M,EAAKC,uBAAuB5I,OAE5D0I,EAAWpM,KAAKuM,kBAAkB3G,KAAK5F,sDAK3C6E,aAAalH,QAAQlD,QAGrBoK,aAAajM,OAAS,OAGtBkM,iBAAkB,4CAQP0H,iBACZA,EAAQ5T,OAAQ,KACZ6T,EAAWD,EAAQjN,IAAI,mBAAOmE,EAAI+D,KAAK9P,YAErC+U,iBAAiBD,EAAU,aACzB9O,QAAQ,SAAC+F,KACX+D,KAAKtE,SAASwJ,EAAKjB,uBAAuBhI,MAC1C3I,iEAOL8J,aAAajM,OAAS,OACtBkM,iBAAkB,OAClBmH,UAAU7H,EAAQ8H,UAAUC,uCAS5BjF,EAAU0F,GACV5M,KAAK0E,cAILwC,GAAaA,GAAgC,IAApBA,EAAStO,YAC1BwL,EAAQI,gBAGhBqI,QAAQ3F,QAGR4F,eAGAC,wBAGAjT,KAAK8S,uCAOPI,yDAAchN,KAAKsE,YACjBtE,KAAK0E,gBAILuI,iBAEC9N,EAAQjG,EAAO8G,KAAK6I,oBAAqBmE,QAE1CE,QAAQ/N,QAIRgO,qBAGAC,yBAEA9I,SAAW0I,kCAQXK,GACDrN,KAAK0E,YACF2I,QAEEpH,mBAIFnM,8CAUFuR,QAAO,+BAQViC,OACInO,EAAQK,EAAY8N,GAAU/N,IAAI,mBAAM,IAAIgD,EAAYjB,UAGzDiE,WAAWpG,QAGXkH,mBAAmBlH,QAGnBoO,cAAcpO,QAGd+G,OAAOlG,KAAKyE,mDAOZC,WAAY,uCAOZ8I,kEACA9I,WAAY,EACb8I,QACGnC,wCAUFoB,iBACAA,EAAS7T,YAIRuO,EAAa3H,EAAYiN,GAEzBgB,EAAWtG,EACd5H,IAAI,mBAAWmO,EAAKC,iBAAiBhW,KACrCuO,OAAO,oBAAUuB,SAcfH,wCAEKmG,SAGLX,QAAQW,QAER3T,YAIAqF,MAAQa,KAAKb,MAAM+G,OAAO,mBAASuH,EAASrO,SAASqI,UACrDsF,wBAEA7M,KAAKkE,EAAQ8H,UAAUC,OA1BP,aACdyB,cAAcH,KAGR9P,QAAQ,SAAChG,KACV+J,WAAWyC,YAAYxM,OAG5BsU,UAAU7H,EAAQ8H,UAAU2B,SAAW1G,2DA0B/BxP,UACRqI,KAAKb,MAAM2O,KAAK,mBAAQrG,EAAK9P,UAAYA,yDAS3CiW,cAAc5N,KAAKb,YACnByF,eAAgB,OAGhBzF,MAAQa,KAAKoF,iBAGbG,WAAWvF,KAAKb,YAEhBe,KAAKkE,EAAQ8H,UAAUC,OAAQ,aAE7B9F,mBAAmB0H,EAAK5O,SACxByF,eAAgB,SAIlB9K,8CAOA8R,yBACEhR,oBAAoB,SAAUoF,KAAKwF,gBAGrC7N,QAAQ8K,UAAUC,OAAO,gBACzB/K,QAAQoL,gBAAgB,cAGxB6K,cAAc5N,KAAKb,YAEnBA,MAAMvG,OAAS,OACfiM,aAAajM,OAAS,OAGtBQ,QAAQiM,MAAQ,UAChB1N,QAAU,UAIVgN,aAAc,OACdD,WAAY,oCAyBJ/M,EAASqW,OAEhBnW,EAASC,OAAOC,iBAAiBJ,EAAS,MAC5CqF,EAAQtF,EAAeC,EAAS,QAASE,GACzCyF,EAAS5F,EAAeC,EAAS,SAAUE,UAE3CmW,OACiBtW,EAAeC,EAAS,aAAcE,GACrCH,EAAeC,EAAS,cAAeE,MACzCH,EAAeC,EAAS,YAAaE,GAClCH,EAAeC,EAAS,eAAgBE,gEAkBzC4U,EAAU1R,OAI1ByF,EAAOiM,EAASlN,IAAI,SAAC5H,OACnBC,EAAQD,EAAQC,MAChBqW,EAAWrW,EAAMsW,mBACjBC,EAAQvW,EAAMyS,yBAGd6D,mBATK,QAUL7D,gBAVK,mCAqBJ,GAAGjE,cAGHzI,QAAQ,SAAChG,EAASkB,KACjBjB,MAAMsW,mBAAqB1N,EAAK3H,GAAGoV,WACnCrW,MAAMyS,gBAAkB7J,EAAK3H,GAAGsV,eAphCxBC,UAyhCtBhK,EAAQ7B,YAAcA,EAEtB6B,EAAQI,UAAY,MACpBJ,EAAQ2D,qBAAuB,SAK/B3D,EAAQ8H,kBACE,yBACC,mBAIX9H,EAAQzB,QAAUA,EAKlByB,EAAQkE,gBACD,UACA,OAIPlE,EAAQhL,eAECgL,EAAQI,gBAGR,WAGC,oBAGM,UAIP,iBAIM,cAIA,YAIF,YAIH,kBAIS,gBAIJ,cO3mCf,SAAmB6J,EAAMC,GAcvB,SAAS7N,IACP8N,EAAY,EACZC,GAAQ,IAAIC,KACZC,EAAML,EAAK/S,MAAMwE,EAAK6O,GACtB7O,EAAM,KACN6O,EAAO,KAlBT,IAAI7O,EAAK6O,EAAMD,EAAKH,EAChBC,EAAO,EAEX,OAAO,WACL1O,EAAME,KACN2O,EAAOtO,UACP,IAAIuO,EAAQ,IAAIH,KAASD,EAIzB,OAHKD,IACCK,GAASN,EAAM7N,IACd8N,EAAYM,WAAWpO,EAAM6N,EAAOM,IACpCF,iBPumCK,kBAGC,oBAGG,mBAGH,aAKHtK,EAAQkE,WAAWC,gBAGnB,GAIdnE,EAAQ0K,QAAU1R,EAClBgH,EAAQ2K,OAASnQ,EACjBwF,EAAQ4K,SAAW9V,EACnBkL,EAAQ6K,gBAAkBxT,EAC1B2I,EAAQ8K,wBAA0BhT,EAClCkI,EAAQ+K,iBAAmB5S,EAC3B6H,EAAQgL,uBAAyB7R"} \ No newline at end of file +{"version":3,"file":"shuffle.min.js","sources":["../node_modules/tiny-emitter/index.js","../node_modules/array-parallel/index.js","../src/get-number.js","../src/get-number-style.js","../src/sorter.js","../src/on-transition-end.js","../src/array-max.js","../src/array-min.js","../src/layout.js","../src/shuffle.js","../node_modules/matches-selector/index.js","../src/point.js","../src/rect.js","../src/classes.js","../src/shuffle-item.js","../src/computed-size.js","../node_modules/throttleit/index.js"],"sourcesContent":["function E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\n","module.exports = function parallel(fns, context, callback) {\n if (!callback) {\n if (typeof context === 'function') {\n callback = context\n context = null\n } else {\n callback = noop\n }\n }\n\n var pending = fns && fns.length\n if (!pending) return callback(null, []);\n\n var finished = false\n var results = new Array(pending)\n\n fns.forEach(context ? function (fn, i) {\n fn.call(context, maybeDone(i))\n } : function (fn, i) {\n fn(maybeDone(i))\n })\n\n function maybeDone(i) {\n return function (err, result) {\n if (finished) return;\n\n if (err) {\n callback(err, results)\n finished = true\n return\n }\n\n results[i] = result\n\n if (!--pending) callback(null, results);\n }\n }\n}\n\nfunction noop() {}\n","/**\n * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`.\n * @param {*} value Possibly numeric value.\n * @return {number} `value` or zero if `value` isn't numeric.\n */\nexport default function getNumber(value) {\n return parseFloat(value) || 0;\n}\n","import getNumber from './get-number';\nimport COMPUTED_SIZE_INCLUDES_PADDING from './computed-size';\n\n/**\n * Retrieve the computed style for an element, parsed as a float.\n * @param {Element} element Element to get style for.\n * @param {string} style Style property.\n * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to\n * use instead of asking for them again.\n * @return {number} The parsed computed value or zero if that fails because IE\n * will return 'auto' when the element doesn't have margins instead of\n * the computed style.\n */\nexport default function getNumberStyle(element, style,\n styles = window.getComputedStyle(element, null)) {\n let value = getNumber(styles[style]);\n\n // Support IE<=11 and W3C spec.\n if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'width') {\n value += getNumber(styles.paddingLeft) +\n getNumber(styles.paddingRight) +\n getNumber(styles.borderLeftWidth) +\n getNumber(styles.borderRightWidth);\n } else if (!COMPUTED_SIZE_INCLUDES_PADDING && style === 'height') {\n value += getNumber(styles.paddingTop) +\n getNumber(styles.paddingBottom) +\n getNumber(styles.borderTopWidth) +\n getNumber(styles.borderBottomWidth);\n }\n\n return value;\n}\n","/**\n * Fisher-Yates shuffle.\n * http://stackoverflow.com/a/962890/373422\n * https://bost.ocks.org/mike/shuffle/\n * @param {Array} array Array to shuffle.\n * @return {Array} Randomly sorted array.\n */\nfunction randomize(array) {\n let n = array.length;\n\n while (n) {\n n -= 1;\n const i = Math.floor(Math.random() * (n + 1));\n const temp = array[i];\n array[i] = array[n];\n array[n] = temp;\n }\n\n return array;\n}\n\nconst defaults = {\n // Use array.reverse() to reverse the results\n reverse: false,\n\n // Sorting function\n by: null,\n\n // If true, this will skip the sorting and return a randomized order in the array\n randomize: false,\n\n // Determines which property of each item in the array is passed to the\n // sorting method.\n key: 'element',\n};\n\n// You can return `undefined` from the `by` function to revert to DOM order.\nexport default function sorter(arr, options) {\n const opts = Object.assign({}, defaults, options);\n const original = Array.from(arr);\n let revert = false;\n\n if (!arr.length) {\n return [];\n }\n\n if (opts.randomize) {\n return randomize(arr);\n }\n\n // Sort the elements by the opts.by function.\n // If we don't have opts.by, default to DOM order\n if (typeof opts.by === 'function') {\n arr.sort((a, b) => {\n // Exit early if we already know we want to revert\n if (revert) {\n return 0;\n }\n\n const valA = opts.by(a[opts.key]);\n const valB = opts.by(b[opts.key]);\n\n // If both values are undefined, use the DOM order\n if (valA === undefined && valB === undefined) {\n revert = true;\n return 0;\n }\n\n if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') {\n return -1;\n }\n\n if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') {\n return 1;\n }\n\n return 0;\n });\n }\n\n // Revert to the original array if necessary\n if (revert) {\n return original;\n }\n\n if (opts.reverse) {\n arr.reverse();\n }\n\n return arr;\n}\n","const transitions = {};\nconst eventName = 'transitionend';\nlet count = 0;\n\nfunction uniqueId() {\n count += 1;\n return eventName + count;\n}\n\nexport function cancelTransitionEnd(id) {\n if (transitions[id]) {\n transitions[id].element.removeEventListener(eventName, transitions[id].listener);\n transitions[id] = null;\n return true;\n }\n\n return false;\n}\n\nexport function onTransitionEnd(element, callback) {\n const id = uniqueId();\n const listener = (evt) => {\n if (evt.currentTarget === evt.target) {\n cancelTransitionEnd(id);\n callback(evt);\n }\n };\n\n element.addEventListener(eventName, listener);\n\n transitions[id] = { element, listener };\n\n return id;\n}\n","export default function arrayMax(array) {\n return Math.max.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","export default function arrayMin(array) {\n return Math.min.apply(Math, array); // eslint-disable-line prefer-spread\n}\n","import Point from './point';\nimport Rect from './rect';\nimport arrayMax from './array-max';\nimport arrayMin from './array-min';\n\n/**\n * Determine the number of columns an items spans.\n * @param {number} itemWidth Width of the item.\n * @param {number} columnWidth Width of the column (includes gutter).\n * @param {number} columns Total number of columns\n * @param {number} threshold A buffer value for the size of the column to fit.\n * @return {number}\n */\nexport function getColumnSpan(itemWidth, columnWidth, columns, threshold) {\n let columnSpan = itemWidth / columnWidth;\n\n // If the difference between the rounded column span number and the\n // calculated column span number is really small, round the number to\n // make it fit.\n if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) {\n // e.g. columnSpan = 4.0089945390298745\n columnSpan = Math.round(columnSpan);\n }\n\n // Ensure the column span is not more than the amount of columns in the whole layout.\n return Math.min(Math.ceil(columnSpan), columns);\n}\n\n/**\n * Retrieves the column set to use for placement.\n * @param {number} columnSpan The number of columns this current item spans.\n * @param {number} columns The total columns in the grid.\n * @return {Array.} An array of numbers represeting the column set.\n */\nexport function getAvailablePositions(positions, columnSpan, columns) {\n // The item spans only one column.\n if (columnSpan === 1) {\n return positions;\n }\n\n // The item spans more than one column, figure out how many different\n // places it could fit horizontally.\n // The group count is the number of places within the positions this block\n // could fit, ignoring the current positions of items.\n // Imagine a 2 column brick as the second item in a 4 column grid with\n // 10px height each. Find the places it would fit:\n // [20, 10, 10, 0]\n // | | |\n // * * *\n //\n // Then take the places which fit and get the bigger of the two:\n // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0]\n //\n // Next, find the first smallest number (the short column).\n // [20, 10, 0]\n // |\n // *\n //\n // And that's where it should be placed!\n //\n // Another example where the second column's item extends past the first:\n // [10, 20, 10, 0] => [20, 20, 10] => 10\n const available = [];\n\n // For how many possible positions for this item there are.\n for (let i = 0; i <= columns - columnSpan; i++) {\n // Find the bigger value for each place it could fit.\n available.push(arrayMax(positions.slice(i, i + columnSpan)));\n }\n\n return available;\n}\n\n/**\n * Find index of short column, the first from the left where this item will go.\n *\n * @param {Array.} positions The array to search for the smallest number.\n * @param {number} buffer Optional buffer which is very useful when the height\n * is a percentage of the width.\n * @return {number} Index of the short column.\n */\nexport function getShortColumn(positions, buffer) {\n const minPosition = arrayMin(positions);\n for (let i = 0, len = positions.length; i < len; i++) {\n if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) {\n return i;\n }\n }\n\n return 0;\n}\n\n/**\n * Determine the location of the next item, based on its size.\n * @param {Object} itemSize Object with width and height.\n * @param {Array.} positions Positions of the other current items.\n * @param {number} gridSize The column width or row height.\n * @param {number} total The total number of columns or rows.\n * @param {number} threshold Buffer value for the column to fit.\n * @param {number} buffer Vertical buffer for the height of items.\n * @return {Point}\n */\nexport function getItemPosition({ itemSize, positions, gridSize, total, threshold, buffer }) {\n const span = getColumnSpan(itemSize.width, gridSize, total, threshold);\n const setY = getAvailablePositions(positions, span, total);\n const shortColumnIndex = getShortColumn(setY, buffer);\n\n // Position the item\n const point = new Point(\n Math.round(gridSize * shortColumnIndex),\n Math.round(setY[shortColumnIndex]));\n\n // Update the columns array with the new values for each column.\n // e.g. before the update the columns could be [250, 0, 0, 0] for an item\n // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].\n const setHeight = setY[shortColumnIndex] + itemSize.height;\n for (let i = 0; i < span; i++) {\n positions[shortColumnIndex + i] = setHeight;\n }\n\n return point;\n}\n\n/**\n * This method attempts to center items. This method could potentially be slow\n * with a large number of items because it must place items, then check every\n * previous item to ensure there is no overlap.\n * @param {Array.} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Array.}\n */\nexport function getCenteredPositions(itemRects, containerWidth) {\n const rowMap = {};\n\n // Populate rows by their offset because items could jump between rows like:\n // a c\n // bbb\n itemRects.forEach((itemRect) => {\n if (rowMap[itemRect.top]) {\n // Push the point to the last row array.\n rowMap[itemRect.top].push(itemRect);\n } else {\n // Start of a new row.\n rowMap[itemRect.top] = [itemRect];\n }\n });\n\n // For each row, find the end of the last item, then calculate\n // the remaining space by dividing it by 2. Then add that\n // offset to the x position of each point.\n let rects = [];\n const rows = [];\n const centeredRows = [];\n Object.keys(rowMap).forEach((key) => {\n const itemRects = rowMap[key];\n rows.push(itemRects);\n const lastItem = itemRects[itemRects.length - 1];\n const end = lastItem.left + lastItem.width;\n const offset = Math.round((containerWidth - end) / 2);\n\n let finalRects = itemRects;\n let canMove = false;\n if (offset > 0) {\n const newRects = [];\n canMove = itemRects.every((r) => {\n const newRect = new Rect(r.left + offset, r.top, r.width, r.height, r.id);\n\n // Check all current rects to make sure none overlap.\n const noOverlap = !rects.some(r => Rect.intersects(newRect, r));\n\n newRects.push(newRect);\n return noOverlap;\n });\n\n // If none of the rectangles overlapped, the whole group can be centered.\n if (canMove) {\n finalRects = newRects;\n }\n }\n\n // If the items are not going to be offset, ensure that the original\n // placement for this row will not overlap previous rows (row-spanning\n // elements could be in the way).\n if (!canMove) {\n let intersectingRect;\n const hasOverlap = itemRects.some(itemRect => rects.some((r) => {\n const intersects = Rect.intersects(itemRect, r);\n if (intersects) {\n intersectingRect = r;\n }\n return intersects;\n }));\n\n // If there is any overlap, replace the overlapping row with the original.\n if (hasOverlap) {\n const rowIndex = centeredRows.findIndex(items => items.includes(intersectingRect));\n centeredRows.splice(rowIndex, 1, rows[rowIndex]);\n }\n }\n\n rects = rects.concat(finalRects);\n centeredRows.push(finalRects);\n });\n\n // Reduce array of arrays to a single array of points.\n // https://stackoverflow.com/a/10865042/373422\n // Then reset sort back to how the items were passed to this method.\n // Remove the wrapper object with index, map to a Point.\n return [].concat.apply([], centeredRows) // eslint-disable-line prefer-spread\n .sort((a, b) => (a.id - b.id))\n .map(itemRect => new Point(itemRect.left, itemRect.top));\n}\n","import TinyEmitter from 'tiny-emitter';\nimport matches from 'matches-selector';\nimport throttle from 'throttleit';\nimport parallel from 'array-parallel';\n\nimport Point from './point';\nimport Rect from './rect';\nimport ShuffleItem from './shuffle-item';\nimport Classes from './classes';\nimport getNumberStyle from './get-number-style';\nimport sorter from './sorter';\nimport { onTransitionEnd, cancelTransitionEnd } from './on-transition-end';\nimport {\n getItemPosition,\n getColumnSpan,\n getAvailablePositions,\n getShortColumn,\n getCenteredPositions,\n} from './layout';\nimport arrayMax from './array-max';\n\nfunction arrayUnique(x) {\n return Array.from(new Set(x));\n}\n\n// Used for unique instance variables\nlet id = 0;\n\nclass Shuffle extends TinyEmitter {\n\n /**\n * Categorize, sort, and filter a responsive grid of items.\n *\n * @param {Element} element An element which is the parent container for the grid items.\n * @param {Object} [options=Shuffle.options] Options object.\n * @constructor\n */\n constructor(element, options = {}) {\n super();\n this.options = Object.assign({}, Shuffle.options, options);\n\n this.lastSort = {};\n this.group = Shuffle.ALL_ITEMS;\n this.lastFilter = Shuffle.ALL_ITEMS;\n this.isEnabled = true;\n this.isDestroyed = false;\n this.isInitialized = false;\n this._transitions = [];\n this.isTransitioning = false;\n this._queue = [];\n\n const el = this._getElementOption(element);\n\n if (!el) {\n throw new TypeError('Shuffle needs to be initialized with an element.');\n }\n\n this.element = el;\n this.id = 'shuffle_' + id;\n id += 1;\n\n this._init();\n this.isInitialized = true;\n }\n\n _init() {\n this.items = this._getItems();\n\n this.options.sizer = this._getElementOption(this.options.sizer);\n\n // Add class and invalidate styles\n this.element.classList.add(Shuffle.Classes.BASE);\n\n // Set initial css for each item\n this._initItems(this.items);\n\n // Bind resize events\n this._onResize = this._getResizeFunction();\n window.addEventListener('resize', this._onResize);\n\n // If the page has not already emitted the `load` event, call layout on load.\n // This avoids layout issues caused by images and fonts loading after the\n // instance has been initialized.\n if (document.readyState !== 'complete') {\n const layout = this.layout.bind(this);\n window.addEventListener('load', function onLoad() {\n window.removeEventListener('load', onLoad);\n layout();\n });\n }\n\n // Get container css all in one request. Causes reflow\n const containerCss = window.getComputedStyle(this.element, null);\n const containerWidth = Shuffle.getSize(this.element).width;\n\n // Add styles to the container if it doesn't have them.\n this._validateStyles(containerCss);\n\n // We already got the container's width above, no need to cause another\n // reflow getting it again... Calculate the number of columns there will be\n this._setColumns(containerWidth);\n\n // Kick off!\n this.filter(this.options.group, this.options.initialSort);\n\n // The shuffle items haven't had transitions set on them yet so the user\n // doesn't see the first layout. Set them now that the first layout is done.\n // First, however, a synchronous layout must be caused for the previous\n // styles to be applied without transitions.\n this.element.offsetWidth; // eslint-disable-line no-unused-expressions\n this.setItemTransitions(this.items);\n this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing;\n }\n\n /**\n * Returns a throttled and proxied function for the resize handler.\n * @return {Function}\n * @private\n */\n _getResizeFunction() {\n const resizeFunction = this._handleResize.bind(this);\n return this.options.throttle ?\n this.options.throttle(resizeFunction, this.options.throttleTime) :\n resizeFunction;\n }\n\n /**\n * Retrieve an element from an option.\n * @param {string|jQuery|Element} option The option to check.\n * @return {?Element} The plain element or null.\n * @private\n */\n _getElementOption(option) {\n // If column width is a string, treat is as a selector and search for the\n // sizer element within the outermost container\n if (typeof option === 'string') {\n return this.element.querySelector(option);\n\n // Check for an element\n } else if (option && option.nodeType && option.nodeType === 1) {\n return option;\n\n // Check for jQuery object\n } else if (option && option.jquery) {\n return option[0];\n }\n\n return null;\n }\n\n /**\n * Ensures the shuffle container has the css styles it needs applied to it.\n * @param {Object} styles Key value pairs for position and overflow.\n * @private\n */\n _validateStyles(styles) {\n // Position cannot be static.\n if (styles.position === 'static') {\n this.element.style.position = 'relative';\n }\n\n // Overflow has to be hidden.\n if (styles.overflow !== 'hidden') {\n this.element.style.overflow = 'hidden';\n }\n }\n\n /**\n * Filter the elements by a category.\n * @param {string} [category] Category to filter by. If it's given, the last\n * category will be used to filter the items.\n * @param {Array} [collection] Optionally filter a collection. Defaults to\n * all the items.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _filter(category = this.lastFilter, collection = this.items) {\n const set = this._getFilteredSets(category, collection);\n\n // Individually add/remove hidden/visible classes\n this._toggleFilterClasses(set);\n\n // Save the last filter in case elements are appended.\n this.lastFilter = category;\n\n // This is saved mainly because providing a filter function (like searching)\n // will overwrite the `lastFilter` property every time its called.\n if (typeof category === 'string') {\n this.group = category;\n }\n\n return set;\n }\n\n /**\n * Returns an object containing the visible and hidden elements.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element[]} items A collection of items to filter.\n * @return {!{visible: Array, hidden: Array}}\n * @private\n */\n _getFilteredSets(category, items) {\n let visible = [];\n const hidden = [];\n\n // category === 'all', add visible class to everything\n if (category === Shuffle.ALL_ITEMS) {\n visible = items;\n\n // Loop through each item and use provided function to determine\n // whether to hide it or not.\n } else {\n items.forEach((item) => {\n if (this._doesPassFilter(category, item.element)) {\n visible.push(item);\n } else {\n hidden.push(item);\n }\n });\n }\n\n return {\n visible,\n hidden,\n };\n }\n\n /**\n * Test an item to see if it passes a category.\n * @param {string|Function} category Category or function to filter by.\n * @param {Element} element An element to test.\n * @return {boolean} Whether it passes the category/filter.\n * @private\n */\n _doesPassFilter(category, element) {\n if (typeof category === 'function') {\n return category.call(element, element, this);\n }\n\n // Check each element's data-groups attribute against the given category.\n const attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY);\n const keys = this.options.delimeter ?\n attr.split(this.options.delimeter) :\n JSON.parse(attr);\n\n function testCategory(category) {\n return keys.includes(category);\n }\n\n if (Array.isArray(category)) {\n if (this.options.filterMode === Shuffle.FilterMode.ANY) {\n return category.some(testCategory);\n }\n return category.every(testCategory);\n }\n\n return keys.includes(category);\n }\n\n /**\n * Toggles the visible and hidden class names.\n * @param {{visible, hidden}} Object with visible and hidden arrays.\n * @private\n */\n _toggleFilterClasses({ visible, hidden }) {\n visible.forEach((item) => {\n item.show();\n });\n\n hidden.forEach((item) => {\n item.hide();\n });\n }\n\n /**\n * Set the initial css for each item\n * @param {ShuffleItem[]} items Set to initialize.\n * @private\n */\n _initItems(items) {\n items.forEach((item) => {\n item.init();\n });\n }\n\n /**\n * Remove element reference and styles.\n * @param {ShuffleItem[]} items Set to dispose.\n * @private\n */\n _disposeItems(items) {\n items.forEach((item) => {\n item.dispose();\n });\n }\n\n /**\n * Updates the visible item count.\n * @private\n */\n _updateItemCount() {\n this.visibleItems = this._getFilteredItems().length;\n }\n\n /**\n * Sets css transform transition on a group of elements. This is not executed\n * at the same time as `item.init` so that transitions don't occur upon\n * initialization of Shuffle.\n * @param {ShuffleItem[]} items Shuffle items to set transitions on.\n * @protected\n */\n setItemTransitions(items) {\n const speed = this.options.speed;\n const easing = this.options.easing;\n\n const str = this.options.useTransforms ?\n `transform ${speed}ms ${easing}, opacity ${speed}ms ${easing}` :\n `top ${speed}ms ${easing}, left ${speed}ms ${easing}, opacity ${speed}ms ${easing}`;\n\n items.forEach((item) => {\n item.element.style.transition = str;\n });\n }\n\n _getItems() {\n return Array.from(this.element.children)\n .filter(el => matches(el, this.options.itemSelector))\n .map(el => new ShuffleItem(el));\n }\n\n /**\n * When new elements are added to the shuffle container, update the array of\n * items because that is the order `_layout` calls them.\n * @param {ShuffleItem[]} items Items to track.\n */\n _saveNewItems(items) {\n const children = Array.from(this.element.children);\n this.items = sorter(this.items.concat(items), {\n by(element) {\n return children.indexOf(element);\n },\n });\n }\n\n _getFilteredItems() {\n return this.items.filter(item => item.isVisible);\n }\n\n _getConcealedItems() {\n return this.items.filter(item => !item.isVisible);\n }\n\n /**\n * Returns the column size, based on column width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @param {number} gutterSize Size of the gutters.\n * @return {number}\n * @private\n */\n _getColumnSize(containerWidth, gutterSize) {\n let size;\n\n // If the columnWidth property is a function, then the grid is fluid\n if (typeof this.options.columnWidth === 'function') {\n size = this.options.columnWidth(containerWidth);\n\n // columnWidth option isn't a function, are they using a sizing element?\n } else if (this.options.sizer) {\n size = Shuffle.getSize(this.options.sizer).width;\n\n // if not, how about the explicitly set option?\n } else if (this.options.columnWidth) {\n size = this.options.columnWidth;\n\n // or use the size of the first item\n } else if (this.items.length > 0) {\n size = Shuffle.getSize(this.items[0].element, true).width;\n\n // if there's no items, use size of container\n } else {\n size = containerWidth;\n }\n\n // Don't let them set a column width of zero.\n if (size === 0) {\n size = containerWidth;\n }\n\n return size + gutterSize;\n }\n\n /**\n * Returns the gutter size, based on gutter width and sizer options.\n * @param {number} containerWidth Size of the parent container.\n * @return {number}\n * @private\n */\n _getGutterSize(containerWidth) {\n let size;\n if (typeof this.options.gutterWidth === 'function') {\n size = this.options.gutterWidth(containerWidth);\n } else if (this.options.sizer) {\n size = getNumberStyle(this.options.sizer, 'marginLeft');\n } else {\n size = this.options.gutterWidth;\n }\n\n return size;\n }\n\n /**\n * Calculate the number of columns to be used. Gets css if using sizer element.\n * @param {number} [containerWidth] Optionally specify a container width if\n * it's already available.\n */\n _setColumns(containerWidth = Shuffle.getSize(this.element).width) {\n const gutter = this._getGutterSize(containerWidth);\n const columnWidth = this._getColumnSize(containerWidth, gutter);\n let calculatedColumns = (containerWidth + gutter) / columnWidth;\n\n // Widths given from getStyles are not precise enough...\n if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) <\n this.options.columnThreshold) {\n // e.g. calculatedColumns = 11.998876\n calculatedColumns = Math.round(calculatedColumns);\n }\n\n this.cols = Math.max(Math.floor(calculatedColumns), 1);\n this.containerWidth = containerWidth;\n this.colWidth = columnWidth;\n }\n\n /**\n * Adjust the height of the grid\n */\n _setContainerSize() {\n this.element.style.height = this._getContainerSize() + 'px';\n }\n\n /**\n * Based on the column heights, it returns the biggest one.\n * @return {number}\n * @private\n */\n _getContainerSize() {\n return arrayMax(this.positions);\n }\n\n /**\n * Get the clamped stagger amount.\n * @param {number} index Index of the item to be staggered.\n * @return {number}\n */\n _getStaggerAmount(index) {\n return Math.min(index * this.options.staggerAmount, this.options.staggerAmountMax);\n }\n\n /**\n * Emit an event from this instance.\n * @param {string} name Event name.\n * @param {Object} [data={}] Optional object data.\n */\n _dispatch(name, data = {}) {\n if (this.isDestroyed) {\n return;\n }\n\n data.shuffle = this;\n this.emit(name, data);\n }\n\n /**\n * Zeros out the y columns array, which is used to determine item placement.\n * @private\n */\n _resetCols() {\n let i = this.cols;\n this.positions = [];\n while (i) {\n i -= 1;\n this.positions.push(0);\n }\n }\n\n /**\n * Loops through each item that should be shown and calculates the x, y position.\n * @param {ShuffleItem[]} items Array of items that will be shown/layed\n * out in order in their array.\n */\n _layout(items) {\n const itemPositions = this._getNextPositions(items);\n\n let count = 0;\n items.forEach((item, i) => {\n const currPos = item.point;\n const currScale = item.scale;\n const nextPosition = itemPositions[i];\n\n function callback() {\n item.element.style.transitionDelay = '';\n item.applyCss(ShuffleItem.Css.VISIBLE.after);\n }\n\n // If the item will not change its position, do not add it to the render\n // queue. Transitions don't fire when setting a property to the same value.\n if (Point.equals(currPos, nextPosition) && currScale === ShuffleItem.Scale.VISIBLE) {\n item.applyCss(ShuffleItem.Css.VISIBLE.before);\n callback();\n return;\n }\n\n item.point = nextPosition;\n item.scale = ShuffleItem.Scale.VISIBLE;\n\n // Clone the object so that the `before` object isn't modified when the\n // transition delay is added.\n const styles = Object.assign({}, ShuffleItem.Css.VISIBLE.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Return an array of Point instances representing the future positions of\n * each item.\n * @param {ShuffleItem[]} items Array of sorted shuffle items.\n * @return {Point[]}\n * @private\n */\n _getNextPositions(items) {\n // If position data is going to be changed, add the item's size to the\n // transformer to allow for calculations.\n if (this.options.isCentered) {\n const itemsData = items.map((item, i) => {\n const itemSize = Shuffle.getSize(item.element, true);\n const point = this._getItemPosition(itemSize);\n return new Rect(point.x, point.y, itemSize.width, itemSize.height, i);\n });\n\n return this.getTransformedPositions(itemsData, this.containerWidth);\n }\n\n // If no transforms are going to happen, simply return an array of the\n // future points of each item.\n return items.map(item => this._getItemPosition(Shuffle.getSize(item.element, true)));\n }\n\n /**\n * Determine the location of the next item, based on its size.\n * @param {{width: number, height: number}} itemSize Object with width and height.\n * @return {Point}\n * @private\n */\n _getItemPosition(itemSize) {\n return getItemPosition({\n itemSize,\n positions: this.positions,\n gridSize: this.colWidth,\n total: this.cols,\n threshold: this.options.columnThreshold,\n buffer: this.options.buffer,\n });\n }\n\n /**\n * Mutate positions before they're applied.\n * @param {Rect[]} itemRects Item data objects.\n * @param {number} containerWidth Width of the containing element.\n * @return {Point[]}\n * @protected\n */\n getTransformedPositions(itemRects, containerWidth) {\n return getCenteredPositions(itemRects, containerWidth);\n }\n\n /**\n * Hides the elements that don't match our filter.\n * @param {ShuffleItem[]} collection Collection to shrink.\n * @private\n */\n _shrink(collection = this._getConcealedItems()) {\n let count = 0;\n collection.forEach((item) => {\n function callback() {\n item.applyCss(ShuffleItem.Css.HIDDEN.after);\n }\n\n // Continuing would add a transitionend event listener to the element, but\n // that listener would not execute because the transform and opacity would\n // stay the same.\n // The callback is executed here because it is not guaranteed to be called\n // after the transitionend event because the transitionend could be\n // canceled if another animation starts.\n if (item.scale === ShuffleItem.Scale.HIDDEN) {\n item.applyCss(ShuffleItem.Css.HIDDEN.before);\n callback();\n return;\n }\n\n item.scale = ShuffleItem.Scale.HIDDEN;\n\n const styles = Object.assign({}, ShuffleItem.Css.HIDDEN.before);\n styles.transitionDelay = this._getStaggerAmount(count) + 'ms';\n\n this._queue.push({\n item,\n styles,\n callback,\n });\n\n count += 1;\n });\n }\n\n /**\n * Resize handler.\n * @private\n */\n _handleResize() {\n // If shuffle is disabled, destroyed, don't do anything\n if (!this.isEnabled || this.isDestroyed) {\n return;\n }\n\n this.update();\n }\n\n /**\n * Returns styles which will be applied to the an item for a transition.\n * @param {Object} obj Transition options.\n * @return {!Object} Transforms for transitions, left/top for animate.\n * @protected\n */\n getStylesForTransition({ item, styles }) {\n if (!styles.transitionDelay) {\n styles.transitionDelay = '0ms';\n }\n\n const x = item.point.x;\n const y = item.point.y;\n\n if (this.options.useTransforms) {\n styles.transform = `translate(${x}px, ${y}px) scale(${item.scale})`;\n } else {\n styles.left = x + 'px';\n styles.top = y + 'px';\n }\n\n return styles;\n }\n\n /**\n * Listen for the transition end on an element and execute the itemCallback\n * when it finishes.\n * @param {Element} element Element to listen on.\n * @param {Function} itemCallback Callback for the item.\n * @param {Function} done Callback to notify `parallel` that this one is done.\n */\n _whenTransitionDone(element, itemCallback, done) {\n const id = onTransitionEnd(element, (evt) => {\n itemCallback();\n done(null, evt);\n });\n\n this._transitions.push(id);\n }\n\n /**\n * Return a function which will set CSS styles and call the `done` function\n * when (if) the transition finishes.\n * @param {Object} opts Transition object.\n * @return {Function} A function to be called with a `done` function.\n */\n _getTransitionFunction(opts) {\n return (done) => {\n opts.item.applyCss(this.getStylesForTransition(opts));\n this._whenTransitionDone(opts.item.element, opts.callback, done);\n };\n }\n\n /**\n * Execute the styles gathered in the style queue. This applies styles to elements,\n * triggering transitions.\n * @private\n */\n _processQueue() {\n if (this.isTransitioning) {\n this._cancelMovement();\n }\n\n const hasSpeed = this.options.speed > 0;\n const hasQueue = this._queue.length > 0;\n\n if (hasQueue && hasSpeed && this.isInitialized) {\n this._startTransitions(this._queue);\n } else if (hasQueue) {\n this._styleImmediately(this._queue);\n this._dispatch(Shuffle.EventType.LAYOUT);\n\n // A call to layout happened, but none of the newly visible items will\n // change position or the transition duration is zero, which will not trigger\n // the transitionend event.\n } else {\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n // Remove everything in the style queue\n this._queue.length = 0;\n }\n\n /**\n * Wait for each transition to finish, the emit the layout event.\n * @param {Object[]} transitions Array of transition objects.\n */\n _startTransitions(transitions) {\n // Set flag that shuffle is currently in motion.\n this.isTransitioning = true;\n\n // Create an array of functions to be called.\n const callbacks = transitions.map(obj => this._getTransitionFunction(obj));\n\n parallel(callbacks, this._movementFinished.bind(this));\n }\n\n _cancelMovement() {\n // Remove the transition end event for each listener.\n this._transitions.forEach(cancelTransitionEnd);\n\n // Reset the array.\n this._transitions.length = 0;\n\n // Show it's no longer active.\n this.isTransitioning = false;\n }\n\n /**\n * Apply styles without a transition.\n * @param {Object[]} objects Array of transition objects.\n * @private\n */\n _styleImmediately(objects) {\n if (objects.length) {\n const elements = objects.map(obj => obj.item.element);\n\n Shuffle._skipTransitions(elements, () => {\n objects.forEach((obj) => {\n obj.item.applyCss(this.getStylesForTransition(obj));\n obj.callback();\n });\n });\n }\n }\n\n _movementFinished() {\n this._transitions.length = 0;\n this.isTransitioning = false;\n this._dispatch(Shuffle.EventType.LAYOUT);\n }\n\n /**\n * The magic. This is what makes the plugin 'shuffle'\n * @param {string|Function|string[]} [category] Category to filter by.\n * Can be a function, string, or array of strings.\n * @param {Object} [sortObj] A sort object which can sort the visible set\n */\n filter(category, sortObj) {\n if (!this.isEnabled) {\n return;\n }\n\n if (!category || (category && category.length === 0)) {\n category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign\n }\n\n this._filter(category);\n\n // Shrink each hidden item\n this._shrink();\n\n // How many visible elements?\n this._updateItemCount();\n\n // Update transforms on visible elements so they will animate to their new positions.\n this.sort(sortObj);\n }\n\n /**\n * Gets the visible elements, sorts them, and passes them to layout.\n * @param {Object} sortOptions The options object to pass to `sorter`.\n */\n sort(sortOptions = this.lastSort) {\n if (!this.isEnabled) {\n return;\n }\n\n this._resetCols();\n\n const items = sorter(this._getFilteredItems(), sortOptions);\n\n this._layout(items);\n\n // `_layout` always happens after `_shrink`, so it's safe to process the style\n // queue here with styles from the shrink method.\n this._processQueue();\n\n // Adjust the height of the container.\n this._setContainerSize();\n\n this.lastSort = sortOptions;\n }\n\n /**\n * Reposition everything.\n * @param {boolean} [isOnlyLayout=false] If true, column and gutter widths won't be recalculated.\n */\n update(isOnlyLayout = false) {\n if (this.isEnabled) {\n if (!isOnlyLayout) {\n // Get updated colCount\n this._setColumns();\n }\n\n // Layout items\n this.sort();\n }\n }\n\n /**\n * Use this instead of `update()` if you don't need the columns and gutters updated\n * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations\n * could be off.\n */\n layout() {\n this.update(true);\n }\n\n /**\n * New items have been appended to shuffle. Mix them in with the current\n * filter or sort status.\n * @param {Element[]} newItems Collection of new items.\n */\n add(newItems) {\n const items = arrayUnique(newItems).map(el => new ShuffleItem(el));\n\n // Add classes and set initial positions.\n this._initItems(items);\n\n // Add transition to each item.\n this.setItemTransitions(items);\n\n // Update the list of items.\n this._saveNewItems(items);\n\n // Update layout/visibility of new and old items.\n this.filter(this.lastFilter);\n }\n\n /**\n * Disables shuffle from updating dimensions and layout on resize\n */\n disable() {\n this.isEnabled = false;\n }\n\n /**\n * Enables shuffle again\n * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters\n */\n enable(isUpdateLayout = true) {\n this.isEnabled = true;\n if (isUpdateLayout) {\n this.update();\n }\n }\n\n /**\n * Remove 1 or more shuffle items.\n * @param {Element[]} elements An array containing one or more\n * elements in shuffle\n * @return {Shuffle} The shuffle instance.\n */\n remove(elements) {\n if (!elements.length) {\n return;\n }\n\n const collection = arrayUnique(elements);\n\n const oldItems = collection\n .map(element => this.getItemByElement(element))\n .filter(item => !!item);\n\n const handleLayout = () => {\n this._disposeItems(oldItems);\n\n // Remove the collection in the callback\n collection.forEach((element) => {\n element.parentNode.removeChild(element);\n });\n\n this._dispatch(Shuffle.EventType.REMOVED, { collection });\n };\n\n // Hide collection first.\n this._toggleFilterClasses({\n visible: [],\n hidden: oldItems,\n });\n\n this._shrink(oldItems);\n\n this.sort();\n\n // Update the list of items here because `remove` could be called again\n // with an item that is in the process of being removed.\n this.items = this.items.filter(item => !oldItems.includes(item));\n this._updateItemCount();\n\n this.once(Shuffle.EventType.LAYOUT, handleLayout);\n }\n\n /**\n * Retrieve a shuffle item by its element.\n * @param {Element} element Element to look for.\n * @return {?ShuffleItem} A shuffle item or undefined if it's not found.\n */\n getItemByElement(element) {\n return this.items.find(item => item.element === element);\n }\n\n /**\n * Dump the elements currently stored and reinitialize all child elements which\n * match the `itemSelector`.\n */\n resetItems() {\n // Remove refs to current items.\n this._disposeItems(this.items);\n this.isInitialized = false;\n\n // Find new items in the DOM.\n this.items = this._getItems();\n\n // Set initial styles on the new items.\n this._initItems(this.items);\n\n this.once(Shuffle.EventType.LAYOUT, () => {\n // Add transition to each item.\n this.setItemTransitions(this.items);\n this.isInitialized = true;\n });\n\n // Lay out all items.\n this.sort();\n }\n\n /**\n * Destroys shuffle, removes events, styles, and classes\n */\n destroy() {\n this._cancelMovement();\n window.removeEventListener('resize', this._onResize);\n\n // Reset container styles\n this.element.classList.remove('shuffle');\n this.element.removeAttribute('style');\n\n // Reset individual item styles\n this._disposeItems(this.items);\n\n this.items.length = 0;\n this._transitions.length = 0;\n\n // Null DOM references\n this.options.sizer = null;\n this.element = null;\n\n // Set a flag so if a debounced resize has been triggered,\n // it can first check if it is actually isDestroyed and not doing anything\n this.isDestroyed = true;\n this.isEnabled = false;\n }\n\n /**\n * Returns the outer width of an element, optionally including its margins.\n *\n * There are a few different methods for getting the width of an element, none of\n * which work perfectly for all Shuffle's use cases.\n *\n * 1. getBoundingClientRect() `left` and `right` properties.\n * - Accounts for transform scaled elements, making it useless for Shuffle\n * elements which have shrunk.\n * 2. The `offsetWidth` property.\n * - This value stays the same regardless of the elements transform property,\n * however, it does not return subpixel values.\n * 3. getComputedStyle()\n * - This works great Chrome, Firefox, Safari, but IE<=11 does not include\n * padding and border when box-sizing: border-box is set, requiring a feature\n * test and extra work to add the padding back for IE and other browsers which\n * follow the W3C spec here.\n *\n * @param {Element} element The element.\n * @param {boolean} [includeMargins=false] Whether to include margins.\n * @return {{width: number, height: number}} The width and height.\n */\n static getSize(element, includeMargins = false) {\n // Store the styles so that they can be used by others without asking for it again.\n const styles = window.getComputedStyle(element, null);\n let width = getNumberStyle(element, 'width', styles);\n let height = getNumberStyle(element, 'height', styles);\n\n if (includeMargins) {\n const marginLeft = getNumberStyle(element, 'marginLeft', styles);\n const marginRight = getNumberStyle(element, 'marginRight', styles);\n const marginTop = getNumberStyle(element, 'marginTop', styles);\n const marginBottom = getNumberStyle(element, 'marginBottom', styles);\n width += marginLeft + marginRight;\n height += marginTop + marginBottom;\n }\n\n return {\n width,\n height,\n };\n }\n\n /**\n * Change a property or execute a function which will not have a transition\n * @param {Element[]} elements DOM elements that won't be transitioned.\n * @param {Function} callback A function which will be called while transition\n * is set to 0ms.\n * @private\n */\n static _skipTransitions(elements, callback) {\n const zero = '0ms';\n\n // Save current duration and delay.\n const data = elements.map((element) => {\n const style = element.style;\n const duration = style.transitionDuration;\n const delay = style.transitionDelay;\n\n // Set the duration to zero so it happens immediately\n style.transitionDuration = zero;\n style.transitionDelay = zero;\n\n return {\n duration,\n delay,\n };\n });\n\n callback();\n\n // Cause forced synchronous layout.\n elements[0].offsetWidth; // eslint-disable-line no-unused-expressions\n\n // Put the duration back\n elements.forEach((element, i) => {\n element.style.transitionDuration = data[i].duration;\n element.style.transitionDelay = data[i].delay;\n });\n }\n}\n\nShuffle.ShuffleItem = ShuffleItem;\n\nShuffle.ALL_ITEMS = 'all';\nShuffle.FILTER_ATTRIBUTE_KEY = 'groups';\n\n/** @enum {string} */\nShuffle.EventType = {\n LAYOUT: 'shuffle:layout',\n REMOVED: 'shuffle:removed',\n};\n\n/** @enum {string} */\nShuffle.Classes = Classes;\n\n/** @enum {string} */\nShuffle.FilterMode = {\n ANY: 'any',\n ALL: 'all',\n};\n\n// Overrideable options\nShuffle.options = {\n // Initial filter group.\n group: Shuffle.ALL_ITEMS,\n\n // Transition/animation speed (milliseconds).\n speed: 250,\n\n // CSS easing function to use.\n easing: 'ease',\n\n // e.g. '.picture-item'.\n itemSelector: '*',\n\n // Element or selector string. Use an element to determine the size of columns\n // and gutters.\n sizer: null,\n\n // A static number or function that tells the plugin how wide the gutters\n // between columns are (in pixels).\n gutterWidth: 0,\n\n // A static number or function that returns a number which tells the plugin\n // how wide the columns are (in pixels).\n columnWidth: 0,\n\n // If your group is not json, and is comma delimeted, you could set delimeter\n // to ','.\n delimeter: null,\n\n // Useful for percentage based heights when they might not always be exactly\n // the same (in pixels).\n buffer: 0,\n\n // Reading the width of elements isn't precise enough and can cause columns to\n // jump between values.\n columnThreshold: 0.01,\n\n // Shuffle can be isInitialized with a sort object. It is the same object\n // given to the sort method.\n initialSort: null,\n\n // By default, shuffle will throttle resize events. This can be changed or\n // removed.\n throttle,\n\n // How often shuffle can be called on resize (in milliseconds).\n throttleTime: 300,\n\n // Transition delay offset for each item in milliseconds.\n staggerAmount: 15,\n\n // Maximum stagger delay in milliseconds.\n staggerAmountMax: 250,\n\n // Whether to use transforms or absolute positioning.\n useTransforms: true,\n\n // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With \"any\",\n // the element passes the test if any of its groups are in the array. With \"all\",\n // the element only passes if all groups are in the array.\n filterMode: Shuffle.FilterMode.ANY,\n\n // Whether to center grid items in the row with the leftover space.\n isCentered: false,\n};\n\nShuffle.Point = Point;\nShuffle.Rect = Rect;\n\n// Expose for testing. Hack at your own risk.\nShuffle.__sorter = sorter;\nShuffle.__getColumnSpan = getColumnSpan;\nShuffle.__getAvailablePositions = getAvailablePositions;\nShuffle.__getShortColumn = getShortColumn;\nShuffle.__getCenteredPositions = getCenteredPositions;\n\nexport default Shuffle;\n","'use strict';\n\nvar proto = typeof Element !== 'undefined' ? Element.prototype : {};\nvar vendor = proto.matches\n || proto.matchesSelector\n || proto.webkitMatchesSelector\n || proto.mozMatchesSelector\n || proto.msMatchesSelector\n || proto.oMatchesSelector;\n\nmodule.exports = match;\n\n/**\n * Match `el` to `selector`.\n *\n * @param {Element} el\n * @param {String} selector\n * @return {Boolean}\n * @api public\n */\n\nfunction match(el, selector) {\n if (!el || el.nodeType !== 1) return false;\n if (vendor) return vendor.call(el, selector);\n var nodes = el.parentNode.querySelectorAll(selector);\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i] == el) return true;\n }\n return false;\n}\n","import getNumber from './get-number';\n\nclass Point {\n\n /**\n * Represents a coordinate pair.\n * @param {number} [x=0] X.\n * @param {number} [y=0] Y.\n */\n constructor(x, y) {\n this.x = getNumber(x);\n this.y = getNumber(y);\n }\n\n /**\n * Whether two points are equal.\n * @param {Point} a Point A.\n * @param {Point} b Point B.\n * @return {boolean}\n */\n static equals(a, b) {\n return a.x === b.x && a.y === b.y;\n }\n}\n\nexport default Point;\n","export default class Rect {\n /**\n * Class for representing rectangular regions.\n * https://github.com/google/closure-library/blob/master/closure/goog/math/rect.js\n * @param {number} x Left.\n * @param {number} y Top.\n * @param {number} w Width.\n * @param {number} h Height.\n * @param {number} id Identifier\n * @constructor\n */\n constructor(x, y, w, h, id) {\n this.id = id;\n\n /** @type {number} */\n this.left = x;\n\n /** @type {number} */\n this.top = y;\n\n /** @type {number} */\n this.width = w;\n\n /** @type {number} */\n this.height = h;\n }\n\n /**\n * Returns whether two rectangles intersect.\n * @param {Rect} a A Rectangle.\n * @param {Rect} b A Rectangle.\n * @return {boolean} Whether a and b intersect.\n */\n static intersects(a, b) {\n return (\n a.left < b.left + b.width && b.left < a.left + a.width &&\n a.top < b.top + b.height && b.top < a.top + a.height);\n }\n}\n","export default {\n BASE: 'shuffle',\n SHUFFLE_ITEM: 'shuffle-item',\n VISIBLE: 'shuffle-item--visible',\n HIDDEN: 'shuffle-item--hidden',\n};\n","import Point from './point';\nimport Classes from './classes';\n\nlet id = 0;\n\nclass ShuffleItem {\n constructor(element) {\n id += 1;\n this.id = id;\n this.element = element;\n this.isVisible = true;\n }\n\n show() {\n this.isVisible = true;\n this.element.classList.remove(Classes.HIDDEN);\n this.element.classList.add(Classes.VISIBLE);\n this.element.removeAttribute('aria-hidden');\n }\n\n hide() {\n this.isVisible = false;\n this.element.classList.remove(Classes.VISIBLE);\n this.element.classList.add(Classes.HIDDEN);\n this.element.setAttribute('aria-hidden', true);\n }\n\n init() {\n this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]);\n this.applyCss(ShuffleItem.Css.INITIAL);\n this.scale = ShuffleItem.Scale.VISIBLE;\n this.point = new Point();\n }\n\n addClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.add(className);\n });\n }\n\n removeClasses(classes) {\n classes.forEach((className) => {\n this.element.classList.remove(className);\n });\n }\n\n applyCss(obj) {\n Object.keys(obj).forEach((key) => {\n this.element.style[key] = obj[key];\n });\n }\n\n dispose() {\n this.removeClasses([\n Classes.HIDDEN,\n Classes.VISIBLE,\n Classes.SHUFFLE_ITEM,\n ]);\n\n this.element.removeAttribute('style');\n this.element = null;\n }\n}\n\nShuffleItem.Css = {\n INITIAL: {\n position: 'absolute',\n top: 0,\n left: 0,\n visibility: 'visible',\n 'will-change': 'transform',\n },\n VISIBLE: {\n before: {\n opacity: 1,\n visibility: 'visible',\n },\n after: {},\n },\n HIDDEN: {\n before: {\n opacity: 0,\n },\n after: {\n visibility: 'hidden',\n },\n },\n};\n\nShuffleItem.Scale = {\n VISIBLE: 1,\n HIDDEN: 0.001,\n};\n\nexport default ShuffleItem;\n","const element = document.body || document.documentElement;\nconst e = document.createElement('div');\ne.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;';\nelement.appendChild(e);\n\nconst width = window.getComputedStyle(e, null).width;\nconst ret = width === '10px';\n\nelement.removeChild(e);\n\nexport default ret;\n","module.exports = throttle;\n\n/**\n * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds.\n *\n * @param {Function} func Function to wrap.\n * @param {Number} wait Number of milliseconds that must elapse between `func` invocations.\n * @return {Function} A new function that wraps the `func` function passed in.\n */\n\nfunction throttle (func, wait) {\n var ctx, args, rtn, timeoutID; // caching\n var last = 0;\n\n return function throttled () {\n ctx = this;\n args = arguments;\n var delta = new Date() - last;\n if (!timeoutID)\n if (delta >= wait) call();\n else timeoutID = setTimeout(call, wait - delta);\n return rtn;\n };\n\n function call () {\n timeoutID = 0;\n last = +new Date();\n rtn = func.apply(ctx, args);\n ctx = null;\n args = null;\n }\n}\n"],"names":["E","noop","getNumber","value","parseFloat","getNumberStyle","element","style","styles","window","getComputedStyle","COMPUTED_SIZE_INCLUDES_PADDING","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","paddingLeft","paddingRight","borderLeftWidth","borderRightWidth","randomize","array","n","length","i","Math","floor","random","temp","sorter","arr","options","opts","Object","assign","defaults","original","Array","from","revert","by","sort","a","b","valA","key","valB","undefined","reverse","uniqueId","eventName","count","cancelTransitionEnd","id","transitions","removeEventListener","listener","onTransitionEnd","callback","evt","currentTarget","target","addEventListener","arrayMax","max","apply","arrayMin","min","getColumnSpan","itemWidth","columnWidth","columns","threshold","columnSpan","abs","round","ceil","getAvailablePositions","positions","available","push","slice","getShortColumn","buffer","minPosition","len","getItemPosition","itemSize","gridSize","total","span","width","setY","shortColumnIndex","point","Point","setHeight","height","getCenteredPositions","itemRects","containerWidth","rowMap","forEach","itemRect","top","rects","rows","centeredRows","keys","lastItem","end","left","offset","finalRects","canMove","newRects","every","r","newRect","Rect","noOverlap","some","intersects","intersectingRect","rowIndex","findIndex","items","includes","splice","concat","map","arrayUnique","x","Set","prototype","on","name","ctx","e","this","fn","once","self","off","arguments","_","emit","data","call","evtArr","evts","liveEvents","proto","Element","vendor","matches","matchesSelector","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","el","selector","nodeType","nodes","parentNode","querySelectorAll","fns","context","maybeDone","err","result","finished","results","pending","y","w","h","ShuffleItem","isVisible","classList","remove","Classes","HIDDEN","add","VISIBLE","removeAttribute","setAttribute","addClasses","SHUFFLE_ITEM","applyCss","Css","INITIAL","scale","Scale","classes","className","obj","removeClasses","document","body","documentElement","createElement","cssText","appendChild","ret","removeChild","Shuffle","lastSort","group","ALL_ITEMS","lastFilter","isEnabled","isDestroyed","isInitialized","_transitions","isTransitioning","_queue","_this","_getElementOption","TypeError","_init","_getItems","sizer","BASE","_initItems","_onResize","_getResizeFunction","readyState","layout","bind","onLoad","containerCss","getSize","_validateStyles","_setColumns","filter","initialSort","offsetWidth","setItemTransitions","transition","speed","easing","resizeFunction","_handleResize","throttle","throttleTime","option","querySelector","jquery","position","overflow","category","collection","set","_getFilteredSets","_toggleFilterClasses","visible","hidden","item","_this2","_doesPassFilter","testCategory","attr","getAttribute","FILTER_ATTRIBUTE_KEY","delimeter","split","JSON","parse","isArray","filterMode","FilterMode","ANY","show","hide","init","dispose","visibleItems","_getFilteredItems","str","useTransforms","children","_this3","itemSelector","indexOf","gutterSize","size","gutterWidth","gutter","_getGutterSize","_getColumnSize","calculatedColumns","columnThreshold","cols","colWidth","_getContainerSize","index","staggerAmount","staggerAmountMax","shuffle","itemPositions","_getNextPositions","transitionDelay","after","currPos","currScale","nextPosition","equals","before","_this4","_getStaggerAmount","isCentered","itemsData","_this5","_getItemPosition","getTransformedPositions","_getConcealedItems","_this6","update","transform","itemCallback","done","_this7","getStylesForTransition","_whenTransitionDone","_cancelMovement","hasSpeed","hasQueue","_startTransitions","_styleImmediately","_dispatch","EventType","LAYOUT","callbacks","_this8","_getTransitionFunction","_movementFinished","objects","elements","_skipTransitions","_this9","sortObj","_filter","_shrink","_updateItemCount","sortOptions","_resetCols","_layout","_processQueue","_setContainerSize","isOnlyLayout","newItems","_saveNewItems","isUpdateLayout","oldItems","_this10","getItemByElement","_disposeItems","REMOVED","find","_this11","includeMargins","duration","transitionDuration","delay","TinyEmitter","func","wait","timeoutID","last","Date","rtn","args","delta","setTimeout","__sorter","__getColumnSpan","__getAvailablePositions","__getShortColumn","__getCenteredPositions"],"mappings":"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"} \ No newline at end of file diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..5658801 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,339 @@ +// Type definitions for Shuffle 5.0 +// Project: https://github.com/Vestride/Shuffle +// Definitions by: Glen Cheney + +export as namespace Shuffle; +export = Shuffle; + +interface FilterMode { + ALL: string; + ANY: string; +} + +declare class ShuffleItem { + constructor(element: Element); + addClasses(classes: string[]): void; + applyCss(obj: object): void; + dispose(): void; + hide(): void; + init(): void; + removeClasses(classes: string[]): void; + show(): void; + id: number; + element: Element; + isVisible: boolean; +} + +declare namespace ShuffleItem { + const Css: { + HIDDEN: { + after: object; + before: object; + }; + INITIAL: object; + VISIBLE: { + after: object; + before: object; + }; + }; + const Scale: { + HIDDEN: number; + VISIBLE: number; + }; +} + +declare class Shuffle { + constructor(element: Element, options?: Shuffle.ShuffleOptions); + + /** + * New items have been appended to shuffle. Mix them in with the current filter or sort status. + * @param {Element[]} newItems Collection of new items. + */ + add(newItems: Element[]): void; + + /** + * Destroys shuffle, removes events, styles, and classes + */ + destroy(): void; + + /** + * Disables shuffle from updating dimensions and layout on resize + */ + disable(): void; + + /** + * Enables shuffle again. + * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters + */ + enable(isUpdateLayout?: true): void; + + /** + * Filter items. + * @param {string|string[]|Function} [category] Category to filter by. + * Can be a function, string, or array of strings. + * @param {Object} [sortObj] A sort object which can sort the visible set + */ + filter(category?: string|string[]|Function, sortObj?: object): void; + + /** + * Retrieve a shuffle item by its element. + * @param {Element} element Element to look for. + */ + getItemByElement(element: Element): ShuffleItem|null; + + /** + * 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. + */ + layout(): void; + + /** + * Remove 1 or more shuffle items. + * @param {Element[]} elements An array containing one or more + * elements in shuffle + */ + remove(elements: Element[]): Shuffle; + + /** + * Dump the elements currently stored and reinitialize all child elements which + * match the `itemSelector`. + */ + resetItems(): void; + + /** + * Gets the visible elements, sorts them, and passes them to layout. + * @param {Object} sortOptions The options object to pass to `sorter`. + */ + sort(sortOptions?): void; + + /** + * Reposition everything. + * @param {boolean} [isOnlyLayout=false] If true, column and gutter widths won't be recalculated. + */ + update(isOnlyLayout?: false): void; + + /** + * Returns styles which will be applied to the an item for a transition. + * @param {object} obj Transition options. + */ + protected getStylesForTransition({ item: ShuffleItem, styles: object }): object; + + /** + * Mutate positions before they're applied. + * @param {Shuffle.Rect[]} itemRects Item data objects. + * @param {number} containerWidth Width of the containing element. + */ + protected getTransformedPositions(itemRects: Shuffle.Rect[], containerWidth: number): Shuffle.Point[]; + + /** + * Sets css transform transition on a group of elements. This is not executed + * at the same time as `item.init` so that transitions don't occur upon + * initialization of Shuffle. + * @param {ShuffleItem[]} items Shuffle items to set transitions on. + */ + protected setItemTransitions(items: ShuffleItem[]): void; + + /** Width of one column */ + colWidth: number; + + /** Total number of columns */ + cols: number; + + /** Width of `element` */ + containerWidth: number; + + /** Main element */ + element: Element; + + /** Current filter group */ + group: string; + + /** Unique identifier for this instance */ + id: string; + + /** Whether this instance has been destroyed */ + isDestroyed: boolean; + + /** Whether this instance is enabled */ + isEnabled: boolean; + + /** Whether this instance has been initialized */ + isInitialized: boolean; + + /** Whether items are currently transitioning */ + isTransitioning: boolean; + + /** ShuffleItems being kept track of */ + items: ShuffleItem[]; + lastFilter: any; + lastSort: any; + + /** Current (merged) options */ + options: Shuffle.ShuffleOptions; + + /** Item positions */ + positions: number[]; + + /** Number of currently visible items */ + visibleItems: number; +} + +declare namespace Shuffle { + /** Filter string for all items */ + let ALL_ITEMS: 'all'; + + /** Data attribute key to use. */ + let FILTER_ATTRIBUTE_KEY: 'groups'; + + /** Class name strings */ + const Classes: { + BASE: string; + HIDDEN: string; + SHUFFLE_ITEM: string; + VISIBLE: string; + }; + + /** Event types emitted by the instance */ + const EventType: { + LAYOUT: string; + REMOVED: string; + }; + + /** Available filter modes. */ + const FilterMode: FilterMode; + + /** ShuffleItem class */ + const ShuffleItem: ShuffleItem; + + /** + * Returns the outer width of an element, optionally including its margins. + * @param {Element} element The element. + * @param {boolean} [includeMargins=false] Whether to include margins. + */ + function getSize(element: Element, includeMargins?: false): {width: number, height: number}; + + class Rect { + constructor(x: number, y: number, w: number, h: number, id?: number); + id: number; + left: number; + top: number; + width: number; + height: number; + } + + namespace Rect { + function intersects(a: Rect, b: Rect): boolean; + } + + class Point { + constructor(x?: number, y?: number); + x: number; + y: number; + } + + namespace Point { + function equals(a: Point, b: Point): boolean; + } + + /** Default options that can be overridden. */ + interface ShuffleOptions { + + /** + * Useful for percentage based heights when they might not always be exactly + * the same (in pixels). + */ + buffer?: number; + + /** + * Reading the width of elements isn't precise enough and can cause columns to + * jump between values. + */ + columnThreshold?: number; + + /** + * A static number or function that returns a number which tells the plugin + * how wide the columns are (in pixels). + */ + columnWidth?: number; + + /** + * If your group is not json, and is comma delimeted, you could set delimeter to ','. + */ + delimeter?: string; + + /** + * CSS easing function to use. + */ + easing?: string; + + /** + * Affects using an array with filter. e.g. `filter(['one', 'two'])`. With "any", + * the element passes the test if any of its groups are in the array. With "all", + * the element only passes if all groups are in the array. + */ + filterMode?: FilterMode; + + /** + * Initial filter group. + */ + group?: string; + + /** + * A static number or function that tells the plugin how wide the gutters + * between columns are (in pixels). + */ + gutterWidth?: number; + + /** + * Shuffle can be isInitialized with a sort object. It is the same object + * given to the sort method. + */ + initialSort?: object; + + /** + * Whether to center grid items in the row with the leftover space. + */ + isCentered?: boolean; + + /** + * e.g. '.picture-item'. + */ + itemSelector?: string; + + /** + * Element or selector string. Use an element to determine the size of columns and gutters. + */ + sizer?: Element|string; + + /** + * Transition/animation speed (milliseconds). + */ + speed?: number; + + /** + * Transition delay offset for each item in milliseconds. + */ + staggerAmount?: number; + + /** + * Maximum stagger delay in milliseconds. + */ + staggerAmountMax?: number; + + /** + * How often shuffle can be called on resize (in milliseconds). + */ + throttleTime?: number; + + /** + * Whether to use transforms or absolute positioning. + */ + useTransforms?: boolean; + + /** + * By default, shuffle will throttle resize events. This can be changed or removed. + */ + throttle?(func: Function, wait: number): Function; + } +} diff --git a/package.json b/package.json index c4f32e9..ebdc6e1 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ ], "main": "dist/shuffle.js", "moduleSource": "src/shuffle.js", + "types": "index.d.ts", "scripts": { "compile": "gulp scripts", "css": "gulp css", @@ -37,7 +38,8 @@ "homepage": "https://github.com/Vestride/Shuffle", "files": [ "dist", - "src" + "src", + "index.d.ts" ], "dependencies": { "array-parallel": "^0.1.3", diff --git a/src/shuffle.js b/src/shuffle.js index 6e18474..ca1c2d6 100644 --- a/src/shuffle.js +++ b/src/shuffle.js @@ -39,7 +39,6 @@ class Shuffle extends TinyEmitter { super(); this.options = Object.assign({}, Shuffle.options, options); - this.useSizer = false; this.lastSort = {}; this.group = Shuffle.ALL_ITEMS; this.lastFilter = Shuffle.ALL_ITEMS; @@ -69,10 +68,6 @@ class Shuffle extends TinyEmitter { this.options.sizer = this._getElementOption(this.options.sizer); - if (this.options.sizer) { - this.useSizer = true; - } - // Add class and invalidate styles this.element.classList.add(Shuffle.Classes.BASE); @@ -200,7 +195,7 @@ class Shuffle extends TinyEmitter { /** * Returns an object containing the visible and hidden elements. * @param {string|Function} category Category or function to filter by. - * @param {Array.} items A collection of items to filter. + * @param {Element[]} items A collection of items to filter. * @return {!{visible: Array, hidden: Array}} * @private */ @@ -279,7 +274,7 @@ class Shuffle extends TinyEmitter { /** * Set the initial css for each item - * @param {Array.} items Set to initialize. + * @param {ShuffleItem[]} items Set to initialize. * @private */ _initItems(items) { @@ -290,7 +285,7 @@ class Shuffle extends TinyEmitter { /** * Remove element reference and styles. - * @param {Array.} items Set to dispose. + * @param {ShuffleItem[]} items Set to dispose. * @private */ _disposeItems(items) { @@ -311,7 +306,7 @@ class Shuffle extends TinyEmitter { * Sets css transform transition on a group of elements. This is not executed * at the same time as `item.init` so that transitions don't occur upon * initialization of Shuffle. - * @param {Array.} items Shuffle items to set transitions on. + * @param {ShuffleItem[]} items Shuffle items to set transitions on. * @protected */ setItemTransitions(items) { @@ -336,7 +331,7 @@ class Shuffle extends TinyEmitter { /** * When new elements are added to the shuffle container, update the array of * items because that is the order `_layout` calls them. - * @param {Array.} items Items to track. + * @param {ShuffleItem[]} items Items to track. */ _saveNewItems(items) { const children = Array.from(this.element.children); @@ -370,7 +365,7 @@ class Shuffle extends TinyEmitter { size = this.options.columnWidth(containerWidth); // columnWidth option isn't a function, are they using a sizing element? - } else if (this.useSizer) { + } else if (this.options.sizer) { size = Shuffle.getSize(this.options.sizer).width; // if not, how about the explicitly set option? @@ -404,7 +399,7 @@ class Shuffle extends TinyEmitter { let size; if (typeof this.options.gutterWidth === 'function') { size = this.options.gutterWidth(containerWidth); - } else if (this.useSizer) { + } else if (this.options.sizer) { size = getNumberStyle(this.options.sizer, 'marginLeft'); } else { size = this.options.gutterWidth; @@ -489,7 +484,7 @@ class Shuffle extends TinyEmitter { /** * Loops through each item that should be shown and calculates the x, y position. - * @param {Array.} items Array of items that will be shown/layed + * @param {ShuffleItem[]} items Array of items that will be shown/layed * out in order in their array. */ _layout(items) { @@ -535,8 +530,8 @@ class Shuffle extends TinyEmitter { /** * Return an array of Point instances representing the future positions of * each item. - * @param {Array.} items Array of sorted shuffle items. - * @return {Array.} + * @param {ShuffleItem[]} items Array of sorted shuffle items. + * @return {Point[]} * @private */ _getNextPositions(items) { @@ -576,9 +571,9 @@ class Shuffle extends TinyEmitter { /** * Mutate positions before they're applied. - * @param {Array.} itemRects Item data objects. + * @param {Rect[]} itemRects Item data objects. * @param {number} containerWidth Width of the containing element. - * @return {Array.} + * @return {Point[]} * @protected */ getTransformedPositions(itemRects, containerWidth) { @@ -587,7 +582,7 @@ class Shuffle extends TinyEmitter { /** * Hides the elements that don't match our filter. - * @param {Array.} collection Collection to shrink. + * @param {ShuffleItem[]} collection Collection to shrink. * @private */ _shrink(collection = this._getConcealedItems()) { @@ -722,7 +717,7 @@ class Shuffle extends TinyEmitter { /** * Wait for each transition to finish, the emit the layout event. - * @param {Array.} transitions Array of transition objects. + * @param {Object[]} transitions Array of transition objects. */ _startTransitions(transitions) { // Set flag that shuffle is currently in motion. @@ -747,7 +742,7 @@ class Shuffle extends TinyEmitter { /** * Apply styles without a transition. - * @param {Array.} objects Array of transition objects. + * @param {Object[]} objects Array of transition objects. * @private */ _styleImmediately(objects) { @@ -771,7 +766,7 @@ class Shuffle extends TinyEmitter { /** * The magic. This is what makes the plugin 'shuffle' - * @param {string|Function|Array.} [category] Category to filter by. + * @param {string|Function|string[]} [category] Category to filter by. * Can be a function, string, or array of strings. * @param {Object} [sortObj] A sort object which can sort the visible set */ @@ -823,10 +818,9 @@ class Shuffle extends TinyEmitter { /** * Reposition everything. - * @param {boolean} isOnlyLayout If true, column and gutter widths won't be - * recalculated. + * @param {boolean} [isOnlyLayout=false] If true, column and gutter widths won't be recalculated. */ - update(isOnlyLayout) { + update(isOnlyLayout = false) { if (this.isEnabled) { if (!isOnlyLayout) { // Get updated colCount @@ -850,7 +844,7 @@ class Shuffle extends TinyEmitter { /** * New items have been appended to shuffle. Mix them in with the current * filter or sort status. - * @param {Array.} newItems Collection of new items. + * @param {Element[]} newItems Collection of new items. */ add(newItems) { const items = arrayUnique(newItems).map(el => new ShuffleItem(el)); @@ -887,10 +881,10 @@ class Shuffle extends TinyEmitter { } /** - * Remove 1 or more shuffle items - * @param {Array.} elements An array containing one or more + * Remove 1 or more shuffle items. + * @param {Element[]} elements An array containing one or more * elements in shuffle - * @return {Shuffle} The shuffle object + * @return {Shuffle} The shuffle instance. */ remove(elements) { if (!elements.length) { @@ -935,7 +929,7 @@ class Shuffle extends TinyEmitter { /** * Retrieve a shuffle item by its element. * @param {Element} element Element to look for. - * @return {?ShuffleItem} A shuffle item or null if it's not found. + * @return {?ShuffleItem} A shuffle item or undefined if it's not found. */ getItemByElement(element) { return this.items.find(item => item.element === element); @@ -1012,10 +1006,10 @@ class Shuffle extends TinyEmitter { * follow the W3C spec here. * * @param {Element} element The element. - * @param {boolean} [includeMargins] Whether to include margins. Default is false. + * @param {boolean} [includeMargins=false] Whether to include margins. * @return {{width: number, height: number}} The width and height. */ - static getSize(element, includeMargins) { + static getSize(element, includeMargins = false) { // Store the styles so that they can be used by others without asking for it again. const styles = window.getComputedStyle(element, null); let width = getNumberStyle(element, 'width', styles); @@ -1038,7 +1032,7 @@ class Shuffle extends TinyEmitter { /** * Change a property or execute a function which will not have a transition - * @param {Array.} elements DOM elements that won't be transitioned. + * @param {Element[]} elements DOM elements that won't be transitioned. * @param {Function} callback A function which will be called while transition * is set to 0ms. * @private @@ -1080,9 +1074,7 @@ Shuffle.ShuffleItem = ShuffleItem; Shuffle.ALL_ITEMS = 'all'; Shuffle.FILTER_ATTRIBUTE_KEY = 'groups'; -/** - * @enum {string} - */ +/** @enum {string} */ Shuffle.EventType = { LAYOUT: 'shuffle:layout', REMOVED: 'shuffle:removed', @@ -1091,9 +1083,7 @@ Shuffle.EventType = { /** @enum {string} */ Shuffle.Classes = Classes; -/** - * @enum {string} - */ +/** @enum {string} */ Shuffle.FilterMode = { ANY: 'any', ALL: 'all', @@ -1166,9 +1156,10 @@ Shuffle.options = { isCentered: false, }; +Shuffle.Point = Point; +Shuffle.Rect = Rect; + // Expose for testing. Hack at your own risk. -Shuffle.__Point = Point; -Shuffle.__Rect = Rect; Shuffle.__sorter = sorter; Shuffle.__getColumnSpan = getColumnSpan; Shuffle.__getAvailablePositions = getAvailablePositions; diff --git a/test/test.js b/test/test.js index f985282..ad36006 100644 --- a/test/test.js +++ b/test/test.js @@ -97,7 +97,6 @@ describe('shuffle', function () { expect(instance.options.delimeter).to.equal(null); expect(instance.options.initialSort).to.equal(null); expect(instance.options.throttleTime).to.equal(300); - expect(instance.useSizer).to.equal(false); expect(instance.id).to.equal('shuffle_0'); expect(instance.isInitialized).to.be.true; @@ -307,21 +306,21 @@ describe('shuffle', function () { it('can center already-positioned items', function() { // 4-2-1 even heights expect(Shuffle.__getCenteredPositions([ - new Shuffle.__Rect(0, 0, 250, 100, 0), - new Shuffle.__Rect(250, 0, 250, 100, 1), - new Shuffle.__Rect(500, 0, 250, 100, 2), - new Shuffle.__Rect(750, 0, 250, 100, 3), - new Shuffle.__Rect(0, 100, 600, 100, 4), - new Shuffle.__Rect(600, 100, 300, 100, 5), - new Shuffle.__Rect(0, 200, 250, 100, 6), + new Shuffle.Rect(0, 0, 250, 100, 0), + new Shuffle.Rect(250, 0, 250, 100, 1), + new Shuffle.Rect(500, 0, 250, 100, 2), + new Shuffle.Rect(750, 0, 250, 100, 3), + new Shuffle.Rect(0, 100, 600, 100, 4), + new Shuffle.Rect(600, 100, 300, 100, 5), + new Shuffle.Rect(0, 200, 250, 100, 6), ], 1000)).to.deep.equal([ - new Shuffle.__Point(0, 0), - new Shuffle.__Point(250, 0), - new Shuffle.__Point(500, 0), - new Shuffle.__Point(750, 0), - new Shuffle.__Point(50, 100), - new Shuffle.__Point(650, 100), - new Shuffle.__Point(375, 200), + new Shuffle.Point(0, 0), + new Shuffle.Point(250, 0), + new Shuffle.Point(500, 0), + new Shuffle.Point(750, 0), + new Shuffle.Point(50, 100), + new Shuffle.Point(650, 100), + new Shuffle.Point(375, 200), ]); // 4 columns: @@ -330,13 +329,13 @@ describe('shuffle', function () { // Centers the first row, but then finds that the 3rd item will overlap // the 2x2 and resets the first row. expect(Shuffle.__getCenteredPositions([ - new Shuffle.__Rect(0, 0, 500, 200, 0), - new Shuffle.__Rect(500, 0, 250, 100, 1), - new Shuffle.__Rect(500, 100, 500, 100, 2), + new Shuffle.Rect(0, 0, 500, 200, 0), + new Shuffle.Rect(500, 0, 250, 100, 1), + new Shuffle.Rect(500, 100, 500, 100, 2), ], 1000)).to.deep.equal([ - new Shuffle.__Point(0, 0), - new Shuffle.__Point(500, 0), - new Shuffle.__Point(500, 100), + new Shuffle.Point(0, 0), + new Shuffle.Point(500, 0), + new Shuffle.Point(500, 100), ]); });