1/* ===================================================================== 2 mymind.com â static site behaviour 3 --------------------------------------------------------------------- 4 Everything the Semplice theme runtime used to do for these pages, rewritten without jQuery: 5 1. page reveal on load (navbar slides in, content fades in) and fade-out on internal link clicks 6 2. sticky navbar (adds .is-sticky once the page is scrolled) + the --vh custom property 7 3. hamburger / overlay menu open & close (with the staggered menu items) 8 4. "motion" animations from Semplice's editor (GSAP + ScrollTrigger; data comes from mm.motion([...]) at the end of each page) 9 5. Lottie modules (lottie-web) sized like Semplice did, played when scrolled into view 10 6. lightbox for images marked .semplice-lightbox (PhotoSwipe 4, only loaded on pages that use it) 11 7. YouTube lightbox: mm.videoLightbox({videos, triggers, exclude}) â the video links on /, /adhd, /mobile and /videos 12 open the embed in a lightbox on top of the page (replaces the pages' former jQuery scripts) 13 Dependencies: js/vendor/gsap.min.js + ScrollTrigger.min.js (always); lottie.min.js / photoswipe (per page). 14 ===================================================================== */ 15window.mm = (function () { 16 'use strict'; 17 var $ = function (sel, ctx) { return (ctx || document).querySelector(sel); }; 18 var $$ = function (sel, ctx) { return Array.prototype.slice.call((ctx || document).querySelectorAll(sel)); }; 19 var nav = $('.semplice-navbar'); 20 var overlay = $('#overlay-menu'); 21 var holder = $('#content-holder'); 22 var content = $('.content-container'); 23 var hamburger = $('.hamburger'); 24 var mm = { lottie: {}, gsap: {} }; 25 if (window.gsap && window.ScrollTrigger) gsap.registerPlugin(ScrollTrigger); 26 27 /* ---------- helpers ---------- */ 28 function rgba(str) { // "rgb(255, 255, 255)" / "rgba(...)" â {r,g,b,a} 29 var m = (str || '').match(/[\d.]+/g) || [0, 0, 0, 0]; 30 return { r: +m[0] || 0, g: +m[1] || 0, b: +m[2] || 0, a: m.length > 3 ? +m[3] : 1 }; 31 } 32 function isExternal(href) { 33 if (href.indexOf(':') < 0 && href.indexOf('//') < 0) return false; 34 var a = document.createElement('a'); a.href = href; 35 return a.host !== location.host; 36 } 37 38 /* ---------- 1. page reveal / page change ---------- */ 39 function revealPage() { // pages without a navbar (e.g. /inactive-account-policy) still fade their content in 40 if (!window.gsap) return; 41 if (nav && !nav.classList.contains('non-sticky-nav')) { 42 gsap.to(nav, 0.8, { y: 0, ease: 'expo.out', clearProps: 'y', onComplete: function () { nav.style.transform = 'none'; nav.style.transition = ''; } }); 43 } else if (nav) nav.style.transform = 'translateY(0)'; 44 if (content) gsap.to(content, 0.6, { opacity: 1, ease: 'sine.out' }); 45 } 46 function leavePage(url) { // Semplice "static transitions": navbar up, page fades out, then navigate 47 if (nav && !$('.no-menu-transition')) { nav.style.transition = 'none'; gsap.to(nav, 0.7, { yPercent: -100, ease: 'expo.inOut' }); } 48 gsap.to(holder, 0.6, { opacity: 0, ease: 'sine.out', onComplete: function () { window.location = url; } }); 49 } 50 document.addEventListener('click', function (e) { 51 var a = e.target.closest('a'); 52 if (!a || e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return; 53 if (a.classList.contains('semplice-event')) return; 54 var href = a.getAttribute('href'); 55 if (a.getAttribute('target') === '_blank' || href === null || href === '') return; 56 if (isExternal(href) || href.charAt(0) === '#' || href.indexOf('#') > -1 || href.indexOf('replyto') > -1 || /^(mailto|tel|javascript):/.test(href)) return; 57 e.preventDefault(); 58 leavePage(a.href); 59 }); 60 61 /* ---------- 2. sticky navbar + --vh (site custom JS) ---------- */ 62 var pageTop = holder ? holder.offsetTop : 0; 63 var headerEl = $('.sticky-nav'); 64 window.addEventListener('scroll', function () { 65 var y = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop; 66 if (!headerEl) return; 67 if (y > pageTop) headerEl.classList.add('is-sticky'); else headerEl.classList.remove('is-sticky'); 68 }); 69 window.addEventListener('resize', function () { 70 var vh = window.innerHeight * 0.01; 71 document.documentElement.style.setProperty('--vh', vh + 'px'); 72 }); 73 74 /* ---------- 3. overlay menu ---------- */ 75 var menu = { 76 inner: function () { return $('.overlay-menu-inner nav'); }, 77 responsiveOverlay: function () { 78 var h = $('header') ? $('header').offsetHeight : 0, n = menu.inner(); 79 if (!n) return; 80 if (2 * h + (n.offsetHeight + 40) >= window.innerHeight) { n.classList.add('align-top'); n.style.top = (h + 40) + 'px'; } 81 else { n.classList.remove('align-top'); n.style.top = ''; } 82 }, 83 navbarBg: function (visibility) { 84 var t = visibility === 'visible' ? menu.rgba.a : 0; 85 nav.style.backgroundColor = 'rgba(' + menu.rgba.r + ', ' + menu.rgba.g + ', ' + menu.rgba.b + ', ' + t + ')'; 86 }, 87 open: function (el) { 88 hamburger.setAttribute('disabled', 'disabled'); hamburger.setAttribute('data-status', 'open'); 89 el.classList.remove('open-menu'); el.classList.add('close-menu'); 90 menu.rgba = rgba(getComputedStyle(nav).backgroundColor); 91 menu.navbarBg(nav.getAttribute('data-bg-overlay-visibility')); 92 gsap.killTweensOf(overlay); overlay.style.display = 'block'; overlay.style.zIndex = '119'; 93 gsap.to(overlay, 0.35, { opacity: 1, onComplete: menu.afterOpen }); 94 setTimeout(function () { menu.showItems($$('.overlay-menu-inner nav ul li')); }, 50); 95 }, 96 afterOpen: function () { 97 var innerEl = $('.overlay-menu-inner'); 98 innerEl.parentNode.insertBefore(nav, innerEl); nav.style.position = 'absolute'; 99 var before = window.innerWidth; document.body.classList.add('open-menu'); var after = window.innerWidth; 100 holder.style.width = (100 * before / after) + '%'; 101 hamburger.removeAttribute('disabled'); 102 }, 103 showItems: function (items) { 104 var t = 0;
105 items.forEach(function (li) { 106 li.classList.add('before-fade'); 107 gsap.to(li, 0.35, { opacity: 1, y: 0, clearProps: 'y', delay: t, onComplete: function () { li.classList.remove('before-fade'); } }); 108 t += 0.08; 109 }); 110 }, 111 close: function (el) { 112 if (hamburger.getAttribute('disabled') === 'disabled') return; 113 var cls = 'open-menu'; if ($('nav.standard')) cls += ' responsive-menu'; 114 hamburger.setAttribute('disabled', 'disabled'); hamburger.setAttribute('data-status', 'closed'); 115 el.classList.remove('close-menu'); cls.split(' ').forEach(function (c) { el.classList.add(c); }); 116 menu.navbarBg('visible'); 117 overlay.parentNode.insertBefore(nav, overlay); 118 if ((!nav.classList.contains('non-sticky-nav') && window.innerWidth > 767.9) || nav.classList.contains('use-headroom')) nav.style.position = 'fixed'; 119 document.body.classList.remove('open-menu'); 120 holder.style.width = '100%'; 121 gsap.to(overlay, 0.35, { opacity: 0, onComplete: menu.afterClose }); 122 }, 123 afterClose: function () { 124 overlay.style.zIndex = '-1'; overlay.style.display = 'none'; 125 $$('.overlay-menu-inner nav ul li').forEach(function (li) { li.removeAttribute('style'); }); 126 hamburger.removeAttribute('disabled'); 127 } 128 }; 129 document.addEventListener('click', function (e) { 130 var t = e.target.closest('.semplice-menu'); 131 if (!t || !overlay) return; 132 e.preventDefault(); 133 if (hamburger.getAttribute('data-status') === 'open') menu.close($('.close-menu')); else menu.open($('.open-menu')); 134 }); 135 window.addEventListener('hashchange', function () { if (document.body.classList.contains('open-menu')) menu.close($('.close-menu')); }); 136 window.addEventListener('pageshow', function (e) { if (e.persisted) window.location.reload(); }); 137 138 /* ---------- 4. motion (Semplice editor animations) ---------- */ 139 function motion(items) { 140 if (!window.gsap) return; 141 items.forEach(function (it) { 142 var opts = { repeat: it.repeat || 0 }; 143 if (it.yoyo) opts.yoyo = true; 144 if (it.scroll) opts.scrollTrigger = it.scroll; 145 if (it.scrub) opts.scrollTrigger = it.scrub; 146 if (it.lottieScrub) { // Semplice "on scroll" Lottie: the frame follows the scroll progress 147 var lid = it.lottieScrub; 148 opts.scrollTrigger = Object.assign({}, it.scrub, { onUpdate: function (self) { 149 var a = mm.lottie[lid]; if (a && a.totalFrames) a.goToAndStop(Math.floor(self.progress * (a.totalFrames - 1)), true); 150 } }); 151 } 152 if (it.lottie) opts.onStart = function () { if (mm.lottie[it.lottie]) mm.lottie[it.lottie].play(); }; 153 var tl = gsap.timeline(opts); 154 mm.gsap[it.id] = tl; 155 (it.set || []).forEach(function (s) { gsap.set(s[0], s[1]); }); 156 (it.to || []).forEach(function (s) { tl.to(s[0], s[1]); }); 157 tl.pause(); 158 if (it.hover) { 159 var playing = false; 160 document.addEventListener('mouseover', function (e) { if (e.target.closest(it.hover) && !playing) { playing = true; tl.play(); } }); 161 document.addEventListener('mouseout', function (e) { 162 var el = e.target.closest(it.hover); 163 if (el && playing && !(e.relatedTarget && el.contains(e.relatedTarget))) { playing = false; tl.reverse(); } 164 }); 165 } 166 }); 167 window.dispatchEvent(new Event('scroll')); 168 } 169 170 /* ---------- 5. Lottie ---------- */ 171 function bool(v) { return v === 'true' ? true : v === 'false' ? false : v; } 172 function contentWidth(el) { // like jQuery's .width(): fractional content-box width 173 var cs = getComputedStyle(el); return el.getBoundingClientRect().width - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight) - parseFloat(cs.borderLeftWidth) - parseFloat(cs.borderRightWidth); 174 } 175 function initLottie() { 176 $$('.lottie-holder[data-lottie]').forEach(function (h) { 177 var id = h.id.replace(/_lottie$/, ''), module = document.getElementById(id); 178 var opts = JSON.parse(h.getAttribute('data-lottie-options') || '{}'); 179 var w = +h.getAttribute('data-lottie-width'), hh = +h.getAttribute('data-lottie-height'); 180 var p = { width: 'grid', custom_width: 570, justify: 'left', event: 'on_load', loop: false, speed: 1 }
180, custom = false, type = 'grid'; 181 Object.keys(p).forEach(function (k) { 182 if (opts[k] === undefined) return; 183 var s = bool(opts[k]); 184 if (k === 'speed') s = s / 10; 185 if (k === 'width' && s === 'custom') { custom = true; type = 'custom'; } 186 p[k] = s; 187 }); 188 var ratio = (hh / w).toFixed(2), mw = contentWidth(module), a; 189 if (custom && mw >= parseInt(p.custom_width)) a = parseInt(p.custom_width); else a = mw; 190 var height = Math.round(ratio * a); 191 $('.semplice-lottie', module).style.justifyContent = { left: 'flex-start', center: 'center', right: 'flex-end' }[p.justify]; 192 h.style.width = a + 'px'; h.style.height = height + 'px'; 193 h.setAttribute('data-width-type', type); h.setAttribute('data-ratio', ratio); h.setAttribute('data-custom-width', p.custom_width); 194 mm.lottie[id] = lottie.loadAnimation({ container: h, renderer: 'svg', loop: p.loop, autoplay: false, path: h.getAttribute('data-lottie'), rendererSettings: { className: id + '_lottie_styles', viewBoxOnly: true } }); 195 mm.lottie[id].setSpeed(p.speed); 196 var style = document.createElement('style'); style.textContent = '.' + id + '_lottie_styles{width:100%;height:auto;max-width:100%}'; document.head.appendChild(style); 197 }); 198 } 199 function resizeLottie() { 200 $$('.lottie-holder').forEach(function (h) { 201 var t = h.getAttribute('data-width-type'), s = parseInt(h.getAttribute('data-custom-width')), n = parseFloat(h.getAttribute('data-ratio')); 202 var o = contentWidth(h.closest('.column-content')), e = s; 203 if (t !== 'custom' || o < e) e = o; 204 h.style.width = e + 'px'; h.style.height = Math.round(n * e) + 'px'; 205 }); 206 } 207 208 /* ---------- 6. lightbox ---------- */ 209 function initLightbox() { 210 var items = $$('.lightbox-item'); 211 items.forEach(function (img, i) { img.setAttribute('data-photoswipe-index', i); }); 212 if (!items.length || !window.PhotoSwipe) return; 213 holder.addEventListener('click', function (e) { 214 var a = e.target.closest('.semplice-lightbox'); 215 if (!a) return; 216 var index = parseInt($('img', a).getAttribute('data-photoswipe-index')); 217 var pswp = $('.pswp'), slides = $$('.lightbox-item').map(function (el) { 218 return { src: el.getAttribute('src'), w: el.getAttribute('width'), h: el.getAttribute('height'), msrc: el.getAttribute('src'), title: el.getAttribute('caption') || '' }; 219 }); 220 mm.gallery = new PhotoSwipe(pswp, PhotoSwipeUI_Default, slides, { 221 index: index, history: false, shareEl: false, 222 getThumbBoundsFn: function (i) { var el = $$('.lightbox-item')[i], t = window.pageYOffset || document.documentElement.scrollTop, r = el.getBoundingClientRect(); return { x: r.left, y: r.top + t, w: r.width }; } 223 }); 224 mm.gallery.init(); 225 }); 226 } 227 228 /* ---------- 7. YouTube lightbox ---------- */ 229 var CLOSE_ICON = '<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M0.376009 17.808C-0.125336 18.3093 -0.125336 19.1221 0.376009 19.6235C0.877355 20.1248 1.6902 20.1248 2.19154 19.6235L9.99973 11.8155L17.8085 19.624C18.3098 20.1253 19.1226 20.1253 19.624 19.624C20.1253 19.1227 20.1253 18.3098 19.624 17.8085L11.8153 10L19.624 2.19148C20.1253 1.69015 20.1253 0.877331 19.624 0.375999C19.1226 -0.125333 18.3098 -0.125334 17.8085 0.375999L9.99973 8.18452L2.19154 0.376547C1.6902 -0.124785 0.877355 -0.124785 0.376009 0.376547C-0.125336 0.877879 -0.125336 1.6907 0.376009 2.19203L8.18419 10L0.376009 17.808Z"/></svg>'; 230 function videoLightbox(o) { 231 var videos = o.videos || {}, box = null; 232 function open(id) { 233 if (!videos[id]) return; 234 close(true); 235 box = document.createElement('div'); box.className = 'mm-lightbox'; box.setAttribute('role', 'dialog'); box.setAttribute('aria-modal', 'true'); 236 box.innerHTML = '<div class="mm-lightbox-frame"><iframe src="https://www.youtube.com/embed/' + videos[id] + '?autoplay=1" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>' + 237 '<button class="mm-lightbox-close" type="button" aria-label="Close video">' + CLOSE_ICON + '</button>'; 238 document.body.appendChild(box); document.body.style.overflow = 'hidden'; 239 requestAnimationFrame(function () { requestAnimationFrame(function () { box.classList.add('is-open'); }); }); 240 if (window.location.hash !== '#' + id) history.replaceState(null, document.title, window.location.pathname + window.location.search + '#' + id); 241 } 242 function close(silent) { 243 if (!box) return; 244 var b = box; box = null; b.classList.remove('is-open'); 245 setTimeout(function () { if (b.parentNode) b.parentNode.removeChild(b); }, 200); 246 document.body.style.overflow = ''; 247 if (!silent) history.replaceState(null, document.title, window.location.pathname + window.location.search); 248 } 249 document.addEventListener('click', function (e) { 250 if (box && (e.target.closest('.mm-lightbox-close') || (e.target.closest('.mm-lightbox') && !e.target.closest('.mm-lightbox-frame')))) { close(); return; } 251 var t = e.target.closest(o.triggers); 252 if (!t || (o.exclude && e.target.closest(o.exclude))) return; 253 var id = (t.className.match(/(?:^|\s)videoid-(\S+)/) || [])[1]; 254 if (!id) return; 255 e.preventDefault(); open(id); 256 }); 257 document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); }); 258 var id0 = window.location.hash.replace('#', ''); 259 if (id0 && videos[id0]) open(id0); 260 } 261 262 /* ---------- init ---------- */
263 function init() { 264 if (nav && overlay) menu.responsiveOverlay(); 265 revealPage(); 266 if (window.lottie) initLottie(); 267 initLightbox(); 268 window.addEventListener('resize', function () { 269 if (overlay) menu.responsiveOverlay(); 270 document.body.style.height = window.innerHeight + 'px'; 271 resizeLottie(); 272 }); 273 } 274 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); 275 mm.motion = motion; mm.menu = menu; mm.videoLightbox = videoLightbox; 276 return mm; 277})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.