PageSourceSearch

https://legacyautopartsllc.com/assets/ai-assistant/bw-tabs.js?v=1791113231

js legacyautopartsllc.com collected 2026-10-08 19:57:52 UTC 9,092 bytes, 291 lines download raw bytes

1/**
2 * Category / content tabs — click tab to show matching panel (editor + live pages).
3 */
4(function (global) {
5    'use strict';
6
7    if (global.__bwTabsBooted) {
8        return;
9    }
10    global.__bwTabsBooted = true;
11
12    var delegatedDocs = typeof WeakSet !== 'undefined' ? new WeakSet() : null;
13    var delegatedBoundLegacy = false;
14
15    function isEditorMode() {
16        if (global.BW_IS_CONTENTBOX_EDITOR || global.BW_IS_AIBOX_EDITOR) {
17            return true;
18        }
19        if (global.BwIsContentboxEditor && global.BwIsContentboxEditor()) {
20            return true;
21        }
22        if (global.BwContentboxClickfix && typeof global.BwContentboxClickfix.isEditorMode === 'function') {
23            return global.BwContentboxClickfix.isEditorMode();
24        }
25        if (document.body && document.body.classList.contains('bw-page-editor')) {
26            return true;
27        }
28        return false;
29    }
30
31    function tabButtons(tabs) {
32        return tabs.querySelectorAll('.bw-tab-nav .bw-tab-btn, .bw-tab-nav button[data-bw-tab], .bw-tab-nav button');
33    }
34
35    function tabPanels(tabs) {
36        return tabs.querySelectorAll('.bw-tab-panels > .bw-tab-panel, .bw-tab-panels > [data-bw-tab-panel]');
37    }
38
39    function readBtnSlug(btn) {
40        return btn.getAttribute('data-bw-tab') || '';
41    }
42
43    function panelSlug(panel) {
44        return panel.getAttribute('data-bw-tab-panel') || '';
45    }
46
47    function styleTabButton(btn, active) {
48        btn.classList.toggle('is-active', active);
49        btn.setAttribute('aria-selected', active ? 'true' : 'false');
50    }
51
52    function showPanel(panel, show) {
53        if (show) {
54            panel.removeAttribute('hidden');
55            panel.classList.add('is-active');
56        } else {
57            panel.setAttribute('hidden', 'hidden');
58            panel.classList.remove('is-active');
59        }
60    }
61
62    function activateTabInSection(sec, slug) {
63        if (!sec || !slug) {
64            return false;
65        }
66        var panels = sec.querySelectorAll('.bw-tab-panels > .bw-tab-panel, .bw-tab-panels > [data-bw-tab-panel], .bw-tab-panel[data-bw-tab-panel], [data-bw-tab-panel]');
67        if (!panels.length) {
68            return false;
69        }
70        var matched = false;
71        panels.forEach(function (panel) {
72            var on = panelSlug(panel) === slug;
73            showPanel(panel, on);
74            if (on) {
75                matched = true;
76            }
77        });
78        if (!matched) {
79            return false;
80        }
81        sec.querySelectorAll('.bw-tab-nav .bw-tab-btn, .bw-tab-nav button[data-bw-tab], .bw-tab-nav button').forEach(function (btn) {
82            styleTabButton(btn, readBtnSlug(btn) === slug);
83        });
84        return true;
85    }
86
87    function activateTab(tabs, slug) {
88        if (!tabs || !slug) {
89            return;
90        }
91        var sec = tabs.closest('.is-section');
92        if (sec && activateTabInSection(sec, slug)) {
93            return;
94        }
95        var matched = false;
96        tabPanels(tabs).forEach(function (panel) {
97            var on = panelSlug(panel) === slug;
98            showPanel(panel, on);
99            if (on) {
100                matched = true;
101            }
102        });
103        if (!matched) {
104            return;
105        }
106        tabButtons(tabs).forEach(function (btn) {
107            styleTabButton(btn, readBtnSlug(btn) === slug);
108        });
109    }
110
111    function mergeOrphanTabPanels(tabs) {
112        if (!tabs) {
113            return;
114        }
115        var sec = tabs.closest('.is-section');
116        if (!sec) {
117            return;
118        }
119        var wraps = sec.querySelectorAll('.bw-tab-panels');
120        if (wraps.length < 2) {
121            return;
122        }
123        var best = null;
124        var bestScore = -1;
125        wraps.forEach(function (wrap) {
126            var score = wrap.querySelectorAll('.gallery-item, .bw-tab-panel .column, .bw-tab-panel img').length;
127            score += wrap.querySelectorAll('.bw-tab-panel').length * 3;
128            var btnOnly = wrap.querySelectorAll('a.is-btn, button.is-btn').length;
129            if (btnOnly > 0 && score < 8) {
130                score -= 20;
131            }
132            if (score > bestScore) {
133                bestScore = score;
134                best = wrap;
135            }
136        });
137        if (!best || best.parentElement === tabs) {
138            return;
139        }
140        wraps.forEach(function (wrap) {
141            if (wrap !== best && wrap.parentElement) {
142                wrap.parentElement.removeChild(wrap);
143            }
144        });
145        if (best.parentElement !== tabs) {
146            tabs.appendChild(best);
147        }
148    }
149
150    function prepareTabs(tabs) {
151        if (!tabs) {
152            return;
153        }
154        mergeOrphanTabPanels(tabs);
155
156        var btns = tabButtons(tabs);
157        var panels = tabPanels(tabs);
158        if (!btns.length || !panels.length) {
159            return;
160        }
161        if (tabs.getAttribute('data-bw-tabs-prepared') === '1') {
162            return;
163        }
164        tabs.setAttribute('data-bw-tabs-prepared', '1');
165
166        btns.forEach(function (btn, i) {
167            if (!btn.getAttribute('type')) {
168                btn.setAttribute('type', 'button');
169            }
170            if (!btn.classList.contains('bw-tab-btn')) {
171                btn.classList.add('bw-tab-btn');
172            }
173            btn.setAttribute('role', 'tab');
174            if (!btn.getAttribute('data-bw-tab')) {
175                var label = (btn.textContent || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
176                btn.setAttribute('data-bw-tab', label || ('tab-' + i));
177            }
178        });
179
180        panels.forEach(function (panel, i) {
181            panel.setAttribute('role', 'tabpanel');
182            if (!panel.getAttribute('data-bw-tab-panel')) {
183                var btn = btns[i];
184                if (btn) {
185                    panel.setAttribute('data-bw-tab-panel', readBtnSlug(btn));
186                }
187            }
188        });
189
190        var activeSlug = '';
191        btns.forEach(function (btn) {
192            if (btn.classList.contains('is-active')) {
193                activeSlug = readBtnSlug(btn);
194            }
195        });
196        if (!activeSlug) {
197            activeSlug = readBtnSlug(btns[0]);
198        }
199        activateTab(tabs, activeSlug);
200    }
201
202    function bindDelegation(doc) {
203        doc = doc || document;
204        if (delegatedDocs) {
205            if (delegatedDocs.has(doc)) {
206                return;
207            }
208            delegatedDocs.add(doc);
209        } else if (doc === document) {
210            if (delegatedBoundLegacy) {
211                return;
212            }
213            delegatedBoundLegacy = true;
214        }
215
216        doc.addEventListener('click', function (e) {
217            var btn = e.target.closest('.bw-tab-nav .bw-tab-btn, .bw-tab-nav button');
218            if (!btn) {
219                return;
220            }
221            var slug = readBtnSlug(btn);
222            if (!slug) {
223                return;
224            }
225            var sec = btn.closest('.is-section');
226            e.preventDefault();
227            e.stopPropagation();
228            if (sec && activateTabInSection(sec, slug)) {
229                return;
230            }
231            var tabs = btn.closest('[data-bw-tabs], .bw-tabs');
232            if (!tabs) {
233                return;
234            }
235            activateTab(tabs, slug);
236        }, true);
237
238        doc.addEventListener('keydown', function (e) {
239            if (e.key !== 'Enter' && e.key !== ' ') {
240                return;
241            }
242            var btn = e.target.closest('.bw-tab-nav .bw-tab-btn, .bw-tab-nav button');
243            if (!btn) {
244                return;
245            }
246            var tabs = btn.closest('[data-bw-tabs], .bw-tabs');
247            if (!tabs) {
248                return;
249            }
250            e.preventDefault();
251            activateTab(tabs, readBtnSlug(btn));
252        }, true);
253    }
254
255    function init(root) {
256        root = root || document;
257        var doc = (root.nodeType === 9) ? root : (root.ownerDocument || document);
258        var scope = (root.nodeType === 9) ? (root.body || root) : root;
259        bindDelegation(doc);
260        scope.querySelectorAll('[data-bw-tabs], .bw-tabs').forEach(prepareTabs);
261    }
262
263    function watch() {
264        init(document);
265        if (typeof MutationObserver === 'undefined') {
266            return;
267        }
268        var obs = new MutationObserver(function () {
269            init(document);
270        });
271        var target = document.querySelector('.is-wrapper') || document.body;
272        if (target) {
273            obs.observe(target, { childList: true, subtree: true });
274        }
275    }
276
277    global.BwTabs = { init: init, watch: watch, activateTab: activateTab };
278
279    function boot() {
280        watch();
281        window.addEventListener('load', function () {
282            init(document);
283        });
284    }
285
286    if (document.readyState === 'loading') {
287        document.addEventListener('DOMContentLoaded', boot);
288    } else {
289        boot();
290    }
291})(typeof window !== 'undefined' ? window : this);

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.