PageSourceSearch

https://homezero.ai/js/hz-video.js

js homezero.ai collected 2026-10-05 16:08:57 UTC 3,534 bytes, 106 lines download raw bytes

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.