{"version":3,"sources":["webpack:///./app/javascript/utilities/http/errors.js","webpack:///./app/javascript/profileDropdown/flagButton.js","webpack:///./app/javascript/packs/profileDropdown.js","webpack:///./app/javascript/profileDropdown/blockButton.js","webpack:///./app/javascript/utilities/http/request.js","webpack:///./app/javascript/utilities/viewport.js","webpack:///./app/javascript/utilities/dropdownUtils.js","webpack:///./app/javascript/utilities/debounceAction.js","webpack:///./node_modules/lodash.debounce/index.js","webpack:///./app/javascript/utilities/getUserDataAndCsrfToken.js","webpack:///(webpack)/buildin/global.js"],"names":["handleFetchAPIErrors","response","ok","json","then","data","Error","error","e","SyntaxError","statusText","initFlag","flagButton","document","getElementById","getUserDataAndCsrfToken","user","userData","trustedOrAdmin","trusted","admin","profileUserId","dataset","id","parseInt","remove","profileUserName","isUserFlagged","addEventListener","window","confirm","request","method","body","reactable_type","category","reactable_id","result","innerHTML","Honeybadger","notify","alert","addFlagUserBehavior","initButtons","blockButton","style","display","fetch","innerText","unblock","once","block","headers","Accept","csrfToken","JSON","stringify","user_block","blocked_id","status","initBlock","profileDropdownDiv","querySelector","dropdownInitialized","currentUser","username","classList","initializeDropdown","triggerElementId","dropdownContentId","reportAbuseLink","path","initDropdown","url","options","getCsrfToken","restOfOptions","jsonifiedBody","fetchOptions","credentials","isInViewport","element","offsetTop","allowPartialVisibility","boundingRect","getBoundingClientRect","clientHeight","innerHeight","documentElement","clientWidth","innerWidth","topIsInViewport","top","rightIsInViewport","right","bottomIsInViewport","bottom","leftIsInViewport","left","topIsOutOfViewport","bottomIsOutOfViewport","getDropdownRepositionListener","debounceAction","handleDropdownRepositions","querySelectorAll","isDropdownCurrentlyOpen","opacity","add","removeProperty","INTERACTIVE_ELEMENTS_QUERY","closeDropdown","onClose","dropdownContent","setAttribute","dropdownContentCloseButtonId","onOpen","triggerButton","keyUpListener","key","getAttribute","onCloseCleanupActions","focus","contains","activeElement","clickOutsideListener","target","matches","removeEventListener","openDropdown","action","time","config","leading","configs","debounce","reTrim","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","freeGlobal","global","Object","freeSelf","self","root","Function","objectToString","prototype","toString","nativeMax","Math","max","nativeMin","min","now","Date","isObject","value","type","toNumber","isObjectLike","call","isSymbol","other","valueOf","replace","isBinary","test","slice","module","exports","func","wait","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","maxing","trailing","TypeError","invokeFunc","args","thisArg","undefined","apply","leadingEdge","setTimeout","timerExpired","shouldInvoke","timeSinceLastCall","trailingEdge","remainingWait","debounced","isInvoking","arguments","this","cancel","clearTimeout","flush","getWaitOnUserDataHandler","resolve","reject","waitTime","totalTimeWaiting","waitingOnUserData","content","parse","Promise","g"],"mappings":"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","file":"js/profileDropdown-681d5c45d58932bd8b94.chunk.js","sourcesContent":["// eslint-disable-next-line consistent-return\nexport function handleFetchAPIErrors(response) {\n // pass along a correct response\n if (response.ok) {\n return response;\n }\n\n // API errors contain the error message in {\"error\": \"error message\"}\n // but they could be unhandled 500 errors\n try {\n response.json().then((data) => {\n throw new Error(data.error);\n });\n } catch (e) {\n if (e instanceof SyntaxError) {\n throw new Error(response.statusText);\n } else {\n throw e;\n }\n }\n}\n","/* global userData */\n/* eslint-disable no-alert, import/order */\nimport { request } from '@utilities/http';\nimport { getUserDataAndCsrfToken } from '@utilities/getUserDataAndCsrfToken';\n\nfunction addFlagUserBehavior(flagButton) {\n const { profileUserId, profileUserName } = flagButton.dataset;\n\n let isUserFlagged = flagButton.dataset.isUserFlagged === 'true';\n\n function flag() {\n const confirmFlag = window.confirm(\n isUserFlagged\n ? 'Are you sure you want to unflag this person? This will make all of their posts visible again.'\n : 'Are you sure you want to flag this person? This will make all of their posts less visible.',\n );\n\n if (confirmFlag) {\n request('/reactions', {\n method: 'POST',\n body: {\n reactable_type: 'User',\n category: 'vomit',\n reactable_id: profileUserId,\n },\n })\n .then((response) => response.json())\n .then((response) => {\n if (response.result === 'create') {\n isUserFlagged = true;\n flagButton.innerHTML = `Unflag ${profileUserName}`;\n } else {\n isUserFlagged = false;\n flagButton.innerHTML = `Flag ${profileUserName}`;\n }\n })\n .catch((e) => {\n Honeybadger.notify(\n isUserFlagged ? 'Unable to unflag user' : 'Unable to flag user',\n profileUserId,\n );\n window.alert(`Something went wrong: ${e}`);\n });\n }\n }\n\n flagButton.addEventListener('click', flag);\n}\n\n/**\n * Adds a flag button visible only to trusted users on profile pages.\n * @function initFlag\n * @returns {(void|undefined)} This function has no useable return value.\n */\n\nexport function initFlag() {\n const flagButton = document.getElementById(\n 'user-profile-dropdownmenu-flag-button',\n );\n\n if (!flagButton) {\n // button not always present when this is called\n return;\n }\n\n getUserDataAndCsrfToken().then(() => {\n const user = userData();\n if (!user) {\n flagButton.remove();\n return;\n }\n\n const trustedOrAdmin = user.trusted || user.admin;\n const { profileUserId } = flagButton.dataset;\n\n if (!trustedOrAdmin || user.id === parseInt(profileUserId, 10)) {\n flagButton.remove();\n }\n addFlagUserBehavior(flagButton);\n });\n}\n/* eslint-enable no-alert */\n","import { initBlock } from '../profileDropdown/blockButton';\nimport { initFlag } from '../profileDropdown/flagButton';\nimport { initializeDropdown } from '@utilities/dropdownUtils';\n\n/* global userData */\n\nfunction initButtons() {\n initBlock();\n initFlag();\n}\n\nfunction initDropdown() {\n const profileDropdownDiv = document.querySelector('.profile-dropdown');\n\n if (profileDropdownDiv.dataset.dropdownInitialized === 'true') {\n return;\n }\n const currentUser = userData();\n\n if (\n !profileDropdownDiv ||\n (currentUser &&\n currentUser.username === profileDropdownDiv.dataset.username)\n ) {\n // Hide this menu when user views their own profile\n return;\n }\n\n profileDropdownDiv.classList.remove('hidden');\n\n initializeDropdown({\n triggerElementId: 'user-profile-dropdown',\n dropdownContentId: 'user-profile-dropdownmenu',\n });\n\n // Add actual link location (SEO doesn't like these \"useless\" links, so adding in here instead of in HTML)\n const reportAbuseLink = profileDropdownDiv.querySelector(\n '.report-abuse-link-wrapper',\n );\n reportAbuseLink.innerHTML = `Report Abuse`;\n\n initButtons();\n profileDropdownDiv.dataset.dropdownInitialized = true;\n}\n\ninitDropdown();\n","/* eslint-disable no-alert */\n\nexport function initBlock() {\n const blockButton = document.getElementById(\n 'user-profile-dropdownmenu-block-button',\n );\n if (!blockButton) {\n // button not always present when this is called\n return;\n }\n const { profileUserId } = blockButton.dataset;\n\n function unblock() {\n fetch(`/user_blocks/${profileUserId}`, {\n method: 'DELETE',\n headers: {\n Accept: 'application/json',\n 'X-CSRF-Token': window.csrfToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n user_block: {\n blocked_id: profileUserId,\n },\n }),\n })\n .then((response) => response.json())\n .then((response) => {\n if (response.result === 'unblocked') {\n blockButton.innerText = 'Block';\n /* eslint-disable-next-line no-use-before-define */\n blockButton.addEventListener('click', block, { once: true });\n } else if (response.status === 422) {\n window.alert(\n `Something went wrong: ${response.error} -- Please refresh the page to try again.`,\n );\n }\n })\n .catch((e) => {\n window.alert(\n `Something went wrong: ${e}. -- Please refresh the page to try again.`,\n );\n });\n }\n\n function block() {\n const confirmBlock = window.confirm(\n `Are you sure you want to block this person? This will:\n - prevent them from commenting on your posts\n - block all notifications from them\n - prevent them from messaging you via Connect\n - hide their posts from your feed`,\n );\n if (confirmBlock) {\n fetch(`/user_blocks`, {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'X-CSRF-Token': window.csrfToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n user_block: {\n blocked_id: profileUserId,\n },\n }),\n })\n .then((response) => response.json())\n .then((response) => {\n if (response.result === 'blocked') {\n blockButton.innerText = 'Unblock';\n blockButton.addEventListener('click', unblock, { once: true });\n } else if (response.status === 422) {\n window.alert(\n `Something went wrong: ${response.error}. -- Please refresh the page to try again.`,\n );\n }\n })\n .catch((e) => {\n window.alert(\n `Something went wrong: ${e}. -- Please refresh the page to try again.`,\n );\n });\n } else {\n blockButton.addEventListener('click', block, { once: true });\n }\n }\n\n // userData() is a global function\n /* eslint-disable-next-line no-undef */\n const user = userData();\n if (!user) {\n return;\n }\n\n if (user.id === parseInt(profileUserId, 10)) {\n blockButton.style.display = 'none';\n } else {\n fetch(`/user_blocks/${profileUserId}`)\n .then((response) => response.json())\n .then((response) => {\n if (response.result === 'blocking') {\n blockButton.innerText = 'Unblock';\n blockButton.addEventListener('click', unblock, { once: true });\n } else {\n blockButton.addEventListener('click', block, { once: true });\n }\n });\n }\n}\n\n/* eslint-enable no-alert */\n","/**\n * Generic request with all the default headers required by the application.\n *\n * @example\n * import { request } from '@utilities/http';\n *\n * const response = await request('/notification_subscriptions/Article/26')\n *\n * Note:\n * The body option will typically be passed in as a JavaScript object.\n * A check is performed for this and automatically convert it to JSON if necessary.\n *\n * Requests send JSON by default but this can be easily overridden by adding\n * the Accept and Content-Type headers to the request options.\n *\n * The default method is GET.\n *\n * @param {string} url The URL to make the request to.\n * @param {RequestInit} [options={}] The request options.\n *\n * @return {Promise} the response\n */\nexport async function request(url, options = {}) {\n const {\n headers,\n body,\n method = 'GET',\n csrfToken = await getCsrfToken(),\n // These are any other options that might be passed in e.g. keepalive\n ...restOfOptions\n } = options;\n\n // There should never be a scenario where null is passed as the body,\n // but if ever there is, this logic should change.\n const jsonifiedBody = {\n body: body && typeof body !== 'string' ? JSON.stringify(body) : body,\n };\n\n const fetchOptions = {\n method,\n headers: {\n Accept: 'application/json',\n 'X-CSRF-Token': csrfToken,\n 'Content-Type': 'application/json',\n ...headers,\n },\n credentials: 'same-origin',\n ...jsonifiedBody,\n ...restOfOptions,\n };\n\n return fetch(url, fetchOptions);\n}\n","/**\n * Checks if an element is visible in the viewport\n *\n * @example\n * const element = document.getElementById('element');\n * isInViewport({element, allowPartialVisibility = true}); // true or false\n *\n * @param {HTMLElement} element - The HTML element to check\n * @param {number} [offsetTop=0] - Part of the screen to ignore counting from the top\n * @param {boolean} [allowPartialVisibility=false] - A boolean to flip the check between partial or completely visible in the viewport\n * @returns {boolean} isInViewport - true if the element is visible in the viewport\n */\nexport function isInViewport({\n element,\n offsetTop = 0,\n allowPartialVisibility = false,\n}) {\n const boundingRect = element.getBoundingClientRect();\n const clientHeight =\n window.innerHeight || document.documentElement.clientHeight;\n const clientWidth = window.innerWidth || document.documentElement.clientWidth;\n const topIsInViewport =\n boundingRect.top <= clientHeight && boundingRect.top >= offsetTop;\n const rightIsInViewport =\n boundingRect.right >= 0 && boundingRect.right <= clientWidth;\n const bottomIsInViewport =\n boundingRect.bottom >= offsetTop && boundingRect.bottom <= clientHeight;\n const leftIsInViewport =\n boundingRect.left <= clientWidth && boundingRect.left >= 0;\n const topIsOutOfViewport = boundingRect.top <= offsetTop;\n const bottomIsOutOfViewport = boundingRect.bottom >= clientHeight;\n const elementSpansEntireViewport =\n topIsOutOfViewport && bottomIsOutOfViewport;\n\n if (allowPartialVisibility) {\n return (\n (topIsInViewport || bottomIsInViewport || elementSpansEntireViewport) &&\n (leftIsInViewport || rightIsInViewport)\n );\n }\n return (\n topIsInViewport &&\n bottomIsInViewport &&\n leftIsInViewport &&\n rightIsInViewport\n );\n}\n","import { isInViewport } from '@utilities/viewport';\nimport { debounceAction } from '@utilities/debounceAction';\n\n/**\n * Helper function designed to be used on scroll to detect when dropdowns should switch from dropping downwards/upwards.\n * The action is debounced since scroll events are usually fired several at a time.\n *\n * @returns {Function} a debounced function that handles the repositioning of dropdowns\n * @example\n *\n * document.addEventListener('scroll', getDropdownRepositionListener());\n */\nexport const getDropdownRepositionListener = () =>\n debounceAction(handleDropdownRepositions);\n\n/**\n * Checks for all dropdowns on the page which have the attribute 'data-repositioning-dropdown', signalling\n * they should dynamically change between dropping downwards or upwards, depending on viewport position.\n *\n * Any dropdowns not fully in view when dropping down will be switched to dropping upwards.\n */\nconst handleDropdownRepositions = () => {\n // Select all of the dropdowns which should reposition\n const allRepositioningDropdowns = document.querySelectorAll(\n '[data-repositioning-dropdown]',\n );\n\n for (const element of allRepositioningDropdowns) {\n // Default to dropping downwards\n element.classList.remove('reverse');\n\n const isDropdownCurrentlyOpen = element.style.display === 'block';\n\n if (!isDropdownCurrentlyOpen) {\n // We can't determine position on an element with display:none, so we \"show\" the dropdown with 0 opacity very temporarily\n element.style.opacity = 0;\n element.style.display = 'block';\n }\n\n if (!isInViewport({ element })) {\n // If the element isn't fully visible when dropping down, reverse the direction\n element.classList.add('reverse');\n }\n\n if (!isDropdownCurrentlyOpen) {\n // Revert the temporary changes to determine position\n element.style.removeProperty('display');\n element.style.removeProperty('opacity');\n }\n }\n};\n\n/**\n * Helper query string to identify interactive/focusable HTML elements\n */\nconst INTERACTIVE_ELEMENTS_QUERY =\n 'button, [href], input:not([type=\"hidden\"]), select, textarea, [tabindex=\"0\"]';\n\n/**\n * Open the given dropdown, updating aria attributes, and focusing the first interactive element\n *\n * @param {Object} args\n * @param {string} args.triggerElementId The id of the button which activates the dropdown\n * @param {string} args.dropdownContent The id of the dropdown content element\n */\nconst openDropdown = ({ triggerElementId, dropdownContentId }) => {\n const dropdownContent = document.getElementById(dropdownContentId);\n const triggerElement = document.getElementById(triggerElementId);\n\n triggerElement.setAttribute('aria-expanded', 'true');\n\n // Style set inline to prevent specificity issues\n dropdownContent.style.display = 'block';\n\n // Send focus to the first suitable element\n dropdownContent.querySelector(INTERACTIVE_ELEMENTS_QUERY)?.focus();\n};\n\n/**\n * Close the given dropdown, updating aria attributes\n *\n * @param {Object} args\n * @param {string} args.triggerElementId The id of the button which activates the dropdown\n * @param {string} args.dropdownContent The id of the dropdown content element\n * @param {Function} args.onClose Optional function for any side-effects which should occur on dropdown close\n */\nconst closeDropdown = ({ triggerElementId, dropdownContentId, onClose }) => {\n const dropdownContent = document.getElementById(dropdownContentId);\n\n if (!dropdownContent) {\n // Component may have unmounted\n return;\n }\n\n document\n .getElementById(triggerElementId)\n ?.setAttribute('aria-expanded', 'false');\n\n // Remove the inline style added when we opened the dropdown\n dropdownContent.style.removeProperty('display');\n\n onClose?.();\n};\n\n/**\n * A helper function to initialize dropdown behaviors. This function attaches open/close click and keyup listeners,\n * and makes sure relevant aria properties and keyboard focus are updated.\n *\n * @param {Object} args\n * @param {string} args.triggerButtonElementId The ID of the button which triggers the dropdown open/close behavior\n * @param {string} args.dropdownContentId The ID of the dropdown content which should open/close on trigger button press\n * @param {string} args.dropdownContentCloseButtonId Optional ID of any button within the dropdown content which should close the dropdown\n * @param {Function} args.onClose An optional callback for when the dropdown is closed. This can be passed to execute any side-effects required when the dropdown closes.\n * @param {Function} args.onOpen An optional callback for when the dropdown is opened. This can be passed to execute any side-effects required when the dropdown opens.\n *\n * @returns {{closeDropdown: Function}} Object with callback to close the initialized dropdown\n */\nexport const initializeDropdown = ({\n triggerElementId,\n dropdownContentId,\n dropdownContentCloseButtonId,\n onClose,\n onOpen,\n}) => {\n const triggerButton = document.getElementById(triggerElementId);\n const dropdownContent = document.getElementById(dropdownContentId);\n\n if (!triggerButton || !dropdownContent) {\n // The required props haven't been provided, do nothing\n return;\n }\n\n // Ensure default values have been applied\n triggerButton.setAttribute('aria-expanded', 'false');\n triggerButton.setAttribute('aria-controls', dropdownContentId);\n triggerButton.setAttribute('aria-haspopup', 'true');\n\n const keyUpListener = ({ key }) => {\n if (key === 'Escape') {\n // Close the dropdown and return focus to the trigger button to prevent focus being lost\n const isCurrentlyOpen =\n triggerButton.getAttribute('aria-expanded') === 'true';\n if (isCurrentlyOpen) {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n triggerButton.focus();\n }\n } else if (key === 'Tab') {\n // Close the dropdown if the user has tabbed away from it\n const isInsideDropdown = dropdownContent?.contains(\n document.activeElement,\n );\n if (!isInsideDropdown) {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n }\n }\n };\n\n // Close the dropdown if user has clicked outside\n const clickOutsideListener = ({ target }) => {\n if (\n target !== triggerButton &&\n !dropdownContent.contains(target) &&\n !triggerButton.contains(target)\n ) {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n\n // If the user did not click on another interactive item, return focus to the trigger\n if (!target.matches(INTERACTIVE_ELEMENTS_QUERY)) {\n triggerButton.focus();\n }\n }\n };\n\n // Any necessary side effects required on dropdown close\n const onCloseCleanupActions = () => {\n onClose?.();\n document.removeEventListener('keyup', keyUpListener);\n document.removeEventListener('click', clickOutsideListener);\n };\n\n // Add the main trigger button toggle functionality\n triggerButton.addEventListener('click', () => {\n if (\n document\n .getElementById(triggerElementId)\n ?.getAttribute('aria-expanded') === 'true'\n ) {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n } else {\n openDropdown({\n triggerElementId,\n dropdownContentId,\n });\n onOpen?.();\n\n document.addEventListener('keyup', keyUpListener);\n document.addEventListener('click', clickOutsideListener);\n }\n });\n\n if (dropdownContentCloseButtonId) {\n // The dropdown content has a 'close' button inside that we also need to handle\n document\n .getElementById(dropdownContentCloseButtonId)\n ?.addEventListener('click', () => {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n\n document.getElementById(triggerElementId)?.focus();\n });\n }\n\n return {\n closeDropdown: () => {\n closeDropdown({\n triggerElementId,\n dropdownContentId,\n onClose: onCloseCleanupActions,\n });\n },\n };\n};\n","import debounce from 'lodash.debounce';\n\n/**\n * A util function to wrap any action with lodash's `debounce` (https://lodash.com/docs/#debounce).\n * To use this util, wrap it in the util like so: debounceAction(onSearchBoxType.bind(this));\n *\n * By default, this util uses a default time of 300ms, and includes a default config of `{ leading: false }`.\n * These values can be overridden: debounceAction(this.onSearchBoxType.bind(this), { time: 100, config: { leading: true }});\n *\n *\n * @param {Function} action - The function that should be wrapped with `debounce`.\n * @param {Number} [time=300] - The number of milliseconds to wait.\n * @param {Object} [config={ leading: false }] - Any configuration for the debounce function.\n *\n * @returns {Function} A function wrapped in `debounce`.\n */\nexport function debounceAction(\n action,\n { time = 300, config = { leading: false } } = {},\n) {\n const configs = { ...config };\n return debounce(action, time, configs);\n}\n","/**\n * lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = debounce;\n","export function getCsrfToken() {\n const element = document.querySelector(`meta[name='csrf-token']`);\n\n return element !== null ? element.content : undefined;\n}\n\nconst getWaitOnUserDataHandler = ({ resolve, reject, waitTime = 20 }) => {\n let totalTimeWaiting = 0;\n\n return function waitingOnUserData() {\n if (totalTimeWaiting === 3000) {\n reject(new Error(\"Couldn't find user data on page.\"));\n return;\n }\n\n const csrfToken = getCsrfToken(document);\n const { user } = document.body.dataset;\n\n if (user && csrfToken !== undefined) {\n const currentUser = JSON.parse(user);\n\n resolve({ currentUser, csrfToken });\n return;\n }\n\n totalTimeWaiting += waitTime;\n setTimeout(waitingOnUserData, waitTime);\n };\n};\n\nexport function getUserDataAndCsrfToken() {\n return new Promise((resolve, reject) => {\n getWaitOnUserDataHandler({ resolve, reject })();\n });\n}\n","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n"],"sourceRoot":""}