{"version":3,"file":"js/ecommerce-77f3a88aced21c32a975.js","mappings":"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","sources":["webpack://ios-interview-guide-app/./app/javascript/src/ecommerce_main.ts","webpack://ios-interview-guide-app/./app/javascript/src/button_scrolling.js","webpack://ios-interview-guide-app/./app/javascript/src/click_handlers.js","webpack://ios-interview-guide-app/./app/javascript/src/mixpanel_setup.ts"],"sourcesContent":["import './click_handlers'\nimport './button_scrolling'\nimport mixpanel from 'mixpanel-browser';\nimport \"../src/mixpanel_setup\"\n\nclass Section {\n private readonly internalSectionId: string\n\n get sectionId(): string {\n if (this.parentSection) {\n if (this.parentSection.sectionId.length == 0) {\n return this.internalSectionId\n } else {\n return `${this.parentSection.sectionId}-subsection-${this.internalSectionId}`\n }\n } else {\n return this.internalSectionId\n }\n }\n\n get menuItemId(): string {\n return `${this.sectionId}-menu-item`\n }\n\n parentSection: Section | undefined\n \n isIntersecting: boolean = false\n yRelativeToRoot: number = 0\n \n childrenSections: Section[]\n\n constructor(sectionId: string, parentSection: Section | undefined = undefined, childrenSections: Section[] = []) {\n this.internalSectionId = sectionId\n this.parentSection = parentSection\n this.childrenSections = childrenSections\n childrenSections.forEach(subsection => {\n subsection.parentSection = this\n })\n }\n}\n\ntype JSONSection = {\n name: string\n children: JSONSection[]\n}\n\nconst jsonStructureOfContent: JSONSection = {\n name: \"\", children: [\n {\n name: \"App-Features-Overview\", children: [\n { name: \"Home-Tab\", children: [] },\n { name: \"Favorites-Tab\", children: [] },\n { name: \"Update-Tab\", children: [] },\n { name: \"You-Tab\", children: [] },\n { name: \"Cart-Tab\", children: [] },\n { name: \"Product-Details-Screen\", children: [] },\n ]\n },\n { name: \"What-Architecture-To-Pick\", children: [] },\n { name: \"Brief-Overview-of-VIPER\", children: [] },\n { \n name: \"Overall-App-Architecture\", children: [\n { name: \"Screens\", children: [] },\n { \n name: \"Layers\", children: [\n { name: \"UI-Layer\", children: [] },\n { name: \"Networking-Service-Layer\", children: [] },\n { name: \"Storage-Layer\", children: [] },\n { name: \"Business-Logic-Layer\", children: [] }\n ] \n },\n { name: \"Dependencies\", children: [] },\n { name: \"Domain-Models\", children: [] },\n { name: \"Interactors-Presenters-Coordinators-Routers\", children: [] }\n ] \n },\n\n { \n name: \"Home-Tab-Screen\", children: [\n { name: \"Home-Tab-Features\", children: [] },\n { name: \"Home-Tab-Structure\", children: [] },\n { \n name: \"Home-Screen-Dependencies-Architecture\", children: [\n { name: \"Home-VIPER-stack\", children: [] },\n { name: \"SearchBar-VIPER-Stack\", children: [] },\n { name: \"Product-List-VIPER-Stack\", children: [] },\n { name: \"Hero-Promo-VIPER-Stacks\", children: [] }\n ] \n },\n { name: \"Data-Flow-In-Home-Screen\", children: [] },\n ] \n },\n\n { \n name: \"Product-Details-Screen\", children: [\n { name: \"Product-Details-Features\", children: [] },\n { name: \"Product-Details-Structure\", children: [] },\n { name: \"Product-Details-Dependencies-Architecture\", children: [\n { name: \"Product-Details-VIPER-Stack\", children: [] },\n { name: \"Product-Item-VIPER-Stack\", children: [] },\n { name: \"Price-And-Quantity-VIPER-Stack\", children: [] },\n { name: \"Reviews-VIPER-Stack\", children: [] },\n {name: \"Product-List-VIPER-Stack\", children: [] },\n ] \n },\n { name: \"Data-Flow-In-Product-Details\", children: [] },\n ] \n },\n\n { name: \"AB-Testing-Feature-Flagging\", children: [] },\n ]\n}\n\nfunction mapJSONStructureOfContentToSectionViewModels(jsonStructureOfContent: JSONSection, parentSection: Section | undefined): Section {\n\n const section = new Section(jsonStructureOfContent.name, parentSection)\n\n const childrenSections = jsonStructureOfContent.children.map(childJSON => {\n return mapJSONStructureOfContentToSectionViewModels(childJSON, section)\n })\n\n section.childrenSections = childrenSections\n\n return section\n}\n\nconst rootSection = mapJSONStructureOfContentToSectionViewModels(jsonStructureOfContent, undefined)\n\nfunction getAllSectionAsArrayList(section: Section): Section[] {\n if (section.childrenSections.length == 0) {\n return [section]\n } else {\n let childrenSections: Section[] = []\n\n for (const childSection of section.childrenSections) {\n const childSections = getAllSectionAsArrayList(childSection)\n for (const childSection of childSections) {\n childrenSections.push(childSection)\n }\n }\n\n if (section.sectionId == \"\") { // i.e. when reached the root\n return childrenSections\n } else {\n return childrenSections.concat([section])\n }\n }\n}\n\nfunction checkExistenceOfAllElementsForSectionsAndMenuItems(section: Section) {\n let sideMenuHrefErrorMessages: string[] = []\n\n getAllSectionAsArrayList(section).forEach(section => {\n // console.log(`section.sectionId ${section.sectionId} section.menuItemId ${section.menuItemId}`)\n\n const sectionElement = document.getElementById(section.sectionId)\n if (!sectionElement) {\n throw new Error(`can't find element for ${section.sectionId}`)\n }\n\n const menuItemElement = document.getElementById(section.menuItemId)\n if (!menuItemElement) {\n throw new Error(`can't find element for ${section.menuItemId}`)\n }\n \n if (menuItemElement instanceof HTMLAnchorElement && new URL(menuItemElement.href).hash != `#${section.sectionId}`) {\n sideMenuHrefErrorMessages.push(`wrong href link in ${section.menuItemId}. got ${new URL(menuItemElement.href).hash} but should be #${section.sectionId}`)\n }\n \n })\n\n if (sideMenuHrefErrorMessages.length > 0) {\n throw new Error(sideMenuHrefErrorMessages.join(\"\\n\"))\n }\n}\n\nfunction getAllSectionElements(section: Section): Element[] {\n return getAllSectionAsArrayList(section).map(section => {\n const sectionElement = document.getElementById(section.sectionId)\n if (sectionElement) {\n return sectionElement\n } else {\n throw new Error(`can't find element for ${section.sectionId}`)\n }\n\n })\n}\n\ntype MenuItemHightingGroups = [sectionsToHighlight: Section[], sectionsToUnhighlight: Section[]]\n\nfunction findAllSectionsToHighlightOrUnhighlight(section: Section): MenuItemHightingGroups {\n if (section.childrenSections.length == 0) {\n if (section.isIntersecting) {\n return [[section], []]\n } else {\n return [[], [section]]\n }\n } else {\n let childrenSectionsToHighlight: Section[] = []\n let childrenSectionsToUnhighlight: Section[] = []\n\n for (const childSection of section.childrenSections) {\n const childSections = findAllSectionsToHighlightOrUnhighlight(childSection)\n\n for (const childSection of childSections[0]) {\n childrenSectionsToHighlight.push(childSection)\n }\n\n for (const childSection of childSections[1]) {\n childrenSectionsToUnhighlight.push(childSection)\n }\n }\n\n if (childrenSectionsToHighlight.length > 0) {\n return [childrenSectionsToHighlight.concat([section]), childrenSectionsToUnhighlight]\n } else {\n if (section.isIntersecting) {\n return [[section], childrenSectionsToUnhighlight]\n } else {\n return [[], childrenSectionsToUnhighlight.concat([section])]\n }\n }\n }\n}\n\nfunction getCriticalPathToSection(section: Section): Section[] {\n if (section.parentSection == undefined) {\n return [section]\n }\n return getCriticalPathToSection(section.parentSection).concat([section])\n}\n\n\nfunction printSectionsTree(section: Section, debth: number = 0) {\n\n let spacesToPrint = \"\"\n\n let i = 0\n while (i < debth) {\n spacesToPrint = spacesToPrint + \" \"\n i++\n }\n\n // console.log(`section: ${spacesToPrint}${section.sectionId} with menu-item ${section.menuItemId}`);\n section.childrenSections.forEach(section => {\n printSectionsTree(section, debth + 2)\n })\n}\n\nfunction getAllDuplicateIds() { \n // @ts-ignore\n const elements = [...document.querySelectorAll('[id]')]; \n const ids = elements.map(el => el.id); \n const dups = elements.filter(el => ids.filter(id => id === el.id).length > 1); \n \n return dups; \n}\n\n// printSectionsTree(rootSection)\n// console.log(getAllDuplicateIds())\n// checkExistenceOfAllElementsForSectionsAndMenuItems(rootSection) // TODO: rethink this, not needed for runtime functionality but catches missing HTML ids\n\n\n\nconst allSections = getAllSectionAsArrayList(rootSection)\nconst allSectionElements = getAllSectionElements(rootSection)\n\ndocument.addEventListener(\"DOMContentLoaded\", function(event) {\n\n mixpanel.track('Page View')\n\n setupClicks()\n\n createScrollingVisibilityObserver(Array.from(allSectionElements), (entries, observer) => {\n\n entries.forEach(entry => {\n const entrySection = allSections.find(section => {\n if (section.sectionId == entry.target.id) {\n return true\n } else {\n return false\n }\n })\n if (entrySection) {\n entrySection.isIntersecting = entry.isIntersecting\n if (entry.rootBounds) {\n entrySection.yRelativeToRoot = entry.intersectionRect.top\n }\n }\n })\n\n const rootRect = entries[0].rootBounds ?? DOMRectReadOnly.fromRect(new DOMRect())\n\n const findAllSectionsToHighlightOrUnhighlightResult = findAllSectionsToHighlightOrUnhighlight(rootSection)\n const highlightSections = findAllSectionsToHighlightOrUnhighlightResult[0]\n\n highlightSections.filter(section => { // NOTE: get only leaf nodes\n return section.childrenSections.length == 0\n }).forEach(section => {\n const rootYCenter = (rootRect.top + rootRect.bottom) / 2\n const distance = rootYCenter - section.yRelativeToRoot\n // console.log(`highlightSection leaf: ${section.sectionId} | ${section.yCenterRelativeToRoot} | ${distance}`);\n })\n \n allSections.forEach(section => {\n const sectionMenuItem = document.getElementById(section.menuItemId)\n if (sectionMenuItem) {\n sectionMenuItem.classList.remove('text-blue-400')\n }\n })\n\n if (highlightSections.length > 0) {\n showHoveringTableOfContents()\n\n const theOneLeafSectionToHighlight = highlightSections/*.filter(section => { // NOTE: get only leaf nodes\n return section.childrenSections.length == 0\n })*/.reduce((previousSection, currentSection) => { // NOTE: on a second thought, don't know why we need this.... \n\n const previousSectionElementRect = document.getElementById(previousSection.sectionId)?.getBoundingClientRect()\n const currentSectionElementRect = document.getElementById(currentSection.sectionId)?.getBoundingClientRect()\n if (previousSectionElementRect && currentSectionElementRect) {\n\n if (currentSectionElementRect.y < currentSectionElementRect.y) {\n return currentSection\n } else {\n return previousSection\n }\n\n } else {\n return previousSection\n }\n })\n\n mixpanel.track('scrolled_to_section', {\n section_id: theOneLeafSectionToHighlight.sectionId\n })\n \n const criticalSectionPath = getCriticalPathToSection(theOneLeafSectionToHighlight)\n\n criticalSectionPath.forEach(section => {\n const sectionMenuItem = document.getElementById(section.menuItemId)\n if (sectionMenuItem) {\n sectionMenuItem.scrollIntoView({ behavior: \"auto\", block: \"nearest\" }) // NOTE: behavior: \"smooth\" option doesn't work, likely because there are too many scrolling animations happening at the same time.\n sectionMenuItem.classList.add('text-blue-400')\n }\n })\n } else {\n hideHoveringTableOfContents()\n }\n \n })\n})\n\nfunction createScrollingVisibilityObserver(elements: Element | Element[], callback: IntersectionObserverCallback) {\n const observer = new IntersectionObserver(callback, {\n root: null,\n threshold: [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0]\n })\n\n if (elements instanceof Element) {\n observer.observe(elements)\n } else {\n elements.forEach((element) => {\n observer.observe(element)\n })\n }\n}\n\nconst sidebarTableOfContents = document.getElementById(\"sidebar-table-of-contents\") as HTMLElement\n\nfunction showHoveringTableOfContents() {\n sidebarTableOfContents.classList.add('transition-all', 'duration-1000', 'ease-in-out') \n sidebarTableOfContents.classList.remove('opacity-0');\n sidebarTableOfContents.classList.add('opacity-100');\n}\n\nfunction hideHoveringTableOfContents() {\n sidebarTableOfContents.classList.remove('opacity-100');\n sidebarTableOfContents.classList.add('opacity-0');\n}\n\nfunction setupClicks() {\n mixpanel.track_links(\"a\", \"Click Link\")\n}","// NOTE: this is a duplicate of what is Asset Pipeline JS folder\nimport * as $ from 'jquery'\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // Select all links with hashes\n $('a[href*=\"#\"]')\n // Remove links that don't actually link to anything\n .not('[href=\"#\"]')\n .not('[href=\"#0\"]')\n .on('click', function(event) {\n event.preventDefault();\n // On-page links\n if (\n location.pathname.replace(/^\\//, '') == this.pathname.replace(/^\\//, '') \n && \n location.hostname == this.hostname\n ) {\n // Figure out element to scroll to\n var target = $(this.hash);\n target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');\n // Does a scroll target exist?\n if (target.length) {\n // Only prevent default if animation is actually gonna happen\n event.preventDefault();\n $('html, body').animate({\n scrollTop: target.offset().top\n }, 1000, function() {\n // Callback after animation\n });\n }\n }\n });\n})\n\n","// NOTE: this is a duplicate of what is Asset Pipeline JS folder\nimport * as $ from 'jquery'\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n // execute this after google analytics tracker has loaded\n // ga(function(tracker) {\n // $('.gumroad-button').click(function(event) {\n // tracker.send({\n // hitType: 'event',\n // eventCategory: 'Buy Button',\n // eventAction: 'Click',\n // eventLabel: 'Gumroad Button'\n // });\n // });\n // });\n\n\n // google ads signup tracking upon convertkit sign up button click\n $('#ck_subscribe_button').click(function(event) {\n gtag_report_signup_conversion();\n });\n\n})","import mixpanel from 'mixpanel-browser';\n\nconst shouldDebug = process.env.NODE_ENV === \"development\"\n\n// TODO: move this key to an ENV variable\nvar mixpanelToken = 'development'\nif (process.env.NODE_ENV === \"production\") {\n mixpanelToken = 'd7e440af2190abfd91a52de5b55ea110'\n}\n\nmixpanel.init(mixpanelToken, { debug: shouldDebug }); "],"names":["Section","sectionId","this","parentSection","length","internalSectionId","menuItemId","constructor","childrenSections","forEach","subsection","rootSection","mapJSONStructureOfContentToSectionViewModels","jsonStructureOfContent","section","name","children","map","childJSON","undefined","getAllSectionAsArrayList","childSection","childSections","push","concat","findAllSectionsToHighlightOrUnhighlight","isIntersecting","childrenSectionsToHighlight","childrenSectionsToUnhighlight","getCriticalPathToSection","allSections","allSectionElements","sectionElement","document","getElementById","Error","addEventListener","event","mixpanel","elements","callback","observer","IntersectionObserver","root","threshold","Element","observe","element","createScrollingVisibilityObserver","Array","from","entries","entry","entrySection","find","target","id","rootBounds","yRelativeToRoot","intersectionRect","top","rootRect","DOMRectReadOnly","fromRect","DOMRect","highlightSections","filter","bottom","sectionMenuItem","classList","remove","sidebarTableOfContents","add","theOneLeafSectionToHighlight","reduce","previousSection","currentSection","previousSectionElementRect","getBoundingClientRect","currentSectionElementRect","y","section_id","scrollIntoView","behavior","block","$","not","on","preventDefault","location","pathname","replace","hostname","hash","slice","animate","scrollTop","offset","click","gtag_report_signup_conversion","mixpanelToken","debug","process"],"sourceRoot":""}