{"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:///./node_modules/lodash.debounce/index.js","webpack:///./app/javascript/utilities/billboardDropdown.jsx","webpack:///./app/javascript/packs/billboardAfterRenderActions.js","webpack:///./app/javascript/packs/billboard.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","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","setTimeout","timerExpired","shouldInvoke","timeSinceLastCall","trailingEdge","remainingWait","debounced","isInvoking","cancel","clearTimeout","flush","setupBillboardDropdown","sponsorshipDropdownButtons","forEach","sponsorshipDropdownButton","closest","overflowY","amendBillboardStyle","dataset","initialized","id","initializeBillboardVisibility","billboards","user","userData","ad","display_sponsors","observeBillboards","observer","IntersectionObserver","entries","entry","isIntersecting","elem","intersectionRatio","adBox","isBot","navigator","userAgent","adSeen","impressionRecorded","tokenMeta","csrfToken","dataBody","billboard_event","billboard_id","context_type","contextType","category","categoryImpression","fetch","method","headers","body","JSON","stringify","credentials","error","console","trackAdImpression","rootMargin","threshold","observe","trackAdClick","adClicked","clickRecorded","categoryClick","getBillboard","_getBillboard","_asyncToGenerator","promises","_toConsumableArray","getElementsByClassName","map","generateBillboard","Promise","all","_x","_generateBillboard","asyncUrl","response","concat","htmlContent","text","generatedElement","createElement","innerHTML","appendChild","message","Honeybadger","notify"],"mappings":"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","file":"js/billboard-d95ddc5f8ece7f4ba1e8.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","/**\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","import { initializeDropdown } from './dropdownUtils';\n\nexport function setupBillboardDropdown() {\n const sponsorshipDropdownButtons = document.querySelectorAll(\n 'button[id^=sponsorship-dropdown-trigger-]',\n );\n if (sponsorshipDropdownButtons.length) {\n sponsorshipDropdownButtons.forEach((sponsorshipDropdownButton) => {\n amendBillboardStyle(sponsorshipDropdownButton);\n\n const dropdownContentId =\n sponsorshipDropdownButton.getAttribute('aria-controls');\n if (\n sponsorshipDropdownButton &&\n sponsorshipDropdownButton.dataset.initialized !== 'true'\n ) {\n initializeDropdown({\n triggerElementId: sponsorshipDropdownButton.id,\n dropdownContentId,\n });\n\n sponsorshipDropdownButton.dataset.initialized = 'true';\n }\n });\n }\n}\n\n/**\n * If the billboard container height is less than 220px, then we revert the overflow-y property\n given by the billboard class so that the dropdown does not scroll within the container\n */\nfunction amendBillboardStyle(sponsorshipDropdownButton) {\n if (sponsorshipDropdownButton.closest('.js-billboard').clientHeight < 220) {\n sponsorshipDropdownButton.closest('.js-billboard').style.overflowY =\n 'revert';\n }\n}\n","/* global userData */\n// This is currently a duplicate of app/assets/javascript/initializers/initializeBillboardVisibility.\nexport function initializeBillboardVisibility() {\n const billboards = document.querySelectorAll('[data-display-unit]');\n\n if (billboards && billboards.length == 0) {\n return;\n }\n\n const user = userData();\n\n billboards.forEach((ad) => {\n if (user && !user.display_sponsors && ad.dataset['typeOf'] == 'external') {\n ad.classList.add('hidden');\n } else {\n ad.classList.remove('hidden');\n }\n });\n}\n\nexport function observeBillboards() {\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n const elem = entry.target;\n if (entry.intersectionRatio >= 0.25) {\n setTimeout(() => {\n trackAdImpression(elem);\n }, 1);\n }\n }\n });\n },\n {\n root: null, // defaults to browser viewport\n rootMargin: '0px',\n threshold: 0.25,\n },\n );\n\n document.querySelectorAll('[data-display-unit]').forEach((ad) => {\n observer.observe(ad);\n ad.removeEventListener('click', trackAdClick, false);\n ad.addEventListener('click', () => trackAdClick(ad));\n });\n}\n\nfunction trackAdImpression(adBox) {\n const isBot =\n /bot|google|baidu|bing|msn|duckduckbot|teoma|slurp|yandex/i.test(\n navigator.userAgent,\n ); // is crawler\n const adSeen = adBox.dataset.impressionRecorded;\n if (isBot || adSeen) {\n return;\n }\n\n const tokenMeta = document.querySelector(\"meta[name='csrf-token']\");\n const csrfToken = tokenMeta && tokenMeta.getAttribute('content');\n\n const dataBody = {\n billboard_event: {\n billboard_id: adBox.dataset.id,\n context_type: adBox.dataset.contextType,\n category: adBox.dataset.categoryImpression,\n },\n };\n\n window\n .fetch('/billboard_events', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': csrfToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(dataBody),\n credentials: 'same-origin',\n })\n .catch((error) => console.error(error));\n\n adBox.dataset.impressionRecorded = true;\n}\n\nfunction trackAdClick(adBox) {\n const isBot =\n /bot|google|baidu|bing|msn|duckduckbot|teoma|slurp|yandex/i.test(\n navigator.userAgent,\n ); // is crawler\n const adClicked = adBox.dataset.clickRecorded;\n if (isBot || adClicked) {\n return;\n }\n\n const tokenMeta = document.querySelector(\"meta[name='csrf-token']\");\n const csrfToken = tokenMeta && tokenMeta.getAttribute('content');\n\n const dataBody = {\n billboard_event: {\n billboard_id: adBox.dataset.id,\n context_type: adBox.dataset.contextType,\n category: adBox.dataset.categoryClick,\n },\n };\n\n window.fetch('/billboard_events', {\n method: 'POST',\n headers: {\n 'X-CSRF-Token': csrfToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(dataBody),\n credentials: 'same-origin',\n });\n\n adBox.dataset.clickRecorded = true;\n}\n","import { setupBillboardDropdown } from '../utilities/billboardDropdown';\nimport { observeBillboards } from './billboardAfterRenderActions';\n\nasync function getBillboard() {\n const placeholderElements = document.getElementsByClassName(\n 'js-billboard-container',\n );\n\n const promises = [...placeholderElements].map(generateBillboard);\n await Promise.all(promises);\n}\n\nasync function generateBillboard(element) {\n const { asyncUrl } = element.dataset;\n\n if (asyncUrl) {\n try {\n const response = await window.fetch(`${asyncUrl}`);\n const htmlContent = await response.text();\n\n const generatedElement = document.createElement('div');\n generatedElement.innerHTML = htmlContent;\n\n element.innerHTML = '';\n element.appendChild(generatedElement);\n setupBillboardDropdown();\n // This is called here because the ad is loaded asynchronously.\n // The original code is still in the asset pipeline, so is not importable.\n // This could be refactored to be importable as we continue that migration.\n // eslint-disable-next-line no-undef\n observeBillboards();\n } catch (error) {\n if (!/NetworkError/i.test(error.message)) {\n Honeybadger.notify(error);\n }\n }\n }\n}\n\ngetBillboard();\n\nexport { getBillboard };\n"],"sourceRoot":""}