PageSourceSearch

https://www.brotherssupply.com/wp-content/plugins/hozio-studio/components/nap/nap.js?ver=9be0dea0619a

js brotherssupply.com collected 2026-10-09 00:30:23 UTC 5,664 bytes, 113 lines download raw bytes

1/* ═══════════════════════════════════════════════════════════════════════════
2   LocalBusiness NAP Block (W-001) — progressive-enhancement behavior.
3
4   The card, the hours <dl>, and the canonical JSON-LD are ALL server-rendered
5   and fully functional without this file (progressive enhancement). nap.js adds
6   exactly two additive layers, both guarded so a load failure degrades to the
7   static card:
8
9     1. OPEN-NOW PILL — a guarded CONSUMER of the shared hzo.hours model (W-002).
10        It NEVER re-parses hours (Part 0 rule 3): it reads hzo.hours.state()/today()
11        and re-syncs on the reserved `hzo:hourschange` event, toggling the
12        .hzo-nap__status pill (words carry meaning, not color) and marking today's
13        <dl> row [aria-current]. Absent hours model → no pill; the static <dl>
14        still renders. NAP produces NO hzo:* event of its own.
15
16     2. MEASUREMENT ADAPTER — the fleet's highest-value untracked action. Mirrors a
17        `tel:` tap inside any [data-hzo-nap] to dataLayer as `phone_call`. Hooks the
18        DOM anchor directly (NAP emits no internal event to mirror).
19
20   Reveal is NOT handled here — the shared .hzo-reveal hook (main.js) owns it. This
21   file is idempotent (guarded by data-hzo-nap-ready) and reduced-motion safe (it
22   only toggles classes/text; the pill's transition is killed in CSS under reduce).
23   ═══════════════════════════════════════════════════════════════════════════ */
24(function () {
25    'use strict';
26
27    window.hzo = window.hzo || {};
28
29    function __(s) {
30        return (window.wp && wp.i18n && wp.i18n.__) ? wp.i18n.__(s, 'hozio-studio') : s;
31    }
32
33    // ── Open-now pill ──────────────────────────────────────────────────────────
34    // Reflect the current hours state onto every NAP card's pill + today's row.
35    function reflect(root) {
36        if (!(window.hzo && window.hzo.hours)) { return; } // model absent → leave static <dl>
37        var pill = root.querySelector('[data-hzo-nap-status]');
38        var state, today;
39        try {
40            state = window.hzo.hours.state();
41            today = window.hzo.hours.today();
42        } catch (e) { return; }
43
44        if (pill) {
45            var open = state !== 'closed';
46            pill.classList.toggle('is-open', open);
47            pill.classList.toggle('is-closed', !open);
48            pill.textContent = open ? __('Open now') : __('Closed');
49            pill.hidden = false;
50        }
51
52        // Mark today's <dl> row (match the <dt> whose day matches today.day).
53        if (today && today.day) {
54            var wanted = String(today.day).slice(0, 3).toLowerCase();
55            var dts = root.querySelectorAll('.hzo-hours dt');
56            for (var i = 0; i < dts.length; i++) {
57                var isToday = dts[i].textContent.slice(0, 3).toLowerCase() === wanted;
58                if (isToday) { dts[i].setAttribute('aria-current', 'true'); }
59                else { dts[i].removeAttribute('aria-current'); }
60            }
61        }
62    }
63
64    function reflectAll() {
65        var roots = document.querySelectorAll('[data-hzo-nap]');
66        for (var i = 0; i < roots.length; i++) { reflect(roots[i]); }
67    }
68
69    // ── Measurement: tel: tap → dataLayer phone_call ───────────────────────────
70    // Delegated + idempotent (bound once). Desktop tel: no-ops silently, so the
71    // number is ALSO visible selectable text in the card (server-rendered) — this
72    // only measures the intent, it is not the fallback.
73    function bindMeasurement() {
74        if (window.hzo.__napMeasureBound) { return; }
75        window.hzo.__napMeasureBound = true;
76        document.addEventListener('click', function (e) {
77            var a = e.target && e.target.closest ? e.target.closest('[data-hzo-nap] a[href^="tel:"]') : null;
78            if (!a) { return; }
79            window.dataLayer = window.dataLayer || [];
80            window.dataLayer.push({
81                event: 'phone_call',
82                phone_number: a.getAttribute('href').replace(/^tel:/, ''),
83                source: 'nap'
84            });
85        }, true);
86    }
87
88    // ── Init (idempotent) ──────────────────────────────────────────────────────
89    function init() {
90        var roots = document.querySelectorAll('[data-hzo-nap]:not([data-hzo-nap-ready])');
91        if (roots.length) {
92            for (var i = 0; i < roots.length; i++) { roots[i].setAttribute('data-hzo-nap-ready', ''); }
93        }
94        bindMeasurement();
95        reflectAll();
96    }
97
98    // Re-sync the pill whenever the shared model flips open/after-hours state.
99    // Guarded + bound once; NAP is a consumer, never a producer, of this event.
100    if (!window.hzo.__napHoursBound) {
101        window.hzo.__napHoursBound = true;
102        document.addEventListener('hzo:hourschange', reflectAll);
103    }
104
105    // Expose for AJAX-injected instances (mirrors the widget convention).
106    window.hzo.nap = { init: init, reflect: reflect };
107
108    if (document.readyState === 'loading') {
109        document.addEventListener('DOMContentLoaded', init);
110    } else {
111        init();
112    }
113})();

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.