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.