PageSourceSearch

https://www.brotherssupply.com/wp-content/plugins/hozio-studio/com…/pricing-toggle.js?ver=d8345b8f4a7d

js brotherssupply.com collected 2026-10-09 00:31:03 UTC 7,764 bytes, 135 lines download raw bytes

1/* ═════════════════════════════════════════════════════════════════════════
2   PRICING PERIOD TOGGLE — widget behavior (Phase-2 widget system; moved out
3   of main.js "Pricing period toggle — monthly/annual price swap").
4
5   Self-contained, no hard dependencies (uses no main.js primitives). As a
6   shortcode widget the toggle ALWAYS loads: pricing-toggle.php un-gates it
7   via the hzostudio_component_markers filter — [hzo_pricing_toggle] can
8   render from surfaces the loader's post_content scan can't see.
9
10   MARKUP CONTRACT (unchanged from main.js — this is public API; the CSS in
11   pricing-toggle.css and authored pages depend on it):
12     .hzo-price-toggle[data-hzo-price-toggle]     the button-group root
13       > button[data-hzo-price-period="monthly"|"annual"] with aria-pressed
14     [data-hzo-price-group]                       closest ancestor; the
15                                                  choice is mirrored into
16                                                  data-period="…" on it
17     [data-price-monthly] / [data-price-annual]   swapped by the CSS inside
18                                                  the group (monthly is the
19                                                  default AND the no-JS state)
20
21   Activating a button sets aria-pressed across the group's buttons and
22   data-period on the closest [data-hzo-price-group] ancestor. Init seeds a
23   consistent state — the author-pre-pressed button, else the
24   data-hzo-pricing-toggle-default option, else "monthly" (the no-JS
25   default) — silently (see Events). Real <button>s, so keyboard comes free.
26
27   OPTION CONTRACT — settings are data-attributes on the root, so authored
28   markup and the [hzo_pricing_toggle] shortcode (pricing-toggle.php) drive
29   the SAME behavior. Every option defaults to the legacy value —
30   attribute-free markup behaves exactly as before:
31
32     data-hzo-pricing-toggle-default   period to seed at init when NO button
33                                       is author-pre-pressed (absent =
34                                       "monthly", the legacy/no-JS default).
35                                       A pre-pressed button always wins. The
36                                       shortcode pre-presses the chosen
37                                       button server-side instead (no flash),
38                                       so it never emits this attribute.
39
40   Events (new, additive — the legacy IIFE emitted none): an activation
41   (click or hzo.pricingToggle.set) that CHANGES the period dispatches a
42   bubbling `hzo:periodchange` CustomEvent from the root, detail
43   { period, group }. Init seeding never emits (no phantom listener work on
44   load — parity with the silent legacy seed).
45
46   A11y (APG button / toggle-button group): real <button>s carrying
47   aria-pressed announce their state; role="group" + aria-label live in the
48   markup / are emitted by the shortcode. Nothing here animates — the CSS
49   owns the button transitions and kills them under prefers-reduced-motion —
50   so there is no reduced-motion branch in the JS.
51
52   Public API (the old main.js IIFE exposed no window.hzo names — nothing
53   historical to preserve):
54     hzo.pricingToggle = { init, setup, set }   (init(scope) for AJAX content)
55   ═════════════════════════════════════════════════════════════════════════ */
56(function () {
57    'use strict';
58
59    /* Mirror `period` into aria-pressed across the group's buttons and into
60       data-period on the closest [data-hzo-price-group] ancestor — the exact
61       legacy DOM writes (always run, idempotent). Only the (new) event is
62       gated on an actual change. */
63    function setPeriod(toggle, period, emit) {
64        var btns = toggle.querySelectorAll('[data-hzo-price-period]');
65        var prior = null;
66        for (var i = 0; i < btns.length; i++) {
67            if (btns[i].getAttribute('aria-pressed') === 'true') { prior = btns[i].getAttribute('data-hzo-price-period'); }
68            btns[i].setAttribute('aria-pressed',
69                btns[i].getAttribute('data-hzo-price-period') === period ? 'true' : 'false');
70        }
71        var group = toggle.closest('[data-hzo-price-group]');
72        if (group) { group.setAttribute('data-period', period); }
73        if (emit && prior !== period) {
74            // G36: announce the change through the visually-hidden live status
75            // (the visible prices otherwise swap silently for SR users).
76            var status = toggle.querySelector('[data-hzo-price-toggle-status]');
77            if (status) {
78                var tpl = toggle.getAttribute('data-hzo-price-announce') || 'Showing %s pricing';
79                var sel = toggle.querySelector('[data-hzo-price-period="' + period + '"]');
80                var lbl = sel ? (sel.textContent || period).replace(/^\s+|\s+$/g, '') : period;
81                status.textContent = tpl.replace('%s', lbl);
82            }
83            toggle.dispatchEvent(new CustomEvent('hzo:periodchange', { bubbles: true, detail: { period: period, group: group } }));
84        }
85    }
86
87    // ── Delegated activation — bound ONCE at module scope, so dynamically-
88    //    injected toggles work without setup() (the legacy bound per-toggle at
89    //    load; delegation covers the same clicks plus AJAX-inserted markup).
90    document.addEventListener('click', function (e) {
91        var btn = e.target.closest ? e.target.closest('[data-hzo-price-period]') : null;
92        if (!btn) return;
93        var toggle = btn.closest('[data-hzo-price-toggle]');
94        if (!toggle) return;
95        setPeriod(toggle, btn.getAttribute('data-hzo-price-period'), true);
96    });
97
98    /* Per-instance seeding: the author-pre-pressed button, else the default
99       option, else monthly — WITHOUT emitting (legacy parity: the old IIFE
100       seeded silently). Idempotent via the ready guard. */
101    function setup(toggle) {
102        if (!toggle || toggle.getAttribute('data-hzo-pricing-toggle-ready') === 'true') { return; }
103        toggle.setAttribute('data-hzo-pricing-toggle-ready', 'true');
104        var pressed = toggle.querySelector('[data-hzo-price-period][aria-pressed="true"]');
105        var period = pressed
106            ? pressed.getAttribute('data-hzo-price-period')
107            : (toggle.getAttribute('data-hzo-pricing-toggle-default') || 'monthly');
108        setPeriod(toggle, period, false);   // seed a consistent state, no event on load
109    }
110
111    function init(scope) {
112        var toggles = (scope || document).querySelectorAll('[data-hzo-price-toggle]');
113        for (var t = 0; t < toggles.length; t++) { setup(toggles[t]); }
114    }
115
116    // Programmatic setter for integrations: seeds if needed, then swaps +
117    // emits. rootOrId: the .hzo-price-toggle element or its id; period:
118    // "monthly" | "annual" (any period string a button carries).
119    function set(rootOrId, period) {
120        var toggle = typeof rootOrId === 'string' ? document.getElementById(rootOrId) : rootOrId;
121        if (!toggle) return;
122        setup(toggle);   // covers toggles injected after init (AJAX content)
123        setPeriod(toggle, period, true);
124    }
125
126    if (document.readyState === 'loading') {
127        document.addEventListener('DOMContentLoaded', function () { init(); });
128    } else {
129        init();
130    }
131
132    // Shared engine namespace (never a new top-level global).
133    window.hzo = window.hzo || {};
134    window.hzo.pricingToggle = { init: init, setup: setup, set: set };
135})();

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.