1/* HomeZero on-brand native video player. 2 * - Autoplays muted when scrolled into view (IntersectionObserver). 3 * - Pauses when scrolled away. 4 * - Click anywhere to play/pause. 5 * - "Tap for sound" pill toggles mute. Disappears once user has unmuted. 6 */ 7(function () { 8 function init(wrap) { 9 if (wrap.dataset.hzInit === "1") return; 10 wrap.dataset.hzInit = "1"; 11 12 var video = wrap.querySelector("video"); 13 if (!video) return; 14 15 var soundBtn = wrap.querySelector(".hz-video__sound"); 16 var playOverlay = wrap.querySelector(".hz-video__overlay"); 17 18 function refreshSoundIcon() { 19 if (!soundBtn) return; 20 soundBtn.setAttribute("aria-pressed", String(!video.muted)); 21 soundBtn.dataset.muted = video.muted ? "1" : "0"; 22 } 23 function refreshPlayIcon() { 24 wrap.dataset.playing = video.paused ? "0" : "1"; 25 } 26 27 refreshSoundIcon(); 28 refreshPlayIcon(); 29 30 // Toggle play/pause when clicking the video area (but not the sound button). 31 wrap.addEventListener("click", function (e) { 32 if (e.target.closest(".hz-video__sound")) return; 33 if (video.paused) { 34 video.play().catch(function () {}); 35 } else { 36 video.pause(); 37 } 38 }); 39 40 if (soundBtn) { 41 soundBtn.addEventListener("click", function (e) { 42 e.stopPropagation(); 43 video.muted = !video.muted; 44 if (!video.muted) { 45 wrap.dataset.unmuted = "1"; 46 video.play().catch(function () {}); 47 } 48 refreshSoundIcon(); 49 }); 50 } 51 52 video.addEventListener("play", refreshPlayIcon); 53 video.addEventListener("pause", refreshPlayIcon); 54 video.addEventListener("volumechange", refreshSoundIcon); 55 56 // Autoplay (muted) when in view, pause when out. 57 if ("IntersectionObserver" in window) { 58 var io = new IntersectionObserver(function (entries) { 59 entries.forEach(function (entry) { 60 if (entry.intersectionRatio >= 0.5) { 61 // Only autoplay-mute if user has not explicitly unmuted. 62 if (wrap.dataset.unmuted !== "1") video.muted = true; 63 video.play().catch(function () {}); 64 } else if (entry.intersectionRatio < 0.15) { 65 video.pause(); 66 } 67 }); 68 }, { threshold: [0, 0.15, 0.5, 0.75] }); 69 io.observe(wrap); 70 } else { 71 video.muted = true; 72 video.play().catch(function () {}); 73 } 74 75 // Hide the central play overlay shortly after first play. 76 if (playOverlay) { 77 video.addEventListener("playing", function () { 78 playOverlay.setAttribute("data-state", "hidden"); 79 }); 80 } 81 } 82 83 function scan() { 84 document.querySelectorAll(".hz-video[data-native]").forEach(init); 85 } 86 87 if (document.readyState !== "loading") scan(); 88 else document.addEventListener("DOMContentLoaded", scan); 89 90 // Re-scan when SPA mounts content later. 91 var mo = new MutationObserver(function (muts) { 92 for (var i = 0; i < muts.length; i++) { 93 var added = muts[i].addedNodes; 94 for (var j = 0; j < (added && added.length); j++) { 95 var n = added[j]; 96 if (n.nodeType !== 1) continue; 97 if (n.matches && n.matches(".hz-video[data-native]")) init(n); 98 else if (n.querySelectorAll) n.querySelectorAll(".hz-video[data-native]").forEach(init); 99 } 100 } 101 }); 102 if (document.body) mo.observe(document.body, { childList: true, subtree: true }); 103 else document.addEventListener("DOMContentLoaded", function () { 104 mo.observe(document.body, { childList: true, subtree: true }); 105 }); 106})();
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.