{"version":3,"sources":["webpack:///./app/javascript/utilities/dropdownUtils.js","webpack:///./app/javascript/utilities/viewport.js","webpack:///./app/javascript/utilities/debounceAction.js","webpack:///(webpack)/buildin/global.js","webpack:///./app/javascript/utilities/getUserDataAndCsrfToken.js","webpack:///./node_modules/lodash.debounce/index.js","webpack:///./app/javascript/utilities/http/errors.js","webpack:///./app/javascript/utilities/http/csrfToken.js","webpack:///./app/javascript/utilities/http/request.js","webpack:///./app/javascript/profileDropdown/flagButton.js","webpack:///./app/javascript/packs/profileDropdown.js","webpack:///./app/javascript/profileDropdown/blockButton.js"],"names":["getDropdownRepositionListener","debounceAction","handleDropdownRepositions","_step","_iterator","_createForOfIteratorHelper","document","querySelectorAll","s","n","done","element","value","classList","remove","isDropdownCurrentlyOpen","style","display","opacity","isInViewport","add","removeProperty","err","e","f","INTERACTIVE_ELEMENTS_QUERY","openDropdown","_ref","_dropdownContent$quer","triggerElementId","dropdownContentId","dropdownContent","getElementById","setAttribute","querySelector","focus","closeDropdown","_ref2","_document$getElementB","onClose","initializeDropdown","_ref3","dropdownContentCloseButtonId","onOpen","triggerButton","_document$getElementB3","keyUpListener","_ref4","key","getAttribute","onCloseCleanupActions","contains","activeElement","clickOutsideListener","_ref5","target","matches","removeEventListener","addEventListener","_document$getElementB2","_document$getElementB4","_ref$offsetTop","offsetTop","_ref$allowPartialVisi","allowPartialVisibility","boundingRect","getBoundingClientRect","clientHeight","window","innerHeight","documentElement","clientWidth","innerWidth","topIsInViewport","top","rightIsInViewport","right","bottomIsInViewport","bottom","leftIsInViewport","left","topIsOutOfViewport","bottomIsOutOfViewport","action","arguments","length","undefined","_ref$time","time","_ref$config","config","leading","configs","_objectSpread","debounce","g","this","Function","module","exports","getWaitOnUserDataHandler","resolve","reject","_ref$safe","safe","_ref$waitTime","waitTime","totalTimeWaiting","waitingOnUserData","user","csrfToken","Error","content","body","dataset","currentUser","JSON","parse","setTimeout","getUserDataAndCsrfTokenSafely","Promise","getUserDataAndCsrfToken","reTrim","reIsBadHex","reIsBinary","reIsOctal","freeParseInt","parseInt","freeGlobal","global","Object","freeSelf","self","root","objectToString","prototype","toString","nativeMax","Math","max","nativeMin","min","now","Date","isObject","type","toNumber","isObjectLike","call","isSymbol","other","valueOf","replace","isBinary","test","slice","func","wait","options","lastArgs","lastThis","maxWait","result","timerId","lastCallTime","lastInvokeTime","maxing","trailing","TypeError","invokeFunc","args","thisArg","apply","leadingEdge","timerExpired","shouldInvoke","timeSinceLastCall","trailingEdge","remainingWait","debounced","isInvoking","cancel","clearTimeout","flush","handleFetchAPIErrors","response","ok","json","then","data","error","SyntaxError","statusText","getCSRFToken","i","waitingOnCSRF","setInterval","metaTag","clearInterval","authToken","Honeybadger","notify","concat","stringify","localStorage","current_user","request","_x","_request","_asyncToGenerator","url","headers","_options$method","method","_options$csrfToken","restOfOptions","_objectWithoutProperties","_excluded","jsonifiedBody","fetchOptions","Accept","credentials","fetch","initFlag","flagButton","userData","trustedOrAdmin","trusted","admin","profileUserId","id","_flagButton$dataset","profileUserName","isUserFlagged","confirm","reactable_type","category","reactable_id","innerHTML","alert","addFlagUserBehavior","initButtons","blockButton","innerText","unblock","once","block","user_block","blocked_id","status","initBlock","profileDropdownDiv","dropdownInitialized","username","reportAbuseLink","path","initDropdown"],"mappings":"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","file":"js/profileDropdown-c676df0449cebd41ef72.chunk.js","sourcesContent":["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 */\nexport const 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 */\nexport const 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 */\nexport const closeDropdown = ({\n triggerElementId,\n dropdownContentId,\n onClose,\n}) => {\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 // Get fresh handle every time, resulting in more streamlined functionality for cypress\n const triggerButton = document.getElementById(triggerElementId);\n if (\n triggerButton &&\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","/**\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 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","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","export function getCsrfToken() {\n const element = document.querySelector(`meta[name='csrf-token']`);\n\n return element !== null ? element.content : undefined;\n}\n\nconst getWaitOnUserDataHandler = ({\n resolve,\n reject,\n safe = false,\n waitTime = 20,\n}) => {\n let totalTimeWaiting = 0;\n\n return function waitingOnUserData() {\n if (totalTimeWaiting === 3000) {\n if (!safe) {\n reject(new Error(\"Couldn't find user data on page.\"));\n return;\n } \n resolve({ user, csrfToken });\n return;\n \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 getUserDataAndCsrfTokenSafely() {\n return new Promise((resolve, reject) => {\n const safe = true;\n getWaitOnUserDataHandler({ resolve, reject, safe })();\n });\n}\n\nexport function getUserDataAndCsrfToken() {\n return new Promise((resolve, reject) => {\n getWaitOnUserDataHandler({ resolve, reject })();\n });\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","// 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","const MAX_RETRIES = 30;\nconst RETRY_INTERVAL = 250;\n\nexport function getCSRFToken() {\n const promise = new Promise((resolve, reject) => {\n // eslint-disable-next-line consistent-return\n let i = 0;\n const waitingOnCSRF = setInterval(() => {\n const metaTag = document.querySelector(\"meta[name='csrf-token']\");\n i += 1;\n\n if (metaTag) {\n clearInterval(waitingOnCSRF);\n const authToken = metaTag.getAttribute('content');\n return resolve(authToken);\n }\n\n if (i === MAX_RETRIES) {\n clearInterval(waitingOnCSRF);\n Honeybadger.notify(\n `Could not locate CSRF metatag ${JSON.stringify(\n localStorage.current_user,\n )}`,\n );\n return reject(new Error('Could not locate CSRF meta tag on the page.'));\n }\n }, RETRY_INTERVAL);\n });\n return promise;\n}\n","import { getCSRFToken } from './csrfToken';\n\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","/* 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 - 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"],"sourceRoot":""}