{"version":3,"sources":["webpack:///./node_modules/ahoy.js/dist/ahoy.esm.js","webpack:///./app/javascript/utilities/showModal.jsx","webpack:///./app/javascript/shared/preact/preact-root-fragment.js","webpack:///./app/javascript/packs/initializers/initializeDashboardSort.js","webpack:///./app/javascript/utilities/ahoy/trackEvents.jsx","webpack:///./app/javascript/utilities/waitOnBaseData.js","webpack:///./app/javascript/topNavigation/utilities.js","webpack:///./node_modules/focus-visible/dist/focus-visible.js","webpack:///./app/javascript/utilities/podcastPlayback.js","webpack:///./app/javascript/utilities/videoPlayback.js","webpack:///./app/javascript/packs/base.jsx","webpack:///./app/javascript/utilities/runtime.js"],"names":["Cookies","name","value","ttl","domain","expires","cookieDomain","date","Date","setTime","getTime","toGMTString","document","cookie","escape","i","c","nameEQ","ca","split","length","charAt","substring","indexOf","unescape","config","urlPrefix","visitsUrl","eventsUrl","page","platform","useBeacon","startOnReady","trackVisits","cookies","headers","visitParams","withCredentials","visitDuration","visitorDuration","ahoy","window","Ahoy","configure","options","key","Object","prototype","hasOwnProperty","call","visitId","visitorId","track","callback","$","jQuery","Zepto","isReady","queue","canStringify","JSON","eventQueue","canTrackNow","trackNow","obj","keys","navigator","setCookie","getCookie","destroyCookie","log","message","console","setReady","shift","matchesSelector","element","selector","matches","mozMatchesSelector","msMatchesSelector","oMatchesSelector","webkitMatchesSelector","apply","parentElement","onEvent","eventName","addEventListener","e","matchedElement","target","skip","getClosest","generateId","replace","r","Math","random","toString","saveEventQueue","stringify","csrfToken","meta","querySelector","content","CSRFProtection","xhr","token","setRequestHeader","sendRequest","url","data","success","ajax","type","contentType","dataType","beforeSend","xhrFields","XMLHttpRequest","header","open","onload","status","send","eventData","event","events","visit_token","visitor_token","trackEvent","ready","id","splice","trackEventNow","param","events_json","sendBeacon","object","FormData","append","serialize","location","pathname","presence","str","eventProperties","cleanObject","tag","this","tagName","toLowerCase","className","section","attribute","parentNode","hasAttribute","getAttribute","createVisit","getVisitId","getVisitorId","landing_page","href","screen_width","screen","width","screen_height","height","js","referrer","push","getVisitToken","getVisitorToken","reset","debug","enabled","properties","time","setTimeout","trackView","additionalProperties","title","propName","trackClicks","undefined","Error","text","textContent","innerText","innerHTML","trim","trackSubmits","trackChanges","parse","start","readyState","preactImport","modalImports","WINDOW_MODAL_ID","getPreactImport","showWindowModal","_ref2","_asyncToGenerator","_ref","_document$querySelect","modalContent","contentSelector","onOpen","_ref$document","modalProps","_objectWithoutProperties","_excluded","_yield$getModalImport2","_slicedToArray","Promise","all","Modal","_yield$getModalImport3","render","h","currentModalContainer","getElementById","createElement","setAttribute","body","appendChild","_extends","onClose","focusTrapSelector","concat","dangerouslySetInnerHTML","__html","_x","arguments","closeWindowModal","_ref3","_yield$getPreactImpor","createRootFragment","parent","replaceNode","Array","isArray","s","nextSibling","rootFragment","nodeType","firstChild","childNodes","insertBefore","removeChild","__k","selectNavigation","select","trigger","InstantClick","preload","display","initializeDashboardSort","trackCommentClicks","elementId","_document$getElementB","_relevantNode$dataset","relevantNode","getTrackingNode","dataset","trackingName","trackCreateAccountClicks","_document$getElementB2","_relevantNode$dataset2","version","source","trackingSource","trackingElement","closest","waitOnBaseData","resolve","waitingForDataLoad","setInterval","clearInterval","closeHeaderMenu","memberMenu","menuNavButton","classList","remove","clicked","firstItem","initializeMemberMenu","memberTopMenu","userAgent","add","_event","contains","focus","focusFirstItem","activeElement","requestAnimationFrame","openHeaderMenu","isTouchDevice","stopPropagation","secondToLastNavLink","toggleBurgerMenu","_document$body$datase","leftNavState","getInstantClick","_getInstantClick","waitTime","reject","failTimer","timer","clearTimeout","initializeMobileMenu","menuTriggers","forEach","onclick","setCurrentPageIconLink","currentPage","pageEntries","filter","_ref4","iconLink","blur","removeAttribute","applyFocusVisiblePolyfill","scope","hadKeyboardEvent","hadFocusVisibleRecently","hadFocusVisibleRecentlyTimeout","inputTypesAllowlist","search","tel","email","password","number","month","week","datetime","isValidFocusTarget","el","nodeName","focusTriggersKeyboardModality","readOnly","isContentEditable","addFocusVisibleClass","removeFocusVisibleClass","onKeyDown","metaKey","altKey","ctrlKey","onPointerDown","onFocus","onBlur","onVisibilityChange","visibilityState","addInitialPointerMoveListeners","onInitialPointerMove","removeInitialPointerMoveListeners","removeEventListener","Node","DOCUMENT_FRAGMENT_NODE","host","DOCUMENT_NODE","documentElement","CustomEvent","error","createEvent","initCustomEvent","dispatchEvent","factory","initializePodcastPlayback","podcastPageRecords","podcastLiquidTagrecords","records","deviceType","getById","getByClass","getElementsByClassName","newAudioState","_audio$dataset","_audio$dataset2","_audio$dataset3","audio","activeEpisode","episode","activePodcast","podcast","html","currentTime","playing","muted","volume","duration","updated","playbackName","currentAudioState","currentState","localStorage","getItem","spinPodcastRecord","customMessage","podcastPlaybackButton","changeStatusMessage","stopRotatingActivePodcastIfExist","saveMediaState","state","newState","setItem","applyOnclickToPodcastBar","playPause","muteUnmute","progress","clientX","percent","innerWidth","Forem","Runtime","podcastMessage","action","seconds","readableDuration","style","goToTime","onchange","updateVolume","speed","parseFloat","playbackRate","rate","changePlaybackRate","updateProgressListener","terminatePodcastBar","bufferValue","buffered","end","updateProgress","loadAudio","getElementsByTagName","src","load","statusBox","startPodcastBar","pausePodcastBar","playAudio","setPlaying","play","then","sendMetadataMessage","metadata","episodeContainer","episodeName","podcastName","podcastImageUrl","ahoyMessage","pause","pauseAudioPlayback","startAudioPlayback","buffer","firstDecimal","floor","sec","min","handlePodcastMessages","detail","namespace","isNativeIOS","isNativeAndroid","msg","ForemMobile","injectNativeMessage","record","episodeSlug","podcastBarAlreadyExistAndPlayingTargetEpisode","loadAndPlayNewPodcast","audioInitialized","initializeMedia","audioContent","initializeVideoPlayback","lastEvent","videoPlayerEvent","isPlaying","article","videoMetadata","videoSource","requestFocus","videoMessage","video_source_url","handleVideoMessages","hms","a","waitingOnJWP","jwplayer","setup","file","mediaid","video_code","image","video_thumbnail_url","playbackRateControls","tracks","video_closed_caption_track_url","label","kind","default","on","seek","initWebPlayer","playerElement","initializePlayer","_initializeEnhancedCommentTextArea","initializeNav","_toConsumableArray","querySelectorAll","entries","Document","enhancedCommentTextAreaImport","getEnhancedCommentTextAreaImports","initializeEnhancedCommentTextArea","originalTextArea","parentContainer","_yield$window$Forem$g2","CommentTextArea","_yield$window$Forem$g3","vanillaTextArea","showModal","closeModal","runtime","currentContext","getNavigation","_getNavigation","placeholderElement","response","fetch","htmlContent","generatedElement","_loadCreatorSettings","_yield$Promise$all2","LogoUploadController","Application","register","Honeybadger","notify","module","foremMobileNamespace","userSessionBroadcast","loadCreatorSettings","history","scrollRestoration","currentMedium","currentOS","test","includes","nativeCheck","webkit","messageHandlers","namespaceCheck","AndroidBridge","copyToClipboard","clipboard","writeText","hasOSSpecificModifier","KeyboardEvent","getOSKeyboardModifierKeyString","getCurrentLocale","language"],"mappings":"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","file":"js/base-f0e3fc73f4670cb0467b.chunk.js","sourcesContent":["/*!\n * Ahoy.js v0.4.3\n * Simple, powerful JavaScript analytics\n * https://github.com/ankane/ahoy.js\n * MIT License\n */\n\n// https://www.quirksmode.org/js/cookies.html\n\nvar Cookies = {\n set: function (name, value, ttl, domain) {\n var expires = \"\";\n var cookieDomain = \"\";\n if (ttl) {\n var date = new Date();\n date.setTime(date.getTime() + (ttl * 60 * 1000));\n expires = \"; expires=\" + date.toGMTString();\n }\n if (domain) {\n cookieDomain = \"; domain=\" + domain;\n }\n document.cookie = name + \"=\" + escape(value) + expires + cookieDomain + \"; path=/; samesite=lax\";\n },\n get: function (name) {\n var i, c;\n var nameEQ = name + \"=\";\n var ca = document.cookie.split(';');\n for (i = 0; i < ca.length; i++) {\n c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1, c.length);\n }\n if (c.indexOf(nameEQ) === 0) {\n return unescape(c.substring(nameEQ.length, c.length));\n }\n }\n return null;\n }\n};\n\nvar config = {\n urlPrefix: \"\",\n visitsUrl: \"/ahoy/visits\",\n eventsUrl: \"/ahoy/events\",\n page: null,\n platform: \"Web\",\n useBeacon: true,\n startOnReady: true,\n trackVisits: true,\n cookies: true,\n cookieDomain: null,\n headers: {},\n visitParams: {},\n withCredentials: false,\n visitDuration: 4 * 60, // default 4 hours\n visitorDuration: 2 * 365 * 24 * 60 // default 2 years\n};\n\nvar ahoy = window.ahoy || window.Ahoy || {};\n\nahoy.configure = function (options) {\n for (var key in options) {\n if (Object.prototype.hasOwnProperty.call(options, key)) {\n config[key] = options[key];\n }\n }\n};\n\n// legacy\nahoy.configure(ahoy);\n\nvar $ = window.jQuery || window.Zepto || window.$;\nvar visitId, visitorId, track;\nvar isReady = false;\nvar queue = [];\nvar canStringify = typeof(JSON) !== \"undefined\" && typeof(JSON.stringify) !== \"undefined\";\nvar eventQueue = [];\n\nfunction visitsUrl() {\n return config.urlPrefix + config.visitsUrl;\n}\n\nfunction eventsUrl() {\n return config.urlPrefix + config.eventsUrl;\n}\n\nfunction isEmpty(obj) {\n return Object.keys(obj).length === 0;\n}\n\nfunction canTrackNow() {\n return (config.useBeacon || config.trackNow) && isEmpty(config.headers) && canStringify && typeof(window.navigator.sendBeacon) !== \"undefined\" && !config.withCredentials;\n}\n\nfunction serialize(object) {\n var data = new FormData();\n for (var key in object) {\n if (Object.prototype.hasOwnProperty.call(object, key)) {\n data.append(key, object[key]);\n }\n }\n return data;\n}\n\n// cookies\n\nfunction setCookie(name, value, ttl) {\n Cookies.set(name, value, ttl, config.cookieDomain || config.domain);\n}\n\nfunction getCookie(name) {\n return Cookies.get(name);\n}\n\nfunction destroyCookie(name) {\n Cookies.set(name, \"\", -1);\n}\n\nfunction log(message) {\n if (getCookie(\"ahoy_debug\")) {\n window.console.log(message);\n }\n}\n\nfunction setReady() {\n var callback;\n while ((callback = queue.shift())) {\n callback();\n }\n isReady = true;\n}\n\nahoy.ready = function (callback) {\n if (isReady) {\n callback();\n } else {\n queue.push(callback);\n }\n};\n\nfunction matchesSelector(element, selector) {\n var matches = element.matches ||\n element.matchesSelector ||\n element.mozMatchesSelector ||\n element.msMatchesSelector ||\n element.oMatchesSelector ||\n element.webkitMatchesSelector;\n\n if (matches) {\n if (matches.apply(element, [selector])) {\n return element;\n } else if (element.parentElement) {\n return matchesSelector(element.parentElement, selector);\n }\n return null;\n } else {\n log(\"Unable to match\");\n return null;\n }\n}\n\nfunction onEvent(eventName, selector, callback) {\n document.addEventListener(eventName, function (e) {\n var matchedElement = matchesSelector(e.target, selector);\n if (matchedElement) {\n var skip = getClosest(matchedElement, \"data-ahoy-skip\");\n if (skip !== null && skip !== \"false\") { return; }\n\n callback.call(matchedElement, e);\n }\n });\n}\n\n// http://beeker.io/jquery-document-ready-equivalent-vanilla-javascript\nfunction documentReady(callback) {\n if (document.readyState === \"interactive\" || document.readyState === \"complete\") {\n setTimeout(callback, 0);\n } else {\n document.addEventListener(\"DOMContentLoaded\", callback);\n }\n}\n\n// https://stackoverflow.com/a/2117523/1177228\nfunction generateId() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n var r = Math.random() * 16 | 0;\n var v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\nfunction saveEventQueue() {\n if (config.cookies && canStringify) {\n setCookie(\"ahoy_events\", JSON.stringify(eventQueue), 1);\n }\n}\n\n// from rails-ujs\n\nfunction csrfToken() {\n var meta = document.querySelector(\"meta[name=csrf-token]\");\n return meta && meta.content;\n}\n\nfunction csrfParam() {\n var meta = document.querySelector(\"meta[name=csrf-param]\");\n return meta && meta.content;\n}\n\nfunction CSRFProtection(xhr) {\n var token = csrfToken();\n if (token) { xhr.setRequestHeader(\"X-CSRF-Token\", token); }\n}\n\nfunction sendRequest(url, data, success) {\n if (canStringify) {\n if ($ && $.ajax) {\n $.ajax({\n type: \"POST\",\n url: url,\n data: JSON.stringify(data),\n contentType: \"application/json; charset=utf-8\",\n dataType: \"json\",\n beforeSend: CSRFProtection,\n success: success,\n headers: config.headers,\n xhrFields: {\n withCredentials: config.withCredentials\n }\n });\n } else {\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.withCredentials = config.withCredentials;\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n for (var header in config.headers) {\n if (Object.prototype.hasOwnProperty.call(config.headers, header)) {\n xhr.setRequestHeader(header, config.headers[header]);\n }\n }\n xhr.onload = function () {\n if (xhr.status === 200) {\n success();\n }\n };\n CSRFProtection(xhr);\n xhr.send(JSON.stringify(data));\n }\n }\n}\n\nfunction eventData(event) {\n var data = {\n events: [event]\n };\n if (config.cookies) {\n data.visit_token = event.visit_token;\n data.visitor_token = event.visitor_token;\n }\n delete event.visit_token;\n delete event.visitor_token;\n return data;\n}\n\nfunction trackEvent(event) {\n ahoy.ready(function () {\n sendRequest(eventsUrl(), eventData(event), function () {\n // remove from queue\n for (var i = 0; i < eventQueue.length; i++) {\n if (eventQueue[i].id === event.id) {\n eventQueue.splice(i, 1);\n break;\n }\n }\n saveEventQueue();\n });\n });\n}\n\nfunction trackEventNow(event) {\n ahoy.ready(function () {\n var data = eventData(event);\n var param = csrfParam();\n var token = csrfToken();\n if (param && token) { data[param] = token; }\n // stringify so we keep the type\n data.events_json = JSON.stringify(data.events);\n delete data.events;\n window.navigator.sendBeacon(eventsUrl(), serialize(data));\n });\n}\n\nfunction page() {\n return config.page || window.location.pathname;\n}\n\nfunction presence(str) {\n return (str && str.length > 0) ? str : null;\n}\n\nfunction cleanObject(obj) {\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n if (obj[key] === null) {\n delete obj[key];\n }\n }\n }\n return obj;\n}\n\nfunction eventProperties() {\n return cleanObject({\n tag: this.tagName.toLowerCase(),\n id: presence(this.id),\n \"class\": presence(this.className),\n page: page(),\n section: getClosest(this, \"data-section\")\n });\n}\n\nfunction getClosest(element, attribute) {\n for (; element && element !== document; element = element.parentNode) {\n if (element.hasAttribute(attribute)) {\n return element.getAttribute(attribute);\n }\n }\n\n return null;\n}\n\nfunction createVisit() {\n isReady = false;\n\n visitId = ahoy.getVisitId();\n visitorId = ahoy.getVisitorId();\n track = getCookie(\"ahoy_track\");\n\n if (config.cookies === false || config.trackVisits === false) {\n log(\"Visit tracking disabled\");\n setReady();\n } else if (visitId && visitorId && !track) {\n // TODO keep visit alive?\n log(\"Active visit\");\n setReady();\n } else {\n if (!visitId) {\n visitId = generateId();\n setCookie(\"ahoy_visit\", visitId, config.visitDuration);\n }\n\n // make sure cookies are enabled\n if (getCookie(\"ahoy_visit\")) {\n log(\"Visit started\");\n\n if (!visitorId) {\n visitorId = generateId();\n setCookie(\"ahoy_visitor\", visitorId, config.visitorDuration);\n }\n\n var data = {\n visit_token: visitId,\n visitor_token: visitorId,\n platform: config.platform,\n landing_page: window.location.href,\n screen_width: window.screen.width,\n screen_height: window.screen.height,\n js: true\n };\n\n // referrer\n if (document.referrer.length > 0) {\n data.referrer = document.referrer;\n }\n\n for (var key in config.visitParams) {\n if (Object.prototype.hasOwnProperty.call(config.visitParams, key)) {\n data[key] = config.visitParams[key];\n }\n }\n\n log(data);\n\n sendRequest(visitsUrl(), data, function () {\n // wait until successful to destroy\n destroyCookie(\"ahoy_track\");\n setReady();\n });\n } else {\n log(\"Cookies disabled\");\n setReady();\n }\n }\n}\n\nahoy.getVisitId = ahoy.getVisitToken = function () {\n return getCookie(\"ahoy_visit\");\n};\n\nahoy.getVisitorId = ahoy.getVisitorToken = function () {\n return getCookie(\"ahoy_visitor\");\n};\n\nahoy.reset = function () {\n destroyCookie(\"ahoy_visit\");\n destroyCookie(\"ahoy_visitor\");\n destroyCookie(\"ahoy_events\");\n destroyCookie(\"ahoy_track\");\n return true;\n};\n\nahoy.debug = function (enabled) {\n if (enabled === false) {\n destroyCookie(\"ahoy_debug\");\n } else {\n setCookie(\"ahoy_debug\", \"t\", 365 * 24 * 60); // 1 year\n }\n return true;\n};\n\nahoy.track = function (name, properties) {\n // generate unique id\n var event = {\n name: name,\n properties: properties || {},\n time: (new Date()).getTime() / 1000.0,\n id: generateId(),\n js: true\n };\n\n ahoy.ready(function () {\n if (config.cookies && !ahoy.getVisitId()) {\n createVisit();\n }\n\n ahoy.ready(function () {\n log(event);\n\n event.visit_token = ahoy.getVisitId();\n event.visitor_token = ahoy.getVisitorId();\n\n if (canTrackNow()) {\n trackEventNow(event);\n } else {\n eventQueue.push(event);\n saveEventQueue();\n\n // wait in case navigating to reduce duplicate events\n setTimeout(function () {\n trackEvent(event);\n }, 1000);\n }\n });\n });\n\n return true;\n};\n\nahoy.trackView = function (additionalProperties) {\n var properties = {\n url: window.location.href,\n title: document.title,\n page: page()\n };\n\n if (additionalProperties) {\n for (var propName in additionalProperties) {\n if (Object.prototype.hasOwnProperty.call(additionalProperties, propName)) {\n properties[propName] = additionalProperties[propName];\n }\n }\n }\n ahoy.track(\"$view\", properties);\n};\n\nahoy.trackClicks = function (selector) {\n if (selector === undefined) {\n throw new Error(\"Missing selector\");\n }\n onEvent(\"click\", selector, function (e) {\n var properties = eventProperties.call(this, e);\n properties.text = properties.tag === \"input\" ? this.value : (this.textContent || this.innerText || this.innerHTML).replace(/[\\s\\r\\n]+/g, \" \").trim();\n properties.href = this.href;\n ahoy.track(\"$click\", properties);\n });\n};\n\nahoy.trackSubmits = function (selector) {\n if (selector === undefined) {\n throw new Error(\"Missing selector\");\n }\n onEvent(\"submit\", selector, function (e) {\n var properties = eventProperties.call(this, e);\n ahoy.track(\"$submit\", properties);\n });\n};\n\nahoy.trackChanges = function (selector) {\n log(\"trackChanges is deprecated and will be removed in 0.5.0\");\n if (selector === undefined) {\n throw new Error(\"Missing selector\");\n }\n onEvent(\"change\", selector, function (e) {\n var properties = eventProperties.call(this, e);\n ahoy.track(\"$change\", properties);\n });\n};\n\n// push events from queue\ntry {\n eventQueue = JSON.parse(getCookie(\"ahoy_events\") || \"[]\");\n} catch (e) {\n // do nothing\n}\n\nfor (var i = 0; i < eventQueue.length; i++) {\n trackEvent(eventQueue[i]);\n}\n\nahoy.start = function () {\n createVisit();\n\n ahoy.start = function () {};\n};\n\ndocumentReady(function () {\n if (config.startOnReady) {\n ahoy.start();\n }\n});\n\nexport { ahoy as default };\n","// Unique ID applied to modals created using the showWindowModal function\nexport const WINDOW_MODAL_ID = 'window-modal';\n\n// We only import these modules if a user actually triggers a modal. Here we cache them so they are only imported once.\nlet preactImport;\nlet modalImports;\n\nconst getPreactImport = () => {\n if (!preactImport) {\n preactImport = import('preact');\n }\n return preactImport;\n};\n\nconst getModalImports = () => {\n if (!modalImports) {\n modalImports = [import('@crayons/Modal'), getPreactImport()];\n }\n return Promise.all(modalImports);\n};\n\n/**\n * This helper function presents content inside a Preact modal.\n *\n * The modal content may be passed either as:\n * - the actual HTML (using modalContent prop), which will be dropped straight into the modal\n * - a CSS selector (using contentSelector prop), which will be used to locate the HTML content on the current page before dropping it into the modal\n *\n * Only one modal will be presented at any given time. All additional props will be passed directly to the Modal component.\n *\n * @param {Object} args\n * @param {HTMLElement} args.modalContent The HTML to display inside of the modal\n * @param {string} args.contentSelector The CSS query to locate the HTML to be presented in the modal, as an alternative to passing the actual HTML (e.g. '#my-modal-content')\n * @param {Function} args.onOpen A callback function to run when the modal opens. This can be useful, for example, to attach any event listeners to items inside the modal.\n * @param {Object} args.document Allows us to specify which \"document\" is relevant; e.g. use within iframes.\n */\nexport const showWindowModal = async ({\n modalContent,\n contentSelector,\n onOpen,\n document = window.document,\n ...modalProps\n}) => {\n const [{ Modal }, { render, h }] = await getModalImports();\n\n // Guard against two modals being opened at once\n let currentModalContainer = document.getElementById(WINDOW_MODAL_ID);\n if (currentModalContainer) {\n render(null, currentModalContainer);\n } else {\n currentModalContainer = document.createElement('div');\n currentModalContainer.setAttribute('id', WINDOW_MODAL_ID);\n document.body.appendChild(currentModalContainer);\n }\n\n render(\n {\n render(null, currentModalContainer);\n }}\n focusTrapSelector={`#${WINDOW_MODAL_ID}`}\n document={document}\n {...modalProps}\n >\n \n ,\n currentModalContainer,\n );\n\n onOpen?.();\n};\n\n/**\n * This helper function closes any currently open window modal. This can be useful, for example, if your modal contains a \"cancel\" button.\n */\nexport const closeWindowModal = async (document = window.document) => {\n const currentModalContainer = document.getElementById(WINDOW_MODAL_ID);\n if (currentModalContainer) {\n const { render } = await getPreactImport();\n render(null, currentModalContainer);\n }\n};\n","/**\n * A Preact 11+ implementation of the `replaceNode` parameter from Preact 10.\n *\n * This creates a \"Persistent Fragment\" (a fake DOM element) containing one or more\n * DOM nodes, which can then be passed as the `parent` argument to Preact's `render()` method.\n * Source: https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c\n */\nexport function createRootFragment(parent, replaceNode) {\n if (replaceNode) {\n replaceNode = Array.isArray(replaceNode) ? replaceNode : [replaceNode];\n } else {\n replaceNode = [parent];\n parent = parent.parentNode;\n }\n\n const s = replaceNode[replaceNode.length - 1].nextSibling;\n\n const rootFragment = {\n nodeType: 1,\n parentNode: parent,\n firstChild: replaceNode[0],\n childNodes: replaceNode,\n insertBefore: (c, r) => {\n parent.insertBefore(c, r || s);\n return c;\n },\n appendChild: (c) => {\n parent.insertBefore(c, s);\n return c;\n },\n removeChild: (c) => {\n parent.removeChild(c);\n return c;\n },\n };\n\n parent.__k = rootFragment;\n return rootFragment;\n}\n","function selectNavigation(select, urlPrefix) {\n const trigger = document.getElementById(select);\n if (trigger) {\n trigger.addEventListener('change', (event) => {\n let url = event.target.value;\n if (urlPrefix) {\n url = urlPrefix + url;\n }\n\n InstantClick.preload(url);\n InstantClick.display(url);\n });\n }\n}\n\nfunction initializeDashboardSort() {\n selectNavigation('dashboard_sort', '/dashboard?sort=');\n selectNavigation('dashboard_author');\n selectNavigation('mobile_nav_dashboard');\n}\n\nexport { selectNavigation, initializeDashboardSort };\n","import ahoy from 'ahoy.js';\n\n// * Create an ahoy event that will track a click on the\n// * passed in element.\n// *\n// * @param {string} elementId A unique identifier to identify the element that is being tracked\n// */\nexport function trackCommentClicks(elementId) {\n document\n .getElementById(elementId)\n ?.addEventListener('click', ({ target }) => {\n const relevantNode = getTrackingNode(target, '[data-tracking-name]');\n\n if (relevantNode) {\n ahoy.track('Comment section click', {\n page: location.href,\n element: relevantNode.dataset?.trackingName,\n });\n }\n });\n}\n\n// * Create an ahoy event that will track a click on the\n// * passed in element.\n// *\n// * @param {string} elementId A unique identifier to identify the element that is being tracked\n// */\nexport function trackCreateAccountClicks(elementId) {\n document\n .getElementById(elementId)\n ?.addEventListener('click', ({ target }) => {\n const relevantNode = getTrackingNode(target, '[data-tracking-id]');\n if (relevantNode) {\n ahoy.track('Clicked on Create Account', {\n version: 0.1,\n page: location.href,\n source: relevantNode.dataset?.trackingSource,\n });\n }\n });\n}\n\nfunction getTrackingNode(target, trackingElement) {\n // We check for any parent container with a trackingElement attribute, as otherwise\n // SVGs inside buttons can cause events to be missed\n const relevantNode = target.closest(trackingElement);\n return relevantNode;\n}\n","/**\n * A util function to wrap any code that needs to wait until the page has\n * initialized correctly before executing. This is generally the case for\n * packs/components that require `/app/assets/initializers` to execute first,\n * this way you're ensured that global functions/namespaces will be available\n * (i.e. the Runtime class).\n *\n * @returns {Promise} A chainable promise that will fulfill when the page has\n * loaded correctly and all initializers have run.\n */\nexport function waitOnBaseData() {\n return new Promise((resolve) => {\n const waitingForDataLoad = setInterval(() => {\n if (document.body.getAttribute('data-loaded') === 'true') {\n clearInterval(waitingForDataLoad);\n resolve();\n }\n }, 100);\n });\n}\n","/* global isTouchDevice */\n\nfunction closeHeaderMenu(memberMenu, menuNavButton) {\n menuNavButton.setAttribute('aria-expanded', 'false');\n memberMenu.classList.remove('desktop', 'showing');\n delete memberMenu.dataset.clicked;\n}\n\nconst firstItem = document.getElementById('first-nav-link');\n\nfunction openHeaderMenu(memberMenu, menuNavButton) {\n menuNavButton.setAttribute('aria-expanded', 'true');\n memberMenu.classList.add('showing');\n\n if (!firstItem) {\n return;\n }\n\n // Focus on the first item in the menu\n (function focusFirstItem() {\n if (document.activeElement === firstItem) {\n // The first element has focus\n return;\n }\n\n firstItem.focus();\n // requestAnimationFrame is faster and more reliable than setTimeout\n // https://swizec.com/blog/how-to-wait-for-dom-elements-to-show-up-in-modern-browsers\n window.requestAnimationFrame(focusFirstItem);\n })();\n}\n\n/**\n * Initializes the member navigation menu events.\n *\n * @param {HTMLElement} memberTopMenu The member menu in the top right navigation.\n * @param {HTMLElement} menuNavButton The button to activate the member navigation menu.\n */\nexport function initializeMemberMenu(memberTopMenu, menuNavButton) {\n // Typically using CSS for hovering for the menu is the way to go. But... since we use InstantClick for\n // loading pages, the top header navigation never changes in terms of the DOM references.\n // Because of this, we're using mouse events to mouseover/mouseout on the member's avatar\n // to attach styles to get it to show the menu so that this works on desktop and mobile.\n if (navigator.userAgent === 'DEV-Native-ios') {\n document.body.classList.add('dev-ios-native-body');\n }\n const { classList } = memberTopMenu;\n menuNavButton.addEventListener('click', (_event) => {\n if (classList.contains('showing') && memberTopMenu.dataset.clicked) {\n closeHeaderMenu(memberTopMenu, menuNavButton);\n menuNavButton.focus();\n } else {\n openHeaderMenu(memberTopMenu, menuNavButton);\n memberTopMenu.dataset.clicked = 'clicked';\n }\n });\n\n if (isTouchDevice()) {\n memberTopMenu.addEventListener('focus', (_event) => {\n menuNavButton.setAttribute('aria-expanded', 'true');\n });\n } else {\n memberTopMenu.addEventListener('keyup', (e) => {\n if (e.key === 'Escape' && classList.contains('showing')) {\n closeHeaderMenu(memberTopMenu, menuNavButton);\n menuNavButton.focus();\n }\n });\n }\n\n memberTopMenu\n .querySelector('.crayons-header__menu__dropdown')\n .addEventListener('click', (event) => {\n // There is a click event listener on the body and we do not want\n // this click to be caught by it\n event.stopPropagation();\n\n // Close the menu if the user clicked or touched on mobile a link in the menu.\n closeHeaderMenu(memberTopMenu, menuNavButton);\n menuNavButton.focus();\n });\n\n document.addEventListener('click', (event) => {\n if (event.target.closest('#member-menu-button') === menuNavButton) {\n // The menu navigation button manages it's own click event.\n return;\n }\n\n // Close the menu if the user clicked or touched on mobile a link in the menu.\n closeHeaderMenu(memberTopMenu, menuNavButton);\n });\n\n const secondToLastNavLink = document.getElementById('second-last-nav-link');\n\n document\n .getElementById('last-nav-link')\n .addEventListener('blur', (_event) => {\n // When we tab out of the last link in the member menu, close\n // the menu.\n setTimeout(() => {\n if (document.activeElement === secondToLastNavLink) {\n return;\n }\n\n closeHeaderMenu(memberTopMenu, menuNavButton);\n }, 10);\n });\n}\n\nfunction toggleBurgerMenu() {\n const { leftNavState = 'closed' } = document.body.dataset;\n document.body.dataset.leftNavState =\n leftNavState === 'open' ? 'closed' : 'open';\n}\n\n/**\n * Gets a reference to InstantClick\n *\n * @param {number} [waitTime=2000] The amount of time to wait\n * until giving up waiting for InstantClick to exist\n *\n * @returns {Promise} The global instance of InstantClick.\n */\nexport async function getInstantClick(waitTime = 2000) {\n return new Promise((resolve, reject) => {\n const failTimer = setTimeout(() => {\n clearInterval(timer);\n reject(new Error('Unable to resolve InstantClick'));\n }, waitTime);\n\n const timer = setInterval(() => {\n if (typeof InstantClick !== 'undefined') {\n clearTimeout(failTimer);\n clearInterval(timer);\n resolve(InstantClick);\n }\n });\n });\n}\n\n/**\n * Initializes the hamburger menu for mobile navigation\n *\n * @param {HTMLElement[]} menuTriggers The menuTriggers include the hamburger to open the menu,\n * the close icon to close the menu and the overlay to close the menu.\n */\nexport function initializeMobileMenu(menuTriggers) {\n menuTriggers.forEach((trigger) => {\n trigger.onclick = toggleBurgerMenu;\n });\n}\n\n/**\n * Sets the icon link visually for the current page if the current page\n * is one of the main icon links of the top navigation.\n *\n * @param {string} currentPage\n * @param {[string, HTMLElement][]} pageEntries\n */\nexport function setCurrentPageIconLink(currentPage, pageEntries) {\n pageEntries\n // Filter out nulls (means the user is logged out so most icons are not in the logged out view)\n .filter(([, iconLink]) => iconLink)\n .forEach(([page, iconLink]) => {\n if (currentPage === page) {\n iconLink.blur();\n iconLink.setAttribute('aria-current', 'page');\n } else {\n iconLink.removeAttribute('aria-current');\n }\n });\n}\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. ¯\\_(ツ)_/¯\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n","/**\n * This script hunts for podcast's \"Record\" for both the podcast_episode's\n * show page and an article page containing podcast liquid tag. It handles\n * playback and makes sure the record will spin when the podcast is currently\n * playing.\n *\n * The media is initialized (once) and the \"state\" is stored using localStorage.\n * When playback is the website's responsability it's run using the `audio` HTML\n * element. The iOS/Android apps uses a bridging strategy that sends messages\n * using webkit messageHandlers and receives incoming messages through the\n * `contentaudio` element, which allows for native audio playback.\n *\n * The high level functions are the following:\n * - spinPodcastRecord()\n * - findAndApplyOnclickToRecords()\n * - initializeMedia()\n * - currentAudioState()\n * - saveMediaState()\n *\n * The following are useful eslint disables for this file in particular. Because\n * of the way it's wrapped around its own function (own context) we don't have\n * the problem of using a method before it's defined:\n */\n\n/* eslint no-use-before-define: 0 */\n/* eslint no-param-reassign: 0 */\n\nimport ahoy from 'ahoy.js';\n\nexport function initializePodcastPlayback() {\n let deviceType = 'web';\n\n function getById(name) {\n return document.getElementById(name);\n }\n\n function getByClass(name) {\n return document.getElementsByClassName(name);\n }\n\n function newAudioState() {\n const audio = getById('audio');\n window.activeEpisode = audio?.dataset?.episode;\n window.activePodcast = audio?.dataset?.podcast;\n\n return {\n html: getById('audiocontent').innerHTML,\n currentTime: 0,\n playing: false,\n muted: false,\n volume: 1,\n duration: 1,\n updated: new Date().getTime(),\n playbackName: audio?.dataset?.episode,\n };\n }\n\n function currentAudioState() {\n try {\n const currentState = JSON.parse(\n localStorage.getItem('media_playback_state_v3'),\n );\n if (!currentState) {\n return newAudioState();\n }\n return currentState;\n } catch (e) {\n return newAudioState();\n }\n }\n\n function audioExistAndIsPlaying() {\n return getById('audio') && currentAudioState().playing;\n }\n\n function recordExist() {\n return getById(`record-${window.activeEpisode}`);\n }\n\n function spinPodcastRecord(customMessage) {\n if (audioExistAndIsPlaying() && recordExist()) {\n const podcastPlaybackButton = getById(`record-${window.activeEpisode}`);\n podcastPlaybackButton.classList.add('playing');\n podcastPlaybackButton.setAttribute('aria-pressed', 'true');\n changeStatusMessage(customMessage);\n } else {\n stopRotatingActivePodcastIfExist();\n }\n }\n\n function stopRotatingActivePodcastIfExist() {\n if (window.activeEpisode && getById(`record-${window.activeEpisode}`)) {\n const podcastPlaybackButton = getById(`record-${window.activeEpisode}`);\n podcastPlaybackButton.classList.remove('playing');\n podcastPlaybackButton.setAttribute('aria-pressed', 'false');\n window.activeEpisode = undefined;\n }\n }\n\n function findRecords() {\n const podcastPageRecords = getByClass('record-wrapper');\n const podcastLiquidTagrecords = getByClass('podcastliquidtag__record');\n if (podcastPageRecords.length > 0) {\n return podcastPageRecords;\n }\n return podcastLiquidTagrecords;\n }\n\n function saveMediaState(state) {\n const currentState = state || currentAudioState();\n const newState = newAudioState();\n newState.currentTime = currentState.currentTime;\n newState.playing = currentState.playing;\n newState.muted = currentState.muted;\n newState.volume = currentState.volume;\n newState.duration = currentState.duration;\n localStorage.setItem('media_playback_state_v3', JSON.stringify(newState));\n return newState;\n }\n\n function applyOnclickToPodcastBar(audio) {\n const currentState = currentAudioState();\n getById('barPlayPause').onclick = function () {\n playPause(audio);\n };\n getById('mutebutt').onclick = function () {\n muteUnmute(audio);\n };\n getById('volbutt').onclick = function () {\n muteUnmute(audio);\n };\n getById('bufferwrapper').onclick = function (e) {\n goToTime(e, audio);\n };\n getById('volumeslider').value = currentState.volume * 100;\n getById('volumeslider').onchange = function (e) {\n updateVolume(e, audio);\n };\n getById('speed').onclick = function () {\n changePlaybackRate(audio);\n };\n getById('closebutt').onclick = function () {\n terminatePodcastBar(audio);\n };\n }\n\n function podcastBarAlreadyExistAndPlayingTargetEpisode(episodeSlug) {\n return getById('audiocontent').innerHTML.indexOf(`${episodeSlug}`) !== -1;\n }\n\n function updateProgressListener(audio) {\n return () => {\n let bufferValue = 0;\n if (audio.currentTime > 0) {\n const bufferEnd = audio.buffered.end(audio.buffered.length - 1);\n bufferValue = (bufferEnd / audio.duration) * 100;\n }\n updateProgress(audio.currentTime, audio.duration, bufferValue);\n };\n }\n\n function loadAudio(audio) {\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'load',\n url: audio.getElementsByTagName('source')[0].src,\n });\n } else {\n audio.load();\n }\n }\n\n function loadAndPlayNewPodcast(episodeSlug) {\n getById('audiocontent').innerHTML = getById(\n `hidden-audio-${episodeSlug}`,\n ).innerHTML;\n const audio = getById('audio');\n audio.addEventListener('timeupdate', updateProgressListener(audio), false);\n loadAudio(audio);\n playPause(audio);\n applyOnclickToPodcastBar(audio);\n }\n\n function findAndApplyOnclickToRecords() {\n const records = findRecords();\n Array.prototype.forEach.call(records, (record) => {\n const episodeSlug = record.getAttribute('data-episode');\n const togglePodcastState = () => {\n if (podcastBarAlreadyExistAndPlayingTargetEpisode(episodeSlug)) {\n const audio = getById('audio');\n if (audio) {\n playPause(audio);\n }\n } else {\n stopRotatingActivePodcastIfExist();\n loadAndPlayNewPodcast(episodeSlug);\n }\n };\n record.addEventListener('click', togglePodcastState);\n });\n }\n\n function changePlaybackRate(audio) {\n const currentState = currentAudioState();\n const el = getById('speed');\n const speed = parseFloat(el.getAttribute('data-speed'));\n if (speed === 2) {\n el.setAttribute('data-speed', 0.5);\n el.innerHTML = '0.5x';\n currentState.playbackRate = 0.5;\n } else {\n el.setAttribute('data-speed', speed + 0.5);\n el.innerHTML = `${speed + 0.5}x`;\n currentState.playbackRate = speed + 0.5;\n }\n saveMediaState(currentState);\n\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'rate',\n rate: currentState.playbackRate.toString(),\n });\n } else {\n audio.playbackRate = currentState.playbackRate;\n }\n }\n\n function changeStatusMessage(message) {\n const currentState = currentAudioState();\n const statusBox = getById(`status-message-${currentState.playbackName}`);\n if (statusBox) {\n if (message) {\n statusBox.classList.add('showing');\n statusBox.innerHTML = message;\n } else {\n statusBox.classList.remove('showing');\n }\n } else if (\n message === 'initializing...' &&\n getByClass('status-message')[0]\n ) {\n getByClass('status-message')[0].innerHTML = message;\n }\n }\n\n function startPodcastBar() {\n getById('barPlayPause').classList.add('playing');\n getById('progressBar').classList.add('playing');\n getById('animated-bars').classList.add('playing');\n }\n\n function pausePodcastBar() {\n getById('barPlayPause').classList.remove('playing');\n getById('animated-bars').classList.remove('playing');\n }\n\n function playAudio(audio) {\n return new Promise((resolve, reject) => {\n const currentState = currentAudioState();\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'play',\n url: audio.getElementsByTagName('source')[0].src,\n seconds: currentState.currentTime.toString(),\n });\n setPlaying(true);\n resolve();\n } else {\n audio.currentTime = currentState.currentTime;\n audio\n .play()\n .then(() => {\n setPlaying(true);\n resolve();\n })\n .catch(() => {\n setPlaying(false);\n reject();\n });\n }\n });\n }\n\n function fetchMetadataString() {\n let episodeContainer = getByClass('podcast-episode-container')[0];\n if (episodeContainer === undefined) {\n episodeContainer = getByClass('podcastliquidtag')[0];\n }\n return episodeContainer.dataset.meta;\n }\n\n function sendMetadataMessage() {\n if (window.Forem.Runtime.podcastMessage) {\n try {\n const metadata = JSON.parse(fetchMetadataString());\n window.Forem.Runtime.podcastMessage({\n action: 'metadata',\n episodeName: metadata.episodeName,\n podcastName: metadata.podcastName,\n podcastImageUrl: metadata.podcastImageUrl,\n });\n } catch (e) {\n console.log('Unable to load Podcast Episode metadata', e); // eslint-disable-line no-console\n }\n }\n }\n\n function startAudioPlayback(audio) {\n sendMetadataMessage();\n\n playAudio(audio)\n .then(() => {\n spinPodcastRecord();\n startPodcastBar();\n })\n .catch(() => {\n playAudio(audio);\n setTimeout(() => {\n spinPodcastRecord('initializing...');\n startPodcastBar();\n }, 5);\n });\n }\n\n function pauseAudioPlayback(audio) {\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({ action: 'pause' });\n } else {\n audio.pause();\n }\n setPlaying(false);\n stopRotatingActivePodcastIfExist();\n pausePodcastBar();\n }\n\n function ahoyMessage(action) {\n const properties = {\n action,\n episode: window.activeEpisode,\n podcast: window.activePodcast,\n deviceType,\n };\n ahoy.track('Podcast Player Streaming', properties);\n }\n\n function playPause(audio) {\n let currentState = currentAudioState();\n if (currentState.playbackName != getById('audio').dataset.episode) {\n currentState = newAudioState();\n saveMediaState(currentState);\n }\n\n if (!currentState.playing) {\n ahoyMessage('play');\n changeStatusMessage(null);\n startAudioPlayback(audio);\n } else {\n ahoyMessage('pause');\n pauseAudioPlayback(audio);\n changeStatusMessage(null);\n }\n spinPodcastRecord();\n }\n\n function muteUnmute(audio) {\n const currentState = currentAudioState();\n getById('mutebutt').classList.add(\n currentState.muted ? 'hidden' : 'showing',\n );\n getById('volumeindicator').classList.add(\n currentState.muted ? 'showing' : 'hidden',\n );\n getById('mutebutt').classList.remove(\n currentState.muted ? 'showing' : 'hidden',\n );\n getById('volumeindicator').classList.remove(\n currentState.muted ? 'hidden' : 'showing',\n );\n\n currentState.muted = !currentState.muted;\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'muted',\n muted: currentState.muted.toString(),\n });\n } else {\n audio.muted = currentState.muted;\n }\n saveMediaState(currentState);\n }\n\n function updateVolume(e, audio) {\n const currentState = currentAudioState();\n currentState.volume = e.target.value / 100;\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'volume',\n volume: currentState.volume,\n });\n } else {\n audio.volume = currentState.volume;\n }\n saveMediaState(currentState);\n }\n\n function updateProgress(currentTime, duration, bufferValue) {\n const progress = getById('progress');\n const buffer = getById('buffer');\n const time = getById('time');\n let value = 0;\n const firstDecimal = currentTime - Math.floor(currentTime);\n if (currentTime > 0) {\n value = Math.floor((100.0 / duration) * currentTime);\n if (firstDecimal < 0.4) {\n // Rewrite to mediaState storage every few beats.\n const currentState = currentAudioState();\n currentState.duration = duration;\n currentState.currentTime = currentTime;\n saveMediaState(currentState);\n }\n }\n if (progress && time && currentTime > 0) {\n progress.style.width = `${value}%`;\n buffer.style.width = `${bufferValue}%`;\n time.innerHTML = `${readableDuration(currentTime)} / ${readableDuration(\n duration,\n )}`;\n }\n }\n\n function goToTime(e, audio) {\n const currentState = currentAudioState();\n const progress = getById('progress');\n const time = getById('time');\n if (e.clientX > 128) {\n const percent = (e.clientX - 128) / (window.innerWidth - 133);\n currentState.currentTime = currentState.duration * percent; // jumps to 29th secs\n\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({\n action: 'seek',\n seconds: currentState.currentTime.toString(),\n });\n } else {\n audio.currentTime = currentState.currentTime;\n }\n\n const currentTime = readableDuration(currentState.currentTime);\n const duration = readableDuration(currentState.duration);\n time.innerHTML = `${currentTime} / ${duration}`;\n progress.style.width = `${percent * 100.0}%`;\n }\n }\n\n function readableDuration(seconds) {\n let sec = Math.floor(seconds);\n let min = Math.floor(sec / 60);\n min = min >= 10 ? min : `0${min}`;\n sec = Math.floor(sec % 60);\n sec = sec >= 10 ? sec : `0${sec}`;\n return `${min}:${sec}`;\n }\n\n function terminatePodcastBar(audio) {\n audio.removeEventListener(\n 'timeupdate',\n updateProgressListener(audio),\n false,\n );\n getById('audiocontent').innerHTML = '';\n stopRotatingActivePodcastIfExist();\n saveMediaState(newAudioState());\n if (window.Forem.Runtime.podcastMessage) {\n window.Forem.Runtime.podcastMessage({ action: 'terminate' });\n }\n }\n\n function handlePodcastMessages(event) {\n const message = JSON.parse(event.detail);\n if (message.namespace !== 'podcast') {\n return;\n }\n\n const currentState = currentAudioState();\n switch (message.action) {\n case 'init':\n getById('time').innerHTML = 'initializing...';\n currentState.currentTime = 0;\n break;\n case 'play':\n ahoyMessage('play');\n spinPodcastRecord();\n startPodcastBar();\n break;\n case 'pause':\n ahoyMessage('pause');\n setPlaying(false);\n stopRotatingActivePodcastIfExist();\n pausePodcastBar();\n break;\n case 'tick':\n currentState.currentTime = message.currentTime;\n currentState.duration = message.duration;\n updateProgress(currentState.currentTime, currentState.duration, 100);\n break;\n default:\n console.log('Unrecognized message: ', message); // eslint-disable-line no-console\n }\n\n saveMediaState(currentState);\n }\n\n // When window.Forem.Runtime.podcastMessage is undefined we need to execute web logic\n function initRuntime() {\n if (window.Forem.Runtime.isNativeIOS('podcast')) {\n deviceType = 'iOS';\n } else if (window.Forem.Runtime.isNativeAndroid('podcastMessage')) {\n deviceType = 'Android';\n }\n\n if (deviceType !== 'web') {\n window.Forem.Runtime.podcastMessage = (msg) => {\n window.ForemMobile.injectNativeMessage('podcast', msg);\n };\n }\n }\n\n function initializeMedia() {\n const currentState = currentAudioState();\n document.getElementById('audiocontent').innerHTML = currentState.html;\n const audio = getById('audio');\n if (audio === undefined || audio === null) {\n window.Forem.audioInitialized = false;\n return;\n }\n if (window.Forem.Runtime.podcastMessage) {\n audio.currentTime = currentState.currentTime || 0;\n }\n loadAudio(audio);\n if (currentState.playing) {\n playAudio(audio).catch(() => {\n pausePodcastBar();\n });\n }\n setTimeout(() => {\n audio.addEventListener(\n 'timeupdate',\n updateProgressListener(audio),\n false,\n );\n document.addEventListener('ForemMobile', handlePodcastMessages);\n }, 500);\n applyOnclickToPodcastBar(audio);\n }\n\n function setPlaying(playing) {\n const currentState = currentAudioState();\n currentState.playing = playing;\n saveMediaState(currentState);\n }\n\n initRuntime();\n spinPodcastRecord();\n findAndApplyOnclickToRecords();\n if (!window.Forem.audioInitialized) {\n window.Forem.audioInitialized = true;\n initializeMedia();\n }\n const audio = getById('audio');\n const audioContent = getById('audiocontent');\n if (audio && audioContent && audioContent.innerHTML.length < 25) {\n // audio not already loaded\n loadAudio(audio);\n }\n}\n","/**\n * This script hunts for video tags and initializes the correct player\n * depending on the platform:\n * - web: jwplayer\n * - iOS/Android: Native player\n *\n * Once jwplayer is initialized there's no follow up actions to be taken.\n * Mobile Native players send back information into the DOM in order to\n * interact and update the UI, therefore a MutationObserver is registered.\n */\n\n/* eslint no-use-before-define: 0 */\n/* eslint no-param-reassign: 0 */\n/* eslint no-useless-escape: 0 */\n/* global jwplayer */\n\nimport ahoy from 'ahoy.js';\n\nexport function initializeVideoPlayback() {\n let currentTime = '0';\n let deviceType = 'web';\n let lastEvent = '';\n\n function getById(name) {\n return document.getElementById(name);\n }\n\n function timeToSeconds(hms) {\n let a;\n if (hms.length < 3) {\n return hms;\n } else if (hms.length < 6) {\n a = hms.split(':');\n return (hms = +a[0] * 60 + +a[1]);\n }\n a = hms.split(':');\n return (hms = +a[0] * 60 * 60 + +a[1] * 60 + +a[2]);\n }\n\n function videoPlayerEvent(isPlaying) {\n // jwtplayer tends to send multiple 'play' actions. This check makes sure\n // we're not tracking repeated 'play' events for a single interaction.\n const eventName = isPlaying ? 'play' : 'pause';\n if (lastEvent === eventName) {\n return;\n }\n lastEvent = eventName;\n\n const metadata = videoMetadata(getById('video-player-source'));\n const properties = {\n article: metadata.id,\n deviceType,\n action: eventName,\n };\n ahoy.track('Video Player Streaming', properties);\n }\n\n function initWebPlayer(seconds, metadata) {\n const waitingOnJWP = setInterval(() => {\n if (typeof jwplayer !== 'undefined') {\n clearInterval(waitingOnJWP);\n const playerInstance = jwplayer(`video-player-${metadata.id}`);\n playerInstance.setup({\n file: metadata.video_source_url,\n mediaid: metadata.video_code,\n image: metadata.video_thumbnail_url,\n playbackRateControls: true,\n tracks: [\n {\n file: metadata.video_closed_caption_track_url,\n label: 'English',\n kind: 'captions',\n default: false,\n },\n ],\n });\n if (seconds) {\n jwplayer().on('firstFrame', () => {\n jwplayer().seek(seconds);\n });\n jwplayer().on('play', () => {\n videoPlayerEvent(true);\n });\n jwplayer().on('pause', () => {\n videoPlayerEvent(false);\n });\n }\n }\n }, 2);\n }\n\n function videoMetadata(videoSource) {\n try {\n return JSON.parse(videoSource.dataset.meta);\n } catch (e) {\n console.log('Unable to load Podcast Episode metadata', e); // eslint-disable-line no-console\n }\n }\n\n function requestFocus() {\n const metadata = videoMetadata(videoSource);\n\n getById('pause-butt').classList.add('active');\n getById('play-butt').classList.remove('active');\n\n window.Forem.Runtime.videoMessage({\n action: 'play',\n url: metadata.video_source_url,\n seconds: currentTime,\n });\n\n videoPlayerEvent(true);\n }\n\n function handleVideoMessages(event) {\n const message = JSON.parse(event.detail);\n if (message.namespace !== 'video') {\n return;\n }\n\n switch (message.action) {\n case 'play':\n getById('pause-butt').classList.add('active');\n getById('play-butt').classList.remove('active');\n videoPlayerEvent(true);\n break;\n case 'pause':\n getById('pause-butt').classList.remove('active');\n getById('play-butt').classList.add('active');\n videoPlayerEvent(false);\n break;\n case 'tick':\n currentTime = message.currentTime; // eslint-disable-line prefer-destructuring\n break;\n default:\n console.log('Unrecognized message: ', message); // eslint-disable-line no-console\n }\n }\n\n function initializePlayer(videoSource) {\n const seconds = timeToSeconds('0');\n const metadata = videoMetadata(videoSource);\n\n if (window.Forem.Runtime.isNativeIOS('video')) {\n deviceType = 'iOS';\n } else if (window.Forem.Runtime.isNativeAndroid('videoMessage')) {\n deviceType = 'Android';\n } else {\n // jwplayer is initialized and no further interaction is needed\n initWebPlayer(seconds, metadata);\n return;\n }\n\n window.Forem.Runtime.videoMessage = (msg) => {\n window.ForemMobile.injectNativeMessage('video', msg);\n };\n\n const playerElement = getById(`video-player-${metadata.id}`);\n playerElement.addEventListener('click', requestFocus);\n\n playerElement.classList.add('native');\n getById('play-butt').classList.add('active');\n\n document.addEventListener('ForemMobile', handleVideoMessages);\n\n currentTime = `${seconds}`;\n }\n\n // If an video player element is found initialize it\n const videoSource = getById('video-player-source');\n if (videoSource !== null) {\n initializePlayer(videoSource);\n }\n}\n","import 'focus-visible';\nimport {\n initializeMobileMenu,\n setCurrentPageIconLink,\n initializeMemberMenu,\n} from '../topNavigation/utilities';\nimport { waitOnBaseData } from '../utilities/waitOnBaseData';\nimport { initializePodcastPlayback } from '../utilities/podcastPlayback';\nimport { initializeVideoPlayback } from '../utilities/videoPlayback';\nimport { createRootFragment } from '../shared/preact/preact-root-fragment';\nimport { initializeDashboardSort } from './initializers/initializeDashboardSort';\nimport { trackCreateAccountClicks } from '@utilities/ahoy/trackEvents';\nimport { showWindowModal, closeWindowModal } from '@utilities/showModal';\nimport * as Runtime from '@utilities/runtime';\n\nDocument.prototype.ready = new Promise((resolve) => {\n if (document.readyState !== 'loading') {\n return resolve();\n }\n document.addEventListener('DOMContentLoaded', () => resolve());\n return null;\n});\n\n// Namespace for functions which need to be accessed in plain JS initializers\nwindow.Forem = {\n audioInitialized: false,\n preactImport: undefined,\n getPreactImport() {\n if (!this.preactImport) {\n this.preactImport = import('preact');\n }\n return this.preactImport;\n },\n enhancedCommentTextAreaImport: undefined,\n getEnhancedCommentTextAreaImports() {\n if (!this.enhancedCommentTextAreaImport) {\n this.enhancedCommentTextAreaImport = import(\n './CommentTextArea/CommentTextArea'\n );\n }\n return Promise.all([\n this.enhancedCommentTextAreaImport,\n this.getPreactImport(),\n ]);\n },\n initializeEnhancedCommentTextArea: async (originalTextArea) => {\n const parentContainer = originalTextArea.parentElement;\n\n const alreadyInitialized =\n parentContainer.classList.contains('c-autocomplete');\n\n if (alreadyInitialized) {\n return;\n }\n\n const [{ CommentTextArea }, { render, h }] =\n await window.Forem.getEnhancedCommentTextAreaImports();\n\n render(\n ,\n createRootFragment(parentContainer, originalTextArea),\n );\n },\n showModal: showWindowModal,\n closeModal: () => closeWindowModal(),\n Runtime,\n};\n\ninitializeDashboardSort();\ninitializePodcastPlayback();\ninitializeVideoPlayback();\nInstantClick.on('change', () => {\n initializeDashboardSort();\n initializePodcastPlayback();\n initializeVideoPlayback();\n});\n\n// Initialize data-runtime context to the body data-attribute\ndocument.body.dataset.runtime = window.Forem.Runtime.currentContext();\n\nfunction getPageEntries() {\n return Object.entries({\n 'notifications-index': document.getElementById('notifications-link'),\n 'moderations-index': document.getElementById('moderation-link'),\n 'articles_search-index': document.getElementById('search-link'),\n });\n}\n\n/**\n * Initializes the left hand side hamburger menu\n */\nfunction initializeNav() {\n const { currentPage } = document.getElementById('page-content').dataset;\n const menuTriggers = [\n ...document.querySelectorAll('.js-hamburger-trigger, .hamburger a'),\n ];\n\n setCurrentPageIconLink(currentPage, getPageEntries());\n initializeMobileMenu(menuTriggers);\n}\n\nconst memberMenu = document.getElementById('crayons-header__menu');\nconst menuNavButton = document.getElementById('member-menu-button');\n\nif (memberMenu) {\n initializeMemberMenu(memberMenu, menuNavButton);\n}\n\n/**\n * Fetches the html for the navigation_links from an endpoint and dynamically insterts it in the DOM.\n */\nasync function getNavigation() {\n const placeholderElement = document.getElementsByClassName(\n 'js-navigation-links-container',\n )[0];\n\n if (placeholderElement.innerHTML.trim() === '') {\n const response = await window.fetch(`/async_info/navigation_links`);\n const htmlContent = await response.text();\n\n const generatedElement = document.createElement('div');\n generatedElement.innerHTML = htmlContent;\n\n placeholderElement.appendChild(generatedElement);\n }\n}\n\n// Initialize when asset pipeline (sprockets) initializers have executed\nwaitOnBaseData()\n .then(() => {\n InstantClick.on('change', () => {\n initializeNav();\n });\n\n if (Runtime.currentMedium() === 'ForemWebView') {\n // Dynamic import of the namespace\n import('../mobile/foremMobile.js').then((module) => {\n // Load the namespace\n window.ForemMobile = module.foremMobileNamespace();\n // Run the first session\n window.ForemMobile.userSessionBroadcast();\n });\n }\n })\n .catch((error) => {\n Honeybadger.notify(error);\n });\n\n// we need to call initializeNav here for the initial page load\ninitializeNav();\n\nasync function loadCreatorSettings() {\n try {\n const [{ LogoUploadController }, { Application }] = await Promise.all([\n import('@admin/controllers/logo_upload_controller'),\n import('@hotwired/stimulus'),\n ]);\n\n const application = Application.start();\n application.register('logo-upload', LogoUploadController);\n } catch (error) {\n Honeybadger.notify(\n `Error loading the creator settings controller: ${error.message}`,\n );\n }\n}\n\nif (document.location.pathname === '/admin/creator_settings/new') {\n loadCreatorSettings();\n}\n\ndocument.ready.then(() => {\n const hamburgerTrigger = document.getElementsByClassName(\n 'js-hamburger-trigger',\n )[0];\n hamburgerTrigger.addEventListener('click', getNavigation);\n});\n\ntrackCreateAccountClicks('authentication-hamburger-actions');\ntrackCreateAccountClicks('authentication-top-nav-actions');\ntrackCreateAccountClicks('comments-locked-cta');\n\n// Our infinite scroll pattern causes problems with the browser's back button:\n// specifically, if you've scrolled into page 2+, click into a post, then back\n// to the feed, the browser scroll position will not be where you had previously\n// scrolled. This seems to fix it, even though it seems like it should have\n// the opposite effect.\nhistory.scrollRestoration = 'manual';\n","/**\n * This function returns a string combining the current Medium and OS\n * that represents the current Context where the app is running.\n *\n * @returns {String} \"Medium-OS\", for example \"Browser-Android\"\n */\nexport const currentContext = () => `${currentMedium()}-${currentOS()}`;\n\n/**\n * This function returns a string that represents the current Medium where\n * the app is currently running. The currently supported mediums are Browser,\n * and ForemWebView.\n *\n * @returns {String} One of the supported Mediums\n */\nexport const currentMedium = () =>\n /ForemWebView/i.test(navigator.userAgent) ? 'ForemWebView' : 'Browser';\n\n/**\n * This function returns a string that represents the current OS where the app\n * is currently running. The currently supported Operating Systems are\n * Windows, Linux, macOS, Android and iOS.\n *\n * @returns {String} One of the supported Operating Systems or 'Unsupported'\n */\nexport const currentOS = () => {\n const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'];\n const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];\n const iosPlatforms = ['iPhone', 'iPad', 'iPod'];\n\n if (macosPlatforms.includes(window.navigator.platform)) {\n return 'macOS';\n } else if (iosPlatforms.includes(window.navigator.platform)) {\n return 'iOS';\n } else if (windowsPlatforms.includes(window.navigator.platform)) {\n return 'Windows';\n } else if (/Android/i.test(window.navigator.userAgent)) {\n return 'Android';\n } else if (/Linux/i.test(window.navigator.platform)) {\n return 'Linux';\n }\n\n return 'Unsupported';\n};\n\n/**\n * Checks the device for iOS (webkit) native feature support\n *\n * @function isNativeIOS\n * @param {string} namespace Specifies support for a specific feature\n * (i.e. video, podcast, etc)\n * @returns {boolean} true if current environment support native features\n */\nexport const isNativeIOS = (namespace = null) => {\n const nativeCheck =\n /DEV-Native-ios|ForemWebView/i.test(navigator.userAgent) &&\n window &&\n window.webkit &&\n window.webkit.messageHandlers;\n\n let namespaceCheck = true;\n if (nativeCheck && namespace) {\n namespaceCheck = window.webkit.messageHandlers[namespace] != undefined;\n }\n\n return nativeCheck && namespaceCheck;\n};\n\n/**\n * Checks the device for Android native feature support\n *\n * @function isNativeAndroid\n * @param {string} namespace Specifies support for a specific feature\n * (i.e. videoMessage, podcastMessage, etc)\n * @returns {boolean} true if current environment support native features\n */\nexport const isNativeAndroid = (namespace = null) => {\n const nativeCheck =\n /DEV-Native-android|ForemWebView/i.test(navigator.userAgent) &&\n typeof AndroidBridge !== 'undefined';\n\n let namespaceCheck = true;\n if (nativeCheck && namespace) {\n namespaceCheck = AndroidBridge[namespace] != undefined;\n }\n\n return nativeCheck && namespaceCheck;\n};\n\n/**\n * This function copies text to clipboard taking in consideration all\n * supported platforms.\n *\n * @param {string} text to be copied to the clipboard\n *\n * @returns {Promise} Resolves when successful in copying to clipboard\n */\nexport const copyToClipboard = (text) => {\n return new Promise((resolve, reject) => {\n if (isNativeAndroid('copyToClipboard')) {\n AndroidBridge.copyToClipboard(text);\n resolve();\n } else if (navigator.clipboard != null) {\n navigator.clipboard\n .writeText(text)\n .then(() => {\n resolve();\n })\n .catch((e) => {\n reject(e);\n });\n } else {\n reject('Unable to copy the text. Try reloading the page');\n }\n });\n};\n\n/**\n * Returns true if the supplied KeyboardEvent includes the OS-specific\n * modifier key. For example, the Cmd key on Apple platforms or the Ctrl key\n * on others.\n *\n * @param {KeyboardEvent} The event to check for the OS-specific modifier key\n *\n * @returns {Boolean} true if the event was fired with the OS-specific\n * modifier key, false otherwise. Also returns false if\n * the event is not a KeyboardEvent.\n */\nexport const hasOSSpecificModifier = (event) => {\n if (!(event instanceof KeyboardEvent)) {\n return false;\n }\n\n if (navigator.userAgent.indexOf('Mac OS X') >= 0) {\n return event.metaKey;\n }\n return event.ctrlKey;\n};\n\n/**\n * Returns a string representation of the expected modifier key for the current OS.\n * This allows us to display correct shortcut key hints to users in the UI, and set up correct shortcut key bindings.\n *\n * @returns {string} either 'cmd' if on macOS, or 'ctrl' otherwise\n */\nexport const getOSKeyboardModifierKeyString = () =>\n currentOS() === 'macOS' ? 'cmd' : 'ctrl';\n\n/**\n * @returns {string} A string representing the locale as per the user's browser settings\n */\nexport const getCurrentLocale = () => navigator.language;\n"],"sourceRoot":""}