{"version":3,"file":"fjGallery.min.js","sources":["../src/utils/global.js","../node_modules/throttle-debounce/esm/index.js","../node_modules/raf-schd/dist/raf-schd.esm.js","../node_modules/better-justified-layout/dist/better-justified-layout.js","../src/utils/get-img-dimensions.js","../src/fjGallery.js","../src/utils/ready.js","../src/fjGallery.umd.js"],"sourcesContent":["/* eslint-disable import/no-mutable-exports */\n/* eslint-disable no-restricted-globals */\nlet win;\n\nif (typeof window !== 'undefined') {\n win = window;\n} else if (typeof global !== 'undefined') {\n win = global;\n} else if (typeof self !== 'undefined') {\n win = self;\n} else {\n win = {};\n}\n\nexport default win;\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher)\n * are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through,\n * as-is, to `callback` when the throttled-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds\n * while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed\n * one final time after the last throttled-function call. (After the throttled-function has not been called for\n * `delay` milliseconds, the internal counter is reset).\n * @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback\n * immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that\n * callback will never executed if both noLeading = true and noTrailing = true.\n * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is\n * false (at end), schedule `callback` to execute after `delay` ms.\n *\n * @returns {Function} A new, throttled, function.\n */\nfunction throttle (delay, callback, options) {\n var _ref = options || {},\n _ref$noTrailing = _ref.noTrailing,\n noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing,\n _ref$noLeading = _ref.noLeading,\n noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading,\n _ref$debounceMode = _ref.debounceMode,\n debounceMode = _ref$debounceMode === void 0 ? undefined : _ref$debounceMode;\n /*\n * After wrapper has stopped being called, this timeout ensures that\n * `callback` is executed at the proper times in `throttle` and `end`\n * debounce modes.\n */\n\n\n var timeoutID;\n var cancelled = false; // Keep track of the last time `callback` was executed.\n\n var lastExec = 0; // Function to clear existing timeout\n\n function clearExistingTimeout() {\n if (timeoutID) {\n clearTimeout(timeoutID);\n }\n } // Function to cancel next exec\n\n\n function cancel(options) {\n var _ref2 = options || {},\n _ref2$upcomingOnly = _ref2.upcomingOnly,\n upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly;\n\n clearExistingTimeout();\n cancelled = !upcomingOnly;\n }\n /*\n * The `wrapper` function encapsulates all of the throttling / debouncing\n * functionality and when executed will limit the rate at which `callback`\n * is executed.\n */\n\n\n function wrapper() {\n for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) {\n arguments_[_key] = arguments[_key];\n }\n\n var self = this;\n var elapsed = Date.now() - lastExec;\n\n if (cancelled) {\n return;\n } // Execute `callback` and update the `lastExec` timestamp.\n\n\n function exec() {\n lastExec = Date.now();\n callback.apply(self, arguments_);\n }\n /*\n * If `debounceMode` is true (at begin) this is used to clear the flag\n * to allow future `callback` executions.\n */\n\n\n function clear() {\n timeoutID = undefined;\n }\n\n if (!noLeading && debounceMode && !timeoutID) {\n /*\n * Since `wrapper` is being called for the first time and\n * `debounceMode` is true (at begin), execute `callback`\n * and noLeading != true.\n */\n exec();\n }\n\n clearExistingTimeout();\n\n if (debounceMode === undefined && elapsed > delay) {\n if (noLeading) {\n /*\n * In throttle mode with noLeading, if `delay` time has\n * been exceeded, update `lastExec` and schedule `callback`\n * to execute after `delay` ms.\n */\n lastExec = Date.now();\n\n if (!noTrailing) {\n timeoutID = setTimeout(debounceMode ? clear : exec, delay);\n }\n } else {\n /*\n * In throttle mode without noLeading, if `delay` time has been exceeded, execute\n * `callback`.\n */\n exec();\n }\n } else if (noTrailing !== true) {\n /*\n * In trailing throttle mode, since `delay` time has not been\n * exceeded, schedule `callback` to execute `delay` ms after most\n * recent execution.\n *\n * If `debounceMode` is true (at begin), schedule `clear` to execute\n * after `delay` ms.\n *\n * If `debounceMode` is false (at end), schedule `callback` to\n * execute after `delay` ms.\n */\n timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);\n }\n }\n\n wrapper.cancel = cancel; // Return the wrapper function.\n\n return wrapper;\n}\n\n/* eslint-disable no-undefined */\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n * @param {object} [options] - An object to configure options.\n * @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n *\n * @returns {Function} A new, debounced function.\n */\n\nfunction debounce (delay, callback, options) {\n var _ref = options || {},\n _ref$atBegin = _ref.atBegin,\n atBegin = _ref$atBegin === void 0 ? false : _ref$atBegin;\n\n return throttle(delay, callback, {\n debounceMode: atBegin !== false\n });\n}\n\nexport { debounce, throttle };\n//# sourceMappingURL=index.js.map\n","var rafSchd = function rafSchd(fn) {\n var lastArgs = [];\n var frameId = null;\n\n var wrapperFn = function wrapperFn() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n lastArgs = args;\n\n if (frameId) {\n return;\n }\n\n frameId = requestAnimationFrame(function () {\n frameId = null;\n fn.apply(void 0, lastArgs);\n });\n };\n\n wrapperFn.cancel = function () {\n if (!frameId) {\n return;\n }\n\n cancelAnimationFrame(frameId);\n frameId = null;\n };\n\n return wrapperFn;\n};\n\nexport default rafSchd;\n","'use strict';\n\n/**\n * Row\n * Wrapper for each row in a justified layout.\n * Stores relevant values and provides methods for calculating layout of individual rows.\n *\n * @param {Object} layoutConfig - The same as that passed\n * @param {Object} Initialization parameters. The following are all required:\n * @param params.index {Number} The index of this row\n * @param params.top {Number} Top of row, relative to container\n * @param params.left {Number} Left side of row relative to container (equal to container left padding)\n * @param params.width {Number} Width of row, not including container padding\n * @param params.spacing {Number} Horizontal spacing between items\n * @param params.targetRowHeight {Number} Layout algorithm will aim for this row height\n * @param params.targetRowHeightTolerance {Number} Row heights may vary +/- (`targetRowHeight` x `targetRowHeightTolerance`)\n * @param params.edgeCaseMinRowHeight {Number} Absolute minimum row height for edge cases that cannot be resolved within tolerance.\n * @param params.edgeCaseMaxRowHeight {Number} Absolute maximum row height for edge cases that cannot be resolved within tolerance.\n * @param params.isBreakoutRow {Boolean} Is this row in particular one of those breakout rows? Always false if it's not that kind of photo list\n * @param params.widowLayoutStyle {String} If widows are visible, how should they be laid out?\n * @constructor\n */\nconst Row = function (params) {\n // The index of this row\n this.index = params.index;\n\n // Top of row, relative to container\n this.top = params.top;\n\n // Left side of row relative to container (equal to container left padding)\n this.left = params.left;\n\n // Width of row, not including container padding\n this.width = params.width;\n\n // Horizontal spacing between items\n this.spacing = params.spacing;\n\n // Row height calculation values\n this.targetRowHeight = params.targetRowHeight;\n this.targetRowHeightTolerance = params.targetRowHeightTolerance;\n this.minAspectRatio = this.width / params.targetRowHeight * (1 - params.targetRowHeightTolerance);\n this.maxAspectRatio = this.width / params.targetRowHeight * (1 + params.targetRowHeightTolerance);\n\n // Edge case row height minimum/maximum\n this.edgeCaseMinRowHeight = params.edgeCaseMinRowHeight;\n this.edgeCaseMaxRowHeight = params.edgeCaseMaxRowHeight;\n\n // Widow layout direction\n this.widowLayoutStyle = params.widowLayoutStyle;\n\n // Full width breakout rows\n this.isBreakoutRow = params.isBreakoutRow;\n\n // Store layout data for each item in row\n this.items = [];\n\n // Height remains at 0 until it's been calculated\n this.height = 0;\n};\nRow.prototype = {\n /**\n * Attempt to add a single item to the row.\n * This is the heart of the justified algorithm.\n * This method is direction-agnostic; it deals only with sizes, not positions.\n *\n * If the item fits in the row, without pushing row height beyond min/max tolerance,\n * the item is added and the method returns true.\n *\n * If the item leaves row height too high, there may be room to scale it down and add another item.\n * In this case, the item is added and the method returns true, but the row is incomplete.\n *\n * If the item leaves row height too short, there are too many items to fit within tolerance.\n * The method will either accept or reject the new item, favoring the resulting row height closest to within tolerance.\n * If the item is rejected, left/right padding will be required to fit the row height within tolerance;\n * if the item is accepted, top/bottom cropping will be required to fit the row height within tolerance.\n *\n * @method addItem\n * @param itemData {Object} Item layout data, containing item aspect ratio.\n * @return {Boolean} True if successfully added; false if rejected.\n */\n addItem: function (itemData) {\n const newItems = this.items.concat(itemData);\n // Calculate aspect ratios for items only; exclude spacing\n const rowWidthWithoutSpacing = this.width - (newItems.length - 1) * this.spacing;\n const newAspectRatio = newItems.reduce(function (sum, item) {\n return sum + item.aspectRatio;\n }, 0);\n const targetAspectRatio = rowWidthWithoutSpacing / this.targetRowHeight;\n let previousRowWidthWithoutSpacing;\n let previousAspectRatio;\n let previousTargetAspectRatio;\n\n // Handle big full-width breakout photos if we're doing them\n if (this.isBreakoutRow) {\n // Only do it if there's no other items in this row\n if (this.items.length === 0) {\n // Only go full width if this photo is a square or landscape\n if (itemData.aspectRatio >= 1) {\n // Close out the row with a full width photo\n this.items.push(itemData);\n this.completeLayout(rowWidthWithoutSpacing / itemData.aspectRatio, \"justify\");\n return true;\n }\n }\n }\n if (newAspectRatio < this.minAspectRatio) {\n // New aspect ratio is too narrow / scaled row height is too tall.\n // Accept this item and leave row open for more items.\n\n this.items.push(Object.assign({}, itemData));\n return true;\n } else if (newAspectRatio > this.maxAspectRatio) {\n // New aspect ratio is too wide / scaled row height will be too short.\n // Accept item if the resulting aspect ratio is closer to target than it would be without the item.\n // NOTE: Any row that falls into this block will require cropping/padding on individual items.\n\n if (this.items.length === 0) {\n // When there are no existing items, force acceptance of the new item and complete the layout.\n // This is the pano special case.\n this.items.push(Object.assign({}, itemData));\n this.completeLayout(rowWidthWithoutSpacing / newAspectRatio, \"justify\");\n return true;\n }\n\n // Calculate width/aspect ratio for row before adding new item\n previousRowWidthWithoutSpacing = this.width - (this.items.length - 1) * this.spacing;\n previousAspectRatio = this.items.reduce(function (sum, item) {\n return sum + item.aspectRatio;\n }, 0);\n previousTargetAspectRatio = previousRowWidthWithoutSpacing / this.targetRowHeight;\n if (Math.abs(newAspectRatio - targetAspectRatio) > Math.abs(previousAspectRatio - previousTargetAspectRatio)) {\n // Row with new item is us farther away from target than row without; complete layout and reject item.\n this.completeLayout(previousRowWidthWithoutSpacing / previousAspectRatio, \"justify\");\n return false;\n } else {\n // Row with new item is us closer to target than row without;\n // accept the new item and complete the row layout.\n this.items.push(Object.assign({}, itemData));\n this.completeLayout(rowWidthWithoutSpacing / newAspectRatio, \"justify\");\n return true;\n }\n } else {\n // New aspect ratio / scaled row height is within tolerance;\n // accept the new item and complete the row layout.\n this.items.push(Object.assign({}, itemData));\n this.completeLayout(rowWidthWithoutSpacing / newAspectRatio, \"justify\");\n return true;\n }\n },\n /**\n * Check if a row has completed its layout.\n *\n * @method isLayoutComplete\n * @return {Boolean} True if complete; false if not.\n */\n isLayoutComplete: function () {\n return this.height > 0;\n },\n /**\n * Set row height and compute item geometry from that height.\n * Will justify items within the row unless instructed not to.\n *\n * @method completeLayout\n * @param newHeight {Number} Set row height to this value.\n * @param widowLayoutStyle {String} How should widows display? Supported: left | justify | center\n */\n completeLayout: function (newHeight, widowLayoutStyle) {\n let itemWidthSum = this.left;\n const rowWidthWithoutSpacing = this.width - (this.items.length - 1) * this.spacing;\n let clampedToNativeRatio;\n let clampedHeight;\n let errorWidthPerItem;\n let roundedCumulativeErrors;\n let singleItemGeometry;\n let centerOffset;\n\n // Justify unless explicitly specified otherwise.\n if (typeof widowLayoutStyle === \"undefined\" || [\"justify\", \"center\", \"left\"].indexOf(widowLayoutStyle) < 0) {\n widowLayoutStyle = \"left\";\n }\n\n // Clamp row height to edge case minimum/maximum.\n clampedHeight = Math.max(this.edgeCaseMinRowHeight, Math.min(newHeight, this.edgeCaseMaxRowHeight));\n if (newHeight !== clampedHeight) {\n // If row height was clamped, the resulting row/item aspect ratio will be off,\n // so force it to fit the width (recalculate aspectRatio to match clamped height).\n // NOTE: this will result in cropping/padding commensurate to the amount of clamping.\n this.height = clampedHeight;\n clampedToNativeRatio = rowWidthWithoutSpacing / clampedHeight / (rowWidthWithoutSpacing / newHeight);\n } else {\n // If not clamped, leave ratio at 1.0.\n this.height = newHeight;\n clampedToNativeRatio = 1.0;\n }\n\n // Compute item geometry based on newHeight.\n this.items.forEach(function (item) {\n item.row = this.index;\n item.top = this.top;\n item.width = item.aspectRatio * this.height * clampedToNativeRatio;\n item.height = this.height;\n\n // Left-to-right.\n // TODO right to left\n // item.left = this.width - itemWidthSum - item.width;\n item.left = itemWidthSum;\n\n // Increment width.\n itemWidthSum += item.width + this.spacing;\n }, this);\n\n // If specified, ensure items fill row and distribute error\n // caused by rounding width and height across all items.\n if (widowLayoutStyle === \"justify\") {\n itemWidthSum -= this.spacing + this.left;\n errorWidthPerItem = (itemWidthSum - this.width) / this.items.length;\n roundedCumulativeErrors = this.items.map(function (item, i) {\n return Math.round((i + 1) * errorWidthPerItem);\n });\n if (this.items.length === 1) {\n // For rows with only one item, adjust item width to fill row.\n singleItemGeometry = this.items[0];\n singleItemGeometry.width -= Math.round(errorWidthPerItem);\n } else {\n // For rows with multiple items, adjust item width and shift items to fill the row,\n // while maintaining equal spacing between items in the row.\n this.items.forEach(function (item, i) {\n if (i > 0) {\n item.left -= roundedCumulativeErrors[i - 1];\n item.width -= roundedCumulativeErrors[i] - roundedCumulativeErrors[i - 1];\n } else {\n item.width -= roundedCumulativeErrors[i];\n }\n });\n }\n } else if (widowLayoutStyle === \"center\") {\n // Center widows\n centerOffset = (this.width - itemWidthSum) / 2;\n this.items.forEach(function (item) {\n item.left += centerOffset + this.spacing;\n }, this);\n }\n },\n /**\n * Force completion of row layout with current items.\n *\n * @method forceComplete\n * @param fitToWidth {Boolean} Stretch current items to fill the row width.\n * This will likely result in padding.\n * @param fitToWidth {Number}\n */\n forceComplete: function (fitToWidth, rowHeight) {\n // TODO Handle fitting to width\n // var rowWidthWithoutSpacing = this.width - (this.items.length - 1) * this.spacing,\n // \tcurrentAspectRatio = this.items.reduce(function (sum, item) {\n // \t\treturn sum + item.aspectRatio;\n // \t}, 0);\n\n if (typeof rowHeight === \"number\") {\n this.completeLayout(rowHeight, this.widowLayoutStyle);\n } else {\n // Complete using target row height.\n this.completeLayout(this.targetRowHeight, this.widowLayoutStyle);\n }\n },\n /**\n * Return layout data for items within row.\n * Note: returns actual list, not a copy.\n *\n * @method getItems\n * @return Layout data for items within row.\n */\n getItems: function () {\n return this.items;\n }\n};\n\n/*!\n * Copyright 2019 SmugMug, Inc. | Copyright 2024 nK\n * Licensed under the terms of the MIT license. Please see LICENSE file in the project root for terms.\n * @license\n */\n\n/**\n * Create a new, empty row.\n *\n * @method createNewRow\n * @param layoutConfig {Object} The layout configuration\n * @param layoutData {Object} The current state of the layout\n * @return A new, empty row of the type specified by this layout.\n */\nfunction createNewRow(layoutConfig, layoutData) {\n let isBreakoutRow;\n\n // Work out if this is a full width breakout row\n if (layoutConfig.fullWidthBreakoutRowCadence !== false) {\n if ((layoutData._rows.length + 1) % layoutConfig.fullWidthBreakoutRowCadence === 0) {\n isBreakoutRow = true;\n }\n }\n return new Row({\n index: layoutData._rows.length,\n top: layoutData._containerHeight,\n left: layoutConfig.containerPadding.left,\n width: layoutConfig.containerWidth - layoutConfig.containerPadding.left - layoutConfig.containerPadding.right,\n spacing: layoutConfig.boxSpacing.horizontal,\n targetRowHeight: layoutConfig.targetRowHeight,\n targetRowHeightTolerance: layoutConfig.targetRowHeightTolerance,\n edgeCaseMinRowHeight: layoutConfig.edgeCaseMinRowHeight * layoutConfig.targetRowHeight,\n edgeCaseMaxRowHeight: layoutConfig.edgeCaseMaxRowHeight * layoutConfig.targetRowHeight,\n rightToLeft: false,\n isBreakoutRow: isBreakoutRow,\n widowLayoutStyle: layoutConfig.widowLayoutStyle\n });\n}\n\n/**\n * Add a completed row to the layout.\n * Note: the row must have already been completed.\n *\n * @method addRow\n * @param layoutConfig {Object} The layout configuration\n * @param layoutData {Object} The current state of the layout\n * @param row {Row} The row to add.\n * @return {Array} Each item added to the row.\n */\nfunction addRow(layoutConfig, layoutData, row) {\n layoutData._rows.push(row);\n layoutData._layoutItems = layoutData._layoutItems.concat(row.getItems());\n\n // Increment the container height\n layoutData._containerHeight += row.height + layoutConfig.boxSpacing.vertical;\n return row.items;\n}\n\n/**\n * Calculate the current layout for all items in the list that require layout.\n * \"Layout\" means geometry: position within container and size\n *\n * @method computeLayout\n * @param layoutConfig {Object} The layout configuration\n * @param layoutData {Object} The current state of the layout\n * @param itemLayoutData {Array} Array of items to lay out, with data required to lay out each item\n * @return {Object} The newly-calculated layout, containing the new container height, and lists of layout items\n */\nfunction computeLayout(layoutConfig, layoutData, itemLayoutData) {\n let laidOutItems = [];\n let itemAdded;\n let currentRow;\n let nextToLastRowHeight;\n\n // Apply forced aspect ratio if specified, and set a flag.\n if (layoutConfig.forceAspectRatio) {\n itemLayoutData.forEach(function (itemData) {\n itemData.forcedAspectRatio = true;\n itemData.aspectRatio = layoutConfig.forceAspectRatio;\n });\n }\n\n // Loop through the items\n itemLayoutData.some(function (itemData, i) {\n if (isNaN(itemData.aspectRatio)) {\n throw new Error(\"Item \" + i + \" has an invalid aspect ratio\");\n }\n\n // If not currently building up a row, make a new one.\n if (!currentRow) {\n currentRow = createNewRow(layoutConfig, layoutData);\n }\n\n // Attempt to add item to the current row.\n itemAdded = currentRow.addItem(itemData);\n if (currentRow.isLayoutComplete()) {\n // Row is filled; add it and start a new one\n laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));\n if (layoutData._rows.length >= layoutConfig.maxNumRows) {\n currentRow = null;\n return true;\n }\n currentRow = createNewRow(layoutConfig, layoutData);\n\n // Item was rejected; add it to its own row\n if (!itemAdded) {\n itemAdded = currentRow.addItem(itemData);\n if (currentRow.isLayoutComplete()) {\n // If the rejected item fills a row on its own, add the row and start another new one\n laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));\n if (layoutData._rows.length >= layoutConfig.maxNumRows) {\n currentRow = null;\n return true;\n }\n currentRow = createNewRow(layoutConfig, layoutData);\n }\n }\n }\n });\n\n // Handle any leftover content (orphans) depending on where they lie\n // in this layout update, and in the total content set.\n if (currentRow && currentRow.getItems().length && layoutConfig.showWidows) {\n // Last page of all content or orphan suppression is suppressed; lay out orphans.\n if (layoutData._rows.length) {\n // Only Match previous row's height if it exists and it isn't a breakout row\n if (layoutData._rows[layoutData._rows.length - 1].isBreakoutRow) {\n nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].targetRowHeight;\n } else {\n nextToLastRowHeight = layoutData._rows[layoutData._rows.length - 1].height;\n }\n currentRow.forceComplete(false, nextToLastRowHeight);\n } else {\n // ...else use target height if there is no other row height to reference.\n currentRow.forceComplete(false);\n }\n laidOutItems = laidOutItems.concat(addRow(layoutConfig, layoutData, currentRow));\n layoutConfig._widowCount = currentRow.getItems().length;\n }\n\n // We need to clean up the bottom container padding\n // First remove the height added for box spacing\n layoutData._containerHeight = layoutData._containerHeight - layoutConfig.boxSpacing.vertical;\n // Then add our bottom container padding\n layoutData._containerHeight = layoutData._containerHeight + layoutConfig.containerPadding.bottom;\n return {\n containerHeight: layoutData._containerHeight,\n widowCount: layoutConfig._widowCount,\n boxes: layoutData._layoutItems\n };\n}\n\n/**\n * Takes in a bunch of box data and config. Returns\n * geometry to lay them out in a justified view.\n *\n * @method covertSizesToAspectRatios\n * @param sizes {Array} Array of objects with widths and heights\n * @return {Array} A list of aspect ratios\n */\nfunction index (input, config) {\n let layoutConfig = {};\n const layoutData = {};\n\n // Defaults\n const defaults = {\n containerWidth: 1060,\n containerPadding: 10,\n boxSpacing: 10,\n targetRowHeight: 320,\n targetRowHeightTolerance: 0.25,\n edgeCaseMinRowHeight: 0.5,\n edgeCaseMaxRowHeight: 2.5,\n maxNumRows: Number.POSITIVE_INFINITY,\n forceAspectRatio: false,\n showWidows: true,\n fullWidthBreakoutRowCadence: false,\n widowLayoutStyle: \"left\"\n };\n const containerPadding = {};\n const boxSpacing = {};\n config = config || {};\n\n // Merge defaults and config passed in\n layoutConfig = Object.assign(defaults, config);\n\n // Sort out padding and spacing values\n containerPadding.top = !isNaN(parseFloat(layoutConfig.containerPadding.top)) ? layoutConfig.containerPadding.top : layoutConfig.containerPadding;\n containerPadding.right = !isNaN(parseFloat(layoutConfig.containerPadding.right)) ? layoutConfig.containerPadding.right : layoutConfig.containerPadding;\n containerPadding.bottom = !isNaN(parseFloat(layoutConfig.containerPadding.bottom)) ? layoutConfig.containerPadding.bottom : layoutConfig.containerPadding;\n containerPadding.left = !isNaN(parseFloat(layoutConfig.containerPadding.left)) ? layoutConfig.containerPadding.left : layoutConfig.containerPadding;\n boxSpacing.horizontal = !isNaN(parseFloat(layoutConfig.boxSpacing.horizontal)) ? layoutConfig.boxSpacing.horizontal : layoutConfig.boxSpacing;\n boxSpacing.vertical = !isNaN(parseFloat(layoutConfig.boxSpacing.vertical)) ? layoutConfig.boxSpacing.vertical : layoutConfig.boxSpacing;\n layoutConfig.containerPadding = containerPadding;\n layoutConfig.boxSpacing = boxSpacing;\n\n // Local\n layoutData._layoutItems = [];\n layoutData._awakeItems = [];\n layoutData._inViewportItems = [];\n layoutData._leadingOrphans = [];\n layoutData._trailingOrphans = [];\n layoutData._containerHeight = layoutConfig.containerPadding.top;\n layoutData._rows = [];\n layoutData._orphans = [];\n layoutConfig._widowCount = 0;\n\n // Convert widths and heights to aspect ratios if we need to\n return computeLayout(layoutConfig, layoutData, input.map(function (item) {\n if (item.width && item.height) {\n return {\n aspectRatio: item.width / item.height\n };\n } else {\n return {\n aspectRatio: item\n };\n }\n }));\n}\n\nmodule.exports = index;\n//# sourceMappingURL=better-justified-layout.js.map\n","// get image dimensions\n// thanks https://gist.github.com/dimsemenov/5382856\nfunction getImgDimensions(img, cb) {\n let interval;\n let hasSize = false;\n let addedListeners = false;\n\n const onHasSize = () => {\n if (hasSize) {\n cb(hasSize);\n return;\n }\n\n // check for non-zero, non-undefined naturalWidth\n if (!img.naturalWidth) {\n return;\n }\n\n hasSize = {\n width: img.naturalWidth,\n height: img.naturalHeight,\n };\n cb(hasSize);\n\n clearInterval(interval);\n if (addedListeners) {\n // eslint-disable-next-line no-use-before-define\n removeListeners();\n }\n };\n const onLoaded = () => {\n onHasSize();\n };\n const onError = () => {\n onHasSize();\n };\n const checkSize = () => {\n if (img.naturalWidth > 0) {\n onHasSize();\n }\n };\n const addListeners = () => {\n addedListeners = true;\n img.addEventListener('load', onLoaded);\n img.addEventListener('error', onError);\n };\n const removeListeners = () => {\n addedListeners = false;\n img.removeEventListener('load', onLoaded);\n img.removeEventListener('error', onError);\n };\n\n checkSize();\n\n if (!hasSize) {\n addListeners();\n interval = setInterval(checkSize, 100);\n }\n}\n\nexport default getImgDimensions;\n","import { debounce } from 'throttle-debounce';\nimport rafSchd from 'raf-schd';\nimport justifiedLayout from 'better-justified-layout';\n\nimport domReady from './utils/ready';\nimport global from './utils/global';\nimport getImgDimensions from './utils/get-img-dimensions';\n\n// list with all fjGallery instances\n// need to render all in one scroll/resize event\nconst fjGalleryList = [];\n\nconst updateFjGallery = rafSchd(() => {\n fjGalleryList.forEach((item) => {\n item.resize();\n });\n});\n\nglobal.addEventListener('resize', updateFjGallery);\nglobal.addEventListener('orientationchange', updateFjGallery);\nglobal.addEventListener('load', updateFjGallery);\ndomReady(() => {\n updateFjGallery();\n});\n\nlet instanceID = 0;\n\n// fjGallery class\nclass FJGallery {\n constructor(container, userOptions) {\n const self = this;\n\n self.instanceID = instanceID;\n instanceID += 1;\n\n self.$container = container;\n\n self.images = [];\n\n self.defaults = {\n itemSelector: '.fj-gallery-item',\n imageSelector: 'img',\n gutter: 10, // supports object like `{ horizontal: 10, vertical: 10 }`.\n rowHeight: 320,\n rowHeightTolerance: 0.25, // [0, 1]\n maxRowsCount: Number.POSITIVE_INFINITY,\n edgeCaseMinRowHeight: 0.5,\n edgeCaseMaxRowHeight: 2.5,\n lastRow: 'left', // left, center, right, hide\n transitionDuration: '0.3s',\n calculateItemsHeight: false,\n resizeDebounce: 100,\n isRtl: self.css(self.$container, 'direction') === 'rtl',\n\n // events\n onInit: null, // function() {}\n onDestroy: null, // function() {}\n onAppendImages: null, // function() {}\n onBeforeJustify: null, // function() {}\n onJustify: null, // function() {}\n };\n\n // prepare data-options\n const dataOptions = self.$container.dataset || {};\n const pureDataOptions = {};\n Object.keys(dataOptions).forEach((key) => {\n const loweCaseOption = key.substr(0, 1).toLowerCase() + key.substr(1);\n if (loweCaseOption && typeof self.defaults[loweCaseOption] !== 'undefined') {\n pureDataOptions[loweCaseOption] = dataOptions[key];\n }\n });\n\n self.options = {\n ...self.defaults,\n ...pureDataOptions,\n ...userOptions,\n };\n\n self.pureOptions = {\n ...self.options,\n };\n\n // debounce for resize\n self.resize = debounce(self.options.resizeDebounce, self.resize);\n self.justify = rafSchd(self.justify.bind(self));\n\n self.init();\n }\n\n // add styles to element\n // eslint-disable-next-line class-methods-use-this\n css(el, styles) {\n if (typeof styles === 'string') {\n return global.getComputedStyle(el).getPropertyValue(styles);\n }\n\n Object.keys(styles).forEach((key) => {\n el.style[key] = styles[key];\n });\n return el;\n }\n\n // set temporary transition with event listener\n applyTransition($item, properties) {\n const self = this;\n\n // Remove previous event listener\n self.onTransitionEnd($item)();\n\n // Add transitions\n self.css($item, {\n 'transition-property': properties.join(', '),\n 'transition-duration': self.options.transitionDuration,\n });\n\n // Add event listener\n $item.addEventListener('transitionend', self.onTransitionEnd($item, properties), false);\n }\n\n onTransitionEnd($item) {\n const self = this;\n\n return () => {\n self.css($item, {\n 'transition-property': '',\n 'transition-duration': '',\n });\n\n $item.removeEventListener('transitionend', self.onTransitionEnd($item));\n };\n }\n\n // add to fjGallery instances list\n addToFjGalleryList() {\n fjGalleryList.push(this);\n updateFjGallery();\n }\n\n // remove from fjGallery instances list\n removeFromFjGalleryList() {\n const self = this;\n\n fjGalleryList.forEach((item, key) => {\n if (item.instanceID === self.instanceID) {\n fjGalleryList.splice(key, 1);\n }\n });\n }\n\n init() {\n const self = this;\n\n self.appendImages(self.$container.querySelectorAll(self.options.itemSelector));\n\n self.addToFjGalleryList();\n\n // call onInit event\n if (self.options.onInit) {\n self.options.onInit.call(self);\n }\n }\n\n // append images\n appendImages($images) {\n const self = this;\n\n // check if jQuery\n if (global.jQuery && $images instanceof global.jQuery) {\n $images = $images.get();\n }\n\n if (!$images || !$images.length) {\n return;\n }\n\n $images.forEach(($item) => {\n // if $images is jQuery, for some reason in this array there is undefined item, that not a DOM,\n // so we need to check for $item.querySelector.\n if ($item && !$item.fjGalleryImage && $item.querySelector) {\n const $image = $item.querySelector(self.options.imageSelector);\n\n if ($image) {\n $item.fjGalleryImage = self;\n const data = {\n $item,\n $image,\n width: parseFloat($image.getAttribute('width')) || false,\n height: parseFloat($image.getAttribute('height')) || false,\n loadSizes() {\n const itemData = this;\n getImgDimensions($image, (dimensions) => {\n if (itemData.width !== dimensions.width || itemData.height !== dimensions.height) {\n itemData.width = dimensions.width;\n itemData.height = dimensions.height;\n self.resize();\n }\n });\n },\n };\n data.loadSizes();\n\n self.images.push(data);\n }\n }\n });\n\n // call onAppendImages event\n if (self.options.onAppendImages) {\n self.options.onAppendImages.call(self, [$images]);\n }\n\n self.justify();\n }\n\n // justify images\n justify() {\n const self = this;\n const justifyArray = [];\n\n self.justifyCount = (self.justifyCount || 0) + 1;\n\n // call onBeforeJustify event\n if (self.options.onBeforeJustify) {\n self.options.onBeforeJustify.call(self);\n }\n\n self.images.forEach((data) => {\n if (data.width && data.height) {\n justifyArray.push(data.width / data.height);\n }\n });\n\n const justifiedOptions = {\n containerWidth: self.$container.getBoundingClientRect().width,\n containerPadding: {\n top: parseFloat(self.css(self.$container, 'padding-top')) || 0,\n right: parseFloat(self.css(self.$container, 'padding-right')) || 0,\n bottom: parseFloat(self.css(self.$container, 'padding-bottom')) || 0,\n left: parseFloat(self.css(self.$container, 'padding-left')) || 0,\n },\n boxSpacing: self.options.gutter,\n targetRowHeight: self.options.rowHeight,\n targetRowHeightTolerance: self.options.rowHeightTolerance,\n maxNumRows: self.options.maxRowsCount,\n edgeCaseMinRowHeight: self.options.edgeCaseMinRowHeight,\n edgeCaseMaxRowHeight: self.options.edgeCaseMaxRowHeight,\n showWidows: self.options.lastRow !== 'hide',\n };\n const justifiedData = justifiedLayout(justifyArray, justifiedOptions);\n\n // Align last row\n if (\n justifiedData.widowCount &&\n (self.options.lastRow === 'center' || self.options.lastRow === 'right')\n ) {\n const lastItemData = justifiedData.boxes[justifiedData.boxes.length - 1];\n let gapSize = justifiedOptions.containerWidth - lastItemData.width - lastItemData.left;\n\n if (self.options.lastRow === 'center') {\n gapSize /= 2;\n }\n if (self.options.lastRow === 'right') {\n gapSize -= justifiedOptions.containerPadding.right;\n }\n\n for (let i = 1; i <= justifiedData.widowCount; i += 1) {\n justifiedData.boxes[justifiedData.boxes.length - i].left =\n justifiedData.boxes[justifiedData.boxes.length - i].left + gapSize;\n }\n }\n\n // RTL compatibility\n if (self.options.isRtl) {\n justifiedData.boxes.forEach((boxData, i) => {\n justifiedData.boxes[i].left =\n justifiedOptions.containerWidth -\n justifiedData.boxes[i].left -\n justifiedData.boxes[i].width -\n justifiedOptions.containerPadding.right +\n justifiedOptions.containerPadding.left;\n });\n }\n\n let i = 0;\n let additionalTopOffset = 0;\n const rowsMaxHeight = {};\n\n // Set image sizes.\n self.images.forEach((data, imgI) => {\n if (justifiedData.boxes[i] && data.width && data.height) {\n // calculate additional offset based on actual items height.\n if (\n self.options.calculateItemsHeight &&\n typeof rowsMaxHeight[justifiedData.boxes[i].row] === 'undefined' &&\n Object.keys(rowsMaxHeight).length\n ) {\n additionalTopOffset +=\n rowsMaxHeight[Object.keys(rowsMaxHeight).pop()] - justifiedData.boxes[imgI - 1].height;\n }\n\n if (self.options.transitionDuration && self.justifyCount > 1) {\n self.applyTransition(data.$item, ['transform']);\n }\n\n self.css(data.$item, {\n display: '',\n position: 'absolute',\n transform: `translateX(${justifiedData.boxes[i].left}px) translateY(${\n justifiedData.boxes[i].top + additionalTopOffset\n }px) translateZ(0)`,\n width: `${justifiedData.boxes[i].width}px`,\n });\n\n // calculate actual items height.\n if (self.options.calculateItemsHeight) {\n const rect = data.$item.getBoundingClientRect();\n\n if (\n typeof rowsMaxHeight[justifiedData.boxes[i].row] === 'undefined' ||\n rowsMaxHeight[justifiedData.boxes[i].row] < rect.height\n ) {\n rowsMaxHeight[justifiedData.boxes[i].row] = rect.height;\n }\n }\n\n i += 1;\n } else {\n self.css(data.$item, {\n display: 'none',\n });\n }\n });\n\n // increase additional offset based on the latest row items height.\n if (self.options.calculateItemsHeight && Object.keys(rowsMaxHeight).length) {\n additionalTopOffset +=\n rowsMaxHeight[Object.keys(rowsMaxHeight).pop()] -\n justifiedData.boxes[justifiedData.boxes.length - 1].height;\n }\n\n if (self.options.transitionDuration) {\n self.applyTransition(self.$container, ['height']);\n }\n\n // Set container height.\n self.css(self.$container, {\n height: `${justifiedData.containerHeight + additionalTopOffset}px`,\n });\n\n // call onJustify event\n if (self.options.onJustify) {\n self.options.onJustify.call(self);\n }\n }\n\n // update options and resize gallery items\n updateOptions(options) {\n const self = this;\n self.options = {\n ...self.options,\n ...options,\n };\n self.justify();\n }\n\n destroy() {\n const self = this;\n\n self.removeFromFjGalleryList();\n\n self.justifyCount = 0;\n\n // call onDestroy event\n if (self.options.onDestroy) {\n self.options.onDestroy.call(self);\n }\n\n // remove styles.\n self.css(self.$container, {\n height: '',\n transition: '',\n });\n self.images.forEach((data) => {\n self.css(data.$item, {\n position: '',\n transform: '',\n transition: '',\n width: '',\n height: '',\n });\n });\n\n // delete fjGalleryImage instance from images\n self.images.forEach((val) => {\n delete val.$item.fjGalleryImage;\n });\n\n // delete fjGallery instance from container\n delete self.$container.fjGallery;\n }\n\n resize() {\n const self = this;\n\n self.justify();\n }\n}\n\n// global definition\nconst fjGallery = function (items, options, ...args) {\n // check for dom element\n // thanks: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n if (\n typeof HTMLElement === 'object'\n ? items instanceof HTMLElement\n : items &&\n typeof items === 'object' &&\n items !== null &&\n items.nodeType === 1 &&\n typeof items.nodeName === 'string'\n ) {\n items = [items];\n }\n\n const len = items.length;\n let k = 0;\n let ret;\n\n for (k; k < len; k += 1) {\n if (typeof options === 'object' || typeof options === 'undefined') {\n if (!items[k].fjGallery) {\n // eslint-disable-next-line new-cap\n items[k].fjGallery = new FJGallery(items[k], options);\n }\n } else if (items[k].fjGallery) {\n // eslint-disable-next-line prefer-spread\n ret = items[k].fjGallery[options].apply(items[k].fjGallery, args);\n }\n if (typeof ret !== 'undefined') {\n return ret;\n }\n }\n\n return items;\n};\nfjGallery.constructor = FJGallery;\n\nexport default fjGallery;\n","function ready(callback) {\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n // Already ready or interactive, execute callback\n callback();\n } else {\n document.addEventListener('DOMContentLoaded', callback, {\n capture: true,\n once: true,\n passive: true,\n });\n }\n}\n\nexport default ready;\n","import global from './utils/global';\nimport fjGallery from './fjGallery';\n\nconst $ = global.jQuery;\n\n// jQuery support\nif (typeof $ !== 'undefined') {\n // add data to jQuery .data('fjGallery')\n const oldInit = fjGallery.constructor.prototype.init;\n fjGallery.constructor.prototype.init = function () {\n $(this.$container).data('fjGallery', this);\n\n if (oldInit) {\n oldInit.call(this);\n }\n };\n\n // remove data from jQuery .data('fjGallery')\n const oldDestroy = fjGallery.constructor.prototype.destroy;\n fjGallery.constructor.prototype.destroy = function () {\n if (this.$container) {\n $(this.$container).removeData('fjGallery');\n }\n if (oldDestroy) {\n oldDestroy.call(this);\n }\n };\n\n const $Plugin = function (...args) {\n Array.prototype.unshift.call(args, this);\n const res = fjGallery.apply(global, args);\n return typeof res !== 'object' ? res : this;\n };\n $Plugin.constructor = fjGallery.constructor;\n\n // no conflict\n const old$Plugin = $.fn.fjGallery;\n $.fn.fjGallery = $Plugin;\n $.fn.fjGallery.noConflict = function () {\n $.fn.fjGallery = old$Plugin;\n return this;\n };\n}\n\nexport default fjGallery;\n"],"names":["win","window","global","self","global$1","delay","callback","options","timeoutID","_ref","_ref$noTrailing","noTrailing","_ref$noLeading","noLeading","_ref$debounceMode","debounceMode","undefined","cancelled","lastExec","clearExistingTimeout","clearTimeout","wrapper","_len","arguments","length","arguments_","Array","_key","this","elapsed","Date","now","exec","apply","clear","setTimeout","cancel","_ref2$upcomingOnly","upcomingOnly","rafSchd","fn","lastArgs","frameId","wrapperFn","args","requestAnimationFrame","cancelAnimationFrame","Row","params","index","top","left","width","spacing","targetRowHeight","targetRowHeightTolerance","maxAspectRatio","edgeCaseMaxRowHeight","widowLayoutStyle","isBreakoutRow","items","height","prototype","addItem","itemData","newItems","concat","rowWidthWithoutSpacing","targetAspectRatio","previousRowWidthWithoutSpacing","previousTargetAspectRatio","aspectRatio","push","completeLayout","newAspectRatio","minAspectRatio","Object","assign","previousAspectRatio","reduce","sum","item","Math","abs","isLayoutComplete","newHeight","itemWidthSum","clampedToNativeRatio","clampedHeight","errorWidthPerItem","roundedCumulativeErrors","centerOffset","indexOf","max","edgeCaseMinRowHeight","min","forEach","row","map","i","round","singleItemGeometry","forceComplete","fitToWidth","rowHeight","getItems","getImgDimensions","img","cb","interval","hasSize","addedListeners","onHasSize","naturalWidth","naturalHeight","clearInterval","removeListeners","onLoaded","onError","checkSize","removeEventListener","addEventListener","setInterval","fjGalleryList","updateFjGallery","resize","document","readyState","capture","once","passive","instanceID","FJGallery","constructor","container","userOptions","$container","images","defaults","itemSelector","imageSelector","gutter","rowHeightTolerance","maxRowsCount","Number","POSITIVE_INFINITY","lastRow","transitionDuration","calculateItemsHeight","resizeDebounce","isRtl","css","onInit","onDestroy","onAppendImages","onBeforeJustify","onJustify","dataOptions","dataset","pureDataOptions","keys","key","loweCaseOption","substr","toLowerCase","pureOptions","debounce","justify","bind","init","el","styles","getComputedStyle","getPropertyValue","style","applyTransition","$item","properties","onTransitionEnd","join","addToFjGalleryList","removeFromFjGalleryList","splice","appendImages","querySelectorAll","call","$images","jQuery","get","fjGalleryImage","querySelector","$image","data","parseFloat","getAttribute","loadSizes","dimensions","justifyArray","justifyCount","justifiedOptions","containerWidth","getBoundingClientRect","containerPadding","right","bottom","boxSpacing","maxNumRows","showWidows","justifiedData","justifiedLayout","widowCount","lastItemData","boxes","gapSize","boxData","additionalTopOffset","rowsMaxHeight","imgI","pop","display","position","transform","rect","containerHeight","updateOptions","destroy","transition","val","fjGallery","HTMLElement","nodeType","nodeName","len","ret","k","$","oldInit","oldDestroy","removeData","$Plugin","unshift","res","old$Plugin","noConflict"],"mappings":"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","x_google_ignoreList":[1,2,3]}