-- ============================================================================== -- CV Site - Hyperscript Functions -- ============================================================================== -- Global hyperscript functions for CV interactive features -- Keeps HTML templates clean and behavior organized -- ============================================================================== -- PRINT FUNCTIONS -- ============================================================================== def printFriendly() -- Store current state set container to the first .cv-container set paper to the first .cv-paper set wasClean to container.classList.contains('theme-clean') set wasLong to paper.classList.contains('cv-long') set currentZoom to localStorage.getItem('cv-zoom') or '100' -- Apply print-friendly settings if wasClean is false add .theme-clean to container end remove .cv-long from paper add .cv-short to paper -- Reset zoom for consistent printing set #zoom-wrapper's *zoom to 1 -- Let CSS apply, then print wait 50ms call window.print() -- Wait for print dialog to close, then restore wait 100ms -- Restore original theme if wasClean is false remove .theme-clean from container end -- Restore original length if wasLong is true remove .cv-short from paper add .cv-long to paper end -- Restore original zoom by triggering slider input event if currentZoom is not '100' set #zoom-slider's value to currentZoom send input to #zoom-slider end end -- ============================================================================== -- SCROLL BEHAVIOR -- ============================================================================== def initScrollBehavior() set :lastScroll to 0 set :scrollThreshold to 100 set :keepHeaderVisible to false end def handleScroll() set currentScroll to window.pageYOffset set menu to the first .navigation-menu set isMenuOpen to menu.classList.contains('menu-open') -- Calculate if at bottom (within 50px) set scrollHeight to the document's documentElement's scrollHeight set clientHeight to the document's documentElement's clientHeight set isAtBottom to (scrollHeight - currentScroll - clientHeight) < 50 -- Reset keepHeaderVisible when scrolling up if currentScroll < :lastScroll set :keepHeaderVisible to false end -- Header visibility: Scrolling down past threshold if currentScroll > :scrollThreshold and currentScroll > :lastScroll and :keepHeaderVisible is false add .header-hidden to .action-bar if isMenuOpen is true add .header-hidden to menu end end -- Header visibility: Scrolling up past threshold if currentScroll > :scrollThreshold and (currentScroll <= :lastScroll or :keepHeaderVisible is true) remove .header-hidden from .action-bar if isMenuOpen is true remove .header-hidden from menu end end -- Header visibility: At top if currentScroll <= :scrollThreshold remove .header-hidden from .action-bar if isMenuOpen is true remove .header-hidden from menu end end -- Back to top button visibility (with null check) set backToTop to #back-to-top if backToTop is not null if currentScroll > 300 set backToTop's *display to 'flex' end if currentScroll <= 300 set backToTop's *display to 'none' end end -- At-bottom class for fixed buttons (with null checks) if isAtBottom if backToTop is not null then add .at-bottom to backToTop end if #info-button is not null then add .at-bottom to #info-button end if #shortcuts-button is not null then add .at-bottom to #shortcuts-button end if #download-button is not null then add .at-bottom to #download-button end if #print-friendly-button is not null then add .at-bottom to #print-friendly-button end if #cmd-k-button is not null then add .at-bottom to #cmd-k-button end add .at-bottom to .color-theme-switcher if #zoom-toggle-button is not null then add .at-bottom to #zoom-toggle-button end end if not isAtBottom if backToTop is not null then remove .at-bottom from backToTop end if #info-button is not null then remove .at-bottom from #info-button end if #shortcuts-button is not null then remove .at-bottom from #shortcuts-button end if #download-button is not null then remove .at-bottom from #download-button end if #print-friendly-button is not null then remove .at-bottom from #print-friendly-button end if #cmd-k-button is not null then remove .at-bottom from #cmd-k-button end remove .at-bottom from .color-theme-switcher if #zoom-toggle-button is not null then remove .at-bottom from #zoom-toggle-button end end -- Update last scroll position set :lastScroll to currentScroll end -- ============================================================================== -- EXPAND/COLLAPSE ALL SECTIONS -- ============================================================================== -- Expand all
elements in the CV def expandAllSections(evt) if evt then call evt.preventDefault() end set details to
for d in details set d's @open to '' end end -- Collapse all
elements in the CV def collapseAllSections(evt) if evt then call evt.preventDefault() end set details to
for d in details call d.removeAttribute('open') end end -- ============================================================================== -- FOOTER HOVER INTERACTION -- ============================================================================== -- Adds/removes footer-hovered class to fixed buttons when hovering footer def setFooterHover(show) set buttons to <.download-btn, .print-friendly-btn, .shortcuts-btn, .info-button, .back-to-top, .color-theme-switcher/> for btn in buttons if show add .footer-hovered to btn else remove .footer-hovered from btn end end end -- ============================================================================== -- MODAL HELPERS -- ============================================================================== -- Close modal when clicking backdrop (outside content) def closeOnBackdrop(modal, evt) if evt.target is modal call modal.close() end end -- ============================================================================== -- SCROLL HELPERS -- ============================================================================== -- Smooth scroll to top of page def scrollToTop(evt) call evt.preventDefault() call window.scrollTo({top: 0, behavior: 'smooth'}) end -- ============================================================================== -- NAVIGATION SCROLL -- ============================================================================== -- Smooth scroll to a section by ID def scrollToSection(evt, sectionId) if evt then call evt.preventDefault() end set el to #{sectionId} if el is not null call el.scrollIntoView({ behavior: 'smooth' }) -- Close the menu after navigation set menu to the first .navigation-menu if menu is not null remove .menu-hover from menu remove .menu-open from menu end end end -- ============================================================================== -- KEYBOARD SHORTCUTS -- ============================================================================== -- Note: Keyboard event handlers are now defined inline in the body tag -- because hyperscript 0.9.12 doesn't support nested event handlers (on ... inside def)